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.36 2004/06/12 01:11:35 taylor
19 * x86 compile fixes for OSX patch
21 * Revision 1.35 2004/06/11 00:53:02 tigital
22 * OSX: .app name, casts for gcc
24 * Revision 1.34 2003/08/09 03:18:03 taylor
25 * fix tips popup not having any tips
27 * Revision 1.33 2003/08/03 15:57:00 taylor
28 * simpler mouse usage; default ini settings in os_init(); cleanup
30 * Revision 1.32 2003/06/19 11:51:41 taylor
31 * adjustments to memory leak fixes
33 * Revision 1.31 2003/06/11 18:30:32 taylor
36 * Revision 1.30 2003/06/03 04:00:39 taylor
37 * Polish language support (Janusz Dziemidowicz)
39 * Revision 1.29 2003/05/25 02:30:42 taylor
42 * Revision 1.28 2003/05/18 03:55:30 taylor
43 * automatic language selection support
45 * Revision 1.27 2003/03/03 04:54:44 theoddone33
46 * Commit Taylor's ShowFPS fix
48 * Revision 1.26 2003/02/20 17:41:07 theoddone33
49 * Userdir patch from Taylor Richards
51 * Revision 1.25 2003/01/30 19:54:10 relnev
52 * ini config option for the frames per second counter (Taylor Richards)
54 * Revision 1.24 2002/08/31 01:39:13 theoddone33
55 * Speed up the renderer a tad
57 * Revision 1.23 2002/08/04 02:31:00 relnev
58 * make numlock not overlap with pause
60 * Revision 1.22 2002/08/02 23:07:03 relnev
61 * don't access the mouse in standalone mode
63 * Revision 1.21 2002/07/28 05:05:08 relnev
64 * removed some old stuff
66 * Revision 1.20 2002/07/24 00:20:41 relnev
69 * Revision 1.19 2002/06/17 06:33:08 relnev
70 * ryan's struct patch for gcc 2.95
72 * Revision 1.18 2002/06/16 04:46:33 relnev
73 * set up correct checksums for demo
75 * Revision 1.17 2002/06/09 04:41:17 relnev
76 * added copyright header
78 * Revision 1.16 2002/06/09 03:16:04 relnev
81 * removed unneeded asm, old sdl 2d setup.
83 * fixed crash caused by opengl_get_region.
85 * Revision 1.15 2002/06/05 08:05:28 relnev
86 * stub/warning removal.
88 * reworked the sound code.
90 * Revision 1.14 2002/06/05 04:03:32 relnev
91 * finished cfilesystem.
93 * removed some old code.
95 * fixed mouse save off-by-one.
99 * Revision 1.13 2002/06/02 04:26:34 relnev
102 * Revision 1.12 2002/06/02 00:31:35 relnev
103 * implemented osregistry
105 * Revision 1.11 2002/06/01 09:00:34 relnev
106 * silly debug memmanager
108 * Revision 1.10 2002/06/01 07:12:32 relnev
109 * a few NDEBUG updates.
111 * removed a few warnings.
113 * Revision 1.9 2002/05/31 03:05:59 relnev
116 * Revision 1.8 2002/05/29 02:52:32 theoddone33
117 * Enable OpenGL renderer
119 * Revision 1.7 2002/05/28 08:52:03 relnev
120 * implemented two assembly stubs.
122 * cleaned up a few warnings.
124 * added a little demo hackery to make it progress a little farther.
126 * Revision 1.6 2002/05/28 06:28:20 theoddone33
127 * Filesystem mods, actually reads some data files now
129 * Revision 1.5 2002/05/28 04:07:28 theoddone33
130 * New graphics stubbing arrangement
132 * Revision 1.4 2002/05/27 22:46:52 theoddone33
133 * Remove more undefined symbols
135 * Revision 1.3 2002/05/26 23:31:18 relnev
136 * added a few files that needed to be compiled
138 * freespace.cpp: now compiles
140 * Revision 1.2 2002/05/07 03:16:44 theoddone33
141 * The Great Newline Fix
143 * Revision 1.1.1.1 2002/05/03 03:28:09 root
147 * 201 6/16/00 3:15p Jefff
148 * sim of the year dvd version changes, a few german soty localization
151 * 200 11/03/99 11:06a Jefff
154 * 199 10/26/99 5:07p Jamest
155 * fixed jeffs dumb debug code
157 * 198 10/25/99 5:53p Jefff
158 * call control_config_common_init() on startup
160 * 197 10/14/99 10:18a Daveb
161 * Fixed incorrect CD checking problem on standalone server.
163 * 196 10/13/99 9:22a Daveb
164 * Fixed Fred jumpnode placing bug. Fixed 1024 glide tiled texture problem
165 * related to movies. Fixed launcher spawning from PXO screen.
167 * 195 10/06/99 11:05a Jefff
168 * new oem upsell 3 hotspot coords
170 * 194 10/06/99 10:31a Jefff
173 * 193 10/01/99 9:10a Daveb
176 * 192 9/15/99 4:57a Dave
177 * Updated ships.tbl checksum
179 * 191 9/15/99 3:58a Dave
180 * Removed framerate warning at all times.
182 * 190 9/15/99 3:16a Dave
183 * Remove mt-011.fs2 from the builtin mission list.
185 * 189 9/15/99 1:45a Dave
186 * Don't init joystick on standalone. Fixed campaign mode on standalone.
187 * Fixed no-score-report problem in TvT
189 * 188 9/14/99 6:08a Dave
190 * Updated (final) single, multi, and campaign list.
192 * 187 9/14/99 3:26a Dave
193 * Fixed laser fogging problem in nebula (D3D)> Fixed multiplayer
194 * respawn-too-early problem. Made a few crash points safe.
196 * 186 9/13/99 4:52p Dave
199 * 185 9/12/99 8:09p Dave
200 * Fixed problem where skip-training button would cause mission messages
201 * not to get paged out for the current mission.
203 * 184 9/10/99 11:53a Dave
204 * Shutdown graphics before sound to eliminate apparent lockups when
205 * Directsound decides to be lame. Fix TOPMOST problem with D3D windows.
207 * 183 9/09/99 11:40p Dave
208 * Handle an Assert() in beam code. Added supernova sounds. Play the right
209 * 2 end movies properly, based upon what the player did in the mission.
211 * 182 9/08/99 10:29p Dave
212 * Make beam sound pausing and unpausing much safer.
214 * 181 9/08/99 10:01p Dave
215 * Make sure game won't run in a drive's root directory. Make sure
216 * standalone routes suqad war messages properly to the host.
218 * 180 9/08/99 3:22p Dave
219 * Updated builtin mission list.
221 * 179 9/08/99 12:01p Jefff
222 * fixed Game_builtin_mission_list typo on Training-2.fs2
224 * 178 9/08/99 9:48a Andsager
225 * Add force feedback for engine wash.
227 * 177 9/07/99 4:01p Dave
228 * Fixed up a string.tbl paroblem (self destruct message). Make sure IPX
229 * does everything properly (setting up address when binding). Remove
230 * black rectangle background from UI_INPUTBOX.
232 * 176 9/13/99 2:40a Dave
233 * Comment in full 80 minute CD check for RELEASE_REAL builds.
235 * 175 9/06/99 6:38p Dave
236 * Improved CD detection code.
238 * 174 9/06/99 1:30a Dave
239 * Intermediate checkin. Started on enforcing CD-in-drive to play the
242 * 173 9/06/99 1:16a Dave
243 * Make sure the user sees the intro movie.
245 * 172 9/04/99 8:00p Dave
246 * Fixed up 1024 and 32 bit movie support.
248 * 171 9/03/99 1:32a Dave
249 * CD checking by act. Added support to play 2 cutscenes in a row
250 * seamlessly. Fixed super low level cfile bug related to files in the
251 * root directory of a CD. Added cheat code to set campaign mission # in
254 * 170 9/01/99 10:49p Dave
255 * Added nice SquadWar checkbox to the client join wait screen.
257 * 169 9/01/99 10:14a Dave
260 * 168 8/29/99 4:51p Dave
261 * Fixed damaged checkin.
263 * 167 8/29/99 4:18p Andsager
264 * New "burst" limit for friendly damage. Also credit more damage done
265 * against large friendly ships.
267 * 166 8/27/99 6:38p Alanl
268 * crush the blasted repeating messages bug
270 * 164 8/26/99 9:09p Dave
271 * Force framerate check in everything but a RELEASE_REAL build.
273 * 163 8/26/99 9:45a Dave
274 * First pass at easter eggs and cheats.
276 * 162 8/24/99 8:55p Dave
277 * Make sure nondimming pixels work properly in tech menu.
279 * 161 8/24/99 1:49a Dave
280 * Fixed client-side afterburner stuttering. Added checkbox for no version
281 * checking on PXO join. Made button info passing more friendly between
284 * 160 8/22/99 5:53p Dave
285 * Scoring fixes. Added self destruct key. Put callsigns in the logfile
286 * instead of ship designations for multiplayer players.
288 * 159 8/22/99 1:19p Dave
289 * Fixed up http proxy code. Cleaned up scoring code. Reverse the order in
290 * which d3d cards are detected.
292 * 158 8/20/99 2:09p Dave
293 * PXO banner cycling.
295 * 157 8/19/99 10:59a Dave
296 * Packet loss detection.
298 * 156 8/19/99 10:12a Alanl
299 * preload mission-specific messages on machines greater than 48MB
301 * 155 8/16/99 4:04p Dave
302 * Big honking checkin.
304 * 154 8/11/99 5:54p Dave
305 * Fixed collision problem. Fixed standalone ghost problem.
307 * 153 8/10/99 7:59p Jefff
310 * 152 8/10/99 6:54p Dave
311 * Mad optimizations. Added paging to the nebula effect.
313 * 151 8/10/99 3:44p Jefff
314 * loads Intelligence information on startup
316 * 150 8/09/99 3:47p Dave
317 * Fixed incorrect nebula regeneration. Default HUD to low-contrast in
318 * non-nebula missions.
320 * 149 8/09/99 2:21p Andsager
321 * Fix patching from multiplayer direct to launcher update tab.
323 * 148 8/09/99 10:36a Dave
324 * Version info for game.
326 * 147 8/06/99 9:46p Dave
327 * Hopefully final changes for the demo.
329 * 146 8/06/99 3:34p Andsager
330 * Make title version info "(D)" -> "D" show up nicely
332 * 145 8/06/99 2:59p Adamp
333 * Fixed NT launcher/update problem.
335 * 144 8/06/99 1:52p Dave
336 * Bumped up MAX_BITMAPS for the demo.
338 * 143 8/06/99 12:17p Andsager
339 * Demo: down to just 1 demo dog
341 * 142 8/05/99 9:39p Dave
342 * Yet another new checksum.
344 * 141 8/05/99 6:19p Dave
345 * New demo checksums.
347 * 140 8/05/99 5:31p Andsager
348 * Up demo version 1.01
350 * 139 8/05/99 4:22p Andsager
351 * No time limit on upsell screens. Reverse order of display of upsell
354 * 138 8/05/99 4:17p Dave
355 * Tweaks to client interpolation.
357 * 137 8/05/99 3:52p Danw
359 * 136 8/05/99 3:01p Danw
361 * 135 8/05/99 2:43a Anoop
362 * removed duplicate definition.
364 * 134 8/05/99 2:13a Dave
367 * 133 8/05/99 2:05a Dave
370 * 132 8/05/99 1:22a Andsager
373 * 131 8/04/99 9:51p Andsager
374 * Add title screen to demo
376 * 130 8/04/99 6:47p Jefff
377 * fixed link error resulting from #ifdefs
379 * 129 8/04/99 6:26p Dave
380 * Updated ship tbl checksum.
382 * 128 8/04/99 5:40p Andsager
383 * Add multiple demo dogs
385 * 127 8/04/99 5:36p Andsager
386 * Show upsell screens at end of demo campaign before returning to main
389 * 126 8/04/99 11:42a Danw
390 * tone down EAX reverb
392 * 125 8/04/99 11:23a Dave
393 * Updated demo checksums.
395 * 124 8/03/99 11:02p Dave
396 * Maybe fixed sync problems in multiplayer.
398 * 123 8/03/99 6:21p Jefff
401 * 122 8/03/99 3:44p Andsager
402 * Launch laucher if trying to run FS without first having configured
405 * 121 8/03/99 12:45p Dave
408 * 120 8/02/99 9:13p Dave
411 * 119 7/30/99 10:31p Dave
412 * Added comm menu to the configurable hud files.
414 * 118 7/30/99 5:17p Andsager
415 * first fs2demo checksums
417 * 117 7/29/99 3:09p Anoop
419 * 116 7/29/99 12:05a Dave
420 * Nebula speed optimizations.
422 * 115 7/27/99 8:59a Andsager
423 * Make major, minor version consistent for all builds. Only show major
424 * and minor for launcher update window.
426 * 114 7/26/99 5:50p Dave
427 * Revised ingame join. Better? We'll see....
429 * 113 7/26/99 5:27p Andsager
430 * Add training mission as builtin to demo build
432 * 112 7/24/99 1:54p Dave
433 * Hud text flash gauge. Reworked dead popup to use 4 buttons in red-alert
436 * 111 7/22/99 4:00p Dave
437 * Fixed beam weapon muzzle glow rendering. Externalized hud shield info.
439 * 110 7/21/99 8:10p Dave
440 * First run of supernova effect.
442 * 109 7/20/99 1:49p Dave
443 * Peter Drake build. Fixed some release build warnings.
445 * 108 7/19/99 2:26p Andsager
446 * set demo multiplayer missions
448 * 107 7/18/99 5:19p Dave
449 * Jump node icon. Fixed debris fogging. Framerate warning stuff.
451 * 106 7/16/99 1:50p Dave
452 * 8 bit aabitmaps. yay.
454 * 105 7/15/99 3:07p Dave
455 * 32 bit detection support. Mouse coord commandline.
457 * 104 7/15/99 2:13p Dave
458 * Added 32 bit detection.
460 * 103 7/15/99 9:20a Andsager
461 * FS2_DEMO initial checkin
463 * 102 7/14/99 11:02a Dave
464 * Skill level default back to easy. Blech.
466 * 101 7/09/99 5:54p Dave
467 * Seperated cruiser types into individual types. Added tons of new
468 * briefing icons. Campaign screen.
470 * 100 7/08/99 4:43p Andsager
471 * New check for sparky_hi and print if not found.
473 * 99 7/08/99 10:53a Dave
474 * New multiplayer interpolation scheme. Not 100% done yet, but still
475 * better than the old way.
477 * 98 7/06/99 4:24p Dave
478 * Mid-level checkin. Starting on some potentially cool multiplayer
481 * 97 7/06/99 3:35p Andsager
482 * Allow movie to play before red alert mission.
484 * 96 7/03/99 5:50p Dave
485 * Make rotated bitmaps draw properly in padlock views.
487 * 95 7/02/99 9:55p Dave
488 * Player engine wash sound.
490 * 94 7/02/99 4:30p Dave
491 * Much more sophisticated lightning support.
493 * 93 6/29/99 7:52p Dave
494 * Put in exception handling in FS2.
496 * 92 6/22/99 9:37p Dave
497 * Put in pof spewing.
499 * 91 6/16/99 4:06p Dave
500 * New pilot info popup. Added new draw-bitmap-as-poly function.
502 * 90 6/15/99 1:56p Andsager
503 * For release builds, allow start up in high res only with
506 * 89 6/15/99 9:34a Dave
507 * Fixed key checking in single threaded version of the stamp notification
510 * 88 6/09/99 2:55p Andsager
511 * Allow multiple asteroid subtypes (of large, medium, small) and follow
514 * 87 6/08/99 1:14a Dave
515 * Multi colored hud test.
517 * 86 6/04/99 9:52a Dave
518 * Fixed some rendering problems.
520 * 85 6/03/99 10:15p Dave
521 * Put in temporary main hall screen.
523 * 84 6/02/99 6:18p Dave
524 * Fixed TNT lockup problems! Wheeeee!
526 * 83 6/01/99 3:52p Dave
527 * View footage screen. Fixed xstrings to not display the & symbol. Popup,
528 * dead popup, pxo find player popup, pxo private room popup.
530 * 82 5/26/99 1:28p Jasenw
531 * changed coords for loading ani
533 * 81 5/26/99 11:46a Dave
534 * Added ship-blasting lighting and made the randomization of lighting
535 * much more customizable.
537 * 80 5/24/99 5:45p Dave
538 * Added detail levels to the nebula, with a decent speedup. Split nebula
539 * lightning into its own section.
557 #include "systemvars.h"
562 #include "starfield.h"
563 #include "lighting.h"
568 #include "fireballs.h"
572 #include "floating.h"
573 #include "gamesequence.h"
575 #include "optionsmenu.h"
576 #include "playermenu.h"
577 #include "trainingmenu.h"
578 #include "techmenu.h"
581 #include "hudmessage.h"
583 #include "missiongoals.h"
584 #include "missionparse.h"
589 #include "multiutil.h"
590 #include "multimsgs.h"
594 #include "freespace.h"
595 #include "managepilot.h"
597 #include "contexthelp.h"
600 #include "missionbrief.h"
601 #include "missiondebrief.h"
603 #include "missionshipchoice.h"
605 #include "hudconfig.h"
606 #include "controlsconfig.h"
607 #include "missionmessage.h"
608 #include "missiontraining.h"
610 #include "hudtarget.h"
612 #include "eventmusic.h"
613 #include "animplay.h"
614 #include "missionweaponchoice.h"
615 #include "missionlog.h"
616 #include "audiostr.h"
618 #include "missioncampaign.h"
620 #include "missionhotkey.h"
621 #include "objectsnd.h"
622 #include "cmeasure.h"
624 #include "linklist.h"
625 #include "shockwave.h"
626 #include "afterburner.h"
631 #include "stand_gui.h"
632 #include "pcxutils.h"
633 #include "hudtargetbox.h"
634 #include "multi_xfer.h"
635 #include "hudescort.h"
636 #include "multiutil.h"
639 #include "multiteamselect.h"
642 #include "readyroom.h"
643 #include "mainhallmenu.h"
644 #include "multilag.h"
646 #include "particle.h"
648 #include "multi_ingame.h"
649 #include "snazzyui.h"
650 #include "asteroid.h"
651 #include "popupdead.h"
652 #include "multi_voice.h"
653 #include "missioncmdbrief.h"
654 #include "redalert.h"
655 #include "gameplayhelp.h"
656 #include "multilag.h"
657 #include "staticrand.h"
658 #include "multi_pmsg.h"
659 #include "levelpaging.h"
660 #include "observer.h"
661 #include "multi_pause.h"
662 #include "multi_endgame.h"
663 #include "cutscenes.h"
664 #include "multi_respawn.h"
666 #include "multi_obj.h"
667 #include "multi_log.h"
669 #include "localize.h"
670 #include "osregistry.h"
671 #include "barracks.h"
672 #include "missionpause.h"
674 #include "alphacolors.h"
675 #include "objcollide.h"
678 #include "neblightning.h"
679 #include "shipcontrails.h"
682 #include "multi_dogfight.h"
683 #include "multi_rate.h"
684 #include "muzzleflash.h"
688 #include "mainhalltemp.h"
689 #include "exceptionhandler.h"
693 #include "supernova.h"
694 #include "hudshield.h"
695 // #include "names.h"
697 #include "missionloopbrief.h"
701 #error macro FRED is defined when trying to build release Fred. Please undefine FRED macro in build settings
707 // 1.00.04 5/26/98 MWA -- going final (12 pm)
708 // 1.00.03 5/26/98 MWA -- going final (3 am)
709 // 1.00.02 5/25/98 MWA -- going final
710 // 1.00.01 5/25/98 MWA -- going final
711 // 0.90 5/21/98 MWA -- getting ready for final.
712 // 0.10 4/9/98. Set by MK.
714 // Demo version: (obsolete since DEMO codebase split from tree)
715 // 0.03 4/10/98 AL. Interplay rev
716 // 0.02 4/8/98 MK. Increased when this system was modified.
717 // 0.01 4/7/98? AL. First release to Interplay QA.
720 // 1.00 5/28/98 AL. First release to Interplay QA.
722 void game_level_init(int seed = -1);
723 void game_post_level_init();
724 void game_do_frame();
725 void game_update_missiontime(); // called from game_do_frame() and navmap_do_frame()
726 void game_reset_time();
727 void game_show_framerate(); // draws framerate in lower right corner
729 int Game_no_clear = 0;
731 int Pofview_running = 0;
732 int Nebedit_running = 0;
734 typedef struct big_expl_flash {
735 float max_flash_intensity; // max intensity
736 float cur_flash_intensity; // cur intensity
737 int flash_start; // start time
740 #define FRAME_FILTER 16
742 #define DEFAULT_SKILL_LEVEL 1
743 int Game_skill_level = DEFAULT_SKILL_LEVEL;
745 #define VIEWER_ZOOM_DEFAULT 0.75f // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
746 float Viewer_zoom = VIEWER_ZOOM_DEFAULT;
749 #define EXE_FNAME ("fs2.exe")
750 #define LAUNCHER_FNAME ("freespace2.exe")
752 #define EXE_FNAME ("Freespace2demo.app")
753 #define LAUNCHER_FNAME ("Freespace2demo.app")
754 char app_path[] = "Freespace2demo.app/Contents/MacOS/Freespace2demo";
756 #define EXE_FNAME ("Freespace1demo.app")
757 #define LAUNCHER_FNAME ("Freespace1demo.app")
758 char app_path[] = "Freespace1demo.app/Contents/MacOS/Freespace1demo";
760 #define EXE_FNAME ("Freespace1.app")
761 #define LAUNCHER_FNAME ("Freespace1.app")
762 char app_path[] ="Freespace1.app/Contents/MacOS/Freespace1";
764 #define EXE_FNAME ("Freespace2.app")
765 #define LAUNCHER_FNAME ("Freespace2.app")
766 char app_path[] ="Freespace2.app/Contents/MacOS/Freespace2";
770 extern char full_path[1024];
773 // JAS: Code for warphole camera.
774 // Needs to be cleaned up.
775 vector Camera_pos = { 0.0f, 0.0f, 0.0f };
776 vector Camera_velocity = { 0.0f, 0.0f, 0.0f };
777 vector Camera_desired_velocity = { 0.0f, 0.0f, 0.0f };
778 matrix Camera_orient = IDENTITY_MATRIX;
779 float Camera_damping = 1.0f;
780 float Camera_time = 0.0f;
781 float Warpout_time = 0.0f;
782 int Warpout_forced = 0; // Set if this is a forced warpout that cannot be cancelled.
783 int Warpout_sound = -1;
785 int Use_joy_mouse = 0;
786 int Use_palette_flash = 1;
788 int Use_fullscreen_at_startup = 0;
790 int Show_area_effect = 0;
791 object *Last_view_target = NULL;
793 int dogfight_blown = 0;
796 float frametimes[FRAME_FILTER];
797 float frametotal = 0.0f;
801 int Show_framerate = 0;
803 int Show_framerate = 1;
806 int Framerate_cap = 120;
809 int Show_target_debug_info = 0;
810 int Show_target_weapons = 0;
814 static int Show_player_pos = 0; // debug console command to show player world pos on HUD
817 int Debug_octant = -1;
819 fix Game_time_compression = F1_0;
821 // if the ships.tbl the player has is valid
822 int Game_ships_tbl_valid = 0;
824 // if the weapons.tbl the player has is valid
825 int Game_weapons_tbl_valid = 0;
829 extern int Player_attacking_enabled;
833 int Pre_player_entry;
835 int Fred_running = 0;
836 char Game_current_mission_filename[MAX_FILENAME_LEN];
837 int game_single_step = 0;
838 int last_single_step=0;
840 extern int MSG_WINDOW_X_START; // used to position mission_time and shields output
841 extern int MSG_WINDOW_Y_START;
842 extern int MSG_WINDOW_HEIGHT;
844 int game_zbuffer = 1;
845 //static int Game_music_paused;
846 static int Game_paused;
850 #define EXPIRE_BAD_CHECKSUM 1
851 #define EXPIRE_BAD_TIME 2
853 extern void ssm_init();
854 extern void ssm_level_init();
855 extern void ssm_process();
857 // static variable to contain the time this version was built
858 // commented out for now until
859 // I figure out how to get the username into the file
860 //LOCAL char freespace_build_time[] = "Compiled on:"__DATE__" "__TIME__" by "__USER__;
862 // defines and variables used for dumping frame for making trailers.
864 int Debug_dump_frames = 0; // Set to 0 to not dump frames, else equal hz to dump. (15 or 30 probably)
865 int Debug_dump_trigger = 0;
866 int Debug_dump_frame_count;
867 int Debug_dump_frame_num = 0;
868 #define DUMP_BUFFER_NUM_FRAMES 1 // store every 15 frames
871 // amount of time to wait after the player has died before we display the death died popup
872 #define PLAYER_DIED_POPUP_WAIT 2500
873 int Player_died_popup_wait = -1;
874 int Player_multi_died_check = -1;
876 // builtin mission list stuff
878 int Game_builtin_mission_count = 6;
879 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
880 { "SPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
881 { "SPDemo-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
882 { "DemoTrain.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
883 { "Demo.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
884 { "MPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
885 { "Demo-DOG-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
887 #elif defined(FS1_DEMO)
888 int Game_builtin_mission_count = 5;
889 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
890 { "btmdemo.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
891 { "demo.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
892 { "demo01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
893 { "demo02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
894 { "demo02b.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
896 #elif defined(PD_BUILD)
897 int Game_builtin_mission_count = 4;
898 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
899 { "sm1-01.fs2", (FSB_FROM_VOLITION), "" },
900 { "sm1-05.fs2", (FSB_FROM_VOLITION), "" },
901 { "sm1-01", (FSB_FROM_VOLITION), "" },
902 { "sm1-05", (FSB_FROM_VOLITION), "" },
904 #elif defined(MULTIPLAYER_BETA)
905 int Game_builtin_mission_count = 17;
906 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
908 { "md-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
909 { "md-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
910 { "md-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
911 { "md-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
912 { "md-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
913 { "md-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
914 { "md-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
915 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
916 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
917 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
918 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
919 { "m-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
920 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
921 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
922 { "templar-03a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
923 { "templar-04a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
924 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
926 #elif defined(OEM_BUILD)
927 int Game_builtin_mission_count = 17;
928 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
929 // oem version - act 1 only
930 { "freespace2oem.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
933 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
934 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
935 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
936 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
937 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
938 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
939 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
940 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
941 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
942 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
943 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
944 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
945 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
946 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
947 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
948 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 }
950 #elif defined(MAKE_FS1)
951 int Game_builtin_mission_count = 125;
952 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
953 // single player campaign
954 { "freespace.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
957 { "sm1-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
958 { "sm1-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
959 { "sm1-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
960 { "sm1-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
961 { "sm1-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
962 { "sm1-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
963 { "sm1-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
964 { "sm1-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
965 { "sm1-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
966 { "sm1-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
969 { "sm2-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
970 { "sm2-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
971 { "sm2-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
972 { "sm2-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
973 { "sm2-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
974 { "sm2-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
975 { "sm2-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
976 { "sm2-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
977 { "sm2-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
978 { "sm2-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
981 { "sm3-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
982 { "sm3-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
983 { "sm3-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
984 { "sm3-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
985 { "sm3-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
986 { "sm3-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
987 { "sm3-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
988 { "sm3-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
989 { "sm3-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
992 { "t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
993 { "v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
994 { "s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
997 { "btm-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
998 { "btm-02.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
999 { "btm-03.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
1000 { "btm-04.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
1001 { "btm-05.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
1004 { "m-hope.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1005 { "m-altair.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1007 { "m-v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1008 { "m-va.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1009 { "m-unstoppable.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1010 { "m-t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1011 { "m-s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1012 { "m-rescue.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1013 { "m-pain.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1014 { "m-orecovery.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1015 { "mm3-01a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1016 { "mm3-02a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1017 { "mm3-03a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1018 { "mm3-04a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1019 { "mm3-05a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1020 { "mm3-06a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1021 { "m-guardduty.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1022 { "m-gate.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1023 { "m-duel.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1024 { "m-convoyassault.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1025 { "m-clash.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1027 // SilentThreat missions
1028 // Main SilentThreat campaign
1029 { "SilentThreat.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN_FILE), "" },
1031 { "md-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1032 { "md-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1033 { "md-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1034 { "md-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1035 { "md-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1036 { "md-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1037 { "md-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1038 { "md-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1039 { "md-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1040 { "md-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1041 { "md-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1042 { "md-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1044 // SilentThreat Part 1 - multi-coop
1045 { "ST-Part1.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1047 { "stmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1048 { "stmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1049 { "stmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1051 // SilentThreat Part 2 - multi-coop
1052 { "ST-Part2.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1054 { "stmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1055 { "stmm-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1056 { "stmm-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1058 // SilentThreat Part 3 - multi-coop
1059 { "ST-Part3.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1061 { "stmm-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1062 { "stmm-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1063 { "stmm-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1065 // SilentThreat Part 4 - multi-coop
1066 { "ST-Part4.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1068 { "stmm-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1069 { "stmm-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1070 { "stmm-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1072 // multiplayer missions
1073 { "mdmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1074 { "mdmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1075 { "mdmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1076 { "mdmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1077 // user supplied missions
1078 { "mdu-02.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1079 { "mdu-03.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1080 { "mdu-04.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1081 { "mdu-05.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1082 { "mdu-06.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1083 { "mdu-07.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1084 { "mdu-08.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1085 { "mdu-09.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1086 { "mdu-10.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1087 { "mdu-11.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1088 { "mdu-12.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1089 { "mdu-13.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1090 { "mdu-14.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1091 { "mdu-15.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1092 { "mdu-16.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1093 { "mdu-17.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1094 { "mdu-18.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1095 { "mdu-19.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1096 { "mdu-20.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1097 { "mdu-21.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1098 { "mdu-22.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1099 { "mdu-23.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1100 { "mdu-24.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1101 { "mdu-25.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1102 { "mdu-26.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1103 { "mdu-27.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1104 { "mdu-28.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1105 { "mdu-29.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1106 { "mdu-30.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1107 { "mdu-31.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1108 { "mdumm-01.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1109 { "mdumm-02.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1112 int Game_builtin_mission_count = 92;
1113 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
1114 // single player campaign
1115 { "freespace2.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
1118 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1119 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1120 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1121 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1122 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1123 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1124 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1125 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1126 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1127 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1128 { "loop1-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1129 { "loop1-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1130 { "loop1-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1131 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1132 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1133 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1134 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1135 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1136 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1139 { "sm2-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1140 { "sm2-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1141 { "sm2-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1142 { "sm2-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1143 { "sm2-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1144 { "sm2-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1145 { "sm2-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1146 { "sm2-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1147 { "sm2-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1148 { "sm2-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1151 { "sm3-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1152 { "sm3-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1153 { "sm3-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1154 { "sm3-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1155 { "sm3-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1156 { "sm3-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1157 { "sm3-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1158 { "sm3-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1159 { "sm3-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1160 { "sm3-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1161 { "loop2-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1162 { "loop2-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1164 // multiplayer missions
1167 { "g-shi.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1168 { "g-ter.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1169 { "g-vas.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1172 { "m-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1173 { "m-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1174 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1175 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1178 { "mdh-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1179 { "mdh-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1180 { "mdh-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1181 { "mdh-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1182 { "mdh-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1183 { "mdh-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1184 { "mdh-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1185 { "mdh-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1186 { "mdh-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1187 { "mdl-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1188 { "mdl-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1189 { "mdl-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1190 { "mdl-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1191 { "mdl-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1192 { "mdl-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1193 { "mdl-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1194 { "mdl-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1195 { "mdl-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1196 { "mdm-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1197 { "mdm-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1198 { "mdm-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1199 { "mdm-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1200 { "mdm-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1201 { "mdm-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1202 { "mdm-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1203 { "mdm-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1204 { "mdm-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1205 { "osdog.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1208 { "mt-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1209 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1210 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1211 { "mt-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1212 { "mt-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1213 { "mt-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1214 { "mt-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1215 { "mt-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1216 { "mt-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1217 { "mt-10.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1220 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1221 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1222 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1223 { "templar-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1224 { "templar-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1229 // Internal function prototypes
1230 void game_maybe_draw_mouse(float frametime);
1231 void init_animating_pointer();
1232 void load_animating_pointer(char *filename, int dx, int dy);
1233 void unload_animating_pointer();
1234 void game_do_training_checks();
1235 void game_shutdown(void);
1236 void game_show_event_debug(float frametime);
1237 void game_event_debug_init();
1239 void demo_upsell_show_screens();
1240 void game_start_subspace_ambient_sound();
1241 void game_stop_subspace_ambient_sound();
1242 void verify_ships_tbl();
1243 void verify_weapons_tbl();
1244 void display_title_screen();
1246 // loading background filenames
1247 static char *Game_loading_bground_fname[GR_NUM_RESOLUTIONS] = {
1248 "LoadingBG", // GR_640
1249 "2_LoadingBG" // GR_1024
1253 static char *Game_loading_ani_fname[GR_NUM_RESOLUTIONS] = {
1254 "Loading.ani", // GR_640
1255 "2_Loading.ani" // GR_1024
1258 #if defined(FS2_DEMO) || defined(FS1_DEMO)
1259 static char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1267 #elif defined(OEM_BUILD)
1268 static char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1278 char Game_CDROM_dir[MAX_PATH_LEN];
1281 // How much RAM is on this machine. Set in WinMain
1282 uint Freespace_total_ram = 0;
1285 float Game_flash_red = 0.0f;
1286 float Game_flash_green = 0.0f;
1287 float Game_flash_blue = 0.0f;
1288 float Sun_spot = 0.0f;
1289 big_expl_flash Big_expl_flash = {0.0f, 0.0f, 0};
1291 // game shudder stuff (in ms)
1292 int Game_shudder_time = -1;
1293 int Game_shudder_total = 0;
1294 float Game_shudder_intensity = 0.0f; // should be between 0.0 and 100.0
1297 sound_env Game_sound_env;
1298 //sound_env Game_default_sound_env = {SND_ENV_AUDITORIUM, 0.25f, 0.35f, 3.0f};
1299 sound_env Game_default_sound_env = {SND_ENV_GENERIC, 0.2F,0.2F,1.0F};
1301 int Game_sound_env_update_timestamp;
1303 // WARPIN CRAP BEGIN --------------------------------------------------------------------------------------------
1306 // WARPIN CRAP END --------------------------------------------------------------------------------------------
1308 fs_builtin_mission *game_find_builtin_mission(char *filename)
1312 // look through all existing builtin missions
1313 for(idx=0; idx<Game_builtin_mission_count; idx++){
1314 if(!stricmp(Game_builtin_mission_list[idx].filename, filename)){
1315 return &Game_builtin_mission_list[idx];
1323 int game_get_default_skill_level()
1325 return DEFAULT_SKILL_LEVEL;
1329 void game_flash_reset()
1331 Game_flash_red = 0.0f;
1332 Game_flash_green = 0.0f;
1333 Game_flash_blue = 0.0f;
1335 Big_expl_flash.max_flash_intensity = 0.0f;
1336 Big_expl_flash.cur_flash_intensity = 0.0f;
1337 Big_expl_flash.flash_start = 0;
1340 float Gf_critical = -1.0f; // framerate we should be above on the average for this mission
1341 float Gf_critical_time = 0.0f; // how much time we've been at the critical framerate
1343 void game_framerate_check_init()
1345 // zero critical time
1346 Gf_critical_time = 0.0f;
1349 if(The_mission.flags & MISSION_FLAG_FULLNEB){
1350 // if this is a glide card
1351 if(gr_screen.mode == GR_GLIDE){
1353 extern GrHwConfiguration hwconfig;
1356 if(hwconfig.SSTs[0].sstBoard.VoodooConfig.fbRam >= 4){
1357 Gf_critical = 15.0f;
1361 Gf_critical = 10.0f;
1366 Gf_critical = 15.0f;
1369 // d3d. only care about good cards here I guess (TNT)
1371 Gf_critical = 15.0f;
1374 // if this is a glide card
1375 if(gr_screen.mode == GR_GLIDE){
1377 extern GrHwConfiguration hwconfig;
1380 if(hwconfig.SSTs[0].sstBoard.VoodooConfig.fbRam >= 4){
1381 Gf_critical = 25.0f;
1385 Gf_critical = 20.0f;
1390 Gf_critical = 25.0f;
1393 // d3d. only care about good cards here I guess (TNT)
1395 Gf_critical = 25.0f;
1400 extern float Framerate;
1401 void game_framerate_check()
1405 // if the current framerate is above the critical level, add frametime
1406 if(Framerate >= Gf_critical){
1407 Gf_critical_time += flFrametime;
1410 if(!Show_framerate){
1414 // display if we're above the critical framerate
1415 if(Framerate < Gf_critical){
1416 gr_set_color_fast(&Color_bright_red);
1417 gr_string(200, y_start, "Framerate warning");
1422 // display our current pct of good frametime
1423 if(f2fl(Missiontime) >= 0.0f){
1424 float pct = (Gf_critical_time / f2fl(Missiontime)) * 100.0f;
1427 gr_set_color_fast(&Color_bright_green);
1429 gr_set_color_fast(&Color_bright_red);
1432 gr_printf(200, y_start, "%d%%", (int)pct);
1439 // Adds a flash effect. These can be positive or negative.
1440 // The range will get capped at around -1 to 1, so stick
1441 // with a range like that.
1442 void game_flash( float r, float g, float b )
1444 Game_flash_red += r;
1445 Game_flash_green += g;
1446 Game_flash_blue += b;
1448 if ( Game_flash_red < -1.0f ) {
1449 Game_flash_red = -1.0f;
1450 } else if ( Game_flash_red > 1.0f ) {
1451 Game_flash_red = 1.0f;
1454 if ( Game_flash_green < -1.0f ) {
1455 Game_flash_green = -1.0f;
1456 } else if ( Game_flash_green > 1.0f ) {
1457 Game_flash_green = 1.0f;
1460 if ( Game_flash_blue < -1.0f ) {
1461 Game_flash_blue = -1.0f;
1462 } else if ( Game_flash_blue > 1.0f ) {
1463 Game_flash_blue = 1.0f;
1468 // Adds a flash for Big Ship explosions
1469 // cap range from 0 to 1
1470 void big_explosion_flash(float flash)
1472 Big_expl_flash.flash_start = timestamp(1);
1476 } else if (flash < 0.0f) {
1480 Big_expl_flash.max_flash_intensity = flash;
1481 Big_expl_flash.cur_flash_intensity = 0.0f;
1484 // Amount to diminish palette towards normal, per second.
1485 #define DIMINISH_RATE 0.75f
1486 #define SUN_DIMINISH_RATE 6.00f
1490 float sn_glare_scale = 1.7f;
1493 dc_get_arg(ARG_FLOAT);
1494 sn_glare_scale = Dc_arg_float;
1497 float Supernova_last_glare = 0.0f;
1498 void game_sunspot_process(float frametime)
1502 float Sun_spot_goal = 0.0f;
1505 sn_stage = supernova_active();
1507 // sunspot differently based on supernova stage
1509 // approaching. player still in control
1512 pct = (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME));
1515 light_get_global_dir(&light_dir, 0);
1517 dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec );
1520 // scale it some more
1521 dot = dot * (0.5f + (pct * 0.5f));
1524 Sun_spot_goal += (dot * sn_glare_scale);
1527 // draw the sun glow
1528 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, 0 ) ) {
1529 // draw the glow for this sun
1530 stars_draw_sun_glow(0);
1533 Supernova_last_glare = Sun_spot_goal;
1536 // camera cut. player not in control. note : at this point camera starts out facing the sun. so we can go nice and bright
1539 Sun_spot_goal = 0.9f;
1540 Sun_spot_goal += (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME)) * 0.1f;
1542 if(Sun_spot_goal > 1.0f){
1543 Sun_spot_goal = 1.0f;
1546 Sun_spot_goal *= sn_glare_scale;
1547 Supernova_last_glare = Sun_spot_goal;
1550 // fade to white. display dead popup
1553 Supernova_last_glare += (2.0f * flFrametime);
1554 if(Supernova_last_glare > 2.0f){
1555 Supernova_last_glare = 2.0f;
1558 Sun_spot_goal = Supernova_last_glare;
1565 // check sunspots for all suns
1566 n_lights = light_get_global_count();
1569 for(idx=0; idx<n_lights; idx++){
1570 //(vector *eye_pos, matrix *eye_orient)
1571 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, idx ) ) {
1574 light_get_global_dir(&light_dir, idx);
1576 float dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec )*0.5f+0.5f;
1578 Sun_spot_goal += (float)pow(dot,85.0f);
1580 // draw the glow for this sun
1581 stars_draw_sun_glow(idx);
1583 Sun_spot_goal = 0.0f;
1589 Sun_spot_goal = 0.0f;
1593 float dec_amount = frametime*SUN_DIMINISH_RATE;
1595 if ( Sun_spot < Sun_spot_goal ) {
1596 Sun_spot += dec_amount;
1597 if ( Sun_spot > Sun_spot_goal ) {
1598 Sun_spot = Sun_spot_goal;
1600 } else if ( Sun_spot > Sun_spot_goal ) {
1601 Sun_spot -= dec_amount;
1602 if ( Sun_spot < Sun_spot_goal ) {
1603 Sun_spot = Sun_spot_goal;
1609 // Call once a frame to diminish the
1610 // flash effect to 0.
1611 void game_flash_diminish(float frametime)
1613 float dec_amount = frametime*DIMINISH_RATE;
1615 if ( Game_flash_red > 0.0f ) {
1616 Game_flash_red -= dec_amount;
1617 if ( Game_flash_red < 0.0f )
1618 Game_flash_red = 0.0f;
1620 Game_flash_red += dec_amount;
1621 if ( Game_flash_red > 0.0f )
1622 Game_flash_red = 0.0f;
1625 if ( Game_flash_green > 0.0f ) {
1626 Game_flash_green -= dec_amount;
1627 if ( Game_flash_green < 0.0f )
1628 Game_flash_green = 0.0f;
1630 Game_flash_green += dec_amount;
1631 if ( Game_flash_green > 0.0f )
1632 Game_flash_green = 0.0f;
1635 if ( Game_flash_blue > 0.0f ) {
1636 Game_flash_blue -= dec_amount;
1637 if ( Game_flash_blue < 0.0f )
1638 Game_flash_blue = 0.0f;
1640 Game_flash_blue += dec_amount;
1641 if ( Game_flash_blue > 0.0f )
1642 Game_flash_blue = 0.0f;
1645 // update big_explosion_cur_flash
1646 #define TIME_UP 1500
1647 #define TIME_DOWN 2500
1648 int duration = TIME_UP + TIME_DOWN;
1649 int time = timestamp_until(Big_expl_flash.flash_start);
1650 if (time > -duration) {
1652 if (time < TIME_UP) {
1653 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * time / (float) TIME_UP;
1656 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * ((float) TIME_DOWN - time) / (float) TIME_DOWN;
1660 if ( Use_palette_flash ) {
1662 // static int or=0, og=0, ob=0;
1664 // Change the 200 to change the color range of colors.
1665 r = fl2i( Game_flash_red*128.0f );
1666 g = fl2i( Game_flash_green*128.0f );
1667 b = fl2i( Game_flash_blue*128.0f );
1669 if ( Sun_spot > 0.0f ) {
1670 r += fl2i(Sun_spot*128.0f);
1671 g += fl2i(Sun_spot*128.0f);
1672 b += fl2i(Sun_spot*128.0f);
1675 if ( Big_expl_flash.cur_flash_intensity > 0.0f ) {
1676 r += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1677 g += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1678 b += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1681 if ( r < 0 ) r = 0; else if ( r > 255 ) r = 255;
1682 if ( g < 0 ) g = 0; else if ( g > 255 ) g = 255;
1683 if ( b < 0 ) b = 0; else if ( b > 255 ) b = 255;
1685 if ( (r!=0) || (g!=0) || (b!=0) ) {
1686 gr_flash( r, g, b );
1688 //mprintf(( "Flash! %d,%d,%d\n", r, g, b ));
1699 void game_level_close()
1701 // De-Initialize the game subsystems
1702 event_music_level_close();
1703 game_stop_looped_sounds();
1705 obj_snd_level_close(); // uninit object-linked persistant sounds
1706 gamesnd_unload_gameplay_sounds(); // unload gameplay sounds from memory
1707 anim_level_close(); // stop and clean up any anim instances
1708 message_mission_shutdown(); // called after anim_level_close() to make sure anim instances are free
1709 shockwave_level_close();
1710 fireball_level_close();
1712 mission_event_shutdown();
1713 asteroid_level_close();
1714 model_cache_reset(); // Reset/free all the model caching stuff
1715 flak_level_close(); // unload flak stuff
1716 neb2_level_close(); // shutdown gaseous nebula stuff
1719 mflash_level_close();
1721 audiostream_unpause_all();
1726 // intializes game stuff and loads the mission. Returns 0 on failure, 1 on success
1727 // input: seed => DEFAULT PARAMETER (value -1). Only set by demo playback code.
1728 void game_level_init(int seed)
1730 // seed the random number generator
1732 // if no seed was passed, seed the generator either from the time value, or from the
1733 // netgame security flags -- ensures that all players in multiplayer game will have the
1734 // same randon number sequence (with static rand functions)
1735 if ( Game_mode & GM_NORMAL ) {
1736 Game_level_seed = time(NULL);
1738 Game_level_seed = Netgame.security;
1741 // mwa 9/17/98 -- maybe this assert isn't needed????
1742 Assert( !(Game_mode & GM_MULTIPLAYER) );
1743 Game_level_seed = seed;
1745 srand( Game_level_seed );
1747 // semirand function needs to get re-initted every time in multiplayer
1748 if ( Game_mode & GM_MULTIPLAYER ){
1754 Key_normal_game = (Game_mode & GM_NORMAL);
1757 Game_shudder_time = -1;
1759 // Initialize the game subsystems
1760 // timestamp_reset(); // Must be inited before everything else
1762 game_reset_time(); // resets time, and resets saved time too
1764 obj_init(); // Must be inited before the other systems
1765 model_free_all(); // Free all existing models
1766 mission_brief_common_init(); // Free all existing briefing/debriefing text
1767 weapon_level_init();
1768 ai_level_init(); // Call this before ship_init() because it reads ai.tbl.
1770 player_level_init();
1771 shipfx_flash_init(); // Init the ship gun flash system.
1772 game_flash_reset(); // Reset the flash effect
1773 particle_init(); // Reset the particle system
1777 shield_hit_init(); // Initialize system for showing shield hits
1778 radar_mission_init();
1779 mission_init_goals();
1782 obj_snd_level_init(); // init object-linked persistant sounds
1784 shockwave_level_init();
1785 afterburner_level_init();
1786 scoring_level_init( &Player->stats );
1788 asteroid_level_init();
1789 control_config_clear_used_status();
1790 collide_ship_ship_sounds_init();
1792 Pre_player_entry = 1; // Means the player has not yet entered.
1793 Entry_delay_time = 0; // Could get overwritten in mission read.
1794 fireball_preload(); // page in warphole bitmaps
1796 flak_level_init(); // initialize flak - bitmaps, etc
1797 ct_level_init(); // initialize ships contrails, etc
1798 awacs_level_init(); // initialize AWACS
1799 beam_level_init(); // initialize beam weapons
1800 mflash_level_init();
1802 supernova_level_init();
1804 // multiplayer dogfight hack
1807 shipfx_engine_wash_level_init();
1811 Last_view_target = NULL;
1816 // campaign wasn't ended
1817 Campaign_ended_in_mission = 0;
1820 // called when a mission is over -- does server specific stuff.
1821 void freespace_stop_mission()
1824 Game_mode &= ~GM_IN_MISSION;
1827 // called at frame interval to process networking stuff
1828 void game_do_networking()
1830 Assert( Net_player != NULL );
1831 if (!(Game_mode & GM_MULTIPLAYER)){
1835 // see if this player should be reading/writing data. Bit is set when at join
1836 // screen onward until quits back to main menu.
1837 if ( !(Net_player->flags & NETINFO_FLAG_DO_NETWORKING) ){
1841 if(gameseq_get_state()!=GS_STATE_MULTI_PAUSED){
1844 multi_pause_do_frame();
1849 // Loads the best palette for this level, based
1850 // on nebula color and hud color. You could just call palette_load_table with
1851 // the appropriate filename, but who wants to do that.
1852 void game_load_palette()
1854 char palette_filename[1024];
1856 // We only use 3 hud colors right now
1858 Assert( HUD_config.main_color >= 0 );
1859 Assert( HUD_config.main_color <= 2 );
1862 Assert( Mission_palette >= 0 );
1863 Assert( Mission_palette <= 98 );
1866 if ( The_mission.flags & MISSION_FLAG_SUBSPACE ) {
1867 strcpy( palette_filename, NOX("gamepalette-subspace") );
1869 sprintf( palette_filename, NOX("gamepalette%d-%02d"), HUD_config.main_color+1, Mission_palette+1 );
1872 mprintf(( "Loading palette %s\n", palette_filename ));
1874 palette_load_table(palette_filename);
1876 strcpy( palette_filename, NOX("gamepalette-subspace") );
1878 mprintf(( "Loading palette %s\n", palette_filename ));
1882 void game_post_level_init()
1884 // Stuff which gets called after mission is loaded. Because player isn't created until
1885 // after mission loads, some things must get initted after the level loads
1887 model_level_post_init();
1890 hud_setup_escort_list();
1891 mission_hotkey_set_defaults(); // set up the default hotkeys (from mission file)
1897 game_event_debug_init();
1900 training_mission_init();
1901 asteroid_create_all();
1903 game_framerate_check_init();
1907 // An estimate as to how high the count passed to game_loading_callback will go.
1908 // This is just a guess, it seems to always be about the same. The count is
1909 // proportional to the code being executed, not the time, so this works good
1910 // for a bar, assuming the code does about the same thing each time you
1911 // load a level. You can find this value by looking at the return value
1912 // of game_busy_callback(NULL), which I conveniently print out to the
1913 // debug output window with the '=== ENDING LOAD ==' stuff.
1914 //#define COUNT_ESTIMATE 3706
1915 #define COUNT_ESTIMATE 1111
1917 int Game_loading_callback_inited = 0;
1919 int Game_loading_background = -1;
1920 anim * Game_loading_ani = NULL;
1921 anim_instance *Game_loading_ani_instance;
1922 int Game_loading_frame=-1;
1924 static int Game_loading_ani_coords[GR_NUM_RESOLUTIONS][2] = {
1926 #if defined(FS1_DEMO)
1928 #elif defined(MAKE_FS1)
1939 // This gets called 10x per second and count is the number of times
1940 // game_busy() has been called since the current callback function
1942 void game_loading_callback(int count)
1944 game_do_networking();
1946 Assert( Game_loading_callback_inited==1 );
1947 Assert( Game_loading_ani != NULL );
1949 int framenum = ((Game_loading_ani->total_frames*count) / COUNT_ESTIMATE)+1;
1950 if ( framenum > Game_loading_ani->total_frames-1 ) {
1951 framenum = Game_loading_ani->total_frames-1;
1952 } else if ( framenum < 0 ) {
1957 while ( Game_loading_frame < framenum ) {
1958 Game_loading_frame++;
1959 cbitmap = anim_get_next_frame(Game_loading_ani_instance);
1963 if ( cbitmap > -1 ) {
1964 if ( Game_loading_background > -1 ) {
1965 gr_set_bitmap( Game_loading_background );
1969 //mprintf(( "Showing frame %d/%d [ Bitmap=%d ]\n", Game_loading_frame , Game_loading_ani->total_frames, cbitmap ));
1970 gr_set_bitmap( cbitmap );
1971 gr_bitmap(Game_loading_ani_coords[gr_screen.res][0],Game_loading_ani_coords[gr_screen.res][1]);
1973 bm_release(cbitmap);
1979 void game_loading_callback_init()
1981 Assert( Game_loading_callback_inited==0 );
1983 Game_loading_background = bm_load(Game_loading_bground_fname[gr_screen.res]);
1985 common_set_interface_palette("InterfacePalette"); // set the interface palette
1989 Game_loading_ani = anim_load( Game_loading_ani_fname[gr_screen.res]);
1990 Assert( Game_loading_ani != NULL );
1991 Game_loading_ani_instance = init_anim_instance(Game_loading_ani, 16);
1992 Assert( Game_loading_ani_instance != NULL );
1993 Game_loading_frame = -1;
1995 Game_loading_callback_inited = 1;
1997 game_busy_callback( game_loading_callback, (COUNT_ESTIMATE/Game_loading_ani->total_frames)+1 );
2002 void game_loading_callback_close()
2004 Assert( Game_loading_callback_inited==1 );
2006 // Make sure bar shows all the way over.
2007 game_loading_callback(COUNT_ESTIMATE);
2009 int real_count = game_busy_callback( NULL );
2012 Game_loading_callback_inited = 0;
2015 mprintf(( "=================== ENDING LOAD ================\n" ));
2016 mprintf(( "Real count = %d, Estimated count = %d\n", real_count, COUNT_ESTIMATE ));
2017 mprintf(( "================================================\n" ));
2019 // to remove warnings in release build
2023 free_anim_instance(Game_loading_ani_instance);
2024 Game_loading_ani_instance = NULL;
2025 anim_free(Game_loading_ani);
2026 Game_loading_ani = NULL;
2028 bm_release( Game_loading_background );
2029 common_free_interface_palette(); // restore game palette
2030 Game_loading_background = -1;
2032 gr_set_font( FONT1 );
2035 // Update the sound environment (ie change EAX settings based on proximity to large ships)
2037 void game_maybe_update_sound_environment()
2039 // do nothing for now
2042 // Assign the sound environment for the game, based on the current mission
2044 void game_assign_sound_environment()
2047 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
2048 Game_sound_env.id = SND_ENV_DRUGGED;
2049 Game_sound_env.volume = 0.800f;
2050 Game_sound_env.damping = 1.188f;
2051 Game_sound_env.decay = 6.392f;
2053 } else if (Num_asteroids > 30) {
2054 Game_sound_env.id = SND_ENV_AUDITORIUM;
2055 Game_sound_env.volume = 0.603f;
2056 Game_sound_env.damping = 0.5f;
2057 Game_sound_env.decay = 4.279f;
2060 Game_sound_env = Game_default_sound_env;
2064 Game_sound_env = Game_default_sound_env;
2065 Game_sound_env_update_timestamp = timestamp(1);
2068 // function which gets called before actually entering the mission. It is broken down into a funciton
2069 // since it will get called in one place from a single player game and from another place for
2070 // a multiplayer game
2071 void freespace_mission_load_stuff()
2073 // called if we're not on a freespace dedicated (non rendering, no pilot) server
2074 // IE : we _don't_ want to load any sounds or bitmap/texture info on this machine.
2075 if(!(Game_mode & GM_STANDALONE_SERVER)){
2077 mprintf(( "=================== STARTING LEVEL DATA LOAD ==================\n" ));
2079 game_loading_callback_init();
2081 event_music_level_init(); // preloads the first 2 seconds for each event music track
2084 gamesnd_unload_interface_sounds(); // unload interface sounds from memory
2087 gamesnd_preload_common_sounds(); // load in sounds that are expected to play
2090 ship_assign_sound_all(); // assign engine sounds to ships
2091 game_assign_sound_environment(); // assign the sound environment for this mission
2094 // call function in missionparse.cpp to fixup player/ai stuff.
2095 mission_parse_fixup_players();
2098 // Load in all the bitmaps for this level
2103 game_loading_callback_close();
2105 // the only thing we need to call on the standalone for now.
2107 // call function in missionparse.cpp to fixup player/ai stuff.
2108 mission_parse_fixup_players();
2110 // Load in all the bitmaps for this level
2116 uint load_mission_load;
2117 uint load_post_level_init;
2118 uint load_mission_stuff;
2120 // tells the server to load the mission and initialize structures
2121 int game_start_mission()
2123 mprintf(( "=================== STARTING LEVEL LOAD ==================\n" ));
2125 load_gl_init = time(NULL);
2127 load_gl_init = time(NULL) - load_gl_init;
2129 if (Game_mode & GM_MULTIPLAYER) {
2130 Player->flags |= PLAYER_FLAGS_IS_MULTI;
2132 // clear multiplayer stats
2133 init_multiplayer_stats();
2136 load_mission_load = time(NULL);
2137 if (mission_load()) {
2138 if ( !(Game_mode & GM_MULTIPLAYER) ) {
2139 popup(PF_BODY_BIG, 1, POPUP_OK, XSTR( "Attempt to load the mission failed", 169));
2140 gameseq_post_event(GS_EVENT_MAIN_MENU);
2142 multi_quit_game(PROMPT_NONE, MULTI_END_NOTIFY_NONE, MULTI_END_ERROR_LOAD_FAIL);
2147 load_mission_load = time(NULL) - load_mission_load;
2149 // If this is a red alert mission in campaign mode, bash wingman status
2150 if ( (Game_mode & GM_CAMPAIGN_MODE) && red_alert_mission() ) {
2151 red_alert_bash_wingman_status();
2154 // the standalone server in multiplayer doesn't do any rendering, so we will not even bother loading the palette
2155 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
2156 mprintf(( "=================== LOADING GAME PALETTE ================\n" ));
2158 game_load_palette();
2162 load_post_level_init = time(NULL);
2163 game_post_level_init();
2164 load_post_level_init = time(NULL) - load_post_level_init;
2168 void Do_model_timings_test();
2169 Do_model_timings_test();
2173 load_mission_stuff = time(NULL);
2174 freespace_mission_load_stuff();
2175 load_mission_stuff = time(NULL) - load_mission_stuff;
2180 int Interface_framerate = 0;
2183 DCF_BOOL( mouse_control, Use_mouse_to_fly )
2184 DCF_BOOL( show_framerate, Show_framerate )
2185 DCF_BOOL( show_target_debug_info, Show_target_debug_info )
2186 DCF_BOOL( show_target_weapons, Show_target_weapons )
2187 DCF_BOOL( lead_target_cheat, Players[Player_num].lead_target_cheat )
2188 DCF_BOOL( sound, Sound_enabled )
2189 DCF_BOOL( zbuffer, game_zbuffer )
2190 DCF_BOOL( shield_system, New_shield_system )
2191 DCF_BOOL( show_shield_mesh, Show_shield_mesh)
2192 DCF_BOOL( player_attacking, Player_attacking_enabled )
2193 DCF_BOOL( show_waypoints, Show_waypoints )
2194 DCF_BOOL( show_area_effect, Show_area_effect )
2195 DCF_BOOL( show_net_stats, Show_net_stats )
2196 DCF_BOOL( log, Log_debug_output_to_file )
2197 DCF_BOOL( training_msg_method, Training_msg_method )
2198 DCF_BOOL( show_player_pos, Show_player_pos )
2199 DCF_BOOL(i_framerate, Interface_framerate )
2201 DCF(show_mem,"Toggles showing mem usage")
2204 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2205 if ( Dc_arg_type & ARG_TRUE ) Show_mem = 1;
2206 else if ( Dc_arg_type & ARG_FALSE ) Show_mem = 0;
2207 else if ( Dc_arg_type & ARG_NONE ) Show_mem ^= 1;
2213 if ( Dc_help ) dc_printf( "Usage: Show_mem\nSets show_mem to true or false. If nothing passed, then toggles it.\n" );
2215 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2216 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2220 DCF(show_cpu,"Toggles showing cpu usage")
2223 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2224 if ( Dc_arg_type & ARG_TRUE ) Show_cpu = 1;
2225 else if ( Dc_arg_type & ARG_FALSE ) Show_cpu = 0;
2226 else if ( Dc_arg_type & ARG_NONE ) Show_cpu ^= 1;
2232 if ( Dc_help ) dc_printf( "Usage: Show_cpu\nSets show_cpu to true or false. If nothing passed, then toggles it.\n" );
2234 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2235 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2242 // AL 4-8-98: always allow players to display their framerate
2245 DCF_BOOL( show_framerate, Show_framerate )
2252 DCF(use_joy_mouse,"Makes joystick move mouse cursor")
2255 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2256 if ( Dc_arg_type & ARG_TRUE ) Use_joy_mouse = 1;
2257 else if ( Dc_arg_type & ARG_FALSE ) Use_joy_mouse = 0;
2258 else if ( Dc_arg_type & ARG_NONE ) Use_joy_mouse ^= 1;
2260 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" );
2261 if ( Dc_status ) dc_printf( "use_joy_mouse is %s\n", (Use_joy_mouse?"TRUE":"FALSE") );
2263 os_config_write_uint( NULL, NOX("JoystickMovesCursor"), Use_joy_mouse );
2266 DCF(palette_flash,"Toggles palette flash effect on/off")
2269 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2270 if ( Dc_arg_type & ARG_TRUE ) Use_palette_flash = 1;
2271 else if ( Dc_arg_type & ARG_FALSE ) Use_palette_flash = 0;
2272 else if ( Dc_arg_type & ARG_NONE ) Use_palette_flash ^= 1;
2274 if ( Dc_help ) dc_printf( "Usage: palette_flash [bool]\nSets palette_flash to true or false. If nothing passed, then toggles it.\n" );
2275 if ( Dc_status ) dc_printf( "palette_flash is %s\n", (Use_palette_flash?"TRUE":"FALSE") );
2278 int Use_low_mem = 0;
2280 DCF(low_mem,"Uses low memory settings regardless of RAM")
2283 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2284 if ( Dc_arg_type & ARG_TRUE ) Use_low_mem = 1;
2285 else if ( Dc_arg_type & ARG_FALSE ) Use_low_mem = 0;
2286 else if ( Dc_arg_type & ARG_NONE ) Use_low_mem ^= 1;
2288 if ( Dc_help ) dc_printf( "Usage: low_mem [bool]\nSets low_mem to true or false. If nothing passed, then toggles it.\n" );
2289 if ( Dc_status ) dc_printf( "low_mem is %s\n", (Use_low_mem?"TRUE":"FALSE") );
2291 os_config_write_uint( NULL, NOX("LowMem"), Use_low_mem );
2297 DCF(force_fullscreen, "Forces game to startup in fullscreen mode")
2300 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2301 if ( Dc_arg_type & ARG_TRUE ) Use_fullscreen_at_startup = 1;
2302 else if ( Dc_arg_type & ARG_FALSE ) Use_fullscreen_at_startup = 0;
2303 else if ( Dc_arg_type & ARG_NONE ) Use_fullscreen_at_startup ^= 1;
2305 if ( Dc_help ) dc_printf( "Usage: force_fullscreen [bool]\nSets force_fullscreen to true or false. If nothing passed, then toggles it.\n" );
2306 if ( Dc_status ) dc_printf( "force_fullscreen is %s\n", (Use_fullscreen_at_startup?"TRUE":"FALSE") );
2307 os_config_write_uint( NULL, NOX("ForceFullscreen"), Use_fullscreen_at_startup );
2311 int Framerate_delay = 0;
2313 float Freespace_gamma = 1.0f;
2315 DCF(gamma,"Sets Gamma factor")
2318 dc_get_arg(ARG_FLOAT|ARG_NONE);
2319 if ( Dc_arg_type & ARG_FLOAT ) {
2320 Freespace_gamma = Dc_arg_float;
2322 dc_printf( "Gamma reset to 1.0f\n" );
2323 Freespace_gamma = 1.0f;
2325 if ( Freespace_gamma < 0.1f ) {
2326 Freespace_gamma = 0.1f;
2327 } else if ( Freespace_gamma > 5.0f ) {
2328 Freespace_gamma = 5.0f;
2330 gr_set_gamma(Freespace_gamma);
2332 char tmp_gamma_string[32];
2333 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2334 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2338 dc_printf( "Usage: gamma <float>\n" );
2339 dc_printf( "Sets gamma in range 1-3, no argument resets to default 1.2\n" );
2340 Dc_status = 0; // don't print status if help is printed. Too messy.
2344 dc_printf( "Gamma = %.2f\n", Freespace_gamma );
2353 Game_current_mission_filename[0] = 0;
2355 // seed the random number generator
2356 Game_init_seed = time(NULL);
2357 srand( Game_init_seed );
2359 Framerate_delay = 0;
2365 extern void bm_init();
2371 // Initialize the timer before the os
2379 GetCurrentDirectory(1024, whee);
2382 full_path[strlen(full_path) - strlen(app_path)] = '\0';
2383 strcpy( whee, full_path);
2385 getcwd (whee, 1024);
2388 strcat(whee, EXE_FNAME);
2390 //Initialize the libraries
2391 s1 = timer_get_milliseconds();
2392 if(cfile_init(whee, Game_CDROM_dir)){ // initialize before calling any cfopen stuff!!!
2395 e1 = timer_get_milliseconds();
2397 // time a bunch of cfopens
2399 s2 = timer_get_milliseconds();
2401 for(int idx=0; idx<10000; idx++){
2402 whee = cfopen("capital01.pof", "rb", CFILE_NORMAL, CF_TYPE_MODELS);
2407 //cf_exist("capital01.pof", CF_TYPE_MODELS);
2409 e2 = timer_get_milliseconds();
2412 if (Is_standalone) {
2413 std_init_standalone();
2415 os_init( Osreg_class_name, Osreg_app_name );
2416 os_set_title(Osreg_title);
2419 // initialize localization module. Make sure this is down AFTER initialzing OS.
2420 // int t1 = timer_get_milliseconds();
2421 lcl_init( detect_lang() );
2423 // mprintf(("LCL_INIT() TOOK %d MS\n", timer_get_milliseconds()-t1));
2425 // verify that he has a valid ships.tbl (will Game_ships_tbl_valid if so)
2428 // verify that he has a valid weapons.tbl
2429 verify_weapons_tbl();
2431 // Output version numbers to registry for auto patching purposes
2432 os_config_write_uint(NOX("Version"), NOX("Major"), FS_VERSION_MAJOR);
2433 os_config_write_uint(NOX("Version"), NOX("Minor"), FS_VERSION_MINOR);
2434 os_config_write_uint(NOX("Version"), NOX("Build"), FS_VERSION_BUILD);
2436 Use_joy_mouse = 0; //os_config_read_uint( NULL, NOX("JoystickMovesCursor"), 1 );
2437 //Use_palette_flash = os_config_read_uint( NULL, NOX("PaletteFlash"), 0 );
2438 Use_low_mem = os_config_read_uint( NULL, NOX("LowMem"), 0 );
2441 Use_fullscreen_at_startup = os_config_read_uint( NULL, NOX("ForceFullscreen"), 1 );
2444 #if defined (PLAT_UNIX) && defined(RELEASE_REAL)
2445 // show the FPS counter if the config file says so
2446 Show_framerate = os_config_read_uint( NULL, NOX("ShowFPS"), 0 );
2449 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
2450 Asteroids_enabled = 1;
2453 /////////////////////////////
2455 /////////////////////////////
2460 ptr = os_config_read_string(NULL, NOX("Soundcard"), NULL);
2461 mprintf(("soundcard = %s\n", ptr ? ptr : "<nothing>"));
2463 if (!stricmp(ptr, NOX("no sound"))) {
2464 Cmdline_freespace_no_sound = 1;
2466 } else if (!stricmp(ptr, NOX("Aureal A3D"))) {
2468 } else if (!stricmp(ptr, NOX("EAX"))) {
2473 if (!Is_standalone) {
2474 snd_init(use_a3d, use_eax);
2476 /////////////////////////////
2478 /////////////////////////////
2480 ptr = os_config_read_string(NULL, NOX("Videocard"), NULL);
2483 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);
2485 // fire up the UpdateLauncher executable
2487 PROCESS_INFORMATION pi;
2489 memset( &si, 0, sizeof(STARTUPINFO) );
2492 BOOL ret = CreateProcess( LAUNCHER_FNAME, // pointer to name of executable module
2493 NULL, // pointer to command line string
2494 NULL, // pointer to process security attributes
2495 NULL, // pointer to thread security attributes
2496 FALSE, // handle inheritance flag
2497 CREATE_DEFAULT_ERROR_MODE, // creation flags
2498 NULL, // pointer to new environment block
2499 NULL, // pointer to current directory name
2500 &si, // pointer to STARTUPINFO
2501 &pi // pointer to PROCESS_INFORMATION
2504 // If the Launcher could not be started up, let the user know
2506 MessageBox((HWND)os_get_window(), XSTR("The Launcher could not be restarted.", 1450), XSTR("Error", 1451), MB_OK);
2515 if(!stricmp(ptr, "Aucune accélération 3D") || !stricmp(ptr, "Keine 3D-Beschleunigerkarte") || !stricmp(ptr, "No 3D acceleration")){
2517 MessageBox((HWND)os_get_window(), XSTR("Warning, Freespace 2 requires Glide or Direct3D hardware accleration. You will not be able to run Freespace 2 without it.", 1448), XSTR("Warning", 1449), MB_OK);
2525 // check for hi res pack file
2526 int has_sparky_hi = 0;
2528 // check if sparky_hi exists -- access mode 0 means does file exist
2529 #ifndef MAKE_FS1 // shoudn't have it so don't check
2532 if ( _access("sparky_hi_fs2.vp", 0) == 0) {
2535 mprintf(("No sparky_hi_fs2.vp in directory %s\n", dir));
2539 // see if we've got 32 bit in the string
2540 if(strstr(ptr, "32 bit")){
2547 if (!Is_standalone && ptr && (strstr(ptr, NOX("3DFX Glide")))) {
2549 // always 640 for E3
2550 gr_init(GR_640, GR_GLIDE);
2552 // regular or hi-res ?
2554 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2556 if(strstr(ptr, NOX("(1024x768)"))){
2558 gr_init(GR_1024, GR_GLIDE);
2560 gr_init(GR_640, GR_GLIDE);
2563 } else if (!Is_standalone && ptr && (strstr(ptr, NOX("Direct 3D -") ))) {
2565 // always 640 for E3
2567 gr_init(GR_640, GR_DIRECT3D, depth);
2569 // regular or hi-res ?
2571 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2573 if(strstr(ptr, NOX("(1024x768)"))){
2577 gr_init(GR_1024, GR_DIRECT3D, depth);
2581 gr_init(GR_640, GR_DIRECT3D, depth);
2587 if ( Use_fullscreen_at_startup && !Is_standalone) {
2588 gr_init(GR_640, GR_DIRECTDRAW);
2590 gr_init(GR_640, GR_SOFTWARE);
2593 if ( !Is_standalone ) {
2594 gr_init(GR_640, GR_DIRECTDRAW);
2596 gr_init(GR_640, GR_SOFTWARE);
2601 if (!Is_standalone /* && ptr && (strstr(ptr, NOX("OpenGL"))) */) {
2602 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2603 gr_init(GR_1024, GR_OPENGL);
2605 gr_init(GR_640, GR_OPENGL);
2609 gr_init(GR_640, GR_SOFTWARE);
2611 #endif // !PLAT_UNIX
2614 extern int Gr_inited;
2615 if(trying_d3d && !Gr_inited){
2617 extern char Device_init_error[512];
2618 MessageBox( NULL, Device_init_error, "Error intializing Direct3D", MB_OK|MB_TASKMODAL|MB_SETFOREGROUND );
2627 ptr = os_config_read_string(NULL,NOX("Gamma"),NOX("1.80"));
2628 Freespace_gamma = (float)atof(ptr);
2629 if ( Freespace_gamma == 0.0f ) {
2630 Freespace_gamma = 1.80f;
2631 } else if ( Freespace_gamma < 0.1f ) {
2632 Freespace_gamma = 0.1f;
2633 } else if ( Freespace_gamma > 5.0f ) {
2634 Freespace_gamma = 5.0f;
2636 char tmp_gamma_string[32];
2637 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2638 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2640 gr_set_gamma(Freespace_gamma);
2642 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
2645 display_title_screen();
2649 // attempt to load up master tracker registry info (login and password)
2650 Multi_tracker_id = -1;
2652 // pxo login and password
2653 ptr = os_config_read_string(NOX("PXO"),NOX("Login"),NULL);
2655 nprintf(("Network","Error reading in PXO login data\n"));
2656 strcpy(Multi_tracker_login,"");
2658 strcpy(Multi_tracker_login,ptr);
2660 ptr = os_config_read_string(NOX("PXO"),NOX("Password"),NULL);
2662 nprintf(("Network","Error reading PXO password\n"));
2663 strcpy(Multi_tracker_passwd,"");
2665 strcpy(Multi_tracker_passwd,ptr);
2668 // pxo squad name and password
2669 ptr = os_config_read_string(NOX("PXO"),NOX("SquadName"),NULL);
2671 nprintf(("Network","Error reading in PXO squad name\n"));
2672 strcpy(Multi_tracker_squad_name, "");
2674 strcpy(Multi_tracker_squad_name, ptr);
2677 // If less than 48MB of RAM, use low memory model.
2680 (Freespace_total_ram < 48*1024*1024) ||
2683 mprintf(( "Using normal memory settings...\n" ));
2684 bm_set_low_mem(1); // Use every other frame of bitmaps
2686 mprintf(( "Using high memory settings...\n" ));
2687 bm_set_low_mem(0); // Use all frames of bitmaps
2690 // load non-darkening pixel defs
2691 palman_load_pixels();
2693 // hud shield icon stuff
2694 hud_shield_game_init();
2696 control_config_common_init(); // sets up localization stuff in the control config
2702 gamesnd_parse_soundstbl();
2707 // standalone's don't use hte joystick and it seems to sometimes cause them to not get shutdown properly
2712 player_controls_init();
2715 //if(!Is_standalone){
2723 ship_init(); // read in ships.tbl
2725 mission_campaign_init(); // load in the default campaign
2727 // navmap_init(); // init the navigation map system
2728 context_help_init();
2729 techroom_intel_init(); // parse species.tbl, load intel info
2731 psnet_init( Multi_options_g.protocol, Multi_options_g.port ); // initialize the networking code
2732 init_animating_pointer();
2734 mission_brief_common_init(); // Mark all the briefing structures as empty.
2735 gr_font_init(); // loads up all fonts
2737 neb2_init(); // fullneb stuff
2741 player_tips_init(); // helpful tips
2744 // load the list of pilot pic filenames (for barracks and pilot select popup quick reference)
2745 pilot_load_pic_list();
2746 pilot_load_squad_pic_list();
2748 load_animating_pointer(NOX("cursor"), 0, 0);
2750 // initialize alpha colors
2751 alpha_colors_init();
2754 // Game_music_paused = 0;
2761 nprintf(("General", "Ships.tbl is : %s\n", Game_ships_tbl_valid ? "VALID" : "INVALID!!!!"));
2762 nprintf(("General", "Weapons.tbl is : %s\n", Game_weapons_tbl_valid ? "VALID" : "INVALID!!!!"));
2764 mprintf(("cfile_init() took %d\n", e1 - s1));
2765 // mprintf(("1000 cfopens() took %d\n", e2 - s2));
2768 char transfer_text[128];
2770 float Start_time = 0.0f;
2772 float Framerate = 0.0f;
2774 float Timing_total = 0.0f;
2775 float Timing_render2 = 0.0f;
2776 float Timing_render3 = 0.0f;
2777 float Timing_flip = 0.0f;
2778 float Timing_clear = 0.0f;
2780 MONITOR(NumPolysDrawn);
2786 void game_get_framerate()
2788 char text[128] = "";
2790 if ( frame_int == -1 ) {
2792 for (i=0; i<FRAME_FILTER; i++ ) {
2793 frametimes[i] = 0.0f;
2798 frametotal -= frametimes[frame_int];
2799 frametotal += flFrametime;
2800 frametimes[frame_int] = flFrametime;
2801 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2803 if ( frametotal != 0.0 ) {
2804 if ( Framecount >= FRAME_FILTER )
2805 Framerate = FRAME_FILTER / frametotal;
2807 Framerate = Framecount / frametotal;
2808 sprintf( text, NOX("FPS: %.1f"), Framerate );
2810 sprintf( text, NOX("FPS: ?") );
2814 if (Show_framerate) {
2815 gr_set_color_fast(&HUD_color_debug);
2816 gr_string( 570, 2, text );
2820 void game_show_framerate()
2824 cur_time = f2fl(timer_get_approx_seconds());
2825 if (cur_time - Start_time > 30.0f) {
2826 mprintf(("%i frames executed in %7.3f seconds, %7.3f frames per second.\n", Framecount, cur_time - Start_time, Framecount/(cur_time - Start_time)));
2827 Start_time += 1000.0f;
2830 //mprintf(( "%s\n", text ));
2833 if ( Debug_dump_frames )
2837 // possibly show control checking info
2838 control_check_indicate();
2840 // int bitmaps_used_this_frame, bitmaps_new_this_frame;
2841 // bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
2842 // MONITOR_INC(BmpUsed, bitmaps_used_this_frame);
2843 // MONITOR_INC(BmpNew, bitmaps_new_this_frame);
2846 if ( Show_cpu == 1 ) {
2851 dy = gr_get_font_height() + 1;
2853 gr_set_color_fast(&HUD_color_debug);
2857 extern int D3D_textures_in;
2858 extern int D3D_textures_in_frame;
2859 extern int Glide_textures_in;
2860 extern int Glide_textures_in_frame;
2861 extern int Glide_explosion_vram;
2862 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2864 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame+D3D_textures_in_frame)/1024 );
2866 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2870 // gr_printf( sx, sy, "BPP: %d", gr_screen.bits_per_pixel );
2872 gr_printf( sx, sy, NOX("DMA: %s"), transfer_text );
2874 gr_printf( sx, sy, NOX("POLYP: %d"), modelstats_num_polys );
2876 gr_printf( sx, sy, NOX("POLYD: %d"), modelstats_num_polys_drawn );
2878 gr_printf( sx, sy, NOX("VERTS: %d"), modelstats_num_verts );
2883 extern int Num_pairs; // Number of object pairs that were checked.
2884 gr_printf( sx, sy, NOX("PAIRS: %d"), Num_pairs );
2887 extern int Num_pairs_checked; // What percent of object pairs were checked.
2888 gr_printf( sx, sy, NOX("FVI: %d"), Num_pairs_checked );
2890 Num_pairs_checked = 0;
2894 gr_printf( sx, sy, NOX("Snds: %d"), snd_num_playing() );
2897 if ( Timing_total > 0.01f ) {
2898 gr_printf( sx, sy, NOX("CLEAR: %.0f%%"), Timing_clear*100.0f/Timing_total );
2900 gr_printf( sx, sy, NOX("REND2D: %.0f%%"), Timing_render2*100.0f/Timing_total );
2902 gr_printf( sx, sy, NOX("REND3D: %.0f%%"), Timing_render3*100.0f/Timing_total );
2904 gr_printf( sx, sy, NOX("FLIP: %.0f%%"), Timing_flip*100.0f/Timing_total );
2906 gr_printf( sx, sy, NOX("GAME: %.0f%%"), (Timing_total-(Timing_render2+Timing_render3+Timing_flip+Timing_clear))*100.0f/Timing_total );
2916 dy = gr_get_font_height() + 1;
2918 gr_set_color_fast(&HUD_color_debug);
2921 extern int TotalRam;
2922 gr_printf( sx, sy, NOX("DYN: %d KB\n"), TotalRam/1024 );
2927 extern int Model_ram;
2928 gr_printf( sx, sy, NOX("POF: %d KB\n"), Model_ram/1024 );
2932 gr_printf( sx, sy, NOX("BMP: %d KB\n"), bm_texture_ram/1024 );
2934 gr_printf( sx, sy, NOX("S-SRAM: %d KB\n"), Snd_sram/1024 ); // mem used to store game sound
2936 gr_printf( sx, sy, NOX("S-HRAM: %d KB\n"), Snd_hram/1024 ); // mem used to store game sound
2940 extern int D3D_textures_in;
2941 extern int Glide_textures_in;
2942 extern int Glide_textures_in_frame;
2943 extern int Glide_explosion_vram;
2944 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2946 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame)/1024 );
2948 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2955 if ( Show_player_pos ) {
2959 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));
2962 MONITOR_INC(NumPolys, modelstats_num_polys);
2963 MONITOR_INC(NumPolysDrawn, modelstats_num_polys_drawn );
2964 MONITOR_INC(NumVerts, modelstats_num_verts );
2966 modelstats_num_polys = 0;
2967 modelstats_num_polys_drawn = 0;
2968 modelstats_num_verts = 0;
2969 modelstats_num_sortnorms = 0;
2973 void game_show_standalone_framerate()
2975 float frame_rate=30.0f;
2976 if ( frame_int == -1 ) {
2978 for (i=0; i<FRAME_FILTER; i++ ) {
2979 frametimes[i] = 0.0f;
2984 frametotal -= frametimes[frame_int];
2985 frametotal += flFrametime;
2986 frametimes[frame_int] = flFrametime;
2987 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2989 if ( frametotal != 0.0 ) {
2990 if ( Framecount >= FRAME_FILTER ){
2991 frame_rate = FRAME_FILTER / frametotal;
2993 frame_rate = Framecount / frametotal;
2996 std_set_standalone_fps(frame_rate);
3000 // function to show the time remaining in a mission. Used only when the end-mission sexpression is used
3001 void game_show_time_left()
3005 // mission_end_time is a global from missionparse.cpp that contains the mission time at which the
3006 // mission should end (in fixed seconds). There is code in missionparse.cpp which actually handles
3007 // checking how much time is left
3009 if ( Mission_end_time == -1 ){
3013 diff = f2i(Mission_end_time - Missiontime);
3014 // be sure to bash to 0. diff could be negative on frame that we quit mission
3019 hud_set_default_color();
3020 gr_printf( 5, 40, XSTR( "Mission time remaining: %d seconds", 179), diff );
3023 //========================================================================================
3024 //=================== NEW DEBUG CONSOLE COMMANDS TO REPLACE OLD DEBUG PAUSE MENU =========
3025 //========================================================================================
3029 DCF(ai_pause,"Pauses ai")
3032 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
3033 if ( Dc_arg_type & ARG_TRUE ) ai_paused = 1;
3034 else if ( Dc_arg_type & ARG_FALSE ) ai_paused = 0;
3035 else if ( Dc_arg_type & ARG_NONE ) ai_paused = !ai_paused;
3038 obj_init_all_ships_physics();
3041 if ( Dc_help ) dc_printf( "Usage: ai_paused [bool]\nSets ai_paused to true or false. If nothing passed, then toggles it.\n" );
3042 if ( Dc_status ) dc_printf( "ai_paused is %s\n", (ai_paused?"TRUE":"FALSE") );
3045 DCF(single_step,"Single steps the game")
3048 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
3049 if ( Dc_arg_type & ARG_TRUE ) game_single_step = 1;
3050 else if ( Dc_arg_type & ARG_FALSE ) game_single_step = 0;
3051 else if ( Dc_arg_type & ARG_NONE ) game_single_step = !game_single_step;
3053 last_single_step = 0; // Make so single step waits a frame before stepping
3056 if ( Dc_help ) dc_printf( "Usage: single_step [bool]\nSets single_step to true or false. If nothing passed, then toggles it.\n" );
3057 if ( Dc_status ) dc_printf( "single_step is %s\n", (game_single_step?"TRUE":"FALSE") );
3060 DCF_BOOL(physics_pause, physics_paused)
3061 DCF_BOOL(ai_rendering, Ai_render_debug_flag)
3062 DCF_BOOL(ai_firing, Ai_firing_enabled )
3064 // Create some simple aliases to these commands...
3065 debug_command dc_s("s","shortcut for single_step",dcf_single_step);
3066 debug_command dc_p("p","shortcut for physics_pause", dcf_physics_pause );
3067 debug_command dc_r("r","shortcut for ai_rendering", dcf_ai_rendering );
3068 debug_command dc_f("f","shortcut for ai_firing", dcf_ai_firing);
3069 debug_command dc_a("a","shortcut for ai_pause", dcf_ai_pause);
3072 //========================================================================================
3073 //========================================================================================
3076 void game_training_pause_do()
3080 key = game_check_key();
3082 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
3089 void game_increase_skill_level()
3092 if (Game_skill_level >= NUM_SKILL_LEVELS){
3093 Game_skill_level = 0;
3097 int Player_died_time;
3099 int View_percent = 100;
3102 DCF(view, "Sets the percent of the 3d view to render.")
3105 dc_get_arg(ARG_INT);
3106 if ( (Dc_arg_int >= 5 ) || (Dc_arg_int <= 100) ) {
3107 View_percent = Dc_arg_int;
3109 dc_printf( "Illegal value for view. (Must be from 5-100) \n\n");
3115 dc_printf("Usage: view [n]\nwhere n is percent of view to show (5-100).\n");
3119 dc_printf("View is set to %d%%\n", View_percent );
3124 // Set the clip region for the 3d rendering window
3125 void game_set_view_clip()
3127 if ((Game_mode & GM_DEAD) || (supernova_active() >= 2)) {
3128 // Set the clip region for the letterbox "dead view"
3129 int yborder = gr_screen.max_h/4;
3131 // Numeric constants encouraged by J "pig farmer" S, who shall remain semi-anonymous.
3132 // J.S. I've changed my ways!! See the new "no constants" code!!!
3133 gr_set_clip(0, yborder, gr_screen.max_w, gr_screen.max_h - yborder*2 );
3135 // Set the clip region for normal view
3136 if ( View_percent >= 100 ) {
3139 int xborder, yborder;
3141 if ( View_percent < 5 ) {
3145 float fp = i2fl(View_percent)/100.0f;
3146 int fi = fl2i(fl_sqrt(fp)*100.0f);
3147 if ( fi > 100 ) fi=100;
3149 xborder = ( gr_screen.max_w*(100-fi) )/200;
3150 yborder = ( gr_screen.max_h*(100-fi) )/200;
3152 gr_set_clip(xborder, yborder, gr_screen.max_w-xborder*2,gr_screen.max_h-yborder*2 );
3158 void show_debug_stuff()
3161 int laser_count = 0, missile_count = 0;
3163 for (i=0; i<MAX_OBJECTS; i++) {
3164 if (Objects[i].type == OBJ_WEAPON){
3165 if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_LASER){
3167 } else if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_MISSILE){
3173 nprintf(("Mike", "Frame: %i Lasers: %4i, Missiles: %4i\n", Framecount, laser_count, missile_count));
3176 extern int Tool_enabled;
3181 int tst_bitmap = -1;
3183 float tst_offset, tst_offset_total;
3186 void game_tst_frame_pre()
3194 g3_rotate_vertex(&v, &tst_pos);
3195 g3_project_vertex(&v);
3198 if(!((v.sx >= 0) && (v.sx <= gr_screen.max_w) && (v.sy >= 0) && (v.sy <= gr_screen.max_h))){
3202 // big ship? always tst
3204 // within 3000 meters
3205 if( vm_vec_dist_quick(&tst_pos, &Eye_position) <= 3000.0f){
3209 // within 300 meters
3210 if( (vm_vec_dist_quick(&tst_pos, &Eye_position) <= 300.0f) && ((tst_time == 0) || ((time(NULL) - tst_time) >= 10)) ){
3217 void game_tst_frame()
3227 tst_time = time(NULL);
3229 // load the tst bitmap
3230 switch((int)frand_range(0.0f, 3.0)){
3232 tst_bitmap = bm_load("ig_jim");
3234 mprintf(("TST 0\n"));
3238 tst_bitmap = bm_load("ig_kan");
3240 mprintf(("TST 1\n"));
3244 tst_bitmap = bm_load("ig_jim");
3246 mprintf(("TST 2\n"));
3250 tst_bitmap = bm_load("ig_kan");
3252 mprintf(("TST 3\n"));
3261 // get the tst bitmap dimensions
3263 bm_get_info(tst_bitmap, &w, &h);
3266 tst_y = frand_range(0.0f, (float)gr_screen.max_h - h);
3268 snd_play(&Snds[SND_VASUDAN_BUP]);
3270 // tst x and direction
3274 tst_offset_total = (float)w;
3275 tst_offset = (float)w;
3277 tst_x = (float)gr_screen.max_w;
3278 tst_offset_total = (float)-w;
3279 tst_offset = (float)w;
3287 float diff = (tst_offset_total / 0.5f) * flFrametime;
3293 tst_offset -= fl_abs(diff);
3294 } else if(tst_mode == 2){
3297 tst_offset -= fl_abs(diff);
3301 gr_set_bitmap(tst_bitmap);
3302 gr_bitmap((int)tst_x, (int)tst_y);
3305 if(timestamp_elapsed_safe(tst_stamp, 1100)){
3309 // if we passed the switch point
3310 if(tst_offset <= 0.0f){
3315 tst_stamp = timestamp(1000);
3316 tst_offset = fl_abs(tst_offset_total);
3327 void game_tst_mark(object *objp, ship *shipp)
3336 if((objp == NULL) || (shipp == NULL) || (shipp->ship_info_index < 0) || (shipp->ship_info_index >= Num_ship_types)){
3339 sip = &Ship_info[shipp->ship_info_index];
3346 tst_pos = objp->pos;
3347 if(sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)){
3353 extern void render_shields();
3355 void player_repair_frame(float frametime)
3357 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
3359 for(idx=0;idx<MAX_PLAYERS;idx++){
3362 np = &Net_players[idx];
3364 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)){
3366 // don't rearm/repair if the player is dead or dying/departing
3367 if ( !NETPLAYER_IS_DEAD(np) && !(Ships[Objects[np->player->objnum].instance].flags & (SF_DYING|SF_DEPARTING)) ) {
3368 ai_do_repair_frame(&Objects[Net_players[idx].player->objnum],&Ai_info[Ships[Objects[Net_players[idx].player->objnum].instance].ai_index],frametime);
3373 if ( (Player_obj != NULL) && (Player_obj->type == OBJ_SHIP) && !(Game_mode & GM_STANDALONE_SERVER) && (Player_ship != NULL) && !(Player_ship->flags & SF_DYING) ) {
3374 ai_do_repair_frame(Player_obj, &Ai_info[Ships[Player_obj->instance].ai_index], frametime);
3380 #define NUM_FRAMES_TEST 300
3381 #define NUM_MIXED_SOUNDS 16
3382 void do_timing_test(float flFrametime)
3384 static int framecount = 0;
3385 static int test_running = 0;
3386 static float test_time = 0.0f;
3388 static int snds[NUM_MIXED_SOUNDS];
3391 if ( test_running ) {
3393 test_time += flFrametime;
3394 if ( framecount >= NUM_FRAMES_TEST ) {
3396 nprintf(("General", "%d frames took %.3f seconds\n", NUM_FRAMES_TEST, test_time));
3397 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3402 if ( Test_begin == 1 ) {
3408 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3411 // start looping digital sounds
3412 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3413 snds[i] = snd_play_looping( &Snds[i], 0.0f, -1, -1);
3420 DCF(dcf_fov, "Change the field of view")
3423 dc_get_arg(ARG_FLOAT|ARG_NONE);
3424 if ( Dc_arg_type & ARG_NONE ) {
3425 Viewer_zoom = VIEWER_ZOOM_DEFAULT;
3426 dc_printf( "Zoom factor reset\n" );
3428 if ( Dc_arg_type & ARG_FLOAT ) {
3429 if (Dc_arg_float < 0.25f) {
3430 Viewer_zoom = 0.25f;
3431 dc_printf("Zoom factor pinned at 0.25.\n");
3432 } else if (Dc_arg_float > 1.25f) {
3433 Viewer_zoom = 1.25f;
3434 dc_printf("Zoom factor pinned at 1.25.\n");
3436 Viewer_zoom = Dc_arg_float;
3442 dc_printf( "Usage: fov [factor]\nFactor is the zoom factor btwn .25 and 1.25\nNo parameter resets it to default.\n" );
3445 dc_printf("Zoom factor set to %6.3f (original = 0.5, John = 0.75)", Viewer_zoom);
3449 DCF(framerate_cap, "Sets the framerate cap")
3452 dc_get_arg(ARG_INT);
3453 if ( (Dc_arg_int >= 1 ) || (Dc_arg_int <= 120) ) {
3454 Framerate_cap = Dc_arg_int;
3456 dc_printf( "Illegal value for framerate cap. (Must be from 1-120) \n\n");
3462 dc_printf("Usage: framerate_cap [n]\nwhere n is the frames per second to cap framerate at.\n");
3463 dc_printf("If n is 0 or omitted, then the framerate cap is removed\n");
3464 dc_printf("[n] must be from 1 to 120.\n");
3468 if ( Framerate_cap )
3469 dc_printf("Framerate cap is set to %d fps\n", Framerate_cap );
3471 dc_printf("There is no framerate cap currently active.\n");
3475 #define MIN_DIST_TO_DEAD_CAMERA 50.0f
3476 int Show_viewing_from_self = 0;
3478 void say_view_target()
3480 object *view_target;
3482 if ((Viewer_mode & VM_OTHER_SHIP) && (Player_ai->target_objnum != -1))
3483 view_target = &Objects[Player_ai->target_objnum];
3485 view_target = Player_obj;
3487 if (Game_mode & GM_DEAD) {
3488 if (Player_ai->target_objnum != -1)
3489 view_target = &Objects[Player_ai->target_objnum];
3492 if (!(Game_mode & GM_DEAD_DIED) && ((Game_mode & (GM_DEAD_BLEW_UP)) || ((Last_view_target != NULL) && (Last_view_target != view_target)))) {
3493 if (view_target != Player_obj){
3495 char *view_target_name = NULL;
3496 switch(Objects[Player_ai->target_objnum].type) {
3498 view_target_name = Ships[Objects[Player_ai->target_objnum].instance].ship_name;
3501 view_target_name = Weapon_info[Weapons[Objects[Player_ai->target_objnum].instance].weapon_info_index].name;
3502 Viewer_mode &= ~VM_OTHER_SHIP;
3504 case OBJ_JUMP_NODE: {
3505 char jump_node_name[128];
3506 strcpy(jump_node_name, XSTR( "jump node", 184));
3507 view_target_name = jump_node_name;
3508 Viewer_mode &= ~VM_OTHER_SHIP;
3517 if ( view_target_name ) {
3518 HUD_fixed_printf(0.0f, XSTR( "Viewing %s%s\n", 185), (Viewer_mode & VM_OTHER_SHIP) ? XSTR( "from ", 186) : "", view_target_name);
3519 Show_viewing_from_self = 1;
3522 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER) && (Player_obj->type == OBJ_OBSERVER)){
3523 HUD_fixed_printf(2.0f,XSTR( "Viewing from observer\n", 187));
3524 Show_viewing_from_self = 1;
3526 if (Show_viewing_from_self)
3527 HUD_fixed_printf(2.0f, XSTR( "Viewing from self\n", 188));
3532 Last_view_target = view_target;
3536 float Game_hit_x = 0.0f;
3537 float Game_hit_y = 0.0f;
3539 // Reset at the beginning of each frame
3540 void game_whack_reset()
3546 // Apply a 2d whack to the player
3547 void game_whack_apply( float x, float y )
3549 // Do some force feedback
3550 joy_ff_play_dir_effect(x * 80.0f, y * 80.0f);
3556 // mprintf(( "WHACK = %.1f, %.1f\n", Game_hit_x, Game_hit_y ));
3559 // call to apply a "shudder"
3560 void game_shudder_apply(int time, float intensity)
3562 Game_shudder_time = timestamp(time);
3563 Game_shudder_total = time;
3564 Game_shudder_intensity = intensity;
3567 #define FF_SCALE 10000
3568 void apply_hud_shake(matrix *eye_orient)
3570 if (Viewer_obj == Player_obj) {
3571 physics_info *pi = &Player_obj->phys_info;
3579 // Make eye shake due to afterburner
3580 if ( !timestamp_elapsed(pi->afterburner_decay) ) {
3583 dtime = timestamp_until(pi->afterburner_decay);
3587 tangles.p += 0.07f * (float) (r1-RAND_MAX/2)/RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3588 tangles.h += 0.07f * (float) (r2-RAND_MAX/2)/RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3591 // Make eye shake due to engine wash
3593 if (Player_obj->type == OBJ_SHIP && (Ships[Player_obj->instance].wash_intensity > 0) && Wash_on ) {
3596 tangles.p += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r1-RAND_MAX/2)/RAND_MAX;
3597 tangles.h += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r2-RAND_MAX/2)/RAND_MAX;
3599 // get the intensity
3600 float intensity = FF_SCALE * Ships[Player_obj->instance].wash_intensity;
3604 vm_vec_rand_vec_quick(&rand_vec);
3607 joy_ff_play_dir_effect(intensity*rand_vec.xyz.x, intensity*rand_vec.xyz.y);
3611 // make hud shake due to shuddering
3612 if(Game_shudder_time != -1){
3613 // if the timestamp has elapsed
3614 if(timestamp_elapsed(Game_shudder_time)){
3615 Game_shudder_time = -1;
3617 // otherwise apply some shudder
3621 dtime = timestamp_until(Game_shudder_time);
3625 tangles.p += (Game_shudder_intensity / 200.0f) * (float) (r1-RAND_MAX/2)/RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/(float)Game_shudder_total));
3626 tangles.h += (Game_shudder_intensity / 200.0f) * (float) (r2-RAND_MAX/2)/RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/(float)Game_shudder_total));
3631 vm_angles_2_matrix(&tm, &tangles);
3632 Assert(vm_vec_mag(&tm.v.fvec) > 0.0f);
3633 Assert(vm_vec_mag(&tm.v.rvec) > 0.0f);
3634 Assert(vm_vec_mag(&tm.v.uvec) > 0.0f);
3635 vm_matrix_x_matrix(&tm2, eye_orient, &tm);
3640 extern void compute_slew_matrix(matrix *orient, angles *a); // TODO: move code to proper place and extern in header file
3642 // Player's velocity just before he blew up. Used to keep camera target moving.
3643 vector Dead_player_last_vel = {1.0f, 1.0f, 1.0f};
3645 // Set eye_pos and eye_orient based on view mode.
3646 void game_render_frame_setup(vector *eye_pos, matrix *eye_orient)
3650 static int last_Viewer_mode = 0;
3651 static int last_Game_mode = 0;
3652 static int last_Viewer_objnum = -1;
3654 // This code is supposed to detect camera "cuts"... like going between
3657 // determine if we need to regenerate the nebula
3658 if( (!(last_Viewer_mode & VM_EXTERNAL) && (Viewer_mode & VM_EXTERNAL)) || // internal to external
3659 ((last_Viewer_mode & VM_EXTERNAL) && !(Viewer_mode & VM_EXTERNAL)) || // external to internal
3660 (!(last_Viewer_mode & VM_DEAD_VIEW) && (Viewer_mode & VM_DEAD_VIEW)) || // non dead-view to dead-view
3661 ((last_Viewer_mode & VM_DEAD_VIEW) && !(Viewer_mode & VM_DEAD_VIEW)) || // dead-view to non dead-view
3662 (!(last_Viewer_mode & VM_WARP_CHASE) && (Viewer_mode & VM_WARP_CHASE)) || // non warp-chase to warp-chase
3663 ((last_Viewer_mode & VM_WARP_CHASE) && !(Viewer_mode & VM_WARP_CHASE)) || // warp-chase to non warp-chase
3664 (!(last_Viewer_mode & VM_OTHER_SHIP) && (Viewer_mode & VM_OTHER_SHIP)) || // non other-ship to other-ship
3665 ((last_Viewer_mode & VM_OTHER_SHIP) && !(Viewer_mode & VM_OTHER_SHIP)) || // other-ship to non-other ship
3666 ((Viewer_mode & VM_OTHER_SHIP) && (last_Viewer_objnum != Player_ai->target_objnum)) // other ship mode, but targets changes
3669 // regenerate the nebula
3673 if ( (last_Viewer_mode != Viewer_mode) || (last_Game_mode != Game_mode) ) {
3674 //mprintf(( "************** Camera cut! ************\n" ));
3675 last_Viewer_mode = Viewer_mode;
3676 last_Game_mode = Game_mode;
3678 // Camera moved. Tell stars & debris to not do blurring.
3684 if ( Viewer_mode & VM_PADLOCK_ANY ) {
3685 player_display_packlock_view();
3688 game_set_view_clip();
3690 if (Game_mode & GM_DEAD) {
3691 vector vec_to_deader, view_pos;
3694 Viewer_mode |= VM_DEAD_VIEW;
3696 if (Player_ai->target_objnum != -1) {
3697 int view_from_player = 1;
3699 if (Viewer_mode & VM_OTHER_SHIP) {
3700 // View from target.
3701 Viewer_obj = &Objects[Player_ai->target_objnum];
3703 last_Viewer_objnum = Player_ai->target_objnum;
3705 if ( Viewer_obj->type == OBJ_SHIP ) {
3706 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3707 view_from_player = 0;
3710 last_Viewer_objnum = -1;
3713 if ( view_from_player ) {
3714 // View target from player ship.
3716 *eye_pos = Player_obj->pos;
3717 vm_vec_normalized_dir(&eye_dir, &Objects[Player_ai->target_objnum].pos, eye_pos);
3718 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3721 dist = vm_vec_normalized_dir(&vec_to_deader, &Player_obj->pos, &Dead_camera_pos);
3723 if (dist < MIN_DIST_TO_DEAD_CAMERA)
3724 dist += flFrametime * 16.0f;
3726 vm_vec_scale(&vec_to_deader, -dist);
3727 vm_vec_add(&Dead_camera_pos, &Player_obj->pos, &vec_to_deader);
3729 view_pos = Player_obj->pos;
3731 if (!(Game_mode & GM_DEAD_BLEW_UP)) {
3732 Viewer_mode &= ~(VM_EXTERNAL | VM_CHASE);
3733 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, 25.0f * flFrametime);
3734 Dead_player_last_vel = Player_obj->phys_info.vel;
3735 //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));
3736 } else if (Player_ai->target_objnum != -1) {
3737 view_pos = Objects[Player_ai->target_objnum].pos;
3739 // Make camera follow explosion, but gradually slow down.
3740 vm_vec_scale_add2(&Player_obj->pos, &Dead_player_last_vel, flFrametime);
3741 view_pos = Player_obj->pos;
3742 vm_vec_scale(&Dead_player_last_vel, 0.99f);
3743 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, min(25.0f, vm_vec_mag_quick(&Dead_player_last_vel)) * flFrametime);
3746 *eye_pos = Dead_camera_pos;
3748 vm_vec_normalized_dir(&eye_dir, &Player_obj->pos, eye_pos);
3750 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3755 // if supernova shockwave
3756 if(supernova_camera_cut()){
3760 // call it dead view
3761 Viewer_mode |= VM_DEAD_VIEW;
3763 // set eye pos and orient
3764 supernova_set_view(eye_pos, eye_orient);
3766 // If already blown up, these other modes can override.
3767 if (!(Game_mode & (GM_DEAD | GM_DEAD_BLEW_UP))) {
3768 Viewer_mode &= ~VM_DEAD_VIEW;
3770 Viewer_obj = Player_obj;
3772 if (Viewer_mode & VM_OTHER_SHIP) {
3773 if (Player_ai->target_objnum != -1){
3774 Viewer_obj = &Objects[Player_ai->target_objnum];
3775 last_Viewer_objnum = Player_ai->target_objnum;
3777 Viewer_mode &= ~VM_OTHER_SHIP;
3778 last_Viewer_objnum = -1;
3781 last_Viewer_objnum = -1;
3784 if (Viewer_mode & VM_EXTERNAL) {
3787 vm_angles_2_matrix(&tm2, &Viewer_external_info.angles);
3788 vm_matrix_x_matrix(&tm, &Viewer_obj->orient, &tm2);
3790 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &tm.v.fvec, 2.0f * Viewer_obj->radius + Viewer_external_info.distance);
3792 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3793 vm_vec_normalize(&eye_dir);
3794 vm_vector_2_matrix(eye_orient, &eye_dir, &Viewer_obj->orient.v.uvec, NULL);
3797 // Modify the orientation based on head orientation.
3798 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3800 } else if ( Viewer_mode & VM_CHASE ) {
3803 if ( Viewer_obj->phys_info.speed < 0.1 )
3804 move_dir = Viewer_obj->orient.v.fvec;
3806 move_dir = Viewer_obj->phys_info.vel;
3807 vm_vec_normalize(&move_dir);
3810 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &move_dir, -3.0f * Viewer_obj->radius - Viewer_chase_info.distance);
3811 vm_vec_scale_add2(eye_pos, &Viewer_obj->orient.v.uvec, 0.75f * Viewer_obj->radius);
3812 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3813 vm_vec_normalize(&eye_dir);
3815 // JAS: I added the following code because if you slew up using
3816 // Descent-style physics, eye_dir and Viewer_obj->orient.v.uvec are
3817 // equal, which causes a zero-length vector in the vm_vector_2_matrix
3818 // call because the up and the forward vector are the same. I fixed
3819 // it by adding in a fraction of the right vector all the time to the
3821 vector tmp_up = Viewer_obj->orient.v.uvec;
3822 vm_vec_scale_add2( &tmp_up, &Viewer_obj->orient.v.rvec, 0.00001f );
3824 vm_vector_2_matrix(eye_orient, &eye_dir, &tmp_up, NULL);
3827 // Modify the orientation based on head orientation.
3828 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3829 } else if ( Viewer_mode & VM_WARP_CHASE ) {
3830 *eye_pos = Camera_pos;
3832 ship * shipp = &Ships[Player_obj->instance];
3834 vm_vec_sub(&eye_dir, &shipp->warp_effect_pos, eye_pos);
3835 vm_vec_normalize(&eye_dir);
3836 vm_vector_2_matrix(eye_orient, &eye_dir, &Player_obj->orient.v.uvec, NULL);
3839 // get an eye position based upon the correct type of object
3840 switch(Viewer_obj->type){
3842 // make a call to get the eye point for the player object
3843 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3846 // make a call to get the eye point for the player object
3847 observer_get_eye( eye_pos, eye_orient, Viewer_obj );
3853 #ifdef JOHNS_DEBUG_CODE
3854 john_debug_stuff(&eye_pos, &eye_orient);
3860 apply_hud_shake(eye_orient);
3862 // setup neb2 rendering
3863 neb2_render_setup(eye_pos, eye_orient);
3867 extern void ai_debug_render_stuff();
3870 int Game_subspace_effect = 0;
3871 DCF_BOOL( subspace, Game_subspace_effect );
3873 // Does everything needed to render a frame
3874 void game_render_frame( vector * eye_pos, matrix * eye_orient )
3878 g3_start_frame(game_zbuffer);
3879 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
3881 // maybe offset the HUD (jitter stuff)
3882 dont_offset = ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER));
3883 HUD_set_offsets(Viewer_obj, !dont_offset);
3885 // for multiplayer clients, call code in Shield.cpp to set up the Shield_hit array. Have to
3886 // do this becaues of the disjointed nature of this system (in terms of setup and execution).
3887 // must be done before ships are rendered
3888 if ( MULTIPLAYER_CLIENT ) {
3889 shield_point_multi_setup();
3892 if ( Game_subspace_effect ) {
3893 stars_draw(0,0,0,1);
3895 stars_draw(1,1,1,0);
3898 obj_render_all(obj_render);
3899 beam_render_all(); // render all beam weapons
3900 particle_render_all(); // render particles after everything else.
3901 trail_render_all(); // render missilie trails after everything else.
3902 mflash_render_all(); // render all muzzle flashes
3904 // Why do we not show the shield effect in these modes? Seems ok.
3905 //if (!(Viewer_mode & (VM_EXTERNAL | VM_SLEWED | VM_CHASE | VM_DEAD_VIEW))) {
3909 // render nebula lightning
3912 // render local player nebula
3913 neb2_render_player();
3916 ai_debug_render_stuff();
3919 #ifndef RELEASE_REAL
3920 // game_framerate_check();
3924 extern void snd_spew_debug_info();
3925 snd_spew_debug_info();
3928 //================ END OF 3D RENDERING STUFF ====================
3932 if( (Game_detail_flags & DETAIL_FLAG_HUD) && !(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) ) ) {
3933 hud_maybe_clear_head_area();
3934 anim_render_all(0, flFrametime);
3937 extern int Multi_display_netinfo;
3938 if(Multi_display_netinfo){
3939 extern void multi_display_netinfo();
3940 multi_display_netinfo();
3943 game_tst_frame_pre();
3946 do_timing_test(flFrametime);
3950 extern int OO_update_index;
3951 multi_rate_display(OO_update_index, 375, 0);
3956 extern void oo_display();
3963 //#define JOHNS_DEBUG_CODE 1
3965 #ifdef JOHNS_DEBUG_CODE
3966 void john_debug_stuff(vector *eye_pos, matrix *eye_orient)
3968 //if ( keyd_pressed[KEY_LSHIFT] )
3970 ship_subsys *tsys = Players[Player_num].targeted_subobject;
3972 model_subsystem *turret = tsys->system_info;
3974 if (turret->type == SUBSYSTEM_TURRET ) {
3975 vector v.fvec, v.uvec;
3976 object * tobj = &Objects[Players[Player_num].targeted_subobject_parent];
3978 ship_model_start(tobj);
3980 model_find_world_point(eye_pos, &turret->turret_firing_point[0], turret->model_num, turret->turret_gun_sobj, &tobj->orient, &tobj->pos );
3981 model_find_world_dir(&v.fvec, &turret->turret_matrix.v.fvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3982 model_find_world_dir(&v.uvec, &turret->turret_matrix.v.uvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3984 vm_vector_2_matrix( eye_orient, &v.fvec, &v.uvec, NULL );
3986 ship_model_stop(tobj);
3996 // following function for dumping frames for purposes of building trailers.
3999 // function to toggle state of dumping every frame into PCX when playing the game
4000 DCF(dump_frames, "Starts/stop frame dumping at 15 hz")
4004 if ( Debug_dump_frames == 0 ) {
4006 Debug_dump_frames = 15;
4007 Debug_dump_trigger = 0;
4008 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4009 dc_printf( "Frame dumping at 15 hz is now ON\n" );
4012 Debug_dump_frames = 0;
4013 Debug_dump_trigger = 0;
4014 gr_dump_frame_stop();
4015 dc_printf( "Frame dumping is now OFF\n" );
4021 DCF(dump_frames_trigger, "Starts/stop frame dumping at 15 hz")
4025 if ( Debug_dump_frames == 0 ) {
4027 Debug_dump_frames = 15;
4028 Debug_dump_trigger = 1;
4029 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4030 dc_printf( "Frame dumping at 15 hz is now ON\n" );
4033 Debug_dump_frames = 0;
4034 Debug_dump_trigger = 0;
4035 gr_dump_frame_stop();
4036 dc_printf( "Frame dumping is now OFF\n" );
4042 DCF(dump_frames30, "Starts/stop frame dumping at 30 hz")
4046 if ( Debug_dump_frames == 0 ) {
4048 Debug_dump_frames = 30;
4049 Debug_dump_trigger = 0;
4050 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4051 dc_printf( "Frame dumping at 30 hz is now ON\n" );
4054 Debug_dump_frames = 0;
4055 Debug_dump_trigger = 0;
4056 gr_dump_frame_stop();
4057 dc_printf( "Frame dumping is now OFF\n" );
4063 DCF(dump_frames30_trigger, "Starts/stop frame dumping at 30 hz")
4067 if ( Debug_dump_frames == 0 ) {
4069 Debug_dump_frames = 30;
4070 Debug_dump_trigger = 1;
4071 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4072 dc_printf( "Triggered frame dumping at 30 hz is now ON\n" );
4075 Debug_dump_frames = 0;
4076 Debug_dump_trigger = 0;
4077 gr_dump_frame_stop();
4078 dc_printf( "Triggered frame dumping is now OFF\n" );
4084 void game_maybe_dump_frame()
4086 if ( !Debug_dump_frames ){
4090 if( Debug_dump_trigger && !keyd_pressed[KEY_Q] ){
4097 Debug_dump_frame_num++;
4103 extern int Player_dead_state;
4105 // Flip the page and time how long it took.
4106 void game_flip_page_and_time_it()
4111 t1 = timer_get_fixed_seconds();
4113 t2 = timer_get_fixed_seconds();
4116 t = (gr_screen.max_w*gr_screen.max_h*gr_screen.bytes_per_pixel)/1024;
4117 sprintf( transfer_text, NOX("%ld MB/s"), fixmuldiv(t,65,d) );
4124 void game_simulation_frame()
4126 // blow ships up in multiplayer dogfight
4127 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){
4128 // blow up all non-player ships
4129 ship_obj *moveup = GET_FIRST(&Ship_obj_list);
4132 while((moveup != END_OF_LIST(&Ship_obj_list)) && (moveup != NULL)){
4134 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)){
4135 moveup = GET_NEXT(moveup);
4138 shipp = &Ships[Objects[moveup->objnum].instance];
4139 sip = &Ship_info[shipp->ship_info_index];
4141 // only blow up small ships
4142 if((sip->flags & SIF_SMALL_SHIP) && (multi_find_player_by_object(&Objects[moveup->objnum]) < 0) ){
4143 // function to simply explode a ship where it is currently at
4144 ship_self_destruct( &Objects[moveup->objnum] );
4147 moveup = GET_NEXT(moveup);
4153 // process AWACS stuff - do this first thing
4156 // single player, set Player hits_this_frame to 0
4157 if ( !(Game_mode & GM_MULTIPLAYER) && Player ) {
4158 Player->damage_this_burst -= (flFrametime * MAX_BURST_DAMAGE / (0.001f * BURST_DURATION));
4159 Player->damage_this_burst = max(Player->damage_this_burst, 0.0f);
4163 supernova_process();
4164 if(supernova_active() >= 5){
4168 // fire targeting lasers now so that
4169 // 1 - created this frame
4170 // 2 - collide this frame
4171 // 3 - render this frame
4172 // 4 - ignored and deleted next frame
4173 // the basic idea being that because it con be confusing to deal with them on a multi-frame basis, they are only valid for
4175 ship_process_targeting_lasers();
4177 // do this here so that it works for multiplayer
4179 // get viewer direction
4180 int viewer_direction = PHYSICS_VIEWER_REAR;
4182 if(Viewer_mode == 0){
4183 viewer_direction = PHYSICS_VIEWER_FRONT;
4185 if(Viewer_mode & VM_PADLOCK_UP){
4186 viewer_direction = PHYSICS_VIEWER_UP;
4188 else if(Viewer_mode & VM_PADLOCK_REAR){
4189 viewer_direction = PHYSICS_VIEWER_REAR;
4191 else if(Viewer_mode & VM_PADLOCK_LEFT){
4192 viewer_direction = PHYSICS_VIEWER_LEFT;
4194 else if(Viewer_mode & VM_PADLOCK_RIGHT){
4195 viewer_direction = PHYSICS_VIEWER_RIGHT;
4198 physics_set_viewer( &Viewer_obj->phys_info, viewer_direction );
4200 physics_set_viewer( NULL, PHYSICS_VIEWER_FRONT );
4203 #define VM_PADLOCK_UP (1 << 7)
4204 #define VM_PADLOCK_REAR (1 << 8)
4205 #define VM_PADLOCK_LEFT (1 << 9)
4206 #define VM_PADLOCK_RIGHT (1 << 10)
4208 // evaluate mission departures and arrivals before we process all objects.
4209 if ( !(Game_mode & GM_MULTIPLAYER) || ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending()) ) {
4211 // we don't want to evaluate mission stuff when any ingame joiner in multiplayer is receiving
4212 // ships/wing packets.
4213 if ( !((Game_mode & GM_MULTIPLAYER) && (Netgame.flags & NG_FLAG_INGAME_JOINING_CRITICAL)) && !(Game_mode & GM_DEMO_PLAYBACK)){
4214 mission_parse_eval_stuff();
4217 // if we're an observer, move ourselves seperately from the standard physics
4218 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
4219 obj_observer_move(flFrametime);
4222 // move all the objects now
4223 obj_move_all(flFrametime);
4225 // check for cargo reveal (this has an internal timestamp, so only runs every N ms)
4226 // AL: 3-15-98: It was decided to not let AI ships inspect cargo
4227 // ship_check_cargo_all();
4228 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4229 mission_eval_goals();
4233 // always check training objectives, even in multiplayer missions. we need to do this so that the directives gauge works properly on clients
4234 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4235 training_check_objectives();
4238 // do all interpolation now
4239 if ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending() && !(Netgame.flags & NG_FLAG_SERVER_LOST)) {
4240 // client side processing of warping in effect stages
4241 multi_do_client_warp(flFrametime);
4243 // client side movement of an observer
4244 if((Net_player->flags & NETINFO_FLAG_OBSERVER) || (Player_obj->type == OBJ_OBSERVER)){
4245 obj_observer_move(flFrametime);
4248 // move all objects - does interpolation now as well
4249 obj_move_all(flFrametime);
4252 // only process the message queue when the player is "in" the game
4253 if ( !Pre_player_entry ){
4254 message_queue_process(); // process any messages send to the player
4257 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4258 message_maybe_distort(); // maybe distort incoming message if comms damaged
4259 player_repair_frame(flFrametime); // AI objects get repaired in ai_process, called from move code...deal with player.
4260 player_process_pending_praise(); // maybe send off a delayed praise message to the player
4261 player_maybe_play_all_alone_msg(); // mabye tell the player he is all alone
4264 if(!(Game_mode & GM_STANDALONE_SERVER)){
4265 // process some stuff every frame (before frame is rendered)
4266 emp_process_local();
4268 hud_update_frame(); // update hud systems
4270 if (!physics_paused) {
4271 // Move particle system
4272 particle_move_all(flFrametime);
4274 // Move missile trails
4275 trail_move_all(flFrametime);
4277 // process muzzle flashes
4278 mflash_process_all();
4280 // Flash the gun flashes
4281 shipfx_flash_do_frame(flFrametime);
4283 shockwave_move_all(flFrametime); // update all the shockwaves
4286 // subspace missile strikes
4289 obj_snd_do_frame(); // update the object-linked persistant sounds
4290 game_maybe_update_sound_environment();
4291 snd_update_listener(&View_position, &Player_obj->phys_info.vel, &Player_obj->orient);
4293 // AL: debug code used for testing ambient subspace sound (ie when enabling subspace through debug console)
4295 if ( Game_subspace_effect ) {
4296 game_start_subspace_ambient_sound();
4302 // Maybe render and process the dead-popup
4303 void game_maybe_do_dead_popup(float frametime)
4305 if ( popupdead_is_active() ) {
4307 int choice = popupdead_do_frame(frametime);
4309 if ( Game_mode & GM_NORMAL ) {
4313 if(game_do_cd_mission_check(Game_current_mission_filename)){
4314 gameseq_post_event(GS_EVENT_ENTER_GAME);
4316 gameseq_post_event(GS_EVENT_MAIN_MENU);
4321 gameseq_post_event(GS_EVENT_END_GAME);
4326 if(game_do_cd_mission_check(Game_current_mission_filename)){
4327 gameseq_post_event(GS_EVENT_START_GAME);
4329 gameseq_post_event(GS_EVENT_MAIN_MENU);
4333 // this should only happen during a red alert mission
4336 Assert(The_mission.red_alert);
4337 if(!The_mission.red_alert){
4339 if(game_do_cd_mission_check(Game_current_mission_filename)){
4340 gameseq_post_event(GS_EVENT_START_GAME);
4342 gameseq_post_event(GS_EVENT_MAIN_MENU);
4347 // choose the previous mission
4348 mission_campaign_previous_mission();
4350 if(game_do_cd_mission_check(Game_current_mission_filename)){
4351 gameseq_post_event(GS_EVENT_START_GAME);
4353 gameseq_post_event(GS_EVENT_MAIN_MENU);
4364 case POPUPDEAD_DO_MAIN_HALL:
4365 multi_quit_game(PROMPT_NONE,-1);
4368 case POPUPDEAD_DO_RESPAWN:
4369 multi_respawn_normal();
4370 event_music_player_respawn();
4373 case POPUPDEAD_DO_OBSERVER:
4374 multi_respawn_observer();
4375 event_music_player_respawn_as_observer();
4384 if ( leave_popup ) {
4390 // returns true if player is actually in a game_play stats
4391 int game_actually_playing()
4395 state = gameseq_get_state();
4396 if ( (state != GS_STATE_GAME_PLAY) && (state != GS_STATE_DEATH_DIED) && (state != GS_STATE_DEATH_BLEW_UP) )
4402 // Draw the 2D HUD gauges
4403 void game_render_hud_2d()
4405 if ( !(Game_detail_flags & DETAIL_FLAG_HUD) ) {
4409 HUD_render_2d(flFrametime);
4413 // Draw the 3D-dependant HUD gauges
4414 void game_render_hud_3d(vector *eye_pos, matrix *eye_orient)
4416 g3_start_frame(0); // 0 = turn zbuffering off
4417 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
4419 if ( (Game_detail_flags & DETAIL_FLAG_HUD) && (supernova_active() < 3)/* && !(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) )*/ ) {
4420 HUD_render_3d(flFrametime);
4424 game_sunspot_process(flFrametime);
4426 // Diminish the palette effect
4427 game_flash_diminish(flFrametime);
4435 int actually_playing;
4436 fix total_time1, total_time2;
4437 fix render2_time1=0, render2_time2=0;
4438 fix render3_time1=0, render3_time2=0;
4439 fix flip_time1=0, flip_time2=0;
4440 fix clear_time1=0, clear_time2=0;
4446 if (Framerate_delay) {
4447 int start_time = timer_get_milliseconds();
4448 while (timer_get_milliseconds() < start_time + Framerate_delay)
4454 demo_do_frame_start();
4456 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4461 // start timing frame
4462 timing_frame_start();
4464 total_time1 = timer_get_fixed_seconds();
4466 // var to hold which state we are in
4467 actually_playing = game_actually_playing();
4469 if ((!(Game_mode & GM_MULTIPLAYER)) || ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER))) {
4470 if (!(Game_mode & GM_STANDALONE_SERVER)){
4471 Assert( OBJ_INDEX(Player_obj) >= 0 );
4475 if (Missiontime > Entry_delay_time){
4476 Pre_player_entry = 0;
4478 ; //nprintf(("AI", "Framecount = %i, time = %7.3f\n", Framecount, f2fl(Missiontime)));
4481 // Note: These are done even before the player enters, else buffers can overflow.
4482 if (! (Game_mode & GM_STANDALONE_SERVER)){
4486 shield_frame_init();
4488 if ( Player->control_mode != PCM_NORMAL )
4491 if ( !Pre_player_entry && actually_playing ) {
4492 if (! (Game_mode & GM_STANDALONE_SERVER) ) {
4494 if( (!popup_running_state()) && (!popupdead_is_active()) ){
4495 game_process_keys();
4497 // don't read flying controls if we're playing a demo back
4498 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4499 read_player_controls( Player_obj, flFrametime);
4503 // if we're not the master, we may have to send the server-critical ship status button_info bits
4504 if ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER)){
4505 multi_maybe_send_ship_status();
4510 // Reset the whack stuff
4513 // These two lines must be outside of Pre_player_entry code,
4514 // otherwise too many lights are added.
4517 if ((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4521 game_simulation_frame();
4523 // if not actually in a game play state, then return. This condition could only be true in
4524 // a multiplayer game.
4525 if ( !actually_playing ) {
4526 Assert( Game_mode & GM_MULTIPLAYER );
4530 if (!Pre_player_entry) {
4531 if (! (Game_mode & GM_STANDALONE_SERVER)) {
4532 clear_time1 = timer_get_fixed_seconds();
4533 // clear the screen to black
4535 if ( (Game_detail_flags & DETAIL_FLAG_CLEAR) ) {
4539 clear_time2 = timer_get_fixed_seconds();
4540 render3_time1 = timer_get_fixed_seconds();
4541 game_render_frame_setup(&eye_pos, &eye_orient);
4542 game_render_frame( &eye_pos, &eye_orient );
4544 // save the eye position and orientation
4545 if ( Game_mode & GM_MULTIPLAYER ) {
4546 Net_player->s_info.eye_pos = eye_pos;
4547 Net_player->s_info.eye_orient = eye_orient;
4550 hud_show_target_model();
4552 // check to see if we should display the death died popup
4553 if(Game_mode & GM_DEAD_BLEW_UP){
4554 if(Game_mode & GM_MULTIPLAYER){
4555 // catch the situation where we're supposed to be warping out on this transition
4556 if(Net_player->flags & NETINFO_FLAG_WARPING_OUT){
4557 gameseq_post_event(GS_EVENT_DEBRIEF);
4558 } else if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4559 Player_died_popup_wait = -1;
4563 if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4564 Player_died_popup_wait = -1;
4570 // hack - sometimes this seems to slip by in multiplayer. this should guarantee that we catch it
4571 if((Game_mode & GM_MULTIPLAYER) && (Player_multi_died_check != -1) && (Game_mode & GM_DEAD_BLEW_UP) ){
4572 if(fl_abs(time(NULL) - Player_multi_died_check) > 4){
4573 if(!popupdead_is_active()){
4577 Player_multi_died_check = -1;
4581 render3_time2 = timer_get_fixed_seconds();
4582 render2_time1 = timer_get_fixed_seconds();
4585 game_get_framerate();
4586 game_show_framerate();
4588 game_show_time_left();
4590 // Draw the 2D HUD gauges
4591 if(supernova_active() < 3){
4592 game_render_hud_2d();
4595 game_set_view_clip();
4597 // Draw 3D HUD gauges
4598 game_render_hud_3d(&eye_pos, &eye_orient);
4602 render2_time2 = timer_get_fixed_seconds();
4604 // maybe render and process the dead popup
4605 game_maybe_do_dead_popup(flFrametime);
4607 // start timing frame
4608 timing_frame_stop();
4609 // timing_display(30, 10);
4611 // If a regular popup is active, don't flip (popup code flips)
4612 if( !popup_running_state() ){
4613 flip_time1 = timer_get_fixed_seconds();
4614 game_flip_page_and_time_it();
4615 flip_time2 = timer_get_fixed_seconds();
4619 game_maybe_dump_frame(); // used to dump pcx files for building trailers
4622 game_show_standalone_framerate();
4626 game_do_training_checks();
4629 // process lightning (nebula only)
4632 total_time2 = timer_get_fixed_seconds();
4634 // Got some timing numbers
4635 Timing_total = f2fl( total_time2 - total_time1 ) * 1000.0f;
4636 Timing_clear = f2fl( clear_time2 - clear_time1 ) * 1000.0f;
4637 Timing_render2 = f2fl( render2_time2- render2_time1 ) * 1000.0f;
4638 Timing_render3 = f2fl( render3_time2- render3_time1 ) * 1000.0f;
4639 Timing_flip = f2fl( flip_time2 - flip_time1 ) * 1000.0f;
4642 demo_do_frame_end();
4644 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4650 #define MAX_FRAMETIME (F1_0/4) // Frametime gets saturated at this. Changed by MK on 11/1/97.
4651 // Some bug was causing Frametime to always get saturated at 2.0 seconds after the player
4652 // died. This resulted in screwed up death sequences.
4654 fix Last_time = 0; // The absolute time of game at end of last frame (beginning of this frame)
4655 fix Last_delta_time = 0; // While game is paused, this keeps track of how much elapsed in the frame before paused.
4656 static int timer_paused=0;
4657 #if defined(TIMER_TEST) && !defined(NDEBUG)
4658 static int stop_count,start_count;
4659 static int time_stopped,time_started;
4661 int saved_timestamp_ticker = -1;
4663 void game_reset_time()
4665 if((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4669 // Last_time = timer_get_fixed_seconds();
4675 void game_stop_time()
4677 if (timer_paused==0) {
4679 time = timer_get_fixed_seconds();
4680 // Save how much time progressed so far in the frame so we can
4681 // use it when we unpause.
4682 Last_delta_time = time - Last_time;
4684 //mprintf(("Last_time in game_stop_time = %7.3f\n", f2fl(Last_delta_time)));
4685 if (Last_delta_time < 0) {
4686 #if defined(TIMER_TEST) && !defined(NDEBUG)
4687 Int3(); //get Matt!!!!
4689 Last_delta_time = 0;
4691 #if defined(TIMER_TEST) && !defined(NDEBUG)
4692 time_stopped = time;
4695 // Stop the timer_tick stuff...
4696 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4697 saved_timestamp_ticker = timestamp_ticker;
4701 #if defined(TIMER_TEST) && !defined(NDEBUG)
4706 void game_start_time()
4709 Assert(timer_paused >= 0);
4710 if (timer_paused==0) {
4712 time = timer_get_fixed_seconds();
4713 #if defined(TIMER_TEST) && !defined(NDEBUG)
4715 Int3(); //get Matt!!!!
4718 // Take current time, and set it backwards to account for time
4719 // that the frame already executed, so that timer_get_fixed_seconds() - Last_time
4720 // will be correct when it goes to calculate the frametime next
4722 Last_time = time - Last_delta_time;
4723 #if defined(TIMER_TEST) && !defined(NDEBUG)
4724 time_started = time;
4727 // Restore the timer_tick stuff...
4728 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4729 Assert( saved_timestamp_ticker > -1 ); // Called out of order, get JAS
4730 timestamp_ticker = saved_timestamp_ticker;
4731 saved_timestamp_ticker = -1;
4734 #if defined(TIMER_TEST) && !defined(NDEBUG)
4740 void game_set_frametime(int state)
4743 float frame_cap_diff;
4745 thistime = timer_get_fixed_seconds();
4747 if ( Last_time == 0 )
4748 Frametime = F1_0 / 30;
4750 Frametime = thistime - Last_time;
4752 // Frametime = F1_0 / 30;
4754 fix debug_frametime = Frametime; // Just used to display frametime.
4756 // If player hasn't entered mission yet, make frame take 1/4 second.
4757 if ((Pre_player_entry) && (state == GS_STATE_GAME_PLAY))
4760 else if ((Debug_dump_frames) && (state == GS_STATE_GAME_PLAY)) { // note link to above if!!!!!
4762 fix frame_speed = F1_0 / Debug_dump_frames;
4764 if (Frametime > frame_speed ){
4765 nprintf(("warning","slow frame: %x\n",Frametime));
4768 thistime = timer_get_fixed_seconds();
4769 Frametime = thistime - Last_time;
4770 } while (Frametime < frame_speed );
4772 Frametime = frame_speed;
4776 Assert( Framerate_cap > 0 );
4778 // Cap the framerate so it doesn't get too high.
4782 cap = F1_0/Framerate_cap;
4783 if (Frametime < cap) {
4784 thistime = cap - Frametime;
4785 //mprintf(("Sleeping for %6.3f seconds.\n", f2fl(thistime)));
4786 Sleep( (DWORD)(f2fl(thistime) * 1000.0f) );
4788 thistime = timer_get_fixed_seconds();
4792 if((Game_mode & GM_STANDALONE_SERVER) &&
4793 (f2fl(Frametime) < ((float)1.0/(float)Multi_options_g.std_framecap))){
4795 frame_cap_diff = ((float)1.0/(float)Multi_options_g.std_framecap) - f2fl(Frametime);
4796 Sleep((DWORD)(frame_cap_diff*1000));
4798 thistime += fl2f((frame_cap_diff));
4800 Frametime = thistime - Last_time;
4803 // If framerate is too low, cap it.
4804 if (Frametime > MAX_FRAMETIME) {
4806 mprintf(("Frame %2i too long!!: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4808 // to remove warnings in release build
4809 debug_frametime = fl2f(flFrametime);
4811 Frametime = MAX_FRAMETIME;
4814 Frametime = fixmul(Frametime, Game_time_compression);
4816 Last_time = thistime;
4817 //mprintf(("Frame %i, Last_time = %7.3f\n", Framecount, f2fl(Last_time)));
4819 flFrametime = f2fl(Frametime);
4820 //if(!(Game_mode & GM_PLAYING_DEMO)){
4821 timestamp_inc(flFrametime);
4823 /* if ((Framecount > 0) && (Framecount < 10)) {
4824 mprintf(("Frame %2i: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4829 // This is called from game_do_frame(), and from navmap_do_frame()
4830 void game_update_missiontime()
4832 // TODO JAS: Put in if and move this into game_set_frametime,
4833 // fix navmap to call game_stop/start_time
4834 //if ( !timer_paused )
4835 Missiontime += Frametime;
4838 void game_do_frame()
4840 game_set_frametime(GS_STATE_GAME_PLAY);
4841 game_update_missiontime();
4843 if (Game_mode & GM_STANDALONE_SERVER) {
4844 std_multi_set_standalone_missiontime(f2fl(Missiontime));
4847 if ( game_single_step && (last_single_step == game_single_step) ) {
4848 os_set_title( NOX("SINGLE STEP MODE (Pause exits, any other key steps)") );
4849 while( key_checkch() == 0 )
4851 os_set_title( XSTR( "FreeSpace", 171) );
4852 Last_time = timer_get_fixed_seconds();
4855 last_single_step = game_single_step;
4857 if ((gameseq_get_state() == GS_STATE_GAME_PLAY) && Use_mouse_to_fly){
4858 Keep_mouse_centered = 1; // force mouse to center of our window (so we don't hit movement limits)
4862 Keep_mouse_centered = 0;
4863 monitor_update(); // Update monitor variables
4866 void multi_maybe_do_frame()
4868 if ( (Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_IN_MISSION) && !Multi_pause_status){
4873 int Joymouse_button_status = 0;
4875 // Flush all input devices
4883 Joymouse_button_status = 0;
4885 //mprintf(("Game flush!\n" ));
4888 // function for multiplayer only which calls game_do_state_common() when running the
4890 void game_do_dc_networking()
4892 Assert( Game_mode & GM_MULTIPLAYER );
4894 game_do_state_common( gameseq_get_state() );
4897 // Call this whenever in a loop, or when you need to check for a keystroke.
4898 int game_check_key()
4904 // convert keypad enter to normal enter
4905 if ((k & KEY_MASK) == KEY_PADENTER)
4906 k = (k & ~KEY_MASK) | KEY_ENTER;
4911 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4913 #define DEMO_TRAILER_TIMEOUT_MS 45000 // 45 seconds of no input, play trailer
4914 static int Demo_show_trailer_timestamp = 0;
4916 void demo_reset_trailer_timer()
4918 Demo_show_trailer_timestamp = timer_get_milliseconds();
4921 void demo_maybe_show_trailer(int k)
4924 // if key pressed, reset demo trailer timer
4926 demo_reset_trailer_timer();
4930 // if mouse moved, reset demo trailer timer
4933 mouse_get_delta(&dx, &dy);
4934 if ( (dx > 0) || (dy > 0) ) {
4935 demo_reset_trailer_timer();
4939 // if joystick has moved, reset demo trailer timer
4942 joy_get_delta(&dx, &dy);
4943 if ( (dx > 0) || (dy > 0) ) {
4944 demo_reset_trailer_timer();
4948 // NOTE: reseting the trailer timer on mouse/joystick presses is handled in
4949 // the low-level code. Ugly, I know... but was the simplest and most
4952 // if 30 seconds since last demo trailer time reset, launch movie
4953 if ( os_foreground() ) {
4954 int now = timer_get_milliseconds();
4955 if ( (now - Demo_show_trailer_timestamp) > DEMO_TRAILER_TIMEOUT_MS ) {
4956 // if ( (now - Demo_show_trailer_timestamp) > 10000 ) {
4958 movie_play( NOX("fstrailer2.mve") );
4959 demo_reset_trailer_timer();
4967 // same as game_check_key(), except this is used while actually in the game. Since there
4968 // generally are differences between game control keys and general UI keys, makes sense to
4969 // have seperate functions for each case. If you are not checking a game control while in a
4970 // mission, you should probably be using game_check_key() instead.
4975 if (!os_foreground()) {
4980 // If we're in a single player game, pause it.
4981 if (!(Game_mode & GM_MULTIPLAYER)){
4982 if ( (gameseq_get_state() == GS_STATE_GAME_PLAY) && (!popup_active()) && (!popupdead_is_active()) ) {
4983 game_process_pause_key();
4990 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4991 demo_maybe_show_trailer(k);
4994 // Move the mouse cursor with the joystick.
4995 if (os_foreground() && (!Mouse_hidden) && (Use_joy_mouse) ) {
4996 // Move the mouse cursor with the joystick
5000 joy_get_pos( &jx, &jy, &jz, &jr );
5002 dx = fl2i(f2fl(jx)*flFrametime*500.0f);
5003 dy = fl2i(f2fl(jy)*flFrametime*500.0f);
5006 mouse_get_real_pos( &mx, &my );
5007 mouse_set_pos( mx+dx, my+dy );
5012 m = mouse_down(MOUSE_LEFT_BUTTON);
5014 if ( j != Joymouse_button_status ) {
5015 //mprintf(( "Joy went from %d to %d, mouse is %d\n", Joymouse_button_status, j, m ));
5016 Joymouse_button_status = j;
5018 mouse_mark_button( MOUSE_LEFT_BUTTON, 1 );
5019 } else if ( (!j) && (m) ) {
5020 mouse_mark_button( MOUSE_LEFT_BUTTON, 0 );
5025 // if we should be ignoring keys because of some multiplayer situations
5026 if((Game_mode & GM_MULTIPLAYER) && multi_ignore_controls(k)){
5030 // If a popup is running, don't process all the Fn keys
5031 if( popup_active() ) {
5035 state = gameseq_get_state();
5037 // if ( k ) nprintf(( "General", "Key = %x\n", k ));
5040 case KEY_DEBUGGED + KEY_BACKSP:
5045 launch_context_help();
5050 // if (state != GS_STATE_INITIAL_PLAYER_SELECT) {
5052 // don't allow f2 while warping out in multiplayer
5053 if((Game_mode & GM_MULTIPLAYER) && (Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_WARPING_OUT)){
5058 case GS_STATE_INITIAL_PLAYER_SELECT:
5059 case GS_STATE_OPTIONS_MENU:
5060 case GS_STATE_HUD_CONFIG:
5061 case GS_STATE_CONTROL_CONFIG:
5062 case GS_STATE_DEATH_DIED:
5063 case GS_STATE_DEATH_BLEW_UP:
5064 case GS_STATE_VIEW_MEDALS:
5068 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
5075 // hotkey selection screen -- only valid from briefing and beyond.
5077 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
5078 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) ) {
5079 gameseq_post_event( GS_EVENT_HOTKEY_SCREEN );
5085 case KEY_DEBUGGED + KEY_F3:
5086 gameseq_post_event( GS_EVENT_TOGGLE_FULLSCREEN );
5089 case KEY_DEBUGGED + KEY_F4:
5090 gameseq_post_event( GS_EVENT_TOGGLE_GLIDE );
5094 if(Game_mode & GM_MULTIPLAYER){
5095 if((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_MULTI_PAUSED)){
5096 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
5100 if ((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_DEATH_DIED) || (state == GS_STATE_DEATH_BLEW_UP) || (state == GS_STATE_GAME_PAUSED) ) {
5101 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
5107 case KEY_ESC | KEY_SHIFTED:
5108 // make sure to quit properly out of multiplayer
5109 if(Game_mode & GM_MULTIPLAYER){
5110 multi_quit_game(PROMPT_NONE);
5113 gameseq_post_event( GS_EVENT_QUIT_GAME );
5118 case KEY_DEBUGGED + KEY_P:
5121 case KEY_PRINT_SCRN:
5123 static int counter = 0;
5128 sprintf( tmp_name, NOX("screen%02d"), counter );
5130 mprintf(( "Dumping screen to '%s'\n", tmp_name ));
5131 gr_print_screen(tmp_name);
5139 case KEY_SHIFTED | KEY_ENTER: {
5141 #if !defined(NDEBUG)
5143 if ( Game_mode & GM_NORMAL ){
5147 // if we're in multiplayer mode, do some special networking
5148 if(Game_mode & GM_MULTIPLAYER){
5149 debug_console(game_do_dc_networking);
5156 if ( Game_mode & GM_NORMAL )
5170 gameseq_post_event(GS_EVENT_QUIT_GAME);
5173 void apply_physics( float damping, float desired_vel, float initial_vel, float t, float * new_vel, float * delta_pos );
5176 void camera_set_position( vector *pos )
5181 void camera_set_orient( matrix *orient )
5183 Camera_orient = *orient;
5186 void camera_set_velocity( vector *vel, int instantaneous )
5188 Camera_desired_velocity.xyz.x = 0.0f;
5189 Camera_desired_velocity.xyz.y = 0.0f;
5190 Camera_desired_velocity.xyz.z = 0.0f;
5192 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.rvec, vel->xyz.x );
5193 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.uvec, vel->xyz.y );
5194 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.fvec, vel->xyz.z );
5196 if ( instantaneous ) {
5197 Camera_velocity = Camera_desired_velocity;
5205 vector new_vel, delta_pos;
5207 apply_physics( Camera_damping, Camera_desired_velocity.xyz.x, Camera_velocity.xyz.x, flFrametime, &new_vel.xyz.x, &delta_pos.xyz.x );
5208 apply_physics( Camera_damping, Camera_desired_velocity.xyz.y, Camera_velocity.xyz.y, flFrametime, &new_vel.xyz.y, &delta_pos.xyz.y );
5209 apply_physics( Camera_damping, Camera_desired_velocity.xyz.z, Camera_velocity.xyz.z, flFrametime, &new_vel.xyz.z, &delta_pos.xyz.z );
5211 Camera_velocity = new_vel;
5213 // mprintf(( "Camera velocity = %.1f,%.1f, %.1f\n", Camera_velocity.xyz.x, Camera_velocity.xyz.y, Camera_velocity.xyz.z ));
5215 vm_vec_add2( &Camera_pos, &delta_pos );
5217 float ot = Camera_time+0.0f;
5219 Camera_time += flFrametime;
5221 if ( (ot < 0.667f) && ( Camera_time >= 0.667f ) ) {
5224 tmp.xyz.z = 4.739f; // always go this fast forward.
5226 // pick x and y velocities so they are always on a
5227 // circle with a 25 m radius.
5229 float tmp_angle = frand()*PI2;
5231 tmp.xyz.x = 22.0f * (float)sin(tmp_angle);
5232 tmp.xyz.y = -22.0f * (float)cos(tmp_angle);
5234 //mprintf(( "Angle = %.1f, vx=%.1f, vy=%.1f\n", tmp_angle, tmp.xyz.x, tmp.xyz.y ));
5236 //mprintf(( "Changing velocity!\n" ));
5237 camera_set_velocity( &tmp, 0 );
5240 if ( (ot < 3.0f ) && ( Camera_time >= 3.0f ) ) {
5241 vector tmp = { 0.0f, 0.0f, 0.0f };
5242 camera_set_velocity( &tmp, 0 );
5247 void end_demo_campaign_do()
5249 #if defined(FS2_DEMO) || defined(FS1_DEMO)
5250 // show upsell screens
5251 demo_upsell_show_screens();
5252 #elif defined(OEM_BUILD)
5253 // show oem upsell screens
5254 oem_upsell_show_screens();
5257 // drop into main hall
5258 gameseq_post_event( GS_EVENT_MAIN_MENU );
5261 // All code to process events. This is the only place
5262 // that you should change the state of the game.
5263 void game_process_event( int current_state, int event )
5265 mprintf(("Got event %s in state %s\n", GS_event_text[event], GS_state_text[current_state]));
5268 case GS_EVENT_SIMULATOR_ROOM:
5269 gameseq_set_state(GS_STATE_SIMULATOR_ROOM);
5272 case GS_EVENT_MAIN_MENU:
5273 gameseq_set_state(GS_STATE_MAIN_MENU);
5276 case GS_EVENT_OPTIONS_MENU:
5277 gameseq_push_state( GS_STATE_OPTIONS_MENU );
5280 case GS_EVENT_BARRACKS_MENU:
5281 gameseq_set_state(GS_STATE_BARRACKS_MENU);
5284 case GS_EVENT_TECH_MENU:
5285 gameseq_set_state(GS_STATE_TECH_MENU);
5288 case GS_EVENT_TRAINING_MENU:
5289 gameseq_set_state(GS_STATE_TRAINING_MENU);
5292 case GS_EVENT_START_GAME:
5293 Select_default_ship = 0;
5294 Player_multi_died_check = -1;
5295 gameseq_set_state(GS_STATE_CMD_BRIEF);
5298 case GS_EVENT_START_BRIEFING:
5299 gameseq_set_state(GS_STATE_BRIEFING);
5302 case GS_EVENT_DEBRIEF:
5303 // did we end the campaign in the main freespace 2 single player campaign?
5305 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !stricmp(Campaign.filename, "freespace")) {
5307 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !stricmp(Campaign.filename, "freespace2")) {
5309 gameseq_post_event(GS_EVENT_END_CAMPAIGN);
5311 gameseq_set_state(GS_STATE_DEBRIEF);
5314 Player_multi_died_check = -1;
5317 case GS_EVENT_SHIP_SELECTION:
5318 gameseq_set_state( GS_STATE_SHIP_SELECT );
5321 case GS_EVENT_WEAPON_SELECTION:
5322 gameseq_set_state( GS_STATE_WEAPON_SELECT );
5325 case GS_EVENT_ENTER_GAME:
5327 // maybe start recording a demo
5329 demo_start_record("test.fsd");
5333 if (Game_mode & GM_MULTIPLAYER) {
5334 // if we're respawning, make sure we change the view mode so that the hud shows up
5335 if (current_state == GS_STATE_DEATH_BLEW_UP) {
5339 gameseq_set_state(GS_STATE_GAME_PLAY);
5341 gameseq_set_state(GS_STATE_GAME_PLAY, 1);
5344 Player_multi_died_check = -1;
5346 // clear multiplayer button info
5347 extern button_info Multi_ship_status_bi;
5348 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
5350 Start_time = f2fl(timer_get_approx_seconds());
5352 mprintf(("Entering game at time = %7.3f\n", Start_time));
5356 case GS_EVENT_START_GAME_QUICK:
5357 Select_default_ship = 1;
5358 gameseq_post_event(GS_EVENT_ENTER_GAME);
5362 case GS_EVENT_END_GAME:
5363 if ( (current_state == GS_STATE_GAME_PLAY) || (current_state == GS_STATE_DEATH_DIED) ||
5364 (current_state == GS_STATE_DEATH_BLEW_UP) || (current_state == GS_STATE_DEBRIEF) || (current_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) {
5365 gameseq_set_state(GS_STATE_MAIN_MENU);
5370 Player_multi_died_check = -1;
5373 case GS_EVENT_QUIT_GAME:
5374 main_hall_stop_music();
5375 main_hall_stop_ambient();
5376 gameseq_set_state(GS_STATE_QUIT_GAME);
5378 Player_multi_died_check = -1;
5381 case GS_EVENT_GAMEPLAY_HELP:
5382 gameseq_push_state( GS_STATE_GAMEPLAY_HELP );
5385 case GS_EVENT_PAUSE_GAME:
5386 gameseq_push_state(GS_STATE_GAME_PAUSED);
5389 case GS_EVENT_DEBUG_PAUSE_GAME:
5390 gameseq_push_state(GS_STATE_DEBUG_PAUSED);
5393 case GS_EVENT_TRAINING_PAUSE:
5394 gameseq_push_state(GS_STATE_TRAINING_PAUSED);
5397 case GS_EVENT_PREVIOUS_STATE:
5398 gameseq_pop_state();
5401 case GS_EVENT_TOGGLE_FULLSCREEN:
5402 #ifndef HARDWARE_ONLY
5404 if ( gr_screen.mode == GR_SOFTWARE ) {
5405 gr_init( GR_640, GR_DIRECTDRAW );
5406 } else if ( gr_screen.mode == GR_DIRECTDRAW ) {
5407 gr_init( GR_640, GR_SOFTWARE );
5413 case GS_EVENT_TOGGLE_GLIDE:
5415 if ( gr_screen.mode != GR_GLIDE ) {
5416 gr_init( GR_640, GR_GLIDE );
5418 gr_init( GR_640, GR_SOFTWARE );
5423 case GS_EVENT_LOAD_MISSION_MENU:
5424 gameseq_set_state(GS_STATE_LOAD_MISSION_MENU);
5427 case GS_EVENT_MISSION_LOG_SCROLLBACK:
5428 gameseq_push_state( GS_STATE_MISSION_LOG_SCROLLBACK );
5431 case GS_EVENT_HUD_CONFIG:
5432 gameseq_push_state( GS_STATE_HUD_CONFIG );
5435 case GS_EVENT_CONTROL_CONFIG:
5436 gameseq_push_state( GS_STATE_CONTROL_CONFIG );
5439 case GS_EVENT_DEATH_DIED:
5440 gameseq_set_state( GS_STATE_DEATH_DIED );
5443 case GS_EVENT_DEATH_BLEW_UP:
5444 if ( current_state == GS_STATE_DEATH_DIED ) {
5445 gameseq_set_state( GS_STATE_DEATH_BLEW_UP );
5446 event_music_player_death();
5448 // multiplayer clients set their extra check here
5449 if(Game_mode & GM_MULTIPLAYER){
5450 // set the multi died absolute last chance check
5451 Player_multi_died_check = time(NULL);
5454 mprintf(( "Ignoring GS_EVENT_DEATH_BLEW_UP because we're in state %d\n", current_state ));
5458 case GS_EVENT_NEW_CAMPAIGN:
5459 if (!mission_load_up_campaign()){
5460 readyroom_continue_campaign();
5463 Player_multi_died_check = -1;
5466 case GS_EVENT_CAMPAIGN_CHEAT:
5467 if (!mission_load_up_campaign()){
5469 // bash campaign value
5470 extern char Main_hall_campaign_cheat[512];
5473 // look for the mission
5474 for(idx=0; idx<Campaign.num_missions; idx++){
5475 if(!stricmp(Campaign.missions[idx].name, Main_hall_campaign_cheat)){
5476 Campaign.next_mission = idx;
5477 Campaign.prev_mission = idx - 1;
5484 readyroom_continue_campaign();
5487 Player_multi_died_check = -1;
5490 case GS_EVENT_CAMPAIGN_ROOM:
5491 gameseq_set_state(GS_STATE_CAMPAIGN_ROOM);
5494 case GS_EVENT_CMD_BRIEF:
5495 gameseq_set_state(GS_STATE_CMD_BRIEF);
5498 case GS_EVENT_RED_ALERT:
5499 gameseq_set_state(GS_STATE_RED_ALERT);
5502 case GS_EVENT_CREDITS:
5503 gameseq_set_state( GS_STATE_CREDITS );
5506 case GS_EVENT_VIEW_MEDALS:
5507 gameseq_push_state( GS_STATE_VIEW_MEDALS );
5510 case GS_EVENT_SHOW_GOALS:
5511 gameseq_push_state( GS_STATE_SHOW_GOALS ); // use push_state() since we might get to this screen through a variety of states
5514 case GS_EVENT_HOTKEY_SCREEN:
5515 gameseq_push_state( GS_STATE_HOTKEY_SCREEN ); // use push_state() since we might get to this screen through a variety of states
5518 // multiplayer stuff follow these comments
5520 case GS_EVENT_MULTI_JOIN_GAME:
5521 gameseq_set_state( GS_STATE_MULTI_JOIN_GAME );
5524 case GS_EVENT_MULTI_HOST_SETUP:
5525 gameseq_set_state( GS_STATE_MULTI_HOST_SETUP );
5528 case GS_EVENT_MULTI_CLIENT_SETUP:
5529 gameseq_set_state( GS_STATE_MULTI_CLIENT_SETUP );
5532 case GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN:
5533 gameseq_set_state(GS_STATE_VIEW_CUTSCENES);
5536 case GS_EVENT_MULTI_STD_WAIT:
5537 gameseq_set_state( GS_STATE_MULTI_STD_WAIT );
5540 case GS_EVENT_STANDALONE_MAIN:
5541 gameseq_set_state( GS_STATE_STANDALONE_MAIN );
5544 case GS_EVENT_MULTI_PAUSE:
5545 gameseq_push_state( GS_STATE_MULTI_PAUSED );
5548 case GS_EVENT_INGAME_PRE_JOIN:
5549 gameseq_set_state( GS_STATE_INGAME_PRE_JOIN );
5552 case GS_EVENT_EVENT_DEBUG:
5553 gameseq_push_state(GS_STATE_EVENT_DEBUG);
5556 // Start a warpout where player automatically goes 70 no matter what
5557 // and can't cancel out of it.
5558 case GS_EVENT_PLAYER_WARPOUT_START_FORCED:
5559 Warpout_forced = 1; // If non-zero, bash the player to speed and go through effect
5561 // Same code as in GS_EVENT_PLAYER_WARPOUT_START only ignores current mode
5562 Player->saved_viewer_mode = Viewer_mode;
5563 Player->control_mode = PCM_WARPOUT_STAGE1;
5564 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5565 Warpout_time = 0.0f; // Start timer!
5568 case GS_EVENT_PLAYER_WARPOUT_START:
5569 if ( Player->control_mode != PCM_NORMAL ) {
5570 mprintf(( "Player isn't in normal mode; cannot warp out.\n" ));
5572 Player->saved_viewer_mode = Viewer_mode;
5573 Player->control_mode = PCM_WARPOUT_STAGE1;
5574 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5575 Warpout_time = 0.0f; // Start timer!
5576 Warpout_forced = 0; // If non-zero, bash the player to speed and go through effect
5580 case GS_EVENT_PLAYER_WARPOUT_STOP:
5581 if ( Player->control_mode != PCM_NORMAL ) {
5582 if ( !Warpout_forced ) { // cannot cancel forced warpout
5583 Player->control_mode = PCM_NORMAL;
5584 Viewer_mode = Player->saved_viewer_mode;
5585 hud_subspace_notify_abort();
5586 mprintf(( "Player put back to normal mode.\n" ));
5587 if ( Warpout_sound > -1 ) {
5588 snd_stop( Warpout_sound );
5595 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE1: // player ship got up to speed
5596 if ( Player->control_mode != PCM_WARPOUT_STAGE1 ) {
5597 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5598 mprintf(( "Player put back to normal mode, because of invalid sequence in stage1.\n" ));
5600 mprintf(( "Hit target speed. Starting warp effect and moving to stage 2!\n" ));
5601 shipfx_warpout_start( Player_obj );
5602 Player->control_mode = PCM_WARPOUT_STAGE2;
5603 Player->saved_viewer_mode = Viewer_mode;
5604 Viewer_mode |= VM_WARP_CHASE;
5606 vector tmp = Player_obj->pos;
5608 ship_get_eye( &tmp, &tmp_m, Player_obj );
5609 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.rvec, 0.0f );
5610 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.uvec, 0.952f );
5611 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.fvec, -1.782f );
5613 camera_set_position( &tmp );
5614 camera_set_orient( &Player_obj->orient );
5615 vector tmp_vel = { 0.0f, 5.1919f, 14.7f };
5617 //mprintf(( "Rad = %.1f\n", Player_obj->radius ));
5618 camera_set_velocity( &tmp_vel, 1);
5622 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE2: // player ship got into the warp effect
5623 if ( Player->control_mode != PCM_WARPOUT_STAGE2 ) {
5624 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5625 mprintf(( "Player put back to normal mode, because of invalid sequence in stage2.\n" ));
5627 mprintf(( "Hit warp effect. Moving to stage 3!\n" ));
5628 Player->control_mode = PCM_WARPOUT_STAGE3;
5632 case GS_EVENT_PLAYER_WARPOUT_DONE: // player ship got through the warp effect
5633 mprintf(( "Player warped out. Going to debriefing!\n" ));
5634 Player->control_mode = PCM_NORMAL;
5635 Viewer_mode = Player->saved_viewer_mode;
5638 // we have a special debriefing screen for multiplayer furballs
5639 if((Game_mode & GM_MULTIPLAYER) && (The_mission.game_type & MISSION_TYPE_MULTI_DOGFIGHT)){
5640 gameseq_post_event(GS_EVENT_MULTI_DOGFIGHT_DEBRIEF);
5642 // do the normal debriefing for all other situations
5644 gameseq_post_event(GS_EVENT_DEBRIEF);
5648 case GS_EVENT_STANDALONE_POSTGAME:
5649 gameseq_set_state(GS_STATE_STANDALONE_POSTGAME);
5652 case GS_EVENT_INITIAL_PLAYER_SELECT:
5653 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5656 case GS_EVENT_GAME_INIT:
5657 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
5658 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5660 // see if the command line option has been set to use the last pilot, and act acoordingly
5661 if( player_select_get_last_pilot() ) {
5662 // always enter the main menu -- do the automatic network startup stuff elsewhere
5663 // so that we still have valid checks for networking modes, etc.
5664 gameseq_set_state(GS_STATE_MAIN_MENU);
5666 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5671 case GS_EVENT_MULTI_MISSION_SYNC:
5672 gameseq_set_state(GS_STATE_MULTI_MISSION_SYNC);
5675 case GS_EVENT_MULTI_START_GAME:
5676 gameseq_set_state(GS_STATE_MULTI_START_GAME);
5679 case GS_EVENT_MULTI_HOST_OPTIONS:
5680 gameseq_set_state(GS_STATE_MULTI_HOST_OPTIONS);
5683 case GS_EVENT_MULTI_DOGFIGHT_DEBRIEF:
5684 gameseq_set_state(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
5687 case GS_EVENT_TEAM_SELECT:
5688 gameseq_set_state(GS_STATE_TEAM_SELECT);
5691 case GS_EVENT_END_CAMPAIGN:
5692 gameseq_set_state(GS_STATE_END_OF_CAMPAIGN);
5695 case GS_EVENT_END_DEMO:
5696 gameseq_set_state(GS_STATE_END_DEMO);
5699 case GS_EVENT_LOOP_BRIEF:
5700 gameseq_set_state(GS_STATE_LOOP_BRIEF);
5709 // Called when a state is being left.
5710 // The current state is still at old_state, but as soon as
5711 // this function leaves, then the current state will become
5712 // new state. You should never try to change the state
5713 // in here... if you think you need to, you probably really
5714 // need to post an event, not change the state.
5715 void game_leave_state( int old_state, int new_state )
5717 int end_mission = 1;
5719 switch (new_state) {
5720 case GS_STATE_GAME_PAUSED:
5721 case GS_STATE_DEBUG_PAUSED:
5722 case GS_STATE_OPTIONS_MENU:
5723 case GS_STATE_CONTROL_CONFIG:
5724 case GS_STATE_MISSION_LOG_SCROLLBACK:
5725 case GS_STATE_DEATH_DIED:
5726 case GS_STATE_SHOW_GOALS:
5727 case GS_STATE_HOTKEY_SCREEN:
5728 case GS_STATE_MULTI_PAUSED:
5729 case GS_STATE_TRAINING_PAUSED:
5730 case GS_STATE_EVENT_DEBUG:
5731 case GS_STATE_GAMEPLAY_HELP:
5732 end_mission = 0; // these events shouldn't end a mission
5736 switch (old_state) {
5737 case GS_STATE_BRIEFING:
5738 brief_stop_voices();
5739 if ( (new_state != GS_STATE_OPTIONS_MENU) && (new_state != GS_STATE_WEAPON_SELECT)
5740 && (new_state != GS_STATE_SHIP_SELECT) && (new_state != GS_STATE_HOTKEY_SCREEN)
5741 && (new_state != GS_STATE_TEAM_SELECT) ){
5742 common_select_close();
5743 if ( new_state == GS_STATE_MAIN_MENU ) {
5744 freespace_stop_mission();
5748 // COMMAND LINE OPTION
5749 if (Cmdline_multi_stream_chat_to_file){
5750 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5751 cfclose(Multi_chat_stream);
5755 case GS_STATE_DEBRIEF:
5756 if ( (new_state != GS_STATE_VIEW_MEDALS) && (new_state != GS_STATE_OPTIONS_MENU) ) {
5761 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
5762 multi_df_debrief_close();
5765 case GS_STATE_LOAD_MISSION_MENU:
5766 mission_load_menu_close();
5769 case GS_STATE_SIMULATOR_ROOM:
5773 case GS_STATE_CAMPAIGN_ROOM:
5774 campaign_room_close();
5777 case GS_STATE_CMD_BRIEF:
5778 if (new_state == GS_STATE_OPTIONS_MENU) {
5783 if (new_state == GS_STATE_MAIN_MENU)
5784 freespace_stop_mission();
5789 case GS_STATE_RED_ALERT:
5793 case GS_STATE_SHIP_SELECT:
5794 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_WEAPON_SELECT &&
5795 new_state != GS_STATE_HOTKEY_SCREEN &&
5796 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5797 common_select_close();
5798 if ( new_state == GS_STATE_MAIN_MENU ) {
5799 freespace_stop_mission();
5804 case GS_STATE_WEAPON_SELECT:
5805 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5806 new_state != GS_STATE_HOTKEY_SCREEN &&
5807 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5808 common_select_close();
5809 if ( new_state == GS_STATE_MAIN_MENU ) {
5810 freespace_stop_mission();
5815 case GS_STATE_TEAM_SELECT:
5816 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5817 new_state != GS_STATE_HOTKEY_SCREEN &&
5818 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_WEAPON_SELECT) {
5819 common_select_close();
5820 if ( new_state == GS_STATE_MAIN_MENU ) {
5821 freespace_stop_mission();
5826 case GS_STATE_MAIN_MENU:
5827 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
5834 case GS_STATE_OPTIONS_MENU:
5835 //game_start_time();
5836 if(new_state == GS_STATE_MULTI_JOIN_GAME){
5837 multi_join_clear_game_list();
5839 options_menu_close();
5842 case GS_STATE_BARRACKS_MENU:
5843 if(new_state != GS_STATE_VIEW_MEDALS){
5848 case GS_STATE_MISSION_LOG_SCROLLBACK:
5849 hud_scrollback_close();
5852 case GS_STATE_TRAINING_MENU:
5853 training_menu_close();
5856 case GS_STATE_GAME_PLAY:
5857 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
5858 player_save_target_and_weapon_link_prefs();
5859 game_stop_looped_sounds();
5862 sound_env_disable();
5863 joy_ff_stop_effects();
5865 // stop game time under certain conditions
5866 if ( end_mission || (Game_mode & GM_NORMAL) || ((Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MULTI_PAUSED)) ){
5871 // shut down any recording or playing demos
5876 // when in multiplayer and going back to the main menu, send a leave game packet
5877 // right away (before calling stop mission). stop_mission was taking to long to
5878 // close mission down and I want people to get notified ASAP.
5879 if ( (Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MAIN_MENU) ){
5880 multi_quit_game(PROMPT_NONE);
5883 freespace_stop_mission();
5884 Game_time_compression = F1_0;
5888 case GS_STATE_TECH_MENU:
5892 case GS_STATE_TRAINING_PAUSED:
5893 Training_num_lines = 0;
5894 // fall through to GS_STATE_GAME_PAUSED
5896 case GS_STATE_GAME_PAUSED:
5898 if ( end_mission ) {
5903 case GS_STATE_DEBUG_PAUSED:
5906 pause_debug_close();
5910 case GS_STATE_HUD_CONFIG:
5914 // join/start a game
5915 case GS_STATE_MULTI_JOIN_GAME:
5916 if(new_state != GS_STATE_OPTIONS_MENU){
5917 multi_join_game_close();
5921 case GS_STATE_MULTI_HOST_SETUP:
5922 case GS_STATE_MULTI_CLIENT_SETUP:
5923 // if this is just the host going into the options screen, don't do anything
5924 if((new_state == GS_STATE_MULTI_HOST_OPTIONS) || (new_state == GS_STATE_OPTIONS_MENU)){
5928 // close down the proper state
5929 if(old_state == GS_STATE_MULTI_HOST_SETUP){
5930 multi_create_game_close();
5932 multi_game_client_setup_close();
5935 // COMMAND LINE OPTION
5936 if (Cmdline_multi_stream_chat_to_file){
5937 if( (new_state != GS_STATE_TEAM_SELECT) && (Multi_chat_stream!=NULL) ) {
5938 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5939 cfclose(Multi_chat_stream);
5944 case GS_STATE_CONTROL_CONFIG:
5945 control_config_close();
5948 case GS_STATE_DEATH_DIED:
5949 Game_mode &= ~GM_DEAD_DIED;
5951 // early end while respawning or blowing up in a multiplayer game
5952 if((Game_mode & GM_MULTIPLAYER) && ((new_state == GS_STATE_DEBRIEF) || (new_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) ){
5954 freespace_stop_mission();
5958 case GS_STATE_DEATH_BLEW_UP:
5959 Game_mode &= ~GM_DEAD_BLEW_UP;
5961 // for single player, we might reload mission, etc. For multiplayer, look at my new state
5962 // to determine if I should do anything.
5963 if ( !(Game_mode & GM_MULTIPLAYER) ) {
5965 freespace_stop_mission();
5968 // if we are not respawing as an observer or as a player, our new state will not
5969 // be gameplay state.
5970 if ( (new_state != GS_STATE_GAME_PLAY) && (new_state != GS_STATE_MULTI_PAUSED) ) {
5971 game_stop_time(); // hasn't been called yet!!
5972 freespace_stop_mission();
5978 case GS_STATE_CREDITS:
5982 case GS_STATE_VIEW_MEDALS:
5986 case GS_STATE_SHOW_GOALS:
5987 mission_show_goals_close();
5990 case GS_STATE_HOTKEY_SCREEN:
5991 if ( new_state != GS_STATE_OPTIONS_MENU ) {
5992 mission_hotkey_close();
5996 case GS_STATE_MULTI_MISSION_SYNC:
5997 // if we're moving into the options menu, don't do anything
5998 if(new_state == GS_STATE_OPTIONS_MENU){
6002 Assert( Game_mode & GM_MULTIPLAYER );
6004 if ( new_state == GS_STATE_GAME_PLAY ){
6005 // palette_restore_palette();
6007 // change a couple of flags to indicate our state!!!
6008 Net_player->state = NETPLAYER_STATE_IN_MISSION;
6009 send_netplayer_update_packet();
6011 // set the game mode
6012 Game_mode |= GM_IN_MISSION;
6016 case GS_STATE_VIEW_CUTSCENES:
6017 cutscenes_screen_close();
6020 case GS_STATE_MULTI_STD_WAIT:
6021 multi_standalone_wait_close();
6024 case GS_STATE_STANDALONE_MAIN:
6025 standalone_main_close();
6026 if(new_state == GS_STATE_MULTI_STD_WAIT){
6027 init_multiplayer_stats();
6031 case GS_STATE_MULTI_PAUSED:
6032 // if ( end_mission ){
6037 case GS_STATE_INGAME_PRE_JOIN:
6038 multi_ingame_select_close();
6041 case GS_STATE_STANDALONE_POSTGAME:
6042 multi_standalone_postgame_close();
6045 case GS_STATE_INITIAL_PLAYER_SELECT:
6046 player_select_close();
6049 case GS_STATE_MULTI_START_GAME:
6050 multi_start_game_close();
6053 case GS_STATE_MULTI_HOST_OPTIONS:
6054 multi_host_options_close();
6057 case GS_STATE_END_OF_CAMPAIGN:
6058 mission_campaign_end_close();
6061 case GS_STATE_LOOP_BRIEF:
6067 // Called when a state is being entered.
6068 // The current state is set to the state we're entering at
6069 // this point, and old_state is set to the state we're coming
6070 // from. You should never try to change the state
6071 // in here... if you think you need to, you probably really
6072 // need to post an event, not change the state.
6074 void game_enter_state( int old_state, int new_state )
6076 switch (new_state) {
6077 case GS_STATE_MAIN_MENU:
6078 // in multiplayer mode, be sure that we are not doing networking anymore.
6079 if ( Game_mode & GM_MULTIPLAYER ) {
6080 Assert( Net_player != NULL );
6081 Net_player->flags &= ~NETINFO_FLAG_DO_NETWORKING;
6084 Game_time_compression = F1_0;
6086 // determine which ship this guy is currently based on
6087 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
6090 if (Player->on_bastion) {
6098 case GS_STATE_BRIEFING:
6099 main_hall_stop_music();
6100 main_hall_stop_ambient();
6102 if (Game_mode & GM_NORMAL) {
6103 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
6104 // MWA: or from options or hotkey screens
6105 // JH: or if the command brief state already did this
6106 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
6107 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT)
6108 && (old_state != GS_STATE_CMD_BRIEF) ) {
6109 if ( !game_start_mission() ) // this should put us into a new state on failure!
6113 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
6114 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
6115 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6117 Game_time_compression = F1_0;
6119 if ( red_alert_mission() ) {
6120 gameseq_post_event(GS_EVENT_RED_ALERT);
6127 case GS_STATE_DEBRIEF:
6128 game_stop_looped_sounds();
6129 mission_goal_fail_incomplete(); // fail all incomplete goals before entering debriefing
6130 if ( (old_state != GS_STATE_VIEW_MEDALS) && (old_state != GS_STATE_OPTIONS_MENU) ){
6135 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6136 multi_df_debrief_init();
6139 case GS_STATE_LOAD_MISSION_MENU:
6140 mission_load_menu_init();
6143 case GS_STATE_SIMULATOR_ROOM:
6147 case GS_STATE_CAMPAIGN_ROOM:
6148 campaign_room_init();
6151 case GS_STATE_RED_ALERT:
6152 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6156 case GS_STATE_CMD_BRIEF: {
6157 int team_num = 0; // team number used as index for which cmd brief to use.
6159 if (old_state == GS_STATE_OPTIONS_MENU) {
6163 main_hall_stop_music();
6164 main_hall_stop_ambient();
6166 if (Game_mode & GM_NORMAL) {
6167 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
6168 // MWA: or from options or hotkey screens
6169 // JH: or if the command brief state already did this
6170 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
6171 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT) ) {
6172 if ( !game_start_mission() ) // this should put us into a new state on failure!
6177 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
6178 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
6179 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6181 cmd_brief_init(team_num);
6187 case GS_STATE_SHIP_SELECT:
6191 case GS_STATE_WEAPON_SELECT:
6192 weapon_select_init();
6195 case GS_STATE_TEAM_SELECT:
6199 case GS_STATE_GAME_PAUSED:
6204 case GS_STATE_DEBUG_PAUSED:
6205 // game_stop_time();
6206 // os_set_title("FreeSpace - PAUSED");
6209 case GS_STATE_TRAINING_PAUSED:
6216 case GS_STATE_OPTIONS_MENU:
6218 options_menu_init();
6221 case GS_STATE_GAME_PLAY:
6222 // coming from the gameplay state or the main menu, we might need to load the mission
6223 if ( (Game_mode & GM_NORMAL) && ((old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_GAME_PLAY) || (old_state == GS_STATE_DEATH_BLEW_UP)) ) {
6224 if ( !game_start_mission() ) // this should put us into a new state.
6229 // if we are coming from the briefing, ship select, weapons loadout, or main menu (in the
6230 // case of quick start), then do bitmap loads, etc Don't do any of the loading stuff
6231 // if we are in multiplayer -- this stuff is all handled in the multi-wait section
6232 if ( !(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_BRIEFING) || (old_state == GS_STATE_SHIP_SELECT) ||
6233 (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) ) {
6234 // JAS: Used to do all paging here.
6238 HUD_printf("Skill level is set to ** %s **", Skill_level_names(Game_skill_level));
6242 main_hall_stop_music();
6243 main_hall_stop_ambient();
6244 event_music_first_pattern(); // start the first pattern
6247 // special code that restores player ship selection and weapons loadout when doing a quick start
6248 if ( !(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_DEATH_BLEW_UP) || (old_state == GS_STATE_GAME_PLAY) ) {
6249 if ( !stricmp(Player_loadout.filename, Game_current_mission_filename) ) {
6250 wss_direct_restore_loadout();
6254 // single-player, quick-start after just died... we need to set weapon linking and kick off the event music
6255 if (!(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_DEATH_BLEW_UP) ) {
6256 event_music_first_pattern(); // start the first pattern
6259 if ( !(Game_mode & GM_STANDALONE_SERVER) && (old_state != GS_STATE_GAME_PAUSED) && (old_state != GS_STATE_MULTI_PAUSED) ) {
6260 event_music_first_pattern(); // start the first pattern
6262 player_restore_target_and_weapon_link_prefs();
6264 Game_mode |= GM_IN_MISSION;
6267 // required to truely make mouse deltas zeroed in debug mouse code
6268 void mouse_force_pos(int x, int y);
6269 if (!Is_standalone) {
6270 mouse_force_pos(gr_screen.max_w / 2, gr_screen.max_h / 2);
6276 // only start time if in single player, or coming from multi wait state
6279 (Game_mode & GM_NORMAL) &&
6280 (old_state != GS_STATE_VIEW_CUTSCENES)
6282 (Game_mode & GM_MULTIPLAYER) && (
6283 (old_state == GS_STATE_MULTI_PAUSED) ||
6284 (old_state == GS_STATE_MULTI_MISSION_SYNC)
6290 // when coming from the multi paused state, reset the timestamps
6291 if ( (Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_MULTI_PAUSED) ){
6292 multi_reset_timestamps();
6295 if ((Game_mode & GM_MULTIPLAYER) && (old_state != GS_STATE_DEATH_BLEW_UP) ) {
6296 // initialize all object update details
6297 multi_oo_gameplay_init();
6300 // under certain circumstances, the server should reset the object update rate limiting stuff
6301 if( ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)) &&
6302 (old_state == GS_STATE_MULTI_PAUSED) || (old_state == GS_STATE_MULTI_MISSION_SYNC) ){
6304 // reinitialize the rate limiting system for all clients
6305 multi_oo_rate_init_all();
6308 // multiplayer clients should always re-initialize their control info rate limiting system
6309 if((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)){
6310 multi_oo_rate_init_all();
6314 if(Game_mode & GM_MULTIPLAYER){
6315 multi_ping_reset_players();
6318 Game_subspace_effect = 0;
6319 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
6320 Game_subspace_effect = 1;
6321 if( !(Game_mode & GM_STANDALONE_SERVER) ){
6322 game_start_subspace_ambient_sound();
6326 sound_env_set(&Game_sound_env);
6327 joy_ff_mission_init(Ship_info[Player_ship->ship_info_index].rotation_time);
6329 // clear multiplayer button info i
6330 extern button_info Multi_ship_status_bi;
6331 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
6334 case GS_STATE_HUD_CONFIG:
6338 case GS_STATE_MULTI_JOIN_GAME:
6339 multi_join_clear_game_list();
6341 if (old_state != GS_STATE_OPTIONS_MENU) {
6342 multi_join_game_init();
6347 case GS_STATE_MULTI_HOST_SETUP:
6348 // don't reinitialize if we're coming back from the host options screen
6349 if ((old_state != GS_STATE_MULTI_HOST_OPTIONS) && (old_state != GS_STATE_OPTIONS_MENU)) {
6350 multi_create_game_init();
6355 case GS_STATE_MULTI_CLIENT_SETUP:
6356 if (old_state != GS_STATE_OPTIONS_MENU) {
6357 multi_game_client_setup_init();
6362 case GS_STATE_CONTROL_CONFIG:
6363 control_config_init();
6366 case GS_STATE_TECH_MENU:
6370 case GS_STATE_BARRACKS_MENU:
6371 if(old_state != GS_STATE_VIEW_MEDALS){
6376 case GS_STATE_MISSION_LOG_SCROLLBACK:
6377 hud_scrollback_init();
6380 case GS_STATE_DEATH_DIED:
6381 Player_died_time = timestamp(10);
6383 if(!(Game_mode & GM_MULTIPLAYER)){
6384 player_show_death_message();
6386 Game_mode |= GM_DEAD_DIED;
6389 case GS_STATE_DEATH_BLEW_UP:
6390 if ( !popupdead_is_active() ) {
6391 Player_ai->target_objnum = -1;
6394 // stop any local EMP effect
6397 Players[Player_num].flags &= ~PLAYER_FLAGS_AUTO_TARGETING; // Prevent immediate switch to a hostile ship.
6398 Game_mode |= GM_DEAD_BLEW_UP;
6399 Show_viewing_from_self = 0;
6401 // timestamp how long we should wait before displaying the died popup
6402 if ( !popupdead_is_active() ) {
6403 Player_died_popup_wait = timestamp(PLAYER_DIED_POPUP_WAIT);
6407 case GS_STATE_GAMEPLAY_HELP:
6408 gameplay_help_init();
6411 case GS_STATE_CREDITS:
6412 main_hall_stop_music();
6413 main_hall_stop_ambient();
6417 case GS_STATE_VIEW_MEDALS:
6418 medal_main_init(Player);
6421 case GS_STATE_SHOW_GOALS:
6422 mission_show_goals_init();
6425 case GS_STATE_HOTKEY_SCREEN:
6426 mission_hotkey_init();
6429 case GS_STATE_MULTI_MISSION_SYNC:
6430 // if we're coming from the options screen, don't do any
6431 if(old_state == GS_STATE_OPTIONS_MENU){
6435 switch(Multi_sync_mode){
6436 case MULTI_SYNC_PRE_BRIEFING:
6437 // if moving from game forming to the team select state
6440 case MULTI_SYNC_POST_BRIEFING:
6441 // if moving from briefing into the mission itself
6444 // tell everyone that we're now loading data
6445 Net_player->state = NETPLAYER_STATE_DATA_LOAD;
6446 send_netplayer_update_packet();
6448 // JAS: Used to do all paging here!!!!
6450 Net_player->state = NETPLAYER_STATE_WAITING;
6451 send_netplayer_update_packet();
6453 Game_time_compression = F1_0;
6455 case MULTI_SYNC_INGAME:
6461 case GS_STATE_VIEW_CUTSCENES:
6462 cutscenes_screen_init();
6465 case GS_STATE_MULTI_STD_WAIT:
6466 multi_standalone_wait_init();
6469 case GS_STATE_STANDALONE_MAIN:
6470 // don't initialize if we're coming from one of these 2 states unless there are no
6471 // players left (reset situation)
6472 if((old_state != GS_STATE_STANDALONE_POSTGAME) || multi_endgame_ending()){
6473 standalone_main_init();
6477 case GS_STATE_MULTI_PAUSED:
6481 case GS_STATE_INGAME_PRE_JOIN:
6482 multi_ingame_select_init();
6485 case GS_STATE_STANDALONE_POSTGAME:
6486 multi_standalone_postgame_init();
6489 case GS_STATE_INITIAL_PLAYER_SELECT:
6490 player_select_init();
6493 case GS_STATE_MULTI_START_GAME:
6494 multi_start_game_init();
6497 case GS_STATE_MULTI_HOST_OPTIONS:
6498 multi_host_options_init();
6501 case GS_STATE_END_OF_CAMPAIGN:
6502 mission_campaign_end_init();
6505 case GS_STATE_LOOP_BRIEF:
6512 // do stuff that may need to be done regardless of state
6513 void game_do_state_common(int state,int no_networking)
6515 game_maybe_draw_mouse(flFrametime); // determine if to draw the mouse this frame
6516 snd_do_frame(); // update sound system
6517 event_music_do_frame(); // music needs to play across many states
6519 multi_log_process();
6521 if (no_networking) {
6525 // maybe do a multiplayer frame based on game mode and state type
6526 if (Game_mode & GM_MULTIPLAYER) {
6528 case GS_STATE_OPTIONS_MENU:
6529 case GS_STATE_GAMEPLAY_HELP:
6530 case GS_STATE_HOTKEY_SCREEN:
6531 case GS_STATE_HUD_CONFIG:
6532 case GS_STATE_CONTROL_CONFIG:
6533 case GS_STATE_MISSION_LOG_SCROLLBACK:
6534 case GS_STATE_SHOW_GOALS:
6535 case GS_STATE_VIEW_CUTSCENES:
6536 case GS_STATE_EVENT_DEBUG:
6537 multi_maybe_do_frame();
6541 game_do_networking();
6545 // Called once a frame.
6546 // You should never try to change the state
6547 // in here... if you think you need to, you probably really
6548 // need to post an event, not change the state.
6549 int Game_do_state_should_skip = 0;
6550 void game_do_state(int state)
6552 // always lets the do_state_common() function determine if the state should be skipped
6553 Game_do_state_should_skip = 0;
6555 // legal to set the should skip state anywhere in this function
6556 game_do_state_common(state); // do stuff that may need to be done regardless of state
6558 if(Game_do_state_should_skip){
6563 case GS_STATE_MAIN_MENU:
6564 game_set_frametime(GS_STATE_MAIN_MENU);
6565 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
6568 main_hall_do(flFrametime);
6572 case GS_STATE_OPTIONS_MENU:
6573 game_set_frametime(GS_STATE_OPTIONS_MENU);
6574 options_menu_do_frame(flFrametime);
6577 case GS_STATE_BARRACKS_MENU:
6578 game_set_frametime(GS_STATE_BARRACKS_MENU);
6579 barracks_do_frame(flFrametime);
6582 case GS_STATE_TRAINING_MENU:
6583 game_set_frametime(GS_STATE_TRAINING_MENU);
6584 training_menu_do_frame(flFrametime);
6587 case GS_STATE_TECH_MENU:
6588 game_set_frametime(GS_STATE_TECH_MENU);
6589 techroom_do_frame(flFrametime);
6592 case GS_STATE_GAMEPLAY_HELP:
6593 game_set_frametime(GS_STATE_GAMEPLAY_HELP);
6594 gameplay_help_do_frame(flFrametime);
6597 case GS_STATE_GAME_PLAY: // do stuff that should be done during gameplay
6601 case GS_STATE_GAME_PAUSED:
6605 case GS_STATE_DEBUG_PAUSED:
6607 game_set_frametime(GS_STATE_DEBUG_PAUSED);
6612 case GS_STATE_TRAINING_PAUSED:
6613 game_training_pause_do();
6616 case GS_STATE_LOAD_MISSION_MENU:
6617 game_set_frametime(GS_STATE_LOAD_MISSION_MENU);
6618 mission_load_menu_do();
6621 case GS_STATE_BRIEFING:
6622 game_set_frametime(GS_STATE_BRIEFING);
6623 brief_do_frame(flFrametime);
6626 case GS_STATE_DEBRIEF:
6627 game_set_frametime(GS_STATE_DEBRIEF);
6628 debrief_do_frame(flFrametime);
6631 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6632 game_set_frametime(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
6633 multi_df_debrief_do();
6636 case GS_STATE_SHIP_SELECT:
6637 game_set_frametime(GS_STATE_SHIP_SELECT);
6638 ship_select_do(flFrametime);
6641 case GS_STATE_WEAPON_SELECT:
6642 game_set_frametime(GS_STATE_WEAPON_SELECT);
6643 weapon_select_do(flFrametime);
6646 case GS_STATE_MISSION_LOG_SCROLLBACK:
6647 game_set_frametime(GS_STATE_MISSION_LOG_SCROLLBACK);
6648 hud_scrollback_do_frame(flFrametime);
6651 case GS_STATE_HUD_CONFIG:
6652 game_set_frametime(GS_STATE_HUD_CONFIG);
6653 hud_config_do_frame(flFrametime);
6656 case GS_STATE_MULTI_JOIN_GAME:
6657 game_set_frametime(GS_STATE_MULTI_JOIN_GAME);
6658 multi_join_game_do_frame();
6661 case GS_STATE_MULTI_HOST_SETUP:
6662 game_set_frametime(GS_STATE_MULTI_HOST_SETUP);
6663 multi_create_game_do();
6666 case GS_STATE_MULTI_CLIENT_SETUP:
6667 game_set_frametime(GS_STATE_MULTI_CLIENT_SETUP);
6668 multi_game_client_setup_do_frame();
6671 case GS_STATE_CONTROL_CONFIG:
6672 game_set_frametime(GS_STATE_CONTROL_CONFIG);
6673 control_config_do_frame(flFrametime);
6676 case GS_STATE_DEATH_DIED:
6680 case GS_STATE_DEATH_BLEW_UP:
6684 case GS_STATE_SIMULATOR_ROOM:
6685 game_set_frametime(GS_STATE_SIMULATOR_ROOM);
6686 sim_room_do_frame(flFrametime);
6689 case GS_STATE_CAMPAIGN_ROOM:
6690 game_set_frametime(GS_STATE_CAMPAIGN_ROOM);
6691 campaign_room_do_frame(flFrametime);
6694 case GS_STATE_RED_ALERT:
6695 game_set_frametime(GS_STATE_RED_ALERT);
6696 red_alert_do_frame(flFrametime);
6699 case GS_STATE_CMD_BRIEF:
6700 game_set_frametime(GS_STATE_CMD_BRIEF);
6701 cmd_brief_do_frame(flFrametime);
6704 case GS_STATE_CREDITS:
6705 game_set_frametime(GS_STATE_CREDITS);
6706 credits_do_frame(flFrametime);
6709 case GS_STATE_VIEW_MEDALS:
6710 game_set_frametime(GS_STATE_VIEW_MEDALS);
6714 case GS_STATE_SHOW_GOALS:
6715 game_set_frametime(GS_STATE_SHOW_GOALS);
6716 mission_show_goals_do_frame(flFrametime);
6719 case GS_STATE_HOTKEY_SCREEN:
6720 game_set_frametime(GS_STATE_HOTKEY_SCREEN);
6721 mission_hotkey_do_frame(flFrametime);
6724 case GS_STATE_VIEW_CUTSCENES:
6725 game_set_frametime(GS_STATE_VIEW_CUTSCENES);
6726 cutscenes_screen_do_frame();
6729 case GS_STATE_MULTI_STD_WAIT:
6730 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6731 multi_standalone_wait_do();
6734 case GS_STATE_STANDALONE_MAIN:
6735 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6736 standalone_main_do();
6739 case GS_STATE_MULTI_PAUSED:
6740 game_set_frametime(GS_STATE_MULTI_PAUSED);
6744 case GS_STATE_TEAM_SELECT:
6745 game_set_frametime(GS_STATE_TEAM_SELECT);
6749 case GS_STATE_INGAME_PRE_JOIN:
6750 game_set_frametime(GS_STATE_INGAME_PRE_JOIN);
6751 multi_ingame_select_do();
6754 case GS_STATE_EVENT_DEBUG:
6756 game_set_frametime(GS_STATE_EVENT_DEBUG);
6757 game_show_event_debug(flFrametime);
6761 case GS_STATE_STANDALONE_POSTGAME:
6762 game_set_frametime(GS_STATE_STANDALONE_POSTGAME);
6763 multi_standalone_postgame_do();
6766 case GS_STATE_INITIAL_PLAYER_SELECT:
6767 game_set_frametime(GS_STATE_INITIAL_PLAYER_SELECT);
6771 case GS_STATE_MULTI_MISSION_SYNC:
6772 game_set_frametime(GS_STATE_MULTI_MISSION_SYNC);
6776 case GS_STATE_MULTI_START_GAME:
6777 game_set_frametime(GS_STATE_MULTI_START_GAME);
6778 multi_start_game_do();
6781 case GS_STATE_MULTI_HOST_OPTIONS:
6782 game_set_frametime(GS_STATE_MULTI_HOST_OPTIONS);
6783 multi_host_options_do();
6786 case GS_STATE_END_OF_CAMPAIGN:
6787 mission_campaign_end_do();
6790 case GS_STATE_END_DEMO:
6791 game_set_frametime(GS_STATE_END_DEMO);
6792 end_demo_campaign_do();
6795 case GS_STATE_LOOP_BRIEF:
6796 game_set_frametime(GS_STATE_LOOP_BRIEF);
6800 } // end switch(gs_current_state)
6804 // return 0 if there is enough RAM to run FreeSpace, otherwise return -1
6805 int game_do_ram_check(int ram_in_bytes)
6807 if ( ram_in_bytes < 30*1024*1024 ) {
6808 int allowed_to_run = 1;
6809 if ( ram_in_bytes < 25*1024*1024 ) {
6814 int Freespace_total_ram_MB;
6815 Freespace_total_ram_MB = fl2i(ram_in_bytes/(1024*1024));
6817 if ( allowed_to_run ) {
6819 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), Freespace_total_ram_MB, Freespace_total_ram_MB);
6824 msgbox_rval = MessageBox( NULL, tmp, XSTR( "Not Enough RAM", 194), MB_OKCANCEL );
6825 if ( msgbox_rval == IDCANCEL ) {
6832 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), Freespace_total_ram_MB, Freespace_total_ram_MB);
6834 MessageBox( NULL, tmp, XSTR( "Not Enough RAM", 194), MB_OK );
6845 // Check if there is a freespace.exe in the /update directory (relative to where fs.exe is installed).
6846 // If so, copy it over and remove the update directory.
6847 void game_maybe_update_launcher(char *exe_dir)
6850 char src_filename[MAX_PATH];
6851 char dest_filename[MAX_PATH];
6853 strcpy(src_filename, exe_dir);
6854 strcat(src_filename, NOX("\\update\\freespace.exe"));
6856 strcpy(dest_filename, exe_dir);
6857 strcat(dest_filename, NOX("\\freespace.exe"));
6859 // see if src_filename exists
6861 fp = fopen(src_filename, "rb");
6867 SetFileAttributes(dest_filename, FILE_ATTRIBUTE_NORMAL);
6869 // copy updated freespace.exe to freespace exe dir
6870 if ( CopyFile(src_filename, dest_filename, 0) == 0 ) {
6871 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 );
6875 // delete the file in the update directory
6876 DeleteFile(src_filename);
6878 // safe to assume directory is empty, since freespace.exe should only be the file ever in the update dir
6879 char update_dir[MAX_PATH];
6880 strcpy(update_dir, exe_dir);
6881 strcat(update_dir, NOX("\\update"));
6882 RemoveDirectory(update_dir);
6888 void game_spew_pof_info_sub(int model_num, polymodel *pm, int sm, CFILE *out, int *out_total, int *out_destroyed_total)
6892 int sub_total_destroyed = 0;
6896 // get the total for all his children
6897 for (i=pm->submodel[sm].first_child; i>-1; i = pm->submodel[i].next_sibling ) {
6898 game_spew_pof_info_sub(model_num, pm, i, out, &sub_total, &sub_total_destroyed);
6901 // find the # of faces for this _individual_ object
6902 total = submodel_get_num_polys(model_num, sm);
6903 if(strstr(pm->submodel[sm].name, "-destroyed")){
6904 sub_total_destroyed = total;
6908 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[sm].name, total);
6911 *out_total += total + sub_total;
6912 *out_destroyed_total += sub_total_destroyed;
6915 #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);
6916 void game_spew_pof_info()
6918 char *pof_list[1000];
6921 int idx, model_num, i, j;
6923 int total, root_total, model_total, destroyed_total, counted;
6927 num_files = cf_get_file_list(1000, pof_list, CF_TYPE_MODELS, "*.pof");
6929 // spew info on all the pofs
6935 out = cfopen("pofspew.txt", "wt", CFILE_NORMAL, CF_TYPE_DATA);
6940 for(idx=0; idx<num_files; idx++, counted++){
6941 sprintf(str, "%s.pof", pof_list[idx]);
6942 model_num = model_load(str, 0, NULL);
6944 pm = model_get(model_num);
6946 // if we have a real model
6951 // go through and print all raw submodels
6952 cfputs("RAW\n", out);
6955 for (i=0; i<pm->n_models; i++) {
6956 total = submodel_get_num_polys(model_num, i);
6958 model_total += total;
6959 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[i].name, total);
6962 sprintf(str, "Model total %d\n", model_total);
6965 // now go through and do it by LOD
6966 cfputs("BY LOD\n\n", out);
6967 for(i=0; i<pm->n_detail_levels; i++){
6968 sprintf(str, "LOD %d\n", i);
6972 root_total = submodel_get_num_polys(model_num, pm->detail[i] );
6974 destroyed_total = 0;
6975 for (j=pm->submodel[pm->detail[i]].first_child; j>-1; j = pm->submodel[j].next_sibling ) {
6976 game_spew_pof_info_sub(model_num, pm, j, out, &total, &destroyed_total);
6979 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[pm->detail[i]].name, root_total);
6982 sprintf(str, "TOTAL: %d\n", total + root_total);
6984 sprintf(str, "TOTAL not counting destroyed faces %d\n", (total + root_total) - destroyed_total);
6986 sprintf(str, "TOTAL destroyed faces %d\n\n", destroyed_total);
6989 cfputs("------------------------------------------------------------------------\n\n", out);
6993 if(counted >= MAX_POLYGON_MODELS - 5){
7006 game_spew_pof_info();
7009 int PASCAL WinMainSub(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
7014 // Don't let more than one instance of Freespace run.
7015 HWND hwnd = FindWindow( NOX( "FreeSpaceClass" ), NULL );
7017 SetForegroundWindow(hwnd);
7022 // Find out how much RAM is on this machine
7025 ms.dwLength = sizeof(MEMORYSTATUS);
7026 GlobalMemoryStatus(&ms);
7027 Freespace_total_ram = ms.dwTotalPhys;
7029 if ( game_do_ram_check(Freespace_total_ram) == -1 ) {
7033 if ( ms.dwTotalVirtual < 1024 ) {
7034 MessageBox( NULL, XSTR( "FreeSpace requires virtual memory to run.\r\n", 196), XSTR( "No Virtual Memory", 197), MB_OK );
7038 if (!vm_init(24*1024*1024)) {
7039 MessageBox( NULL, XSTR( "Not enough memory to run Freespace.\r\nTry closing down some other applications.\r\n", 198), XSTR( "Not Enough Memory", 199), MB_OK );
7043 char *tmp_mem = (char *) malloc(16 * 1024 * 1024);
7045 MessageBox(NULL, XSTR( "Not enough memory to run Freespace.\r\nTry closing down some other applications.\r\n", 198), XSTR( "Not Enough Memory", 199), MB_OK);
7053 /* this code doesn't work, and we will hit an error about being unable to load the direct draw
7054 dll before we get here anyway if it's not installed (unless we load it manually, which doesn't
7055 seem worth bothering with.
7059 lResult = RegOpenKeyEx(
7060 HKEY_LOCAL_MACHINE, // Where it is
7061 "Software\\Microsoft\\DirectX", // name of key
7062 NULL, // DWORD reserved
7063 KEY_QUERY_VALUE, // Allows all changes
7064 &hKey // Location to store key
7067 if (lResult == ERROR_SUCCESS) {
7069 DWORD dwType, dwLen;
7072 lResult = RegQueryValueEx(
7073 hKey, // Handle to key
7074 "Version", // The values name
7075 NULL, // DWORD reserved
7076 &dwType, // What kind it is
7077 (ubyte *) version, // value to set
7078 &dwLen // How many bytes to set
7081 if (lResult == ERROR_SUCCESS) {
7082 dx_version = atoi(strstr(version, ".") + 1);
7086 DWORD dwType, dwLen;
7089 lResult = RegQueryValueEx(
7090 hKey, // Handle to key
7091 "InstalledVersion", // The values name
7092 NULL, // DWORD reserved
7093 &dwType, // What kind it is
7094 (ubyte *) &val, // value to set
7095 &dwLen // How many bytes to set
7098 if (lResult == ERROR_SUCCESS) {
7106 if (dx_version < 3) {
7107 MessageBox(NULL, "DirectX 3.0 or higher is required and wasn't detected. You can get the\n"
7108 "latest version of DirectX at:\n\n"
7109 "http://www.microsoft.com/msdownload/directx/dxf/enduser5.0/default.htm", "DirectX required", MB_OK);
7111 MessageBox(NULL, "DirectX 3.0 or higher is required and wasn't detected. You can install\n"
7112 "DirectX 5.2 by pressing the 'Install DirectX' button on the FreeSpace Launcher", "DirectX required", MB_OK);
7117 //=====================================================
7118 // Make sure we're running in the right directory.
7122 if ( GetModuleFileName( hInst, exe_dir, 1023 ) > 0 ) {
7123 char *p = exe_dir + strlen(exe_dir);
7125 // chop off the filename
7126 while( (p>exe_dir) && (*p!='\\') && (*p!='/') && (*p!=':') ) {
7132 if ( strlen(exe_dir) > 0 ) {
7133 SetCurrentDirectory(exe_dir);
7136 // check for updated freespace.exe
7137 game_maybe_update_launcher(exe_dir);
7145 extern void windebug_memwatch_init();
7146 windebug_memwatch_init();
7150 parse_cmdline(szCmdLine);
7152 #ifdef STANDALONE_ONLY_BUILD
7154 nprintf(("Network", "Standalone running"));
7157 nprintf(("Network", "Standalone running"));
7165 // maybe spew pof stuff
7166 if(Cmdline_spew_pof_info){
7167 game_spew_pof_info();
7172 // non-demo, non-standalone, play the intro movie
7178 // to avoid crashes on debug build
7179 for (i=0; i<5; i++) {
7183 if( (cf_get_file_list(2, plist, CF_TYPE_MULTI_PLAYERS, NOX("*.plr")) <= 0) && (cf_get_file_list(2, plist, CF_TYPE_SINGLE_PLAYERS, NOX("*.plr")) <= 0) ){
7185 #if defined(OEM_BUILD)
7186 game_do_cd_check_specific(FS_CDROM_VOLUME_1, 1);
7188 game_do_cd_check_specific(FS_CDROM_VOLUME_2, 2);
7189 #endif // defined(OEM_BUILD)
7192 for (int i=0; i<5; i++) {
7193 if (plist[i] != NULL) {
7198 #endif // RELEASE_REAL
7201 if ( !Is_standalone ) {
7203 // release -- movies always play
7206 // 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
7207 movie_play( NOX("intro.mve"), 0 );
7209 // debug version, movie will only play with -showmovies
7210 #elif !defined(NDEBUG)
7212 movie_play( NOX("intro.mve"), 0);
7215 if ( Cmdline_show_movies )
7216 movie_play( NOX("intro.mve"), 0 );
7225 gameseq_post_event(GS_EVENT_STANDALONE_MAIN);
7227 gameseq_post_event(GS_EVENT_GAME_INIT); // start the game rolling -- check for default pilot, or go to the pilot select screen
7231 // only important for non THREADED mode
7234 state = gameseq_process_events();
7235 if ( state == GS_STATE_QUIT_GAME ){
7240 #if defined(FS2_DEMO) || defined(FS1_DEMO)
7242 demo_upsell_show_screens();
7244 #elif defined(OEM_BUILD)
7245 // show upsell screens on exit
7246 oem_upsell_show_screens();
7253 int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
7259 result = WinMainSub(hInst, hPrev, szCmdLine, nCmdShow);
7261 __except(RecordExceptionInfo(GetExceptionInformation(), "Freespace 2 Main Thread"))
7263 // Do nothing here - RecordExceptionInfo() has already done
7264 // everything that is needed. Actually this code won't even
7265 // get called unless you return EXCEPTION_EXECUTE_HANDLER from
7266 // the __except clause.
7270 nprintf(("WinMain", "exceptions shall fall through"));
7272 result = WinMainSub(hInst, hPrev, szCmdLine, nCmdShow);
7278 // launcher the fslauncher program on exit
7279 void game_launch_launcher_on_exit()
7283 PROCESS_INFORMATION pi;
7284 char cmd_line[2048];
7285 char original_path[1024] = "";
7287 memset( &si, 0, sizeof(STARTUPINFO) );
7291 _getcwd(original_path, 1023);
7293 // set up command line
7294 strcpy(cmd_line, original_path);
7295 strcat(cmd_line, "\\");
7296 strcat(cmd_line, LAUNCHER_FNAME);
7297 strcat(cmd_line, " -straight_to_update");
7299 BOOL ret = CreateProcess( NULL, // pointer to name of executable module
7300 cmd_line, // pointer to command line string
7301 NULL, // pointer to process security attributes
7302 NULL, // pointer to thread security attributes
7303 FALSE, // handle inheritance flag
7304 CREATE_DEFAULT_ERROR_MODE, // creation flags
7305 NULL, // pointer to new environment block
7306 NULL, // pointer to current directory name
7307 &si, // pointer to STARTUPINFO
7308 &pi // pointer to PROCESS_INFORMATION
7310 // to eliminate build warnings
7320 // This function is called when FreeSpace terminates normally.
7322 void game_shutdown(void)
7328 // don't ever flip a page on the standalone!
7329 if(!(Game_mode & GM_STANDALONE_SERVER)){
7335 // if the player has left the "player select" screen and quit the game without actually choosing
7336 // a player, Player will be NULL, in which case we shouldn't write the player file out!
7337 if (!(Game_mode & GM_STANDALONE_SERVER) && (Player!=NULL) && !Is_standalone){
7341 // load up common multiplayer icons
7342 multi_unload_common_icons();
7344 shockwave_close(); // release any memory used by shockwave system
7345 fireball_close(); // free fireball system
7346 ship_close(); // free any memory that was allocated for the ships
7347 weapon_close(); // free any memory that was allocated for the weapons
7348 hud_free_scrollback_list();// free space allocated to store hud messages in hud scrollback
7349 unload_animating_pointer();// frees the frames used for the animating mouse pointer
7350 bm_unload_all(); // free bitmaps
7351 mission_campaign_close(); // close out the campaign stuff
7352 mission_campaign_shutdown(); // get anything that mission_campaign_close can't do
7353 multi_voice_close(); // close down multiplayer voice (including freeing buffers, etc)
7355 #ifdef MULTI_USE_LAG
7359 // the menu close functions will unload the bitmaps if they were displayed during the game
7360 #if !defined(PRESS_TOUR_BUILD) && !defined(PD_BUILD)
7363 context_help_close(); // close out help system
7364 training_menu_close();
7365 lcl_close(); // be sure localization is closed out
7368 // free left-over memory from parsed tables
7369 cutscene_tbl_close();
7371 scoring_tbl_close();
7372 player_tips_close();
7374 extern void joy_close();
7377 audiostream_close();
7379 event_music_close();
7383 // HACKITY HACK HACK
7384 // if this flag is set, we should be firing up the launcher when exiting freespace
7385 extern int Multi_update_fireup_launcher_on_exit;
7386 if(Multi_update_fireup_launcher_on_exit){
7387 game_launch_launcher_on_exit();
7391 // game_stop_looped_sounds()
7393 // This function will call the appropriate stop looped sound functions for those
7394 // modules which use looping sounds. It is not enough just to stop a looping sound
7395 // at the DirectSound level, the game is keeping track of looping sounds, and this
7396 // function is used to inform the game that looping sounds are being halted.
7398 void game_stop_looped_sounds()
7400 hud_stop_looped_locking_sounds();
7401 hud_stop_looped_engine_sounds();
7402 afterburner_stop_sounds();
7403 player_stop_looped_sounds();
7404 obj_snd_stop_all(); // stop all object-linked persistant sounds
7405 game_stop_subspace_ambient_sound();
7406 snd_stop(Radar_static_looping);
7407 Radar_static_looping = -1;
7408 snd_stop(Target_static_looping);
7409 shipfx_stop_engine_wash_sound();
7410 Target_static_looping = -1;
7413 //////////////////////////////////////////////////////////////////////////
7415 // Code for supporting an animating mouse pointer
7418 //////////////////////////////////////////////////////////////////////////
7420 typedef struct animating_obj
7429 static animating_obj Animating_mouse;
7431 // ----------------------------------------------------------------------------
7432 // init_animating_pointer()
7434 // Called by load_animating_pointer() to ensure the Animating_mouse struct
7435 // gets properly initialized
7437 void init_animating_pointer()
7439 Animating_mouse.first_frame = -1;
7440 Animating_mouse.num_frames = 0;
7441 Animating_mouse.current_frame = -1;
7442 Animating_mouse.time = 0.0f;
7443 Animating_mouse.elapsed_time = 0.0f;
7446 // ----------------------------------------------------------------------------
7447 // load_animating_pointer()
7449 // Called at game init to load in the frames for the animating mouse pointer
7451 // input: filename => filename of animation file that holds the animation
7453 void load_animating_pointer(char *filename, int dx, int dy)
7458 init_animating_pointer();
7460 am = &Animating_mouse;
7461 am->first_frame = bm_load_animation(filename, &am->num_frames, &fps);
7462 if ( am->first_frame == -1 )
7463 Error(LOCATION, "Could not load animation %s for the mouse pointer\n", filename);
7464 am->current_frame = 0;
7465 am->time = am->num_frames / i2fl(fps);
7468 // ----------------------------------------------------------------------------
7469 // unload_animating_pointer()
7471 // Called at game shutdown to free the memory used to store the animation frames
7473 void unload_animating_pointer()
7478 am = &Animating_mouse;
7479 for ( i = 0; i < am->num_frames; i++ ) {
7480 Assert( (am->first_frame+i) >= 0 );
7481 bm_release(am->first_frame + i);
7484 am->first_frame = -1;
7486 am->current_frame = -1;
7489 // draw the correct frame of the game mouse... called from game_maybe_draw_mouse()
7490 void game_render_mouse(float frametime)
7495 // if animating cursor exists, play the next frame
7496 am = &Animating_mouse;
7497 if ( am->first_frame != -1 ) {
7498 mouse_get_pos(&mx, &my);
7499 am->elapsed_time += frametime;
7500 am->current_frame = fl2i( ( am->elapsed_time / am->time ) * (am->num_frames-1) );
7501 if ( am->current_frame >= am->num_frames ) {
7502 am->current_frame = 0;
7503 am->elapsed_time = 0.0f;
7505 gr_set_cursor_bitmap(am->first_frame + am->current_frame);
7509 // ----------------------------------------------------------------------------
7510 // game_maybe_draw_mouse()
7512 // determines whether to draw the mouse pointer at all, and what frame of
7513 // animation to use if the mouse is animating
7515 // Sets mouse.cpp globals Mouse_hidden and Mouse_moved based on the state of the game.
7517 // input: frametime => elapsed frame time in seconds since last call
7519 void game_maybe_draw_mouse(float frametime)
7523 game_state = gameseq_get_state();
7525 switch ( game_state ) {
7526 case GS_STATE_GAME_PAUSED:
7527 // case GS_STATE_MULTI_PAUSED:
7528 case GS_STATE_GAME_PLAY:
7529 case GS_STATE_DEATH_DIED:
7530 case GS_STATE_DEATH_BLEW_UP:
7531 if ( popup_active() || popupdead_is_active() ) {
7543 if ( !Mouse_hidden )
7544 game_render_mouse(frametime);
7548 void game_do_training_checks()
7552 waypoint_list *wplp;
7554 if (Training_context & TRAINING_CONTEXT_SPEED) {
7555 s = (int) Player_obj->phys_info.fspeed;
7556 if ((s >= Training_context_speed_min) && (s <= Training_context_speed_max)) {
7557 if (!Training_context_speed_set) {
7558 Training_context_speed_set = 1;
7559 Training_context_speed_timestamp = timestamp();
7563 Training_context_speed_set = 0;
7566 if (Training_context & TRAINING_CONTEXT_FLY_PATH) {
7567 wplp = &Waypoint_lists[Training_context_path];
7568 if (wplp->count > Training_context_goal_waypoint) {
7569 i = Training_context_goal_waypoint;
7571 d = vm_vec_dist(&wplp->waypoints[i], &Player_obj->pos);
7572 if (d <= Training_context_distance) {
7573 Training_context_at_waypoint = i;
7574 if (Training_context_goal_waypoint == i) {
7575 Training_context_goal_waypoint++;
7576 snd_play(&Snds[SND_CARGO_REVEAL], 0.0f);
7583 if (i == wplp->count)
7586 } while (i != Training_context_goal_waypoint);
7590 if ((Players_target == UNINITIALIZED) || (Player_ai->target_objnum != Players_target) || (Player_ai->targeted_subsys != Players_targeted_subsys)) {
7591 Players_target = Player_ai->target_objnum;
7592 Players_targeted_subsys = Player_ai->targeted_subsys;
7593 Players_target_timestamp = timestamp();
7597 /////////// Following is for event debug view screen
7601 #define EVENT_DEBUG_MAX 5000
7602 #define EVENT_DEBUG_EVENT 0x8000
7604 int Event_debug_index[EVENT_DEBUG_MAX];
7607 void game_add_event_debug_index(int n, int indent)
7609 if (ED_count < EVENT_DEBUG_MAX)
7610 Event_debug_index[ED_count++] = n | (indent << 16);
7613 void game_add_event_debug_sexp(int n, int indent)
7618 if (Sexp_nodes[n].first >= 0) {
7619 game_add_event_debug_sexp(Sexp_nodes[n].first, indent);
7620 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7624 game_add_event_debug_index(n, indent);
7625 if (Sexp_nodes[n].subtype == SEXP_ATOM_OPERATOR)
7626 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent + 1);
7628 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7631 void game_event_debug_init()
7636 for (e=0; e<Num_mission_events; e++) {
7637 game_add_event_debug_index(e | EVENT_DEBUG_EVENT, 0);
7638 game_add_event_debug_sexp(Mission_events[e].formula, 1);
7642 void game_show_event_debug(float frametime)
7646 int font_height, font_width;
7648 static int scroll_offset = 0;
7650 k = game_check_key();
7656 if (scroll_offset < 0)
7666 scroll_offset -= 20;
7667 if (scroll_offset < 0)
7672 scroll_offset += 20; // not font-independent, hard-coded since I counted the lines!
7676 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
7682 gr_set_color_fast(&Color_bright);
7684 gr_printf(0x8000, 5, NOX("EVENT DEBUG VIEW"));
7686 gr_set_color_fast(&Color_normal);
7688 gr_get_string_size(&font_width, &font_height, NOX("test"));
7689 y_max = gr_screen.max_h - font_height - 5;
7693 while (k < ED_count) {
7694 if (y_index > y_max)
7697 z = Event_debug_index[k];
7698 if (z & EVENT_DEBUG_EVENT) {
7700 sprintf(buf, NOX("%s%s (%s) %s%d %d"), (Mission_events[z].flags & MEF_CURRENT) ? NOX("* ") : "",
7701 Mission_events[z].name, Mission_events[z].result ? NOX("True") : NOX("False"),
7702 (Mission_events[z].chain_delay < 0) ? "" : NOX("x "),
7703 Mission_events[z].repeat_count, Mission_events[z].interval);
7711 strcat(buf, Sexp_nodes[z & 0x7fff].text);
7712 switch (Sexp_nodes[z & 0x7fff].value) {
7714 strcat(buf, NOX(" (True)"));
7718 strcat(buf, NOX(" (False)"));
7721 case SEXP_KNOWN_TRUE:
7722 strcat(buf, NOX(" (Always true)"));
7725 case SEXP_KNOWN_FALSE:
7726 strcat(buf, NOX(" (Always false)"));
7729 case SEXP_CANT_EVAL:
7730 strcat(buf, NOX(" (Can't eval)"));
7734 case SEXP_NAN_FOREVER:
7735 strcat(buf, NOX(" (Not a number)"));
7740 gr_printf(10, y_index, buf);
7741 y_index += font_height;
7754 extern int Tmap_npixels;
7756 int Tmap_num_too_big = 0;
7757 int Num_models_needing_splitting = 0;
7759 void Time_model( int modelnum )
7761 // mprintf(( "Timing ship '%s'\n", si->name ));
7763 vector eye_pos, model_pos;
7764 matrix eye_orient, model_orient;
7766 polymodel *pm = model_get( modelnum );
7768 int l = strlen(pm->filename);
7770 if ( (l == '/') || (l=='\\') || (l==':')) {
7776 char *pof_file = &pm->filename[l];
7778 int model_needs_splitting = 0;
7780 //fprintf( Texture_fp, "Model: %s\n", pof_file );
7782 for (i=0; i<pm->n_textures; i++ ) {
7783 char filename[1024];
7786 int bmp_num = pm->original_textures[i];
7787 if ( bmp_num > -1 ) {
7788 bm_get_palette(pm->original_textures[i], pal, filename );
7790 bm_get_info( pm->original_textures[i],&w, &h );
7793 if ( (w > 512) || (h > 512) ) {
7794 fprintf( Texture_fp, "%s\t%s\t%d\t%d\n", pof_file, filename, w, h );
7796 model_needs_splitting++;
7799 //fprintf( Texture_fp, "\tTexture %d is bogus\n", i );
7803 if ( model_needs_splitting ) {
7804 Num_models_needing_splitting++;
7806 eye_orient = model_orient = vmd_identity_matrix;
7807 eye_pos = model_pos = vmd_zero_vector;
7809 eye_pos.xyz.z = -pm->rad*2.0f;
7811 vector eye_to_model;
7813 vm_vec_sub( &eye_to_model, &model_pos, &eye_pos );
7814 vm_vector_2_matrix( &eye_orient, &eye_to_model, NULL, NULL );
7816 fix t1 = timer_get_fixed_seconds();
7819 ta.p = ta.b = ta.h = 0.0f;
7824 int bitmaps_used_this_frame, bitmaps_new_this_frame;
7826 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7828 modelstats_num_polys = modelstats_num_verts = 0;
7830 while( ta.h < PI2 ) {
7833 vm_angles_2_matrix(&m1, &ta );
7834 vm_matrix_x_matrix( &model_orient, &vmd_identity_matrix, &m1 );
7841 g3_set_view_matrix( &eye_pos, &eye_orient, Viewer_zoom );
7843 model_clear_instance( modelnum );
7844 model_set_detail_level(0); // use highest detail level
7845 model_render( modelnum, &model_orient, &model_pos, MR_LOCK_DETAIL); //|MR_NO_POLYS );
7853 int k = key_inkey();
7854 if ( k == KEY_ESC ) {
7859 fix t2 = timer_get_fixed_seconds();
7861 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7862 //bitmaps_used_this_frame /= framecount;
7864 modelstats_num_polys /= framecount;
7865 modelstats_num_verts /= framecount;
7867 Tmap_npixels /=framecount;
7870 mprintf(( "'%s' is %.2f FPS\n", pof_file, i2fl(framecount)/f2fl(t2-t1) ));
7871 fprintf( Time_fp, "\"%s\"\t%.0f\t%d\t%d\t%d\t%d\n", pof_file, i2fl(framecount)/f2fl(t2-t1), bitmaps_used_this_frame, modelstats_num_polys, modelstats_num_verts, Tmap_npixels );
7872 // fprintf( Time_fp, "%.0f\t%d\t%d\t%d\t%d\n", i2fl(framecount)/f2fl(t2-t1), bitmaps_used_this_frame, modelstats_num_polys, modelstats_num_verts, Tmap_npixels );
7878 int Time_models = 0;
7879 DCF_BOOL( time_models, Time_models );
7881 void Do_model_timings_test()
7885 if ( !Time_models ) return;
7887 mprintf(( "Timing models!\n" ));
7891 ubyte model_used[MAX_POLYGON_MODELS];
7892 int model_id[MAX_POLYGON_MODELS];
7893 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7898 for (i=0; i<Num_ship_types; i++ ) {
7899 Ship_info[i].modelnum = model_load( Ship_info[i].pof_file, 0, NULL );
7901 model_used[Ship_info[i].modelnum%MAX_POLYGON_MODELS]++;
7902 model_id[Ship_info[i].modelnum%MAX_POLYGON_MODELS] = Ship_info[i].modelnum;
7905 Texture_fp = fopen( NOX("ShipTextures.txt"), "wt" );
7906 if ( !Texture_fp ) return;
7908 Time_fp = fopen( NOX("ShipTimings.txt"), "wt" );
7909 if ( !Time_fp ) return;
7911 fprintf( Time_fp, "Name\tFPS\tTRAM\tPolys\tVerts\tPixels\n" );
7912 // fprintf( Time_fp, "FPS\tTRAM\tPolys\tVerts\tPixels\n" );
7914 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7915 if ( model_used[i] ) {
7916 Time_model( model_id[i] );
7920 fprintf( Texture_fp, "Number too big: %d\n", Tmap_num_too_big );
7921 fprintf( Texture_fp, "Number of models needing splitting: %d\n", Num_models_needing_splitting );
7930 // Call this function when you want to inform the player that a feature is not
7931 // enabled in the DEMO version of FreSpace
7932 void game_feature_not_in_demo_popup()
7934 popup(PF_USE_AFFIRMATIVE_ICON|PF_BODY_BIG, 1, POPUP_OK, XSTR( "Sorry, this feature is available only in the retail version", 200));
7937 // format the specified time (fixed point) into a nice string
7938 void game_format_time(fix m_time,char *time_str)
7941 int hours,minutes,seconds;
7944 mtime = f2fl(m_time);
7946 // get the hours, minutes and seconds
7947 hours = (int)(mtime / 3600.0f);
7949 mtime -= (3600.0f * (float)hours);
7951 seconds = (int)mtime%60;
7952 minutes = (int)mtime/60;
7954 // print the hour if necessary
7956 sprintf(time_str,XSTR( "%d:", 201),hours);
7957 // if there are less than 10 minutes, print a leading 0
7959 strcpy(tmp,NOX("0"));
7960 strcat(time_str,tmp);
7964 // print the minutes
7966 sprintf(tmp,XSTR( "%d:", 201),minutes);
7967 strcat(time_str,tmp);
7969 sprintf(time_str,XSTR( "%d:", 201),minutes);
7972 // print the seconds
7974 strcpy(tmp,NOX("0"));
7975 strcat(time_str,tmp);
7977 sprintf(tmp,"%d",seconds);
7978 strcat(time_str,tmp);
7981 // Stuff version string in *str.
7982 void get_version_string(char *str)
7985 if ( FS_VERSION_BUILD == 0 ) {
7986 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
7988 sprintf(str,"v%d.%02d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD );
7991 #if defined (FS2_DEMO) || defined(FS1_DEMO)
7993 #elif defined (OEM_BUILD)
7994 strcat(str, " (OEM)");
8000 char myname[_MAX_PATH];
8001 int namelen, major, minor, build, waste;
8002 unsigned int buf_size;
8008 // Find my EXE file name
8009 hMod = GetModuleHandle(NULL);
8010 namelen = GetModuleFileName( hMod, myname, _MAX_PATH );
8012 version_size = GetFileVersionInfoSize(myname, &bogus_handle );
8013 infop = (char *)malloc(version_size);
8014 result = GetFileVersionInfo( myname, 0, version_size, (LPVOID)infop );
8016 // get the product version
8017 result = VerQueryValue((LPVOID)infop, TEXT("\\StringFileInfo\\040904b0\\ProductVersion"), &bufp, &buf_size );
8018 sscanf( (char *)bufp, "%d, %d, %d, %d", &major, &minor, &build, &waste );
8020 sprintf(str,"Dv%d.%02d",major, minor);
8022 sprintf(str,"v%d.%02d",major, minor);
8027 void get_version_string_short(char *str)
8029 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
8032 // ----------------------------------------------------------------
8034 // OEM UPSELL SCREENS BEGIN
8036 // ----------------------------------------------------------------
8037 #if defined(OEM_BUILD)
8039 #define NUM_OEM_UPSELL_SCREENS 3
8040 #define OEM_UPSELL_SCREEN_DELAY 10000
8042 static int Oem_upsell_bitmaps_loaded = 0;
8043 static int Oem_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS];
8044 static int Oem_upsell_screen_number = 0;
8045 static int Oem_upsell_show_next_bitmap_time;
8048 static char *Oem_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS] =
8061 static int Oem_normal_cursor = -1;
8062 static int Oem_web_cursor = -1;
8063 //#define OEM_UPSELL_URL "http://www.interplay-store.com/"
8064 #define OEM_UPSELL_URL "http://www.interplay.com/cgi-bin/oemlinks.pl/pid=483421&cid=18384"
8066 void oem_upsell_next_screen()
8068 Oem_upsell_screen_number++;
8069 if ( Oem_upsell_screen_number == (NUM_OEM_UPSELL_SCREENS-1) ) {
8070 // extra long delay, mouse shown on last upsell
8071 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY*2;
8075 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
8079 void oem_upsell_load_bitmaps()
8083 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
8084 Oem_upsell_bitmaps[gr_screen.res][i] = bm_load(Oem_upsell_bitmap_filenames[gr_screen.res][i]);
8088 void oem_upsell_unload_bitmaps()
8092 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
8093 if(Oem_upsell_bitmaps[gr_screen.res][i] >= 0){
8094 bm_unload(Oem_upsell_bitmaps[gr_screen.res][i]);
8099 Oem_upsell_bitmaps_loaded = 0;
8102 // clickable hotspot on 3rd OEM upsell screen
8103 static int Oem_upsell3_button_coords[GR_NUM_RESOLUTIONS][4] = {
8105 28, 350, 287, 96 // x, y, w, h
8108 45, 561, 460, 152 // x, y, w, h
8112 void oem_upsell_show_screens()
8114 int current_time, k;
8117 if ( !Oem_upsell_bitmaps_loaded ) {
8118 oem_upsell_load_bitmaps();
8119 Oem_upsell_bitmaps_loaded = 1;
8122 // may use upsell screens more than once
8123 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
8124 Oem_upsell_screen_number = 0;
8130 int nframes; // used to pass, not really needed (should be 1)
8131 Oem_normal_cursor = gr_get_cursor_bitmap();
8132 Oem_web_cursor = bm_load_animation("cursorweb", &nframes);
8133 Assert(Oem_web_cursor >= 0);
8134 if (Oem_web_cursor < 0) {
8135 Oem_web_cursor = Oem_normal_cursor;
8140 //oem_reset_trailer_timer();
8142 current_time = timer_get_milliseconds();
8147 // advance screen on keypress or timeout
8148 if (( k > 0 ) || (mouse_up_count(MOUSE_LEFT_BUTTON) > 0) || (current_time > Oem_upsell_show_next_bitmap_time)) {
8149 oem_upsell_next_screen();
8152 // check if we are done
8153 if ( Oem_upsell_screen_number >= NUM_OEM_UPSELL_SCREENS ) {
8154 Oem_upsell_screen_number--;
8157 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] < 0 ) {
8162 // show me the upsell
8163 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] >= 0 ) {
8164 gr_set_bitmap(Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number]);
8168 // if this is the 3rd upsell, make it clickable, d00d
8169 if ( Oem_upsell_screen_number == NUM_OEM_UPSELL_SCREENS-1 ) {
8171 int button_state = mouse_get_pos(&mx, &my);
8172 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])
8173 && (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]) )
8176 gr_set_cursor_bitmap(Oem_web_cursor); //, GR_CURSOR_LOCK);
8179 if (button_state & MOUSE_LEFT_BUTTON) {
8181 multi_pxo_url(OEM_UPSELL_URL);
8185 // switch cursor back to normal one
8186 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
8191 if (gameseq_get_state() != GS_STATE_END_DEMO) {
8201 oem_upsell_unload_bitmaps();
8203 // switch cursor back to normal one
8204 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
8208 #endif // defined(OEM_BUILD)
8209 // ----------------------------------------------------------------
8211 // OEM UPSELL SCREENS END
8213 // ----------------------------------------------------------------
8217 // ----------------------------------------------------------------
8219 // DEMO UPSELL SCREENS BEGIN
8221 // ----------------------------------------------------------------
8223 #if defined(FS2_DEMO) || defined(FS1_DEMO)
8226 #define NUM_DEMO_UPSELL_SCREENS 2
8228 #define NUM_DEMO_UPSELL_SCREENS 4
8230 #define DEMO_UPSELL_SCREEN_DELAY 3000
8232 static int Demo_upsell_bitmaps_loaded = 0;
8233 static int Demo_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS];
8234 static int Demo_upsell_screen_number = 0;
8235 static int Demo_upsell_show_next_bitmap_time;
8238 static char *Demo_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS] =
8264 void demo_upsell_next_screen()
8266 Demo_upsell_screen_number++;
8267 if ( Demo_upsell_screen_number == (NUM_DEMO_UPSELL_SCREENS-1) ) {
8268 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY*4;
8270 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
8274 if ( Demo_upsell_screen_number < NUM_DEMO_UPSELL_SCREENS ) {
8275 if ( Demo_upsell_bitmap_filenames[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
8276 #ifndef HARDWARE_ONLY
8277 palette_use_bm_palette(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8284 void demo_upsell_load_bitmaps()
8288 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8289 Demo_upsell_bitmaps[gr_screen.res][i] = bm_load(Demo_upsell_bitmap_filenames[gr_screen.res][i]);
8293 void demo_upsell_unload_bitmaps()
8297 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8298 if(Demo_upsell_bitmaps[gr_screen.res][i] >= 0){
8299 bm_unload(Demo_upsell_bitmaps[gr_screen.res][i]);
8304 Demo_upsell_bitmaps_loaded = 0;
8307 void demo_upsell_show_screens()
8309 int current_time, k;
8312 if ( !Demo_upsell_bitmaps_loaded ) {
8313 demo_upsell_load_bitmaps();
8314 Demo_upsell_bitmaps_loaded = 1;
8317 // may use upsell screens more than once
8318 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
8319 Demo_upsell_screen_number = 0;
8326 demo_reset_trailer_timer();
8328 current_time = timer_get_milliseconds();
8335 // don't time out, wait for keypress
8337 if ( current_time > Demo_upsell_show_next_bitmap_time ) {
8338 demo_upsell_next_screen();
8343 demo_upsell_next_screen();
8346 if ( Demo_upsell_screen_number >= NUM_DEMO_UPSELL_SCREENS ) {
8347 Demo_upsell_screen_number--;
8350 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] < 0 ) {
8355 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
8356 gr_set_bitmap(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8361 if (gameseq_get_state() != GS_STATE_END_DEMO) {
8371 demo_upsell_unload_bitmaps();
8376 // ----------------------------------------------------------------
8378 // DEMO UPSELL SCREENS END
8380 // ----------------------------------------------------------------
8383 // ----------------------------------------------------------------
8385 // Subspace Ambient Sound START
8387 // ----------------------------------------------------------------
8389 static int Subspace_ambient_left_channel = -1;
8390 static int Subspace_ambient_right_channel = -1;
8393 void game_start_subspace_ambient_sound()
8395 if ( Subspace_ambient_left_channel < 0 ) {
8396 Subspace_ambient_left_channel = snd_play_looping(&Snds[SND_SUBSPACE_LEFT_CHANNEL], -1.0f);
8399 if ( Subspace_ambient_right_channel < 0 ) {
8400 Subspace_ambient_right_channel = snd_play_looping(&Snds[SND_SUBSPACE_RIGHT_CHANNEL], 1.0f);
8404 void game_stop_subspace_ambient_sound()
8406 if ( Subspace_ambient_left_channel >= 0 ) {
8407 snd_stop(Subspace_ambient_left_channel);
8408 Subspace_ambient_left_channel = -1;
8411 if ( Subspace_ambient_right_channel >= 0 ) {
8412 snd_stop(Subspace_ambient_right_channel);
8413 Subspace_ambient_right_channel = -1;
8417 // ----------------------------------------------------------------
8419 // Subspace Ambient Sound END
8421 // ----------------------------------------------------------------
8423 // ----------------------------------------------------------------
8425 // CDROM detection code START
8427 // ----------------------------------------------------------------
8429 #define CD_SIZE_72_MINUTE_MAX (697000000)
8431 uint game_get_cd_used_space(char *path)
8435 char use_path[512] = "";
8436 char sub_path[512] = "";
8437 WIN32_FIND_DATA find;
8440 // recurse through all files and directories
8441 strcpy(use_path, path);
8442 strcat(use_path, "*.*");
8443 find_handle = FindFirstFile(use_path, &find);
8446 if(find_handle == INVALID_HANDLE_VALUE){
8452 // subdirectory. make sure to ignore . and ..
8453 if((find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && stricmp(find.cFileName, ".") && stricmp(find.cFileName, "..")){
8455 strcpy(sub_path, path);
8456 strcat(sub_path, find.cFileName);
8457 strcat(sub_path, "\\");
8458 total += game_get_cd_used_space(sub_path);
8460 total += (uint)find.nFileSizeLow;
8462 } while(FindNextFile(find_handle, &find));
8465 FindClose(find_handle);
8477 // if volume_name is non-null, the CD name must match that
8478 int find_freespace_cd(char *volume_name)
8481 char oldpath[MAX_PATH];
8485 int volume_match = 0;
8489 GetCurrentDirectory(MAX_PATH, oldpath);
8491 for (i = 0; i < 26; i++)
8497 path[0] = (char)('A'+i);
8498 if (GetDriveType(path) == DRIVE_CDROM) {
8500 if ( GetVolumeInformation(path, volume, 256, NULL, NULL, NULL, NULL, 0) == TRUE ) {
8501 nprintf(("CD", "CD volume: %s\n", volume));
8503 // check for any CD volume
8504 int volume1_present = 0;
8505 int volume2_present = 0;
8506 int volume3_present = 0;
8508 char full_check[512] = "";
8510 // look for setup.exe
8511 strcpy(full_check, path);
8512 strcat(full_check, "setup.exe");
8513 find_handle = _findfirst(full_check, &find);
8514 if(find_handle != -1){
8515 volume1_present = 1;
8516 _findclose(find_handle);
8519 // look for intro.mve
8520 strcpy(full_check, path);
8521 strcat(full_check, "intro.mve");
8522 find_handle = _findfirst(full_check, &find);
8523 if(find_handle != -1){
8524 volume2_present = 1;
8525 _findclose(find_handle);
8528 // look for endpart1.mve
8529 strcpy(full_check, path);
8530 strcat(full_check, "endpart1.mve");
8531 find_handle = _findfirst(full_check, &find);
8532 if(find_handle != -1){
8533 volume3_present = 1;
8534 _findclose(find_handle);
8537 // see if we have the specific CD we're looking for
8538 if ( volume_name ) {
8540 if ( !stricmp(volume_name, FS_CDROM_VOLUME_1) && volume1_present) {
8544 if ( !stricmp(volume_name, FS_CDROM_VOLUME_2) && volume2_present) {
8548 if ( !stricmp(volume_name, FS_CDROM_VOLUME_3) && volume3_present) {
8552 if ( volume1_present || volume2_present || volume3_present ) {
8557 // here's where we make sure that CD's 2 and 3 are not just ripped - check to make sure its capacity is > 697,000,000 bytes
8558 if ( volume_match ){
8560 // we don't care about CD1 though. let it be whatever size it wants, since the game will demand CD's 2 and 3 at the proper time
8561 if(volume2_present || volume3_present) {
8562 // first step - check to make sure its a cdrom
8563 if(GetDriveType(path) != DRIVE_CDROM){
8567 #if !defined(OEM_BUILD)
8568 // oem not on 80 min cds, so dont check tha size
8570 uint used_space = game_get_cd_used_space(path);
8571 if(used_space < CD_SIZE_72_MINUTE_MAX){
8574 #endif // !defined(OEM_BUILD)
8582 #endif // RELEASE_REAL
8588 SetCurrentDirectory(oldpath);
8597 int set_cdrom_path(int drive_num)
8601 if (drive_num < 0) { //no CD
8603 // strcpy(CDROM_dir,"j:\\FreeSpaceCD\\"); //set directory
8606 strcpy(Game_CDROM_dir,""); //set directory
8610 sprintf(Game_CDROM_dir,NOX("%c:\\"), 'a' + drive_num ); //set directory
8626 i = find_freespace_cd();
8628 rval = set_cdrom_path(i);
8632 nprintf(("CD", "Using %s for FreeSpace CD\n", CDROM_dir));
8634 nprintf(("CD", "FreeSpace CD not found\n"));
8642 int Last_cd_label_found = 0;
8643 char Last_cd_label[256];
8645 int game_cd_changed()
8652 if ( strlen(Game_CDROM_dir) == 0 ) {
8656 found = GetVolumeInformation(Game_CDROM_dir, label, 256, NULL, NULL, NULL, NULL, 0);
8658 if ( found != Last_cd_label_found ) {
8659 Last_cd_label_found = found;
8661 mprintf(( "CD '%s' was inserted\n", label ));
8664 mprintf(( "CD '%s' was removed\n", Last_cd_label ));
8668 if ( Last_cd_label_found ) {
8669 if ( !stricmp( Last_cd_label, label )) {
8670 //mprintf(( "CD didn't change\n" ));
8672 mprintf(( "CD was changed from '%s' to '%s'\n", Last_cd_label, label ));
8676 // none found before, none found now.
8677 //mprintf(( "still no CD...\n" ));
8681 Last_cd_label_found = found;
8683 strcpy( Last_cd_label, label );
8685 strcpy( Last_cd_label, "" );
8696 // check if _any_ FreeSpace2 CDs are in the drive
8697 // return: 1 => CD now in drive
8698 // 0 => Could not find CD, they refuse to put it in the drive
8699 int game_do_cd_check(char *volume_name)
8701 #if !defined(GAME_CD_CHECK)
8707 int num_attempts = 0;
8708 int refresh_files = 0;
8710 int path_set_ok, popup_rval;
8712 cd_drive_num = find_freespace_cd(volume_name);
8713 path_set_ok = set_cdrom_path(cd_drive_num);
8714 if ( path_set_ok ) {
8716 if ( refresh_files ) {
8728 // no CD found, so prompt user
8729 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR( "FreeSpace 2 CD not found\n\nInsert a FreeSpace 2 CD to continue", 202));
8731 if ( popup_rval != 1 ) {
8736 if ( num_attempts++ > 5 ) {
8747 // check if _any_ FreeSpace2 CDs are in the drive
8748 // return: 1 => CD now in drive
8749 // 0 => Could not find CD, they refuse to put it in the drive
8750 int game_do_cd_check_specific(char *volume_name, int cdnum)
8755 int num_attempts = 0;
8756 int refresh_files = 0;
8758 int path_set_ok, popup_rval;
8760 cd_drive_num = find_freespace_cd(volume_name);
8761 path_set_ok = set_cdrom_path(cd_drive_num);
8762 if ( path_set_ok ) {
8764 if ( refresh_files ) {
8775 // no CD found, so prompt user
8776 #if defined(DVD_MESSAGE_HACK)
8777 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert DVD", 1468));
8779 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert CD %d", 1468), cdnum);
8782 if ( popup_rval != 1 ) {
8787 if ( num_attempts++ > 5 ) {
8797 // only need to do this in RELEASE_REAL
8798 int game_do_cd_mission_check(char *filename)
8804 fs_builtin_mission *m = game_find_builtin_mission(filename);
8806 // check for changed CD
8807 if(game_cd_changed()){
8812 if((Game_mode & GM_MULTIPLAYER) || Is_standalone){
8816 // not builtin, so do a general check (any FS2 CD will do)
8818 return game_do_cd_check();
8821 // does not have any CD requirement, do a general check
8822 if(strlen(m->cd_volume) <= 0){
8823 return game_do_cd_check();
8827 if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_1)){
8829 } else if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_2)){
8832 } else if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_3)){
8836 return game_do_cd_check();
8839 // did we find the cd?
8840 if(find_freespace_cd(m->cd_volume) >= 0){
8844 // make sure the volume exists
8845 int num_attempts = 0;
8846 int refresh_files = 0;
8848 int path_set_ok, popup_rval;
8850 cd_drive_num = find_freespace_cd(m->cd_volume);
8851 path_set_ok = set_cdrom_path(cd_drive_num);
8852 if ( path_set_ok ) {
8854 if ( refresh_files ) {
8861 // no CD found, so prompt user
8862 #if defined(DVD_MESSAGE_HACK)
8863 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert DVD", 1468));
8865 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert CD %d", 1468), cd_num);
8869 if ( popup_rval != 1 ) {
8874 if ( num_attempts++ > 5 ) {
8886 // ----------------------------------------------------------------
8888 // CDROM detection code END
8890 // ----------------------------------------------------------------
8892 // ----------------------------------------------------------------
8894 // Language Autodetection stuff
8897 // this layout order must match Lcl_languages in localize.cpp in order for the
8898 // correct language to be detected
8899 int Lang_auto_detect_checksums[LCL_NUM_LANGUAGES] = {
8901 1366105450, // English
8903 589986744, // English
8905 -1132430286, // German
8907 -1131728960, // Polish
8910 // default setting is "-1" to use config file with English as fall back
8911 // DO NOT change the default setting here or something uncouth might happen
8912 // in the localization code
8918 // try and open the file to verify
8919 CFILE *detect = cfopen("font01.vf", "rb");
8921 // will use default setting if something went wrong
8926 // get the long checksum of the file
8928 cfseek(detect, 0, SEEK_SET);
8929 cf_chksum_long(detect, &file_checksum);
8933 // now compare the checksum/filesize against known #'s
8934 for (idx=0; idx<LCL_NUM_LANGUAGES; idx++) {
8935 if (Lang_auto_detect_checksums[idx] == (int)file_checksum) {
8940 // notify if a match was not found, include detected checksum
8941 printf("ERROR: Unknown Language Checksum: %i\n", (int)file_checksum);
8942 printf("Using default language...\n\n");
8948 // End Auto Lang stuff
8950 // ----------------------------------------------------------------
8952 // ----------------------------------------------------------------
8953 // SHIPS TBL VERIFICATION STUFF
8956 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
8957 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
8958 #define NUM_SHIPS_TBL_CHECKSUMS 3
8960 #define NUM_SHIPS_TBL_CHECKSUMS 1
8964 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8965 1696074201, // FS2 demo
8968 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8969 1603375034, // FS1 DEMO
8972 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8973 -129679197, // FS1 Full 1.06 (US)
8974 7762567, // FS1 SilentThreat
8975 1555372475 // FS1 Full 1.06 (German)
8979 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8980 -463907578, // US - beta 1
8981 1696074201, // FS2 demo
8984 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8985 // -1022810006, // 1.0 FULL
8986 -1254285366 // 1.2 FULL (German)
8990 void verify_ships_tbl()
8994 Game_ships_tbl_valid = 1;
9000 // detect if the packfile exists
9001 CFILE *detect = cfopen("ships.tbl", "rb");
9002 Game_ships_tbl_valid = 0;
9006 Game_ships_tbl_valid = 0;
9010 // get the long checksum of the file
9012 cfseek(detect, 0, SEEK_SET);
9013 cf_chksum_long(detect, &file_checksum);
9017 // now compare the checksum/filesize against known #'s
9018 for(idx=0; idx<NUM_SHIPS_TBL_CHECKSUMS; idx++){
9019 if(Game_ships_tbl_checksums[idx] == (int)file_checksum){
9020 Game_ships_tbl_valid = 1;
9027 DCF(shipspew, "display the checksum for the current ships.tbl")
9030 CFILE *detect = cfopen("ships.tbl", "rb");
9031 // get the long checksum of the file
9033 cfseek(detect, 0, SEEK_SET);
9034 cf_chksum_long(detect, &file_checksum);
9037 dc_printf("%d", file_checksum);
9040 // ----------------------------------------------------------------
9041 // WEAPONS TBL VERIFICATION STUFF
9044 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
9045 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
9046 #define NUM_WEAPONS_TBL_CHECKSUMS 3
9048 #define NUM_WEAPONS_TBL_CHECKSUMS 1
9052 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9053 -266420030, // demo 1
9056 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9057 -1246928725, // FS1 DEMO
9060 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9061 -834598107, // FS1 1.06 Full (US)
9062 -1652231417, // FS1 SilentThreat
9063 720209793 // FS1 1.06 Full (German)
9067 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9068 141718090, // US - beta 1
9069 -266420030, // demo 1
9072 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9073 // 399297860, // 1.0 FULL
9074 -553984927 // 1.2 FULL (german)
9078 void verify_weapons_tbl()
9082 Game_weapons_tbl_valid = 1;
9088 // detect if the packfile exists
9089 CFILE *detect = cfopen("weapons.tbl", "rb");
9090 Game_weapons_tbl_valid = 0;
9094 Game_weapons_tbl_valid = 0;
9098 // get the long checksum of the file
9100 cfseek(detect, 0, SEEK_SET);
9101 cf_chksum_long(detect, &file_checksum);
9105 // now compare the checksum/filesize against known #'s
9106 for(idx=0; idx<NUM_WEAPONS_TBL_CHECKSUMS; idx++){
9107 if(Game_weapons_tbl_checksums[idx] == (int)file_checksum){
9108 Game_weapons_tbl_valid = 1;
9115 DCF(wepspew, "display the checksum for the current weapons.tbl")
9118 CFILE *detect = cfopen("weapons.tbl", "rb");
9119 // get the long checksum of the file
9121 cfseek(detect, 0, SEEK_SET);
9122 cf_chksum_long(detect, &file_checksum);
9125 dc_printf("%d", file_checksum);
9128 // if the game is running using hacked data
9129 int game_hacked_data()
9132 if(!Game_weapons_tbl_valid || !Game_ships_tbl_valid){
9140 void display_title_screen()
9142 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
9143 ///int title_bitmap;
9146 int title_bitmap = bm_load(Game_demo_title_screen_fname[gr_screen.res]);
9147 if (title_bitmap == -1) {
9153 if((gr_screen.mode == GR_DIRECT3D) && (Gr_bitmap_poly)){
9154 extern void d3d_start_frame();
9160 gr_set_bitmap(title_bitmap);
9167 if((gr_screen.mode == GR_DIRECT3D) && (Gr_bitmap_poly)){
9168 extern void d3d_stop_frame();
9176 bm_unload(title_bitmap);
9177 #endif // FS2_DEMO || OEM_BUILD || FS1_DEMO
9180 // return true if the game is running with "low memory", which is less than 48MB
9181 bool game_using_low_mem()
9183 if (Use_low_mem == 0) {