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.37 2004/07/04 11:31:43 taylor
19 * amd64 support, compiler warning fixes, don't use software rendering
21 * Revision 1.36 2004/06/12 01:11:35 taylor
22 * x86 compile fixes for OSX patch
24 * Revision 1.35 2004/06/11 00:53:02 tigital
25 * OSX: .app name, casts for gcc
27 * Revision 1.34 2003/08/09 03:18:03 taylor
28 * fix tips popup not having any tips
30 * Revision 1.33 2003/08/03 15:57:00 taylor
31 * simpler mouse usage; default ini settings in os_init(); cleanup
33 * Revision 1.32 2003/06/19 11:51:41 taylor
34 * adjustments to memory leak fixes
36 * Revision 1.31 2003/06/11 18:30:32 taylor
39 * Revision 1.30 2003/06/03 04:00:39 taylor
40 * Polish language support (Janusz Dziemidowicz)
42 * Revision 1.29 2003/05/25 02:30:42 taylor
45 * Revision 1.28 2003/05/18 03:55:30 taylor
46 * automatic language selection support
48 * Revision 1.27 2003/03/03 04:54:44 theoddone33
49 * Commit Taylor's ShowFPS fix
51 * Revision 1.26 2003/02/20 17:41:07 theoddone33
52 * Userdir patch from Taylor Richards
54 * Revision 1.25 2003/01/30 19:54:10 relnev
55 * ini config option for the frames per second counter (Taylor Richards)
57 * Revision 1.24 2002/08/31 01:39:13 theoddone33
58 * Speed up the renderer a tad
60 * Revision 1.23 2002/08/04 02:31:00 relnev
61 * make numlock not overlap with pause
63 * Revision 1.22 2002/08/02 23:07:03 relnev
64 * don't access the mouse in standalone mode
66 * Revision 1.21 2002/07/28 05:05:08 relnev
67 * removed some old stuff
69 * Revision 1.20 2002/07/24 00:20:41 relnev
72 * Revision 1.19 2002/06/17 06:33:08 relnev
73 * ryan's struct patch for gcc 2.95
75 * Revision 1.18 2002/06/16 04:46:33 relnev
76 * set up correct checksums for demo
78 * Revision 1.17 2002/06/09 04:41:17 relnev
79 * added copyright header
81 * Revision 1.16 2002/06/09 03:16:04 relnev
84 * removed unneeded asm, old sdl 2d setup.
86 * fixed crash caused by opengl_get_region.
88 * Revision 1.15 2002/06/05 08:05:28 relnev
89 * stub/warning removal.
91 * reworked the sound code.
93 * Revision 1.14 2002/06/05 04:03:32 relnev
94 * finished cfilesystem.
96 * removed some old code.
98 * fixed mouse save off-by-one.
102 * Revision 1.13 2002/06/02 04:26:34 relnev
105 * Revision 1.12 2002/06/02 00:31:35 relnev
106 * implemented osregistry
108 * Revision 1.11 2002/06/01 09:00:34 relnev
109 * silly debug memmanager
111 * Revision 1.10 2002/06/01 07:12:32 relnev
112 * a few NDEBUG updates.
114 * removed a few warnings.
116 * Revision 1.9 2002/05/31 03:05:59 relnev
119 * Revision 1.8 2002/05/29 02:52:32 theoddone33
120 * Enable OpenGL renderer
122 * Revision 1.7 2002/05/28 08:52:03 relnev
123 * implemented two assembly stubs.
125 * cleaned up a few warnings.
127 * added a little demo hackery to make it progress a little farther.
129 * Revision 1.6 2002/05/28 06:28:20 theoddone33
130 * Filesystem mods, actually reads some data files now
132 * Revision 1.5 2002/05/28 04:07:28 theoddone33
133 * New graphics stubbing arrangement
135 * Revision 1.4 2002/05/27 22:46:52 theoddone33
136 * Remove more undefined symbols
138 * Revision 1.3 2002/05/26 23:31:18 relnev
139 * added a few files that needed to be compiled
141 * freespace.cpp: now compiles
143 * Revision 1.2 2002/05/07 03:16:44 theoddone33
144 * The Great Newline Fix
146 * Revision 1.1.1.1 2002/05/03 03:28:09 root
150 * 201 6/16/00 3:15p Jefff
151 * sim of the year dvd version changes, a few german soty localization
154 * 200 11/03/99 11:06a Jefff
157 * 199 10/26/99 5:07p Jamest
158 * fixed jeffs dumb debug code
160 * 198 10/25/99 5:53p Jefff
161 * call control_config_common_init() on startup
163 * 197 10/14/99 10:18a Daveb
164 * Fixed incorrect CD checking problem on standalone server.
166 * 196 10/13/99 9:22a Daveb
167 * Fixed Fred jumpnode placing bug. Fixed 1024 glide tiled texture problem
168 * related to movies. Fixed launcher spawning from PXO screen.
170 * 195 10/06/99 11:05a Jefff
171 * new oem upsell 3 hotspot coords
173 * 194 10/06/99 10:31a Jefff
176 * 193 10/01/99 9:10a Daveb
179 * 192 9/15/99 4:57a Dave
180 * Updated ships.tbl checksum
182 * 191 9/15/99 3:58a Dave
183 * Removed framerate warning at all times.
185 * 190 9/15/99 3:16a Dave
186 * Remove mt-011.fs2 from the builtin mission list.
188 * 189 9/15/99 1:45a Dave
189 * Don't init joystick on standalone. Fixed campaign mode on standalone.
190 * Fixed no-score-report problem in TvT
192 * 188 9/14/99 6:08a Dave
193 * Updated (final) single, multi, and campaign list.
195 * 187 9/14/99 3:26a Dave
196 * Fixed laser fogging problem in nebula (D3D)> Fixed multiplayer
197 * respawn-too-early problem. Made a few crash points safe.
199 * 186 9/13/99 4:52p Dave
202 * 185 9/12/99 8:09p Dave
203 * Fixed problem where skip-training button would cause mission messages
204 * not to get paged out for the current mission.
206 * 184 9/10/99 11:53a Dave
207 * Shutdown graphics before sound to eliminate apparent lockups when
208 * Directsound decides to be lame. Fix TOPMOST problem with D3D windows.
210 * 183 9/09/99 11:40p Dave
211 * Handle an Assert() in beam code. Added supernova sounds. Play the right
212 * 2 end movies properly, based upon what the player did in the mission.
214 * 182 9/08/99 10:29p Dave
215 * Make beam sound pausing and unpausing much safer.
217 * 181 9/08/99 10:01p Dave
218 * Make sure game won't run in a drive's root directory. Make sure
219 * standalone routes suqad war messages properly to the host.
221 * 180 9/08/99 3:22p Dave
222 * Updated builtin mission list.
224 * 179 9/08/99 12:01p Jefff
225 * fixed Game_builtin_mission_list typo on Training-2.fs2
227 * 178 9/08/99 9:48a Andsager
228 * Add force feedback for engine wash.
230 * 177 9/07/99 4:01p Dave
231 * Fixed up a string.tbl paroblem (self destruct message). Make sure IPX
232 * does everything properly (setting up address when binding). Remove
233 * black rectangle background from UI_INPUTBOX.
235 * 176 9/13/99 2:40a Dave
236 * Comment in full 80 minute CD check for RELEASE_REAL builds.
238 * 175 9/06/99 6:38p Dave
239 * Improved CD detection code.
241 * 174 9/06/99 1:30a Dave
242 * Intermediate checkin. Started on enforcing CD-in-drive to play the
245 * 173 9/06/99 1:16a Dave
246 * Make sure the user sees the intro movie.
248 * 172 9/04/99 8:00p Dave
249 * Fixed up 1024 and 32 bit movie support.
251 * 171 9/03/99 1:32a Dave
252 * CD checking by act. Added support to play 2 cutscenes in a row
253 * seamlessly. Fixed super low level cfile bug related to files in the
254 * root directory of a CD. Added cheat code to set campaign mission # in
257 * 170 9/01/99 10:49p Dave
258 * Added nice SquadWar checkbox to the client join wait screen.
260 * 169 9/01/99 10:14a Dave
263 * 168 8/29/99 4:51p Dave
264 * Fixed damaged checkin.
266 * 167 8/29/99 4:18p Andsager
267 * New "burst" limit for friendly damage. Also credit more damage done
268 * against large friendly ships.
270 * 166 8/27/99 6:38p Alanl
271 * crush the blasted repeating messages bug
273 * 164 8/26/99 9:09p Dave
274 * Force framerate check in everything but a RELEASE_REAL build.
276 * 163 8/26/99 9:45a Dave
277 * First pass at easter eggs and cheats.
279 * 162 8/24/99 8:55p Dave
280 * Make sure nondimming pixels work properly in tech menu.
282 * 161 8/24/99 1:49a Dave
283 * Fixed client-side afterburner stuttering. Added checkbox for no version
284 * checking on PXO join. Made button info passing more friendly between
287 * 160 8/22/99 5:53p Dave
288 * Scoring fixes. Added self destruct key. Put callsigns in the logfile
289 * instead of ship designations for multiplayer players.
291 * 159 8/22/99 1:19p Dave
292 * Fixed up http proxy code. Cleaned up scoring code. Reverse the order in
293 * which d3d cards are detected.
295 * 158 8/20/99 2:09p Dave
296 * PXO banner cycling.
298 * 157 8/19/99 10:59a Dave
299 * Packet loss detection.
301 * 156 8/19/99 10:12a Alanl
302 * preload mission-specific messages on machines greater than 48MB
304 * 155 8/16/99 4:04p Dave
305 * Big honking checkin.
307 * 154 8/11/99 5:54p Dave
308 * Fixed collision problem. Fixed standalone ghost problem.
310 * 153 8/10/99 7:59p Jefff
313 * 152 8/10/99 6:54p Dave
314 * Mad optimizations. Added paging to the nebula effect.
316 * 151 8/10/99 3:44p Jefff
317 * loads Intelligence information on startup
319 * 150 8/09/99 3:47p Dave
320 * Fixed incorrect nebula regeneration. Default HUD to low-contrast in
321 * non-nebula missions.
323 * 149 8/09/99 2:21p Andsager
324 * Fix patching from multiplayer direct to launcher update tab.
326 * 148 8/09/99 10:36a Dave
327 * Version info for game.
329 * 147 8/06/99 9:46p Dave
330 * Hopefully final changes for the demo.
332 * 146 8/06/99 3:34p Andsager
333 * Make title version info "(D)" -> "D" show up nicely
335 * 145 8/06/99 2:59p Adamp
336 * Fixed NT launcher/update problem.
338 * 144 8/06/99 1:52p Dave
339 * Bumped up MAX_BITMAPS for the demo.
341 * 143 8/06/99 12:17p Andsager
342 * Demo: down to just 1 demo dog
344 * 142 8/05/99 9:39p Dave
345 * Yet another new checksum.
347 * 141 8/05/99 6:19p Dave
348 * New demo checksums.
350 * 140 8/05/99 5:31p Andsager
351 * Up demo version 1.01
353 * 139 8/05/99 4:22p Andsager
354 * No time limit on upsell screens. Reverse order of display of upsell
357 * 138 8/05/99 4:17p Dave
358 * Tweaks to client interpolation.
360 * 137 8/05/99 3:52p Danw
362 * 136 8/05/99 3:01p Danw
364 * 135 8/05/99 2:43a Anoop
365 * removed duplicate definition.
367 * 134 8/05/99 2:13a Dave
370 * 133 8/05/99 2:05a Dave
373 * 132 8/05/99 1:22a Andsager
376 * 131 8/04/99 9:51p Andsager
377 * Add title screen to demo
379 * 130 8/04/99 6:47p Jefff
380 * fixed link error resulting from #ifdefs
382 * 129 8/04/99 6:26p Dave
383 * Updated ship tbl checksum.
385 * 128 8/04/99 5:40p Andsager
386 * Add multiple demo dogs
388 * 127 8/04/99 5:36p Andsager
389 * Show upsell screens at end of demo campaign before returning to main
392 * 126 8/04/99 11:42a Danw
393 * tone down EAX reverb
395 * 125 8/04/99 11:23a Dave
396 * Updated demo checksums.
398 * 124 8/03/99 11:02p Dave
399 * Maybe fixed sync problems in multiplayer.
401 * 123 8/03/99 6:21p Jefff
404 * 122 8/03/99 3:44p Andsager
405 * Launch laucher if trying to run FS without first having configured
408 * 121 8/03/99 12:45p Dave
411 * 120 8/02/99 9:13p Dave
414 * 119 7/30/99 10:31p Dave
415 * Added comm menu to the configurable hud files.
417 * 118 7/30/99 5:17p Andsager
418 * first fs2demo checksums
420 * 117 7/29/99 3:09p Anoop
422 * 116 7/29/99 12:05a Dave
423 * Nebula speed optimizations.
425 * 115 7/27/99 8:59a Andsager
426 * Make major, minor version consistent for all builds. Only show major
427 * and minor for launcher update window.
429 * 114 7/26/99 5:50p Dave
430 * Revised ingame join. Better? We'll see....
432 * 113 7/26/99 5:27p Andsager
433 * Add training mission as builtin to demo build
435 * 112 7/24/99 1:54p Dave
436 * Hud text flash gauge. Reworked dead popup to use 4 buttons in red-alert
439 * 111 7/22/99 4:00p Dave
440 * Fixed beam weapon muzzle glow rendering. Externalized hud shield info.
442 * 110 7/21/99 8:10p Dave
443 * First run of supernova effect.
445 * 109 7/20/99 1:49p Dave
446 * Peter Drake build. Fixed some release build warnings.
448 * 108 7/19/99 2:26p Andsager
449 * set demo multiplayer missions
451 * 107 7/18/99 5:19p Dave
452 * Jump node icon. Fixed debris fogging. Framerate warning stuff.
454 * 106 7/16/99 1:50p Dave
455 * 8 bit aabitmaps. yay.
457 * 105 7/15/99 3:07p Dave
458 * 32 bit detection support. Mouse coord commandline.
460 * 104 7/15/99 2:13p Dave
461 * Added 32 bit detection.
463 * 103 7/15/99 9:20a Andsager
464 * FS2_DEMO initial checkin
466 * 102 7/14/99 11:02a Dave
467 * Skill level default back to easy. Blech.
469 * 101 7/09/99 5:54p Dave
470 * Seperated cruiser types into individual types. Added tons of new
471 * briefing icons. Campaign screen.
473 * 100 7/08/99 4:43p Andsager
474 * New check for sparky_hi and print if not found.
476 * 99 7/08/99 10:53a Dave
477 * New multiplayer interpolation scheme. Not 100% done yet, but still
478 * better than the old way.
480 * 98 7/06/99 4:24p Dave
481 * Mid-level checkin. Starting on some potentially cool multiplayer
484 * 97 7/06/99 3:35p Andsager
485 * Allow movie to play before red alert mission.
487 * 96 7/03/99 5:50p Dave
488 * Make rotated bitmaps draw properly in padlock views.
490 * 95 7/02/99 9:55p Dave
491 * Player engine wash sound.
493 * 94 7/02/99 4:30p Dave
494 * Much more sophisticated lightning support.
496 * 93 6/29/99 7:52p Dave
497 * Put in exception handling in FS2.
499 * 92 6/22/99 9:37p Dave
500 * Put in pof spewing.
502 * 91 6/16/99 4:06p Dave
503 * New pilot info popup. Added new draw-bitmap-as-poly function.
505 * 90 6/15/99 1:56p Andsager
506 * For release builds, allow start up in high res only with
509 * 89 6/15/99 9:34a Dave
510 * Fixed key checking in single threaded version of the stamp notification
513 * 88 6/09/99 2:55p Andsager
514 * Allow multiple asteroid subtypes (of large, medium, small) and follow
517 * 87 6/08/99 1:14a Dave
518 * Multi colored hud test.
520 * 86 6/04/99 9:52a Dave
521 * Fixed some rendering problems.
523 * 85 6/03/99 10:15p Dave
524 * Put in temporary main hall screen.
526 * 84 6/02/99 6:18p Dave
527 * Fixed TNT lockup problems! Wheeeee!
529 * 83 6/01/99 3:52p Dave
530 * View footage screen. Fixed xstrings to not display the & symbol. Popup,
531 * dead popup, pxo find player popup, pxo private room popup.
533 * 82 5/26/99 1:28p Jasenw
534 * changed coords for loading ani
536 * 81 5/26/99 11:46a Dave
537 * Added ship-blasting lighting and made the randomization of lighting
538 * much more customizable.
540 * 80 5/24/99 5:45p Dave
541 * Added detail levels to the nebula, with a decent speedup. Split nebula
542 * lightning into its own section.
560 #include "systemvars.h"
565 #include "starfield.h"
566 #include "lighting.h"
571 #include "fireballs.h"
575 #include "floating.h"
576 #include "gamesequence.h"
578 #include "optionsmenu.h"
579 #include "playermenu.h"
580 #include "trainingmenu.h"
581 #include "techmenu.h"
584 #include "hudmessage.h"
586 #include "missiongoals.h"
587 #include "missionparse.h"
592 #include "multiutil.h"
593 #include "multimsgs.h"
597 #include "freespace.h"
598 #include "managepilot.h"
600 #include "contexthelp.h"
603 #include "missionbrief.h"
604 #include "missiondebrief.h"
606 #include "missionshipchoice.h"
608 #include "hudconfig.h"
609 #include "controlsconfig.h"
610 #include "missionmessage.h"
611 #include "missiontraining.h"
613 #include "hudtarget.h"
615 #include "eventmusic.h"
616 #include "animplay.h"
617 #include "missionweaponchoice.h"
618 #include "missionlog.h"
619 #include "audiostr.h"
621 #include "missioncampaign.h"
623 #include "missionhotkey.h"
624 #include "objectsnd.h"
625 #include "cmeasure.h"
627 #include "linklist.h"
628 #include "shockwave.h"
629 #include "afterburner.h"
634 #include "stand_gui.h"
635 #include "pcxutils.h"
636 #include "hudtargetbox.h"
637 #include "multi_xfer.h"
638 #include "hudescort.h"
639 #include "multiutil.h"
642 #include "multiteamselect.h"
645 #include "readyroom.h"
646 #include "mainhallmenu.h"
647 #include "multilag.h"
649 #include "particle.h"
651 #include "multi_ingame.h"
652 #include "snazzyui.h"
653 #include "asteroid.h"
654 #include "popupdead.h"
655 #include "multi_voice.h"
656 #include "missioncmdbrief.h"
657 #include "redalert.h"
658 #include "gameplayhelp.h"
659 #include "multilag.h"
660 #include "staticrand.h"
661 #include "multi_pmsg.h"
662 #include "levelpaging.h"
663 #include "observer.h"
664 #include "multi_pause.h"
665 #include "multi_endgame.h"
666 #include "cutscenes.h"
667 #include "multi_respawn.h"
669 #include "multi_obj.h"
670 #include "multi_log.h"
672 #include "localize.h"
673 #include "osregistry.h"
674 #include "barracks.h"
675 #include "missionpause.h"
677 #include "alphacolors.h"
678 #include "objcollide.h"
681 #include "neblightning.h"
682 #include "shipcontrails.h"
685 #include "multi_dogfight.h"
686 #include "multi_rate.h"
687 #include "muzzleflash.h"
691 #include "mainhalltemp.h"
692 #include "exceptionhandler.h"
696 #include "supernova.h"
697 #include "hudshield.h"
698 // #include "names.h"
700 #include "missionloopbrief.h"
704 #error macro FRED is defined when trying to build release Fred. Please undefine FRED macro in build settings
710 // 1.00.04 5/26/98 MWA -- going final (12 pm)
711 // 1.00.03 5/26/98 MWA -- going final (3 am)
712 // 1.00.02 5/25/98 MWA -- going final
713 // 1.00.01 5/25/98 MWA -- going final
714 // 0.90 5/21/98 MWA -- getting ready for final.
715 // 0.10 4/9/98. Set by MK.
717 // Demo version: (obsolete since DEMO codebase split from tree)
718 // 0.03 4/10/98 AL. Interplay rev
719 // 0.02 4/8/98 MK. Increased when this system was modified.
720 // 0.01 4/7/98? AL. First release to Interplay QA.
723 // 1.00 5/28/98 AL. First release to Interplay QA.
725 void game_level_init(int seed = -1);
726 void game_post_level_init();
727 void game_do_frame();
728 void game_update_missiontime(); // called from game_do_frame() and navmap_do_frame()
729 void game_reset_time();
730 void game_show_framerate(); // draws framerate in lower right corner
732 int Game_no_clear = 0;
734 int Pofview_running = 0;
735 int Nebedit_running = 0;
737 typedef struct big_expl_flash {
738 float max_flash_intensity; // max intensity
739 float cur_flash_intensity; // cur intensity
740 int flash_start; // start time
743 #define FRAME_FILTER 16
745 #define DEFAULT_SKILL_LEVEL 1
746 int Game_skill_level = DEFAULT_SKILL_LEVEL;
748 #define VIEWER_ZOOM_DEFAULT 0.75f // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
749 float Viewer_zoom = VIEWER_ZOOM_DEFAULT;
752 #define EXE_FNAME ("fs2.exe")
753 #define LAUNCHER_FNAME ("freespace2.exe")
755 #define EXE_FNAME ("Freespace2demo.app")
756 #define LAUNCHER_FNAME ("Freespace2demo.app")
757 char app_path[] = "Freespace2demo.app/Contents/MacOS/Freespace2demo";
759 #define EXE_FNAME ("Freespace1demo.app")
760 #define LAUNCHER_FNAME ("Freespace1demo.app")
761 char app_path[] = "Freespace1demo.app/Contents/MacOS/Freespace1demo";
763 #define EXE_FNAME ("Freespace1.app")
764 #define LAUNCHER_FNAME ("Freespace1.app")
765 char app_path[] ="Freespace1.app/Contents/MacOS/Freespace1";
767 #define EXE_FNAME ("Freespace2.app")
768 #define LAUNCHER_FNAME ("Freespace2.app")
769 char app_path[] ="Freespace2.app/Contents/MacOS/Freespace2";
773 extern char full_path[1024];
776 // JAS: Code for warphole camera.
777 // Needs to be cleaned up.
778 vector Camera_pos = { 0.0f, 0.0f, 0.0f };
779 vector Camera_velocity = { 0.0f, 0.0f, 0.0f };
780 vector Camera_desired_velocity = { 0.0f, 0.0f, 0.0f };
781 matrix Camera_orient = IDENTITY_MATRIX;
782 float Camera_damping = 1.0f;
783 float Camera_time = 0.0f;
784 float Warpout_time = 0.0f;
785 int Warpout_forced = 0; // Set if this is a forced warpout that cannot be cancelled.
786 int Warpout_sound = -1;
788 int Use_joy_mouse = 0;
789 int Use_palette_flash = 1;
791 int Use_fullscreen_at_startup = 0;
793 int Show_area_effect = 0;
794 object *Last_view_target = NULL;
796 int dogfight_blown = 0;
799 float frametimes[FRAME_FILTER];
800 float frametotal = 0.0f;
804 int Show_framerate = 0;
806 int Show_framerate = 1;
809 int Framerate_cap = 120;
812 int Show_target_debug_info = 0;
813 int Show_target_weapons = 0;
817 static int Show_player_pos = 0; // debug console command to show player world pos on HUD
820 int Debug_octant = -1;
822 fix Game_time_compression = F1_0;
824 // if the ships.tbl the player has is valid
825 int Game_ships_tbl_valid = 0;
827 // if the weapons.tbl the player has is valid
828 int Game_weapons_tbl_valid = 0;
832 extern int Player_attacking_enabled;
836 int Pre_player_entry;
838 int Fred_running = 0;
839 char Game_current_mission_filename[MAX_FILENAME_LEN];
840 int game_single_step = 0;
841 int last_single_step=0;
843 extern int MSG_WINDOW_X_START; // used to position mission_time and shields output
844 extern int MSG_WINDOW_Y_START;
845 extern int MSG_WINDOW_HEIGHT;
847 int game_zbuffer = 1;
848 //static int Game_music_paused;
849 static int Game_paused;
853 #define EXPIRE_BAD_CHECKSUM 1
854 #define EXPIRE_BAD_TIME 2
856 extern void ssm_init();
857 extern void ssm_level_init();
858 extern void ssm_process();
860 // static variable to contain the time this version was built
861 // commented out for now until
862 // I figure out how to get the username into the file
863 //LOCAL char freespace_build_time[] = "Compiled on:"__DATE__" "__TIME__" by "__USER__;
865 // defines and variables used for dumping frame for making trailers.
867 int Debug_dump_frames = 0; // Set to 0 to not dump frames, else equal hz to dump. (15 or 30 probably)
868 int Debug_dump_trigger = 0;
869 int Debug_dump_frame_count;
870 int Debug_dump_frame_num = 0;
871 #define DUMP_BUFFER_NUM_FRAMES 1 // store every 15 frames
874 // amount of time to wait after the player has died before we display the death died popup
875 #define PLAYER_DIED_POPUP_WAIT 2500
876 int Player_died_popup_wait = -1;
877 int Player_multi_died_check = -1;
879 // builtin mission list stuff
881 int Game_builtin_mission_count = 6;
882 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
883 { "SPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
884 { "SPDemo-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
885 { "DemoTrain.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
886 { "Demo.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
887 { "MPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
888 { "Demo-DOG-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
890 #elif defined(FS1_DEMO)
891 int Game_builtin_mission_count = 5;
892 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
893 { "btmdemo.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
894 { "demo.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
895 { "demo01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
896 { "demo02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
897 { "demo02b.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
899 #elif defined(PD_BUILD)
900 int Game_builtin_mission_count = 4;
901 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
902 { "sm1-01.fs2", (FSB_FROM_VOLITION), "" },
903 { "sm1-05.fs2", (FSB_FROM_VOLITION), "" },
904 { "sm1-01", (FSB_FROM_VOLITION), "" },
905 { "sm1-05", (FSB_FROM_VOLITION), "" },
907 #elif defined(MULTIPLAYER_BETA)
908 int Game_builtin_mission_count = 17;
909 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
911 { "md-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
912 { "md-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
913 { "md-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
914 { "md-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
915 { "md-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
916 { "md-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
917 { "md-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
918 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
919 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
920 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
921 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
922 { "m-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
923 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
924 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
925 { "templar-03a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
926 { "templar-04a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
927 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
929 #elif defined(OEM_BUILD)
930 int Game_builtin_mission_count = 17;
931 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
932 // oem version - act 1 only
933 { "freespace2oem.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
936 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
937 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
938 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
939 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
940 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
941 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
942 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
943 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
944 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
945 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
946 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
947 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
948 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
949 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
950 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
951 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 }
953 #elif defined(MAKE_FS1)
954 int Game_builtin_mission_count = 125;
955 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
956 // single player campaign
957 { "freespace.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
960 { "sm1-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
961 { "sm1-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
962 { "sm1-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
963 { "sm1-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
964 { "sm1-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
965 { "sm1-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
966 { "sm1-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
967 { "sm1-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
968 { "sm1-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
969 { "sm1-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
972 { "sm2-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
973 { "sm2-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
974 { "sm2-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
975 { "sm2-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
976 { "sm2-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
977 { "sm2-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
978 { "sm2-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
979 { "sm2-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
980 { "sm2-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
981 { "sm2-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
984 { "sm3-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
985 { "sm3-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
986 { "sm3-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
987 { "sm3-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
988 { "sm3-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
989 { "sm3-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
990 { "sm3-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
991 { "sm3-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
992 { "sm3-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
995 { "t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
996 { "v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
997 { "s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1000 { "btm-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
1001 { "btm-02.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
1002 { "btm-03.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
1003 { "btm-04.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
1004 { "btm-05.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
1007 { "m-hope.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1008 { "m-altair.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1010 { "m-v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1011 { "m-va.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1012 { "m-unstoppable.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1013 { "m-t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1014 { "m-s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1015 { "m-rescue.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1016 { "m-pain.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1017 { "m-orecovery.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1018 { "mm3-01a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1019 { "mm3-02a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1020 { "mm3-03a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1021 { "mm3-04a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1022 { "mm3-05a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1023 { "mm3-06a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1024 { "m-guardduty.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1025 { "m-gate.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1026 { "m-duel.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1027 { "m-convoyassault.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1028 { "m-clash.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1030 // SilentThreat missions
1031 // Main SilentThreat campaign
1032 { "SilentThreat.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN_FILE), "" },
1034 { "md-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1035 { "md-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1036 { "md-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1037 { "md-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1038 { "md-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1039 { "md-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1040 { "md-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1041 { "md-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1042 { "md-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1043 { "md-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1044 { "md-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1045 { "md-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1047 // SilentThreat Part 1 - multi-coop
1048 { "ST-Part1.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1050 { "stmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1051 { "stmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1052 { "stmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1054 // SilentThreat Part 2 - multi-coop
1055 { "ST-Part2.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1057 { "stmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1058 { "stmm-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1059 { "stmm-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1061 // SilentThreat Part 3 - multi-coop
1062 { "ST-Part3.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1064 { "stmm-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1065 { "stmm-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1066 { "stmm-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1068 // SilentThreat Part 4 - multi-coop
1069 { "ST-Part4.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1071 { "stmm-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1072 { "stmm-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1073 { "stmm-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1075 // multiplayer missions
1076 { "mdmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1077 { "mdmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1078 { "mdmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1079 { "mdmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1080 // user supplied missions
1081 { "mdu-02.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1082 { "mdu-03.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1083 { "mdu-04.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1084 { "mdu-05.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1085 { "mdu-06.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1086 { "mdu-07.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1087 { "mdu-08.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1088 { "mdu-09.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1089 { "mdu-10.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1090 { "mdu-11.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1091 { "mdu-12.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1092 { "mdu-13.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1093 { "mdu-14.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1094 { "mdu-15.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1095 { "mdu-16.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1096 { "mdu-17.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1097 { "mdu-18.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1098 { "mdu-19.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1099 { "mdu-20.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1100 { "mdu-21.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1101 { "mdu-22.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1102 { "mdu-23.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1103 { "mdu-24.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1104 { "mdu-25.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1105 { "mdu-26.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1106 { "mdu-27.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1107 { "mdu-28.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1108 { "mdu-29.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1109 { "mdu-30.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1110 { "mdu-31.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1111 { "mdumm-01.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1112 { "mdumm-02.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1115 int Game_builtin_mission_count = 92;
1116 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
1117 // single player campaign
1118 { "freespace2.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
1121 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1122 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1123 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1124 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1125 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1126 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1127 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1128 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1129 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1130 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1131 { "loop1-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1132 { "loop1-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1133 { "loop1-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1134 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1135 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1136 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1137 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1138 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1139 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1142 { "sm2-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1143 { "sm2-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1144 { "sm2-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1145 { "sm2-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1146 { "sm2-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1147 { "sm2-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1148 { "sm2-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1149 { "sm2-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1150 { "sm2-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1151 { "sm2-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1154 { "sm3-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1155 { "sm3-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1156 { "sm3-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1157 { "sm3-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1158 { "sm3-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1159 { "sm3-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1160 { "sm3-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1161 { "sm3-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1162 { "sm3-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1163 { "sm3-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1164 { "loop2-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1165 { "loop2-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1167 // multiplayer missions
1170 { "g-shi.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1171 { "g-ter.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1172 { "g-vas.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1175 { "m-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1176 { "m-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1177 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1178 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1181 { "mdh-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1182 { "mdh-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1183 { "mdh-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1184 { "mdh-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1185 { "mdh-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1186 { "mdh-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1187 { "mdh-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1188 { "mdh-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1189 { "mdh-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1190 { "mdl-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1191 { "mdl-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1192 { "mdl-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1193 { "mdl-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1194 { "mdl-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1195 { "mdl-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1196 { "mdl-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1197 { "mdl-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1198 { "mdl-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1199 { "mdm-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1200 { "mdm-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1201 { "mdm-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1202 { "mdm-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1203 { "mdm-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1204 { "mdm-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1205 { "mdm-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1206 { "mdm-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1207 { "mdm-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1208 { "osdog.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1211 { "mt-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1212 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1213 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1214 { "mt-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1215 { "mt-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1216 { "mt-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1217 { "mt-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1218 { "mt-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1219 { "mt-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1220 { "mt-10.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1223 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1224 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1225 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1226 { "templar-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1227 { "templar-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1232 // Internal function prototypes
1233 void game_maybe_draw_mouse(float frametime);
1234 void init_animating_pointer();
1235 void load_animating_pointer(char *filename, int dx, int dy);
1236 void unload_animating_pointer();
1237 void game_do_training_checks();
1238 void game_shutdown(void);
1239 void game_show_event_debug(float frametime);
1240 void game_event_debug_init();
1242 void demo_upsell_show_screens();
1243 void game_start_subspace_ambient_sound();
1244 void game_stop_subspace_ambient_sound();
1245 void verify_ships_tbl();
1246 void verify_weapons_tbl();
1247 void display_title_screen();
1249 // loading background filenames
1250 static char *Game_loading_bground_fname[GR_NUM_RESOLUTIONS] = {
1251 "LoadingBG", // GR_640
1252 "2_LoadingBG" // GR_1024
1256 static char *Game_loading_ani_fname[GR_NUM_RESOLUTIONS] = {
1257 "Loading.ani", // GR_640
1258 "2_Loading.ani" // GR_1024
1261 #if defined(FS2_DEMO) || defined(FS1_DEMO)
1262 static char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1270 #elif defined(OEM_BUILD)
1271 static char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1281 char Game_CDROM_dir[MAX_PATH_LEN];
1284 // How much RAM is on this machine. Set in WinMain
1285 uint Freespace_total_ram = 0;
1288 float Game_flash_red = 0.0f;
1289 float Game_flash_green = 0.0f;
1290 float Game_flash_blue = 0.0f;
1291 float Sun_spot = 0.0f;
1292 big_expl_flash Big_expl_flash = {0.0f, 0.0f, 0};
1294 // game shudder stuff (in ms)
1295 int Game_shudder_time = -1;
1296 int Game_shudder_total = 0;
1297 float Game_shudder_intensity = 0.0f; // should be between 0.0 and 100.0
1300 sound_env Game_sound_env;
1301 //sound_env Game_default_sound_env = {SND_ENV_AUDITORIUM, 0.25f, 0.35f, 3.0f};
1302 sound_env Game_default_sound_env = {SND_ENV_GENERIC, 0.2F,0.2F,1.0F};
1304 int Game_sound_env_update_timestamp;
1306 // WARPIN CRAP BEGIN --------------------------------------------------------------------------------------------
1309 // WARPIN CRAP END --------------------------------------------------------------------------------------------
1311 fs_builtin_mission *game_find_builtin_mission(char *filename)
1315 // look through all existing builtin missions
1316 for(idx=0; idx<Game_builtin_mission_count; idx++){
1317 if(!stricmp(Game_builtin_mission_list[idx].filename, filename)){
1318 return &Game_builtin_mission_list[idx];
1326 int game_get_default_skill_level()
1328 return DEFAULT_SKILL_LEVEL;
1332 void game_flash_reset()
1334 Game_flash_red = 0.0f;
1335 Game_flash_green = 0.0f;
1336 Game_flash_blue = 0.0f;
1338 Big_expl_flash.max_flash_intensity = 0.0f;
1339 Big_expl_flash.cur_flash_intensity = 0.0f;
1340 Big_expl_flash.flash_start = 0;
1343 float Gf_critical = -1.0f; // framerate we should be above on the average for this mission
1344 float Gf_critical_time = 0.0f; // how much time we've been at the critical framerate
1346 void game_framerate_check_init()
1348 // zero critical time
1349 Gf_critical_time = 0.0f;
1352 if(The_mission.flags & MISSION_FLAG_FULLNEB){
1353 // if this is a glide card
1354 if(gr_screen.mode == GR_GLIDE){
1356 extern GrHwConfiguration hwconfig;
1359 if(hwconfig.SSTs[0].sstBoard.VoodooConfig.fbRam >= 4){
1360 Gf_critical = 15.0f;
1364 Gf_critical = 10.0f;
1369 Gf_critical = 15.0f;
1372 // d3d. only care about good cards here I guess (TNT)
1374 Gf_critical = 15.0f;
1377 // if this is a glide card
1378 if(gr_screen.mode == GR_GLIDE){
1380 extern GrHwConfiguration hwconfig;
1383 if(hwconfig.SSTs[0].sstBoard.VoodooConfig.fbRam >= 4){
1384 Gf_critical = 25.0f;
1388 Gf_critical = 20.0f;
1393 Gf_critical = 25.0f;
1396 // d3d. only care about good cards here I guess (TNT)
1398 Gf_critical = 25.0f;
1403 extern float Framerate;
1404 void game_framerate_check()
1408 // if the current framerate is above the critical level, add frametime
1409 if(Framerate >= Gf_critical){
1410 Gf_critical_time += flFrametime;
1413 if(!Show_framerate){
1417 // display if we're above the critical framerate
1418 if(Framerate < Gf_critical){
1419 gr_set_color_fast(&Color_bright_red);
1420 gr_string(200, y_start, "Framerate warning");
1425 // display our current pct of good frametime
1426 if(f2fl(Missiontime) >= 0.0f){
1427 float pct = (Gf_critical_time / f2fl(Missiontime)) * 100.0f;
1430 gr_set_color_fast(&Color_bright_green);
1432 gr_set_color_fast(&Color_bright_red);
1435 gr_printf(200, y_start, "%d%%", (int)pct);
1442 // Adds a flash effect. These can be positive or negative.
1443 // The range will get capped at around -1 to 1, so stick
1444 // with a range like that.
1445 void game_flash( float r, float g, float b )
1447 Game_flash_red += r;
1448 Game_flash_green += g;
1449 Game_flash_blue += b;
1451 if ( Game_flash_red < -1.0f ) {
1452 Game_flash_red = -1.0f;
1453 } else if ( Game_flash_red > 1.0f ) {
1454 Game_flash_red = 1.0f;
1457 if ( Game_flash_green < -1.0f ) {
1458 Game_flash_green = -1.0f;
1459 } else if ( Game_flash_green > 1.0f ) {
1460 Game_flash_green = 1.0f;
1463 if ( Game_flash_blue < -1.0f ) {
1464 Game_flash_blue = -1.0f;
1465 } else if ( Game_flash_blue > 1.0f ) {
1466 Game_flash_blue = 1.0f;
1471 // Adds a flash for Big Ship explosions
1472 // cap range from 0 to 1
1473 void big_explosion_flash(float flash)
1475 Big_expl_flash.flash_start = timestamp(1);
1479 } else if (flash < 0.0f) {
1483 Big_expl_flash.max_flash_intensity = flash;
1484 Big_expl_flash.cur_flash_intensity = 0.0f;
1487 // Amount to diminish palette towards normal, per second.
1488 #define DIMINISH_RATE 0.75f
1489 #define SUN_DIMINISH_RATE 6.00f
1493 float sn_glare_scale = 1.7f;
1496 dc_get_arg(ARG_FLOAT);
1497 sn_glare_scale = Dc_arg_float;
1500 float Supernova_last_glare = 0.0f;
1501 void game_sunspot_process(float frametime)
1505 float Sun_spot_goal = 0.0f;
1508 sn_stage = supernova_active();
1510 // sunspot differently based on supernova stage
1512 // approaching. player still in control
1515 pct = (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME));
1518 light_get_global_dir(&light_dir, 0);
1520 dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec );
1523 // scale it some more
1524 dot = dot * (0.5f + (pct * 0.5f));
1527 Sun_spot_goal += (dot * sn_glare_scale);
1530 // draw the sun glow
1531 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, 0 ) ) {
1532 // draw the glow for this sun
1533 stars_draw_sun_glow(0);
1536 Supernova_last_glare = Sun_spot_goal;
1539 // camera cut. player not in control. note : at this point camera starts out facing the sun. so we can go nice and bright
1542 Sun_spot_goal = 0.9f;
1543 Sun_spot_goal += (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME)) * 0.1f;
1545 if(Sun_spot_goal > 1.0f){
1546 Sun_spot_goal = 1.0f;
1549 Sun_spot_goal *= sn_glare_scale;
1550 Supernova_last_glare = Sun_spot_goal;
1553 // fade to white. display dead popup
1556 Supernova_last_glare += (2.0f * flFrametime);
1557 if(Supernova_last_glare > 2.0f){
1558 Supernova_last_glare = 2.0f;
1561 Sun_spot_goal = Supernova_last_glare;
1568 // check sunspots for all suns
1569 n_lights = light_get_global_count();
1572 for(idx=0; idx<n_lights; idx++){
1573 //(vector *eye_pos, matrix *eye_orient)
1574 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, idx ) ) {
1577 light_get_global_dir(&light_dir, idx);
1579 float dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec )*0.5f+0.5f;
1581 Sun_spot_goal += (float)pow(dot,85.0f);
1583 // draw the glow for this sun
1584 stars_draw_sun_glow(idx);
1586 Sun_spot_goal = 0.0f;
1592 Sun_spot_goal = 0.0f;
1596 float dec_amount = frametime*SUN_DIMINISH_RATE;
1598 if ( Sun_spot < Sun_spot_goal ) {
1599 Sun_spot += dec_amount;
1600 if ( Sun_spot > Sun_spot_goal ) {
1601 Sun_spot = Sun_spot_goal;
1603 } else if ( Sun_spot > Sun_spot_goal ) {
1604 Sun_spot -= dec_amount;
1605 if ( Sun_spot < Sun_spot_goal ) {
1606 Sun_spot = Sun_spot_goal;
1612 // Call once a frame to diminish the
1613 // flash effect to 0.
1614 void game_flash_diminish(float frametime)
1616 float dec_amount = frametime*DIMINISH_RATE;
1618 if ( Game_flash_red > 0.0f ) {
1619 Game_flash_red -= dec_amount;
1620 if ( Game_flash_red < 0.0f )
1621 Game_flash_red = 0.0f;
1623 Game_flash_red += dec_amount;
1624 if ( Game_flash_red > 0.0f )
1625 Game_flash_red = 0.0f;
1628 if ( Game_flash_green > 0.0f ) {
1629 Game_flash_green -= dec_amount;
1630 if ( Game_flash_green < 0.0f )
1631 Game_flash_green = 0.0f;
1633 Game_flash_green += dec_amount;
1634 if ( Game_flash_green > 0.0f )
1635 Game_flash_green = 0.0f;
1638 if ( Game_flash_blue > 0.0f ) {
1639 Game_flash_blue -= dec_amount;
1640 if ( Game_flash_blue < 0.0f )
1641 Game_flash_blue = 0.0f;
1643 Game_flash_blue += dec_amount;
1644 if ( Game_flash_blue > 0.0f )
1645 Game_flash_blue = 0.0f;
1648 // update big_explosion_cur_flash
1649 #define TIME_UP 1500
1650 #define TIME_DOWN 2500
1651 int duration = TIME_UP + TIME_DOWN;
1652 int time = timestamp_until(Big_expl_flash.flash_start);
1653 if (time > -duration) {
1655 if (time < TIME_UP) {
1656 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * time / (float) TIME_UP;
1659 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * ((float) TIME_DOWN - time) / (float) TIME_DOWN;
1663 if ( Use_palette_flash ) {
1665 // static int or=0, og=0, ob=0;
1667 // Change the 200 to change the color range of colors.
1668 r = fl2i( Game_flash_red*128.0f );
1669 g = fl2i( Game_flash_green*128.0f );
1670 b = fl2i( Game_flash_blue*128.0f );
1672 if ( Sun_spot > 0.0f ) {
1673 r += fl2i(Sun_spot*128.0f);
1674 g += fl2i(Sun_spot*128.0f);
1675 b += fl2i(Sun_spot*128.0f);
1678 if ( Big_expl_flash.cur_flash_intensity > 0.0f ) {
1679 r += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1680 g += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1681 b += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1684 if ( r < 0 ) r = 0; else if ( r > 255 ) r = 255;
1685 if ( g < 0 ) g = 0; else if ( g > 255 ) g = 255;
1686 if ( b < 0 ) b = 0; else if ( b > 255 ) b = 255;
1688 if ( (r!=0) || (g!=0) || (b!=0) ) {
1689 gr_flash( r, g, b );
1691 //mprintf(( "Flash! %d,%d,%d\n", r, g, b ));
1702 void game_level_close()
1704 // De-Initialize the game subsystems
1705 event_music_level_close();
1706 game_stop_looped_sounds();
1708 obj_snd_level_close(); // uninit object-linked persistant sounds
1709 gamesnd_unload_gameplay_sounds(); // unload gameplay sounds from memory
1710 anim_level_close(); // stop and clean up any anim instances
1711 message_mission_shutdown(); // called after anim_level_close() to make sure anim instances are free
1712 shockwave_level_close();
1713 fireball_level_close();
1715 mission_event_shutdown();
1716 asteroid_level_close();
1717 model_cache_reset(); // Reset/free all the model caching stuff
1718 flak_level_close(); // unload flak stuff
1719 neb2_level_close(); // shutdown gaseous nebula stuff
1722 mflash_level_close();
1723 mission_brief_common_reset(); // close out parsed briefing/mission stuff
1725 audiostream_unpause_all();
1730 // intializes game stuff and loads the mission. Returns 0 on failure, 1 on success
1731 // input: seed => DEFAULT PARAMETER (value -1). Only set by demo playback code.
1732 void game_level_init(int seed)
1734 // seed the random number generator
1736 // if no seed was passed, seed the generator either from the time value, or from the
1737 // netgame security flags -- ensures that all players in multiplayer game will have the
1738 // same randon number sequence (with static rand functions)
1739 if ( Game_mode & GM_NORMAL ) {
1740 Game_level_seed = time(NULL);
1742 Game_level_seed = Netgame.security;
1745 // mwa 9/17/98 -- maybe this assert isn't needed????
1746 Assert( !(Game_mode & GM_MULTIPLAYER) );
1747 Game_level_seed = seed;
1749 srand( Game_level_seed );
1751 // semirand function needs to get re-initted every time in multiplayer
1752 if ( Game_mode & GM_MULTIPLAYER ){
1758 Key_normal_game = (Game_mode & GM_NORMAL);
1761 Game_shudder_time = -1;
1763 // Initialize the game subsystems
1764 // timestamp_reset(); // Must be inited before everything else
1766 game_reset_time(); // resets time, and resets saved time too
1768 obj_init(); // Must be inited before the other systems
1769 model_free_all(); // Free all existing models
1770 mission_brief_common_init(); // Free all existing briefing/debriefing text
1771 weapon_level_init();
1772 ai_level_init(); // Call this before ship_init() because it reads ai.tbl.
1774 player_level_init();
1775 shipfx_flash_init(); // Init the ship gun flash system.
1776 game_flash_reset(); // Reset the flash effect
1777 particle_init(); // Reset the particle system
1781 shield_hit_init(); // Initialize system for showing shield hits
1782 radar_mission_init();
1783 mission_init_goals();
1786 obj_snd_level_init(); // init object-linked persistant sounds
1788 shockwave_level_init();
1789 afterburner_level_init();
1790 scoring_level_init( &Player->stats );
1792 asteroid_level_init();
1793 control_config_clear_used_status();
1794 collide_ship_ship_sounds_init();
1796 Pre_player_entry = 1; // Means the player has not yet entered.
1797 Entry_delay_time = 0; // Could get overwritten in mission read.
1798 fireball_preload(); // page in warphole bitmaps
1800 flak_level_init(); // initialize flak - bitmaps, etc
1801 ct_level_init(); // initialize ships contrails, etc
1802 awacs_level_init(); // initialize AWACS
1803 beam_level_init(); // initialize beam weapons
1804 mflash_level_init();
1806 supernova_level_init();
1808 // multiplayer dogfight hack
1811 shipfx_engine_wash_level_init();
1815 Last_view_target = NULL;
1820 // campaign wasn't ended
1821 Campaign_ended_in_mission = 0;
1824 // called when a mission is over -- does server specific stuff.
1825 void freespace_stop_mission()
1828 Game_mode &= ~GM_IN_MISSION;
1831 // called at frame interval to process networking stuff
1832 void game_do_networking()
1834 Assert( Net_player != NULL );
1835 if (!(Game_mode & GM_MULTIPLAYER)){
1839 // see if this player should be reading/writing data. Bit is set when at join
1840 // screen onward until quits back to main menu.
1841 if ( !(Net_player->flags & NETINFO_FLAG_DO_NETWORKING) ){
1845 if(gameseq_get_state()!=GS_STATE_MULTI_PAUSED){
1848 multi_pause_do_frame();
1853 // Loads the best palette for this level, based
1854 // on nebula color and hud color. You could just call palette_load_table with
1855 // the appropriate filename, but who wants to do that.
1856 void game_load_palette()
1858 char palette_filename[1024];
1860 // We only use 3 hud colors right now
1862 Assert( HUD_config.main_color >= 0 );
1863 Assert( HUD_config.main_color <= 2 );
1866 Assert( Mission_palette >= 0 );
1867 Assert( Mission_palette <= 98 );
1870 if ( The_mission.flags & MISSION_FLAG_SUBSPACE ) {
1871 strcpy( palette_filename, NOX("gamepalette-subspace") );
1873 sprintf( palette_filename, NOX("gamepalette%d-%02d"), HUD_config.main_color+1, Mission_palette+1 );
1876 mprintf(( "Loading palette %s\n", palette_filename ));
1878 palette_load_table(palette_filename);
1880 strcpy( palette_filename, NOX("gamepalette-subspace") );
1882 mprintf(( "Loading palette %s\n", palette_filename ));
1886 void game_post_level_init()
1888 // Stuff which gets called after mission is loaded. Because player isn't created until
1889 // after mission loads, some things must get initted after the level loads
1891 model_level_post_init();
1894 hud_setup_escort_list();
1895 mission_hotkey_set_defaults(); // set up the default hotkeys (from mission file)
1901 game_event_debug_init();
1904 training_mission_init();
1905 asteroid_create_all();
1907 game_framerate_check_init();
1911 // An estimate as to how high the count passed to game_loading_callback will go.
1912 // This is just a guess, it seems to always be about the same. The count is
1913 // proportional to the code being executed, not the time, so this works good
1914 // for a bar, assuming the code does about the same thing each time you
1915 // load a level. You can find this value by looking at the return value
1916 // of game_busy_callback(NULL), which I conveniently print out to the
1917 // debug output window with the '=== ENDING LOAD ==' stuff.
1918 //#define COUNT_ESTIMATE 3706
1919 #define COUNT_ESTIMATE 1111
1921 int Game_loading_callback_inited = 0;
1923 int Game_loading_background = -1;
1924 anim * Game_loading_ani = NULL;
1925 anim_instance *Game_loading_ani_instance;
1926 int Game_loading_frame=-1;
1928 static int Game_loading_ani_coords[GR_NUM_RESOLUTIONS][2] = {
1930 #if defined(FS1_DEMO)
1932 #elif defined(MAKE_FS1)
1943 // This gets called 10x per second and count is the number of times
1944 // game_busy() has been called since the current callback function
1946 void game_loading_callback(int count)
1948 game_do_networking();
1950 Assert( Game_loading_callback_inited==1 );
1951 Assert( Game_loading_ani != NULL );
1953 int framenum = ((Game_loading_ani->total_frames*count) / COUNT_ESTIMATE)+1;
1954 if ( framenum > Game_loading_ani->total_frames-1 ) {
1955 framenum = Game_loading_ani->total_frames-1;
1956 } else if ( framenum < 0 ) {
1961 while ( Game_loading_frame < framenum ) {
1962 Game_loading_frame++;
1963 cbitmap = anim_get_next_frame(Game_loading_ani_instance);
1967 if ( cbitmap > -1 ) {
1968 if ( Game_loading_background > -1 ) {
1969 gr_set_bitmap( Game_loading_background );
1973 //mprintf(( "Showing frame %d/%d [ Bitmap=%d ]\n", Game_loading_frame , Game_loading_ani->total_frames, cbitmap ));
1974 gr_set_bitmap( cbitmap );
1975 gr_bitmap(Game_loading_ani_coords[gr_screen.res][0],Game_loading_ani_coords[gr_screen.res][1]);
1977 bm_release(cbitmap);
1983 void game_loading_callback_init()
1985 Assert( Game_loading_callback_inited==0 );
1987 Game_loading_background = bm_load(Game_loading_bground_fname[gr_screen.res]);
1989 common_set_interface_palette("InterfacePalette"); // set the interface palette
1993 Game_loading_ani = anim_load( Game_loading_ani_fname[gr_screen.res]);
1994 Assert( Game_loading_ani != NULL );
1995 Game_loading_ani_instance = init_anim_instance(Game_loading_ani, 16);
1996 Assert( Game_loading_ani_instance != NULL );
1997 Game_loading_frame = -1;
1999 Game_loading_callback_inited = 1;
2001 game_busy_callback( game_loading_callback, (COUNT_ESTIMATE/Game_loading_ani->total_frames)+1 );
2006 void game_loading_callback_close()
2008 Assert( Game_loading_callback_inited==1 );
2010 // Make sure bar shows all the way over.
2011 game_loading_callback(COUNT_ESTIMATE);
2013 int real_count = game_busy_callback( NULL );
2016 Game_loading_callback_inited = 0;
2019 mprintf(( "=================== ENDING LOAD ================\n" ));
2020 mprintf(( "Real count = %d, Estimated count = %d\n", real_count, COUNT_ESTIMATE ));
2021 mprintf(( "================================================\n" ));
2023 // to remove warnings in release build
2027 free_anim_instance(Game_loading_ani_instance);
2028 Game_loading_ani_instance = NULL;
2029 anim_free(Game_loading_ani);
2030 Game_loading_ani = NULL;
2032 bm_release( Game_loading_background );
2033 common_free_interface_palette(); // restore game palette
2034 Game_loading_background = -1;
2036 gr_set_font( FONT1 );
2039 // Update the sound environment (ie change EAX settings based on proximity to large ships)
2041 void game_maybe_update_sound_environment()
2043 // do nothing for now
2046 // Assign the sound environment for the game, based on the current mission
2048 void game_assign_sound_environment()
2051 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
2052 Game_sound_env.id = SND_ENV_DRUGGED;
2053 Game_sound_env.volume = 0.800f;
2054 Game_sound_env.damping = 1.188f;
2055 Game_sound_env.decay = 6.392f;
2057 } else if (Num_asteroids > 30) {
2058 Game_sound_env.id = SND_ENV_AUDITORIUM;
2059 Game_sound_env.volume = 0.603f;
2060 Game_sound_env.damping = 0.5f;
2061 Game_sound_env.decay = 4.279f;
2064 Game_sound_env = Game_default_sound_env;
2068 Game_sound_env = Game_default_sound_env;
2069 Game_sound_env_update_timestamp = timestamp(1);
2072 // function which gets called before actually entering the mission. It is broken down into a funciton
2073 // since it will get called in one place from a single player game and from another place for
2074 // a multiplayer game
2075 void freespace_mission_load_stuff()
2077 // called if we're not on a freespace dedicated (non rendering, no pilot) server
2078 // IE : we _don't_ want to load any sounds or bitmap/texture info on this machine.
2079 if(!(Game_mode & GM_STANDALONE_SERVER)){
2081 mprintf(( "=================== STARTING LEVEL DATA LOAD ==================\n" ));
2083 game_loading_callback_init();
2085 event_music_level_init(); // preloads the first 2 seconds for each event music track
2088 gamesnd_unload_interface_sounds(); // unload interface sounds from memory
2091 gamesnd_preload_common_sounds(); // load in sounds that are expected to play
2094 ship_assign_sound_all(); // assign engine sounds to ships
2095 game_assign_sound_environment(); // assign the sound environment for this mission
2098 // call function in missionparse.cpp to fixup player/ai stuff.
2099 mission_parse_fixup_players();
2102 // Load in all the bitmaps for this level
2107 game_loading_callback_close();
2109 // the only thing we need to call on the standalone for now.
2111 // call function in missionparse.cpp to fixup player/ai stuff.
2112 mission_parse_fixup_players();
2114 // Load in all the bitmaps for this level
2120 uint load_mission_load;
2121 uint load_post_level_init;
2122 uint load_mission_stuff;
2124 // tells the server to load the mission and initialize structures
2125 int game_start_mission()
2127 mprintf(( "=================== STARTING LEVEL LOAD ==================\n" ));
2129 load_gl_init = time(NULL);
2131 load_gl_init = time(NULL) - load_gl_init;
2133 if (Game_mode & GM_MULTIPLAYER) {
2134 Player->flags |= PLAYER_FLAGS_IS_MULTI;
2136 // clear multiplayer stats
2137 init_multiplayer_stats();
2140 load_mission_load = time(NULL);
2141 if (mission_load()) {
2142 if ( !(Game_mode & GM_MULTIPLAYER) ) {
2143 popup(PF_BODY_BIG, 1, POPUP_OK, XSTR( "Attempt to load the mission failed", 169));
2144 gameseq_post_event(GS_EVENT_MAIN_MENU);
2146 multi_quit_game(PROMPT_NONE, MULTI_END_NOTIFY_NONE, MULTI_END_ERROR_LOAD_FAIL);
2151 load_mission_load = time(NULL) - load_mission_load;
2153 // If this is a red alert mission in campaign mode, bash wingman status
2154 if ( (Game_mode & GM_CAMPAIGN_MODE) && red_alert_mission() ) {
2155 red_alert_bash_wingman_status();
2158 // the standalone server in multiplayer doesn't do any rendering, so we will not even bother loading the palette
2159 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
2160 mprintf(( "=================== LOADING GAME PALETTE ================\n" ));
2162 game_load_palette();
2166 load_post_level_init = time(NULL);
2167 game_post_level_init();
2168 load_post_level_init = time(NULL) - load_post_level_init;
2172 void Do_model_timings_test();
2173 Do_model_timings_test();
2177 load_mission_stuff = time(NULL);
2178 freespace_mission_load_stuff();
2179 load_mission_stuff = time(NULL) - load_mission_stuff;
2184 int Interface_framerate = 0;
2187 DCF_BOOL( mouse_control, Use_mouse_to_fly )
2188 DCF_BOOL( show_framerate, Show_framerate )
2189 DCF_BOOL( show_target_debug_info, Show_target_debug_info )
2190 DCF_BOOL( show_target_weapons, Show_target_weapons )
2191 DCF_BOOL( lead_target_cheat, Players[Player_num].lead_target_cheat )
2192 DCF_BOOL( sound, Sound_enabled )
2193 DCF_BOOL( zbuffer, game_zbuffer )
2194 DCF_BOOL( shield_system, New_shield_system )
2195 DCF_BOOL( show_shield_mesh, Show_shield_mesh)
2196 DCF_BOOL( player_attacking, Player_attacking_enabled )
2197 DCF_BOOL( show_waypoints, Show_waypoints )
2198 DCF_BOOL( show_area_effect, Show_area_effect )
2199 DCF_BOOL( show_net_stats, Show_net_stats )
2200 DCF_BOOL( log, Log_debug_output_to_file )
2201 DCF_BOOL( training_msg_method, Training_msg_method )
2202 DCF_BOOL( show_player_pos, Show_player_pos )
2203 DCF_BOOL(i_framerate, Interface_framerate )
2205 DCF(show_mem,"Toggles showing mem usage")
2208 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2209 if ( Dc_arg_type & ARG_TRUE ) Show_mem = 1;
2210 else if ( Dc_arg_type & ARG_FALSE ) Show_mem = 0;
2211 else if ( Dc_arg_type & ARG_NONE ) Show_mem ^= 1;
2217 if ( Dc_help ) dc_printf( "Usage: Show_mem\nSets show_mem to true or false. If nothing passed, then toggles it.\n" );
2219 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2220 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2224 DCF(show_cpu,"Toggles showing cpu usage")
2227 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2228 if ( Dc_arg_type & ARG_TRUE ) Show_cpu = 1;
2229 else if ( Dc_arg_type & ARG_FALSE ) Show_cpu = 0;
2230 else if ( Dc_arg_type & ARG_NONE ) Show_cpu ^= 1;
2236 if ( Dc_help ) dc_printf( "Usage: Show_cpu\nSets show_cpu to true or false. If nothing passed, then toggles it.\n" );
2238 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2239 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2246 // AL 4-8-98: always allow players to display their framerate
2249 DCF_BOOL( show_framerate, Show_framerate )
2256 DCF(use_joy_mouse,"Makes joystick move mouse cursor")
2259 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2260 if ( Dc_arg_type & ARG_TRUE ) Use_joy_mouse = 1;
2261 else if ( Dc_arg_type & ARG_FALSE ) Use_joy_mouse = 0;
2262 else if ( Dc_arg_type & ARG_NONE ) Use_joy_mouse ^= 1;
2264 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" );
2265 if ( Dc_status ) dc_printf( "use_joy_mouse is %s\n", (Use_joy_mouse?"TRUE":"FALSE") );
2267 os_config_write_uint( NULL, NOX("JoystickMovesCursor"), Use_joy_mouse );
2270 DCF(palette_flash,"Toggles palette flash effect on/off")
2273 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2274 if ( Dc_arg_type & ARG_TRUE ) Use_palette_flash = 1;
2275 else if ( Dc_arg_type & ARG_FALSE ) Use_palette_flash = 0;
2276 else if ( Dc_arg_type & ARG_NONE ) Use_palette_flash ^= 1;
2278 if ( Dc_help ) dc_printf( "Usage: palette_flash [bool]\nSets palette_flash to true or false. If nothing passed, then toggles it.\n" );
2279 if ( Dc_status ) dc_printf( "palette_flash is %s\n", (Use_palette_flash?"TRUE":"FALSE") );
2282 int Use_low_mem = 0;
2284 DCF(low_mem,"Uses low memory settings regardless of RAM")
2287 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2288 if ( Dc_arg_type & ARG_TRUE ) Use_low_mem = 1;
2289 else if ( Dc_arg_type & ARG_FALSE ) Use_low_mem = 0;
2290 else if ( Dc_arg_type & ARG_NONE ) Use_low_mem ^= 1;
2292 if ( Dc_help ) dc_printf( "Usage: low_mem [bool]\nSets low_mem to true or false. If nothing passed, then toggles it.\n" );
2293 if ( Dc_status ) dc_printf( "low_mem is %s\n", (Use_low_mem?"TRUE":"FALSE") );
2295 os_config_write_uint( NULL, NOX("LowMem"), Use_low_mem );
2301 DCF(force_fullscreen, "Forces game to startup in fullscreen mode")
2304 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2305 if ( Dc_arg_type & ARG_TRUE ) Use_fullscreen_at_startup = 1;
2306 else if ( Dc_arg_type & ARG_FALSE ) Use_fullscreen_at_startup = 0;
2307 else if ( Dc_arg_type & ARG_NONE ) Use_fullscreen_at_startup ^= 1;
2309 if ( Dc_help ) dc_printf( "Usage: force_fullscreen [bool]\nSets force_fullscreen to true or false. If nothing passed, then toggles it.\n" );
2310 if ( Dc_status ) dc_printf( "force_fullscreen is %s\n", (Use_fullscreen_at_startup?"TRUE":"FALSE") );
2311 os_config_write_uint( NULL, NOX("ForceFullscreen"), Use_fullscreen_at_startup );
2315 int Framerate_delay = 0;
2317 float Freespace_gamma = 1.0f;
2319 DCF(gamma,"Sets Gamma factor")
2322 dc_get_arg(ARG_FLOAT|ARG_NONE);
2323 if ( Dc_arg_type & ARG_FLOAT ) {
2324 Freespace_gamma = Dc_arg_float;
2326 dc_printf( "Gamma reset to 1.0f\n" );
2327 Freespace_gamma = 1.0f;
2329 if ( Freespace_gamma < 0.1f ) {
2330 Freespace_gamma = 0.1f;
2331 } else if ( Freespace_gamma > 5.0f ) {
2332 Freespace_gamma = 5.0f;
2334 gr_set_gamma(Freespace_gamma);
2336 char tmp_gamma_string[32];
2337 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2338 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2342 dc_printf( "Usage: gamma <float>\n" );
2343 dc_printf( "Sets gamma in range 1-3, no argument resets to default 1.2\n" );
2344 Dc_status = 0; // don't print status if help is printed. Too messy.
2348 dc_printf( "Gamma = %.2f\n", Freespace_gamma );
2357 Game_current_mission_filename[0] = 0;
2359 // seed the random number generator
2360 Game_init_seed = time(NULL);
2361 srand( Game_init_seed );
2363 Framerate_delay = 0;
2369 extern void bm_init();
2375 // Initialize the timer before the os
2383 GetCurrentDirectory(1024, whee);
2386 full_path[strlen(full_path) - strlen(app_path)] = '\0';
2387 strcpy( whee, full_path);
2389 getcwd (whee, 1024);
2392 strcat(whee, EXE_FNAME);
2394 //Initialize the libraries
2395 s1 = timer_get_milliseconds();
2396 if(cfile_init(whee, Game_CDROM_dir)){ // initialize before calling any cfopen stuff!!!
2399 e1 = timer_get_milliseconds();
2401 // time a bunch of cfopens
2403 s2 = timer_get_milliseconds();
2405 for(int idx=0; idx<10000; idx++){
2406 whee = cfopen("capital01.pof", "rb", CFILE_NORMAL, CF_TYPE_MODELS);
2411 //cf_exist("capital01.pof", CF_TYPE_MODELS);
2413 e2 = timer_get_milliseconds();
2416 if (Is_standalone) {
2417 std_init_standalone();
2419 os_init( Osreg_class_name, Osreg_app_name );
2420 os_set_title(Osreg_title);
2423 // initialize localization module. Make sure this is down AFTER initialzing OS.
2424 // int t1 = timer_get_milliseconds();
2425 lcl_init( detect_lang() );
2427 // mprintf(("LCL_INIT() TOOK %d MS\n", timer_get_milliseconds()-t1));
2429 // verify that he has a valid ships.tbl (will Game_ships_tbl_valid if so)
2432 // verify that he has a valid weapons.tbl
2433 verify_weapons_tbl();
2435 // Output version numbers to registry for auto patching purposes
2436 os_config_write_uint(NOX("Version"), NOX("Major"), FS_VERSION_MAJOR);
2437 os_config_write_uint(NOX("Version"), NOX("Minor"), FS_VERSION_MINOR);
2438 os_config_write_uint(NOX("Version"), NOX("Build"), FS_VERSION_BUILD);
2440 Use_joy_mouse = 0; //os_config_read_uint( NULL, NOX("JoystickMovesCursor"), 1 );
2441 //Use_palette_flash = os_config_read_uint( NULL, NOX("PaletteFlash"), 0 );
2442 Use_low_mem = os_config_read_uint( NULL, NOX("LowMem"), 0 );
2445 Use_fullscreen_at_startup = os_config_read_uint( NULL, NOX("ForceFullscreen"), 1 );
2448 #if defined (PLAT_UNIX) && defined(RELEASE_REAL)
2449 // show the FPS counter if the config file says so
2450 Show_framerate = os_config_read_uint( NULL, NOX("ShowFPS"), 0 );
2453 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
2454 Asteroids_enabled = 1;
2457 /////////////////////////////
2459 /////////////////////////////
2464 ptr = os_config_read_string(NULL, NOX("Soundcard"), NULL);
2465 mprintf(("soundcard = %s\n", ptr ? ptr : "<nothing>"));
2467 if (!stricmp(ptr, NOX("no sound"))) {
2468 Cmdline_freespace_no_sound = 1;
2470 } else if (!stricmp(ptr, NOX("Aureal A3D"))) {
2472 } else if (!stricmp(ptr, NOX("EAX"))) {
2477 if (!Is_standalone) {
2478 snd_init(use_a3d, use_eax);
2480 /////////////////////////////
2482 /////////////////////////////
2484 ptr = os_config_read_string(NULL, NOX("Videocard"), NULL);
2487 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);
2489 // fire up the UpdateLauncher executable
2491 PROCESS_INFORMATION pi;
2493 memset( &si, 0, sizeof(STARTUPINFO) );
2496 BOOL ret = CreateProcess( LAUNCHER_FNAME, // pointer to name of executable module
2497 NULL, // pointer to command line string
2498 NULL, // pointer to process security attributes
2499 NULL, // pointer to thread security attributes
2500 FALSE, // handle inheritance flag
2501 CREATE_DEFAULT_ERROR_MODE, // creation flags
2502 NULL, // pointer to new environment block
2503 NULL, // pointer to current directory name
2504 &si, // pointer to STARTUPINFO
2505 &pi // pointer to PROCESS_INFORMATION
2508 // If the Launcher could not be started up, let the user know
2510 MessageBox((HWND)os_get_window(), XSTR("The Launcher could not be restarted.", 1450), XSTR("Error", 1451), MB_OK);
2519 if(!stricmp(ptr, "Aucune accélération 3D") || !stricmp(ptr, "Keine 3D-Beschleunigerkarte") || !stricmp(ptr, "No 3D acceleration")){
2521 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);
2529 // check for hi res pack file
2530 int has_sparky_hi = 0;
2532 // check if sparky_hi exists -- access mode 0 means does file exist
2533 #ifndef MAKE_FS1 // shoudn't have it so don't check
2536 if ( _access("sparky_hi_fs2.vp", 0) == 0) {
2539 mprintf(("No sparky_hi_fs2.vp in directory %s\n", dir));
2543 // see if we've got 32 bit in the string
2544 if(strstr(ptr, "32 bit")){
2551 if (!Is_standalone && ptr && (strstr(ptr, NOX("3DFX Glide")))) {
2553 // always 640 for E3
2554 gr_init(GR_640, GR_GLIDE);
2556 // regular or hi-res ?
2558 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2560 if(strstr(ptr, NOX("(1024x768)"))){
2562 gr_init(GR_1024, GR_GLIDE);
2564 gr_init(GR_640, GR_GLIDE);
2567 } else if (!Is_standalone && ptr && (strstr(ptr, NOX("Direct 3D -") ))) {
2569 // always 640 for E3
2571 gr_init(GR_640, GR_DIRECT3D, depth);
2573 // regular or hi-res ?
2575 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2577 if(strstr(ptr, NOX("(1024x768)"))){
2581 gr_init(GR_1024, GR_DIRECT3D, depth);
2585 gr_init(GR_640, GR_DIRECT3D, depth);
2591 if ( Use_fullscreen_at_startup && !Is_standalone) {
2592 gr_init(GR_640, GR_DIRECTDRAW);
2594 gr_init(GR_640, GR_SOFTWARE);
2597 if ( !Is_standalone ) {
2598 gr_init(GR_640, GR_DIRECTDRAW);
2600 gr_init(GR_640, GR_SOFTWARE);
2605 if (!Is_standalone /* && ptr && (strstr(ptr, NOX("OpenGL"))) */) {
2606 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2607 gr_init(GR_1024, GR_OPENGL);
2609 gr_init(GR_640, GR_OPENGL);
2613 gr_init(GR_640, GR_SOFTWARE);
2615 #endif // !PLAT_UNIX
2618 extern int Gr_inited;
2619 if(trying_d3d && !Gr_inited){
2621 extern char Device_init_error[512];
2622 MessageBox( NULL, Device_init_error, "Error intializing Direct3D", MB_OK|MB_TASKMODAL|MB_SETFOREGROUND );
2631 ptr = os_config_read_string(NULL,NOX("Gamma"),NOX("1.80"));
2632 Freespace_gamma = (float)atof(ptr);
2633 if ( Freespace_gamma == 0.0f ) {
2634 Freespace_gamma = 1.80f;
2635 } else if ( Freespace_gamma < 0.1f ) {
2636 Freespace_gamma = 0.1f;
2637 } else if ( Freespace_gamma > 5.0f ) {
2638 Freespace_gamma = 5.0f;
2640 char tmp_gamma_string[32];
2641 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2642 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2644 gr_set_gamma(Freespace_gamma);
2646 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
2649 display_title_screen();
2653 // attempt to load up master tracker registry info (login and password)
2654 Multi_tracker_id = -1;
2656 // pxo login and password
2657 ptr = os_config_read_string(NOX("PXO"),NOX("Login"),NULL);
2659 nprintf(("Network","Error reading in PXO login data\n"));
2660 strcpy(Multi_tracker_login,"");
2662 strcpy(Multi_tracker_login,ptr);
2664 ptr = os_config_read_string(NOX("PXO"),NOX("Password"),NULL);
2666 nprintf(("Network","Error reading PXO password\n"));
2667 strcpy(Multi_tracker_passwd,"");
2669 strcpy(Multi_tracker_passwd,ptr);
2672 // pxo squad name and password
2673 ptr = os_config_read_string(NOX("PXO"),NOX("SquadName"),NULL);
2675 nprintf(("Network","Error reading in PXO squad name\n"));
2676 strcpy(Multi_tracker_squad_name, "");
2678 strcpy(Multi_tracker_squad_name, ptr);
2681 // If less than 48MB of RAM, use low memory model.
2684 (Freespace_total_ram < 48*1024*1024) ||
2687 mprintf(( "Using normal memory settings...\n" ));
2688 bm_set_low_mem(1); // Use every other frame of bitmaps
2690 mprintf(( "Using high memory settings...\n" ));
2691 bm_set_low_mem(0); // Use all frames of bitmaps
2694 // load non-darkening pixel defs
2695 palman_load_pixels();
2697 // hud shield icon stuff
2698 hud_shield_game_init();
2700 control_config_common_init(); // sets up localization stuff in the control config
2706 gamesnd_parse_soundstbl();
2711 // standalone's don't use hte joystick and it seems to sometimes cause them to not get shutdown properly
2716 player_controls_init();
2719 //if(!Is_standalone){
2727 ship_init(); // read in ships.tbl
2729 mission_campaign_init(); // load in the default campaign
2731 // navmap_init(); // init the navigation map system
2732 context_help_init();
2733 techroom_intel_init(); // parse species.tbl, load intel info
2735 psnet_init( Multi_options_g.protocol, Multi_options_g.port ); // initialize the networking code
2736 init_animating_pointer();
2738 mission_brief_common_init(); // Mark all the briefing structures as empty.
2739 gr_font_init(); // loads up all fonts
2741 neb2_init(); // fullneb stuff
2745 player_tips_init(); // helpful tips
2748 // load the list of pilot pic filenames (for barracks and pilot select popup quick reference)
2749 pilot_load_pic_list();
2750 pilot_load_squad_pic_list();
2752 load_animating_pointer(NOX("cursor"), 0, 0);
2754 // initialize alpha colors
2755 alpha_colors_init();
2758 // Game_music_paused = 0;
2765 nprintf(("General", "Ships.tbl is : %s\n", Game_ships_tbl_valid ? "VALID" : "INVALID!!!!"));
2766 nprintf(("General", "Weapons.tbl is : %s\n", Game_weapons_tbl_valid ? "VALID" : "INVALID!!!!"));
2768 mprintf(("cfile_init() took %d\n", e1 - s1));
2769 // mprintf(("1000 cfopens() took %d\n", e2 - s2));
2772 char transfer_text[128];
2774 float Start_time = 0.0f;
2776 float Framerate = 0.0f;
2778 float Timing_total = 0.0f;
2779 float Timing_render2 = 0.0f;
2780 float Timing_render3 = 0.0f;
2781 float Timing_flip = 0.0f;
2782 float Timing_clear = 0.0f;
2784 MONITOR(NumPolysDrawn);
2790 void game_get_framerate()
2792 char text[128] = "";
2794 if ( frame_int == -1 ) {
2796 for (i=0; i<FRAME_FILTER; i++ ) {
2797 frametimes[i] = 0.0f;
2802 frametotal -= frametimes[frame_int];
2803 frametotal += flFrametime;
2804 frametimes[frame_int] = flFrametime;
2805 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2807 if ( frametotal != 0.0 ) {
2808 if ( Framecount >= FRAME_FILTER )
2809 Framerate = FRAME_FILTER / frametotal;
2811 Framerate = Framecount / frametotal;
2812 sprintf( text, NOX("FPS: %.1f"), Framerate );
2814 sprintf( text, NOX("FPS: ?") );
2818 if (Show_framerate) {
2819 gr_set_color_fast(&HUD_color_debug);
2820 gr_string( 570, 2, text );
2824 void game_show_framerate()
2828 cur_time = f2fl(timer_get_approx_seconds());
2829 if (cur_time - Start_time > 30.0f) {
2830 mprintf(("%i frames executed in %7.3f seconds, %7.3f frames per second.\n", Framecount, cur_time - Start_time, Framecount/(cur_time - Start_time)));
2831 Start_time += 1000.0f;
2834 //mprintf(( "%s\n", text ));
2837 if ( Debug_dump_frames )
2841 // possibly show control checking info
2842 control_check_indicate();
2844 // int bitmaps_used_this_frame, bitmaps_new_this_frame;
2845 // bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
2846 // MONITOR_INC(BmpUsed, bitmaps_used_this_frame);
2847 // MONITOR_INC(BmpNew, bitmaps_new_this_frame);
2850 if ( Show_cpu == 1 ) {
2855 dy = gr_get_font_height() + 1;
2857 gr_set_color_fast(&HUD_color_debug);
2861 extern int D3D_textures_in;
2862 extern int D3D_textures_in_frame;
2863 extern int Glide_textures_in;
2864 extern int Glide_textures_in_frame;
2865 extern int Glide_explosion_vram;
2866 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2868 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame+D3D_textures_in_frame)/1024 );
2870 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2874 // gr_printf( sx, sy, "BPP: %d", gr_screen.bits_per_pixel );
2876 gr_printf( sx, sy, NOX("DMA: %s"), transfer_text );
2878 gr_printf( sx, sy, NOX("POLYP: %d"), modelstats_num_polys );
2880 gr_printf( sx, sy, NOX("POLYD: %d"), modelstats_num_polys_drawn );
2882 gr_printf( sx, sy, NOX("VERTS: %d"), modelstats_num_verts );
2887 extern int Num_pairs; // Number of object pairs that were checked.
2888 gr_printf( sx, sy, NOX("PAIRS: %d"), Num_pairs );
2891 extern int Num_pairs_checked; // What percent of object pairs were checked.
2892 gr_printf( sx, sy, NOX("FVI: %d"), Num_pairs_checked );
2894 Num_pairs_checked = 0;
2898 gr_printf( sx, sy, NOX("Snds: %d"), snd_num_playing() );
2901 if ( Timing_total > 0.01f ) {
2902 gr_printf( sx, sy, NOX("CLEAR: %.0f%%"), Timing_clear*100.0f/Timing_total );
2904 gr_printf( sx, sy, NOX("REND2D: %.0f%%"), Timing_render2*100.0f/Timing_total );
2906 gr_printf( sx, sy, NOX("REND3D: %.0f%%"), Timing_render3*100.0f/Timing_total );
2908 gr_printf( sx, sy, NOX("FLIP: %.0f%%"), Timing_flip*100.0f/Timing_total );
2910 gr_printf( sx, sy, NOX("GAME: %.0f%%"), (Timing_total-(Timing_render2+Timing_render3+Timing_flip+Timing_clear))*100.0f/Timing_total );
2920 dy = gr_get_font_height() + 1;
2922 gr_set_color_fast(&HUD_color_debug);
2925 extern int TotalRam;
2926 gr_printf( sx, sy, NOX("DYN: %d KB\n"), TotalRam/1024 );
2931 extern int Model_ram;
2932 gr_printf( sx, sy, NOX("POF: %d KB\n"), Model_ram/1024 );
2936 gr_printf( sx, sy, NOX("BMP: %d KB\n"), bm_texture_ram/1024 );
2938 gr_printf( sx, sy, NOX("S-SRAM: %d KB\n"), Snd_sram/1024 ); // mem used to store game sound
2940 gr_printf( sx, sy, NOX("S-HRAM: %d KB\n"), Snd_hram/1024 ); // mem used to store game sound
2944 extern int D3D_textures_in;
2945 extern int Glide_textures_in;
2946 extern int Glide_textures_in_frame;
2947 extern int Glide_explosion_vram;
2948 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2950 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame)/1024 );
2952 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2959 if ( Show_player_pos ) {
2963 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));
2966 MONITOR_INC(NumPolys, modelstats_num_polys);
2967 MONITOR_INC(NumPolysDrawn, modelstats_num_polys_drawn );
2968 MONITOR_INC(NumVerts, modelstats_num_verts );
2970 modelstats_num_polys = 0;
2971 modelstats_num_polys_drawn = 0;
2972 modelstats_num_verts = 0;
2973 modelstats_num_sortnorms = 0;
2977 void game_show_standalone_framerate()
2979 float frame_rate=30.0f;
2980 if ( frame_int == -1 ) {
2982 for (i=0; i<FRAME_FILTER; i++ ) {
2983 frametimes[i] = 0.0f;
2988 frametotal -= frametimes[frame_int];
2989 frametotal += flFrametime;
2990 frametimes[frame_int] = flFrametime;
2991 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2993 if ( frametotal != 0.0 ) {
2994 if ( Framecount >= FRAME_FILTER ){
2995 frame_rate = FRAME_FILTER / frametotal;
2997 frame_rate = Framecount / frametotal;
3000 std_set_standalone_fps(frame_rate);
3004 // function to show the time remaining in a mission. Used only when the end-mission sexpression is used
3005 void game_show_time_left()
3009 // mission_end_time is a global from missionparse.cpp that contains the mission time at which the
3010 // mission should end (in fixed seconds). There is code in missionparse.cpp which actually handles
3011 // checking how much time is left
3013 if ( Mission_end_time == -1 ){
3017 diff = f2i(Mission_end_time - Missiontime);
3018 // be sure to bash to 0. diff could be negative on frame that we quit mission
3023 hud_set_default_color();
3024 gr_printf( 5, 40, XSTR( "Mission time remaining: %d seconds", 179), diff );
3027 //========================================================================================
3028 //=================== NEW DEBUG CONSOLE COMMANDS TO REPLACE OLD DEBUG PAUSE MENU =========
3029 //========================================================================================
3033 DCF(ai_pause,"Pauses ai")
3036 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
3037 if ( Dc_arg_type & ARG_TRUE ) ai_paused = 1;
3038 else if ( Dc_arg_type & ARG_FALSE ) ai_paused = 0;
3039 else if ( Dc_arg_type & ARG_NONE ) ai_paused = !ai_paused;
3042 obj_init_all_ships_physics();
3045 if ( Dc_help ) dc_printf( "Usage: ai_paused [bool]\nSets ai_paused to true or false. If nothing passed, then toggles it.\n" );
3046 if ( Dc_status ) dc_printf( "ai_paused is %s\n", (ai_paused?"TRUE":"FALSE") );
3049 DCF(single_step,"Single steps the game")
3052 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
3053 if ( Dc_arg_type & ARG_TRUE ) game_single_step = 1;
3054 else if ( Dc_arg_type & ARG_FALSE ) game_single_step = 0;
3055 else if ( Dc_arg_type & ARG_NONE ) game_single_step = !game_single_step;
3057 last_single_step = 0; // Make so single step waits a frame before stepping
3060 if ( Dc_help ) dc_printf( "Usage: single_step [bool]\nSets single_step to true or false. If nothing passed, then toggles it.\n" );
3061 if ( Dc_status ) dc_printf( "single_step is %s\n", (game_single_step?"TRUE":"FALSE") );
3064 DCF_BOOL(physics_pause, physics_paused)
3065 DCF_BOOL(ai_rendering, Ai_render_debug_flag)
3066 DCF_BOOL(ai_firing, Ai_firing_enabled )
3068 // Create some simple aliases to these commands...
3069 debug_command dc_s("s","shortcut for single_step",dcf_single_step);
3070 debug_command dc_p("p","shortcut for physics_pause", dcf_physics_pause );
3071 debug_command dc_r("r","shortcut for ai_rendering", dcf_ai_rendering );
3072 debug_command dc_f("f","shortcut for ai_firing", dcf_ai_firing);
3073 debug_command dc_a("a","shortcut for ai_pause", dcf_ai_pause);
3076 //========================================================================================
3077 //========================================================================================
3080 void game_training_pause_do()
3084 key = game_check_key();
3086 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
3093 void game_increase_skill_level()
3096 if (Game_skill_level >= NUM_SKILL_LEVELS){
3097 Game_skill_level = 0;
3101 int Player_died_time;
3103 int View_percent = 100;
3106 DCF(view, "Sets the percent of the 3d view to render.")
3109 dc_get_arg(ARG_INT);
3110 if ( (Dc_arg_int >= 5 ) || (Dc_arg_int <= 100) ) {
3111 View_percent = Dc_arg_int;
3113 dc_printf( "Illegal value for view. (Must be from 5-100) \n\n");
3119 dc_printf("Usage: view [n]\nwhere n is percent of view to show (5-100).\n");
3123 dc_printf("View is set to %d%%\n", View_percent );
3128 // Set the clip region for the 3d rendering window
3129 void game_set_view_clip()
3131 if ((Game_mode & GM_DEAD) || (supernova_active() >= 2)) {
3132 // Set the clip region for the letterbox "dead view"
3133 int yborder = gr_screen.max_h/4;
3135 // Numeric constants encouraged by J "pig farmer" S, who shall remain semi-anonymous.
3136 // J.S. I've changed my ways!! See the new "no constants" code!!!
3137 gr_set_clip(0, yborder, gr_screen.max_w, gr_screen.max_h - yborder*2 );
3139 // Set the clip region for normal view
3140 if ( View_percent >= 100 ) {
3143 int xborder, yborder;
3145 if ( View_percent < 5 ) {
3149 float fp = i2fl(View_percent)/100.0f;
3150 int fi = fl2i(fl_sqrt(fp)*100.0f);
3151 if ( fi > 100 ) fi=100;
3153 xborder = ( gr_screen.max_w*(100-fi) )/200;
3154 yborder = ( gr_screen.max_h*(100-fi) )/200;
3156 gr_set_clip(xborder, yborder, gr_screen.max_w-xborder*2,gr_screen.max_h-yborder*2 );
3162 void show_debug_stuff()
3165 int laser_count = 0, missile_count = 0;
3167 for (i=0; i<MAX_OBJECTS; i++) {
3168 if (Objects[i].type == OBJ_WEAPON){
3169 if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_LASER){
3171 } else if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_MISSILE){
3177 nprintf(("Mike", "Frame: %i Lasers: %4i, Missiles: %4i\n", Framecount, laser_count, missile_count));
3180 extern int Tool_enabled;
3185 int tst_bitmap = -1;
3187 float tst_offset, tst_offset_total;
3190 void game_tst_frame_pre()
3198 g3_rotate_vertex(&v, &tst_pos);
3199 g3_project_vertex(&v);
3202 if(!((v.sx >= 0) && (v.sx <= gr_screen.max_w) && (v.sy >= 0) && (v.sy <= gr_screen.max_h))){
3206 // big ship? always tst
3208 // within 3000 meters
3209 if( vm_vec_dist_quick(&tst_pos, &Eye_position) <= 3000.0f){
3213 // within 300 meters
3214 if( (vm_vec_dist_quick(&tst_pos, &Eye_position) <= 300.0f) && ((tst_time == 0) || ((time(NULL) - tst_time) >= 10)) ){
3221 void game_tst_frame()
3231 tst_time = time(NULL);
3233 // load the tst bitmap
3234 switch((int)frand_range(0.0f, 3.0)){
3236 tst_bitmap = bm_load("ig_jim");
3238 mprintf(("TST 0\n"));
3242 tst_bitmap = bm_load("ig_kan");
3244 mprintf(("TST 1\n"));
3248 tst_bitmap = bm_load("ig_jim");
3250 mprintf(("TST 2\n"));
3254 tst_bitmap = bm_load("ig_kan");
3256 mprintf(("TST 3\n"));
3265 // get the tst bitmap dimensions
3267 bm_get_info(tst_bitmap, &w, &h);
3270 tst_y = frand_range(0.0f, (float)gr_screen.max_h - h);
3272 snd_play(&Snds[SND_VASUDAN_BUP]);
3274 // tst x and direction
3278 tst_offset_total = (float)w;
3279 tst_offset = (float)w;
3281 tst_x = (float)gr_screen.max_w;
3282 tst_offset_total = (float)-w;
3283 tst_offset = (float)w;
3291 float diff = (tst_offset_total / 0.5f) * flFrametime;
3297 tst_offset -= fl_abs(diff);
3298 } else if(tst_mode == 2){
3301 tst_offset -= fl_abs(diff);
3305 gr_set_bitmap(tst_bitmap);
3306 gr_bitmap((int)tst_x, (int)tst_y);
3309 if(timestamp_elapsed_safe(tst_stamp, 1100)){
3313 // if we passed the switch point
3314 if(tst_offset <= 0.0f){
3319 tst_stamp = timestamp(1000);
3320 tst_offset = fl_abs(tst_offset_total);
3331 void game_tst_mark(object *objp, ship *shipp)
3340 if((objp == NULL) || (shipp == NULL) || (shipp->ship_info_index < 0) || (shipp->ship_info_index >= Num_ship_types)){
3343 sip = &Ship_info[shipp->ship_info_index];
3350 tst_pos = objp->pos;
3351 if(sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)){
3357 extern void render_shields();
3359 void player_repair_frame(float frametime)
3361 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
3363 for(idx=0;idx<MAX_PLAYERS;idx++){
3366 np = &Net_players[idx];
3368 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)){
3370 // don't rearm/repair if the player is dead or dying/departing
3371 if ( !NETPLAYER_IS_DEAD(np) && !(Ships[Objects[np->player->objnum].instance].flags & (SF_DYING|SF_DEPARTING)) ) {
3372 ai_do_repair_frame(&Objects[Net_players[idx].player->objnum],&Ai_info[Ships[Objects[Net_players[idx].player->objnum].instance].ai_index],frametime);
3377 if ( (Player_obj != NULL) && (Player_obj->type == OBJ_SHIP) && !(Game_mode & GM_STANDALONE_SERVER) && (Player_ship != NULL) && !(Player_ship->flags & SF_DYING) ) {
3378 ai_do_repair_frame(Player_obj, &Ai_info[Ships[Player_obj->instance].ai_index], frametime);
3384 #define NUM_FRAMES_TEST 300
3385 #define NUM_MIXED_SOUNDS 16
3386 void do_timing_test(float flFrametime)
3388 static int framecount = 0;
3389 static int test_running = 0;
3390 static float test_time = 0.0f;
3392 static int snds[NUM_MIXED_SOUNDS];
3395 if ( test_running ) {
3397 test_time += flFrametime;
3398 if ( framecount >= NUM_FRAMES_TEST ) {
3400 nprintf(("General", "%d frames took %.3f seconds\n", NUM_FRAMES_TEST, test_time));
3401 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3406 if ( Test_begin == 1 ) {
3412 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3415 // start looping digital sounds
3416 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3417 snds[i] = snd_play_looping( &Snds[i], 0.0f, -1, -1);
3424 DCF(dcf_fov, "Change the field of view")
3427 dc_get_arg(ARG_FLOAT|ARG_NONE);
3428 if ( Dc_arg_type & ARG_NONE ) {
3429 Viewer_zoom = VIEWER_ZOOM_DEFAULT;
3430 dc_printf( "Zoom factor reset\n" );
3432 if ( Dc_arg_type & ARG_FLOAT ) {
3433 if (Dc_arg_float < 0.25f) {
3434 Viewer_zoom = 0.25f;
3435 dc_printf("Zoom factor pinned at 0.25.\n");
3436 } else if (Dc_arg_float > 1.25f) {
3437 Viewer_zoom = 1.25f;
3438 dc_printf("Zoom factor pinned at 1.25.\n");
3440 Viewer_zoom = Dc_arg_float;
3446 dc_printf( "Usage: fov [factor]\nFactor is the zoom factor btwn .25 and 1.25\nNo parameter resets it to default.\n" );
3449 dc_printf("Zoom factor set to %6.3f (original = 0.5, John = 0.75)", Viewer_zoom);
3453 DCF(framerate_cap, "Sets the framerate cap")
3456 dc_get_arg(ARG_INT);
3457 if ( (Dc_arg_int >= 1 ) || (Dc_arg_int <= 120) ) {
3458 Framerate_cap = Dc_arg_int;
3460 dc_printf( "Illegal value for framerate cap. (Must be from 1-120) \n\n");
3466 dc_printf("Usage: framerate_cap [n]\nwhere n is the frames per second to cap framerate at.\n");
3467 dc_printf("If n is 0 or omitted, then the framerate cap is removed\n");
3468 dc_printf("[n] must be from 1 to 120.\n");
3472 if ( Framerate_cap )
3473 dc_printf("Framerate cap is set to %d fps\n", Framerate_cap );
3475 dc_printf("There is no framerate cap currently active.\n");
3479 #define MIN_DIST_TO_DEAD_CAMERA 50.0f
3480 int Show_viewing_from_self = 0;
3482 void say_view_target()
3484 object *view_target;
3486 if ((Viewer_mode & VM_OTHER_SHIP) && (Player_ai->target_objnum != -1))
3487 view_target = &Objects[Player_ai->target_objnum];
3489 view_target = Player_obj;
3491 if (Game_mode & GM_DEAD) {
3492 if (Player_ai->target_objnum != -1)
3493 view_target = &Objects[Player_ai->target_objnum];
3496 if (!(Game_mode & GM_DEAD_DIED) && ((Game_mode & (GM_DEAD_BLEW_UP)) || ((Last_view_target != NULL) && (Last_view_target != view_target)))) {
3497 if (view_target != Player_obj){
3499 char *view_target_name = NULL;
3500 switch(Objects[Player_ai->target_objnum].type) {
3502 view_target_name = Ships[Objects[Player_ai->target_objnum].instance].ship_name;
3505 view_target_name = Weapon_info[Weapons[Objects[Player_ai->target_objnum].instance].weapon_info_index].name;
3506 Viewer_mode &= ~VM_OTHER_SHIP;
3508 case OBJ_JUMP_NODE: {
3509 char jump_node_name[128];
3510 strcpy(jump_node_name, XSTR( "jump node", 184));
3511 view_target_name = jump_node_name;
3512 Viewer_mode &= ~VM_OTHER_SHIP;
3521 if ( view_target_name ) {
3522 HUD_fixed_printf(0.0f, XSTR( "Viewing %s%s\n", 185), (Viewer_mode & VM_OTHER_SHIP) ? XSTR( "from ", 186) : "", view_target_name);
3523 Show_viewing_from_self = 1;
3526 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER) && (Player_obj->type == OBJ_OBSERVER)){
3527 HUD_fixed_printf(2.0f,XSTR( "Viewing from observer\n", 187));
3528 Show_viewing_from_self = 1;
3530 if (Show_viewing_from_self)
3531 HUD_fixed_printf(2.0f, XSTR( "Viewing from self\n", 188));
3536 Last_view_target = view_target;
3540 float Game_hit_x = 0.0f;
3541 float Game_hit_y = 0.0f;
3543 // Reset at the beginning of each frame
3544 void game_whack_reset()
3550 // Apply a 2d whack to the player
3551 void game_whack_apply( float x, float y )
3553 // Do some force feedback
3554 joy_ff_play_dir_effect(x * 80.0f, y * 80.0f);
3560 // mprintf(( "WHACK = %.1f, %.1f\n", Game_hit_x, Game_hit_y ));
3563 // call to apply a "shudder"
3564 void game_shudder_apply(int time, float intensity)
3566 Game_shudder_time = timestamp(time);
3567 Game_shudder_total = time;
3568 Game_shudder_intensity = intensity;
3571 #define FF_SCALE 10000
3572 void apply_hud_shake(matrix *eye_orient)
3574 if (Viewer_obj == Player_obj) {
3575 physics_info *pi = &Player_obj->phys_info;
3583 // Make eye shake due to afterburner
3584 if ( !timestamp_elapsed(pi->afterburner_decay) ) {
3587 dtime = timestamp_until(pi->afterburner_decay);
3591 tangles.p += 0.07f * (float) (r1-RAND_MAX/2)/RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3592 tangles.h += 0.07f * (float) (r2-RAND_MAX/2)/RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3595 // Make eye shake due to engine wash
3597 if (Player_obj->type == OBJ_SHIP && (Ships[Player_obj->instance].wash_intensity > 0) && Wash_on ) {
3600 tangles.p += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r1-RAND_MAX/2)/RAND_MAX;
3601 tangles.h += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r2-RAND_MAX/2)/RAND_MAX;
3603 // get the intensity
3604 float intensity = FF_SCALE * Ships[Player_obj->instance].wash_intensity;
3608 vm_vec_rand_vec_quick(&rand_vec);
3611 joy_ff_play_dir_effect(intensity*rand_vec.xyz.x, intensity*rand_vec.xyz.y);
3615 // make hud shake due to shuddering
3616 if(Game_shudder_time != -1){
3617 // if the timestamp has elapsed
3618 if(timestamp_elapsed(Game_shudder_time)){
3619 Game_shudder_time = -1;
3621 // otherwise apply some shudder
3625 dtime = timestamp_until(Game_shudder_time);
3629 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));
3630 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));
3635 vm_angles_2_matrix(&tm, &tangles);
3636 Assert(vm_vec_mag(&tm.v.fvec) > 0.0f);
3637 Assert(vm_vec_mag(&tm.v.rvec) > 0.0f);
3638 Assert(vm_vec_mag(&tm.v.uvec) > 0.0f);
3639 vm_matrix_x_matrix(&tm2, eye_orient, &tm);
3644 extern void compute_slew_matrix(matrix *orient, angles *a); // TODO: move code to proper place and extern in header file
3646 // Player's velocity just before he blew up. Used to keep camera target moving.
3647 vector Dead_player_last_vel = {1.0f, 1.0f, 1.0f};
3649 // Set eye_pos and eye_orient based on view mode.
3650 void game_render_frame_setup(vector *eye_pos, matrix *eye_orient)
3654 static int last_Viewer_mode = 0;
3655 static int last_Game_mode = 0;
3656 static int last_Viewer_objnum = -1;
3658 // This code is supposed to detect camera "cuts"... like going between
3661 // determine if we need to regenerate the nebula
3662 if( (!(last_Viewer_mode & VM_EXTERNAL) && (Viewer_mode & VM_EXTERNAL)) || // internal to external
3663 ((last_Viewer_mode & VM_EXTERNAL) && !(Viewer_mode & VM_EXTERNAL)) || // external to internal
3664 (!(last_Viewer_mode & VM_DEAD_VIEW) && (Viewer_mode & VM_DEAD_VIEW)) || // non dead-view to dead-view
3665 ((last_Viewer_mode & VM_DEAD_VIEW) && !(Viewer_mode & VM_DEAD_VIEW)) || // dead-view to non dead-view
3666 (!(last_Viewer_mode & VM_WARP_CHASE) && (Viewer_mode & VM_WARP_CHASE)) || // non warp-chase to warp-chase
3667 ((last_Viewer_mode & VM_WARP_CHASE) && !(Viewer_mode & VM_WARP_CHASE)) || // warp-chase to non warp-chase
3668 (!(last_Viewer_mode & VM_OTHER_SHIP) && (Viewer_mode & VM_OTHER_SHIP)) || // non other-ship to other-ship
3669 ((last_Viewer_mode & VM_OTHER_SHIP) && !(Viewer_mode & VM_OTHER_SHIP)) || // other-ship to non-other ship
3670 ((Viewer_mode & VM_OTHER_SHIP) && (last_Viewer_objnum != Player_ai->target_objnum)) // other ship mode, but targets changes
3673 // regenerate the nebula
3677 if ( (last_Viewer_mode != Viewer_mode) || (last_Game_mode != Game_mode) ) {
3678 //mprintf(( "************** Camera cut! ************\n" ));
3679 last_Viewer_mode = Viewer_mode;
3680 last_Game_mode = Game_mode;
3682 // Camera moved. Tell stars & debris to not do blurring.
3688 if ( Viewer_mode & VM_PADLOCK_ANY ) {
3689 player_display_packlock_view();
3692 game_set_view_clip();
3694 if (Game_mode & GM_DEAD) {
3695 vector vec_to_deader, view_pos;
3698 Viewer_mode |= VM_DEAD_VIEW;
3700 if (Player_ai->target_objnum != -1) {
3701 int view_from_player = 1;
3703 if (Viewer_mode & VM_OTHER_SHIP) {
3704 // View from target.
3705 Viewer_obj = &Objects[Player_ai->target_objnum];
3707 last_Viewer_objnum = Player_ai->target_objnum;
3709 if ( Viewer_obj->type == OBJ_SHIP ) {
3710 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3711 view_from_player = 0;
3714 last_Viewer_objnum = -1;
3717 if ( view_from_player ) {
3718 // View target from player ship.
3720 *eye_pos = Player_obj->pos;
3721 vm_vec_normalized_dir(&eye_dir, &Objects[Player_ai->target_objnum].pos, eye_pos);
3722 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3725 dist = vm_vec_normalized_dir(&vec_to_deader, &Player_obj->pos, &Dead_camera_pos);
3727 if (dist < MIN_DIST_TO_DEAD_CAMERA)
3728 dist += flFrametime * 16.0f;
3730 vm_vec_scale(&vec_to_deader, -dist);
3731 vm_vec_add(&Dead_camera_pos, &Player_obj->pos, &vec_to_deader);
3733 view_pos = Player_obj->pos;
3735 if (!(Game_mode & GM_DEAD_BLEW_UP)) {
3736 Viewer_mode &= ~(VM_EXTERNAL | VM_CHASE);
3737 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, 25.0f * flFrametime);
3738 Dead_player_last_vel = Player_obj->phys_info.vel;
3739 //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));
3740 } else if (Player_ai->target_objnum != -1) {
3741 view_pos = Objects[Player_ai->target_objnum].pos;
3743 // Make camera follow explosion, but gradually slow down.
3744 vm_vec_scale_add2(&Player_obj->pos, &Dead_player_last_vel, flFrametime);
3745 view_pos = Player_obj->pos;
3746 vm_vec_scale(&Dead_player_last_vel, 0.99f);
3747 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, min(25.0f, vm_vec_mag_quick(&Dead_player_last_vel)) * flFrametime);
3750 *eye_pos = Dead_camera_pos;
3752 vm_vec_normalized_dir(&eye_dir, &Player_obj->pos, eye_pos);
3754 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3759 // if supernova shockwave
3760 if(supernova_camera_cut()){
3764 // call it dead view
3765 Viewer_mode |= VM_DEAD_VIEW;
3767 // set eye pos and orient
3768 supernova_set_view(eye_pos, eye_orient);
3770 // If already blown up, these other modes can override.
3771 if (!(Game_mode & (GM_DEAD | GM_DEAD_BLEW_UP))) {
3772 Viewer_mode &= ~VM_DEAD_VIEW;
3774 Viewer_obj = Player_obj;
3776 if (Viewer_mode & VM_OTHER_SHIP) {
3777 if (Player_ai->target_objnum != -1){
3778 Viewer_obj = &Objects[Player_ai->target_objnum];
3779 last_Viewer_objnum = Player_ai->target_objnum;
3781 Viewer_mode &= ~VM_OTHER_SHIP;
3782 last_Viewer_objnum = -1;
3785 last_Viewer_objnum = -1;
3788 if (Viewer_mode & VM_EXTERNAL) {
3791 vm_angles_2_matrix(&tm2, &Viewer_external_info.angles);
3792 vm_matrix_x_matrix(&tm, &Viewer_obj->orient, &tm2);
3794 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &tm.v.fvec, 2.0f * Viewer_obj->radius + Viewer_external_info.distance);
3796 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3797 vm_vec_normalize(&eye_dir);
3798 vm_vector_2_matrix(eye_orient, &eye_dir, &Viewer_obj->orient.v.uvec, NULL);
3801 // Modify the orientation based on head orientation.
3802 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3804 } else if ( Viewer_mode & VM_CHASE ) {
3807 if ( Viewer_obj->phys_info.speed < 0.1 )
3808 move_dir = Viewer_obj->orient.v.fvec;
3810 move_dir = Viewer_obj->phys_info.vel;
3811 vm_vec_normalize(&move_dir);
3814 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &move_dir, -3.0f * Viewer_obj->radius - Viewer_chase_info.distance);
3815 vm_vec_scale_add2(eye_pos, &Viewer_obj->orient.v.uvec, 0.75f * Viewer_obj->radius);
3816 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3817 vm_vec_normalize(&eye_dir);
3819 // JAS: I added the following code because if you slew up using
3820 // Descent-style physics, eye_dir and Viewer_obj->orient.v.uvec are
3821 // equal, which causes a zero-length vector in the vm_vector_2_matrix
3822 // call because the up and the forward vector are the same. I fixed
3823 // it by adding in a fraction of the right vector all the time to the
3825 vector tmp_up = Viewer_obj->orient.v.uvec;
3826 vm_vec_scale_add2( &tmp_up, &Viewer_obj->orient.v.rvec, 0.00001f );
3828 vm_vector_2_matrix(eye_orient, &eye_dir, &tmp_up, NULL);
3831 // Modify the orientation based on head orientation.
3832 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3833 } else if ( Viewer_mode & VM_WARP_CHASE ) {
3834 *eye_pos = Camera_pos;
3836 ship * shipp = &Ships[Player_obj->instance];
3838 vm_vec_sub(&eye_dir, &shipp->warp_effect_pos, eye_pos);
3839 vm_vec_normalize(&eye_dir);
3840 vm_vector_2_matrix(eye_orient, &eye_dir, &Player_obj->orient.v.uvec, NULL);
3843 // get an eye position based upon the correct type of object
3844 switch(Viewer_obj->type){
3846 // make a call to get the eye point for the player object
3847 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3850 // make a call to get the eye point for the player object
3851 observer_get_eye( eye_pos, eye_orient, Viewer_obj );
3857 #ifdef JOHNS_DEBUG_CODE
3858 john_debug_stuff(&eye_pos, &eye_orient);
3864 apply_hud_shake(eye_orient);
3866 // setup neb2 rendering
3867 neb2_render_setup(eye_pos, eye_orient);
3871 extern void ai_debug_render_stuff();
3874 int Game_subspace_effect = 0;
3875 DCF_BOOL( subspace, Game_subspace_effect );
3877 // Does everything needed to render a frame
3878 void game_render_frame( vector * eye_pos, matrix * eye_orient )
3882 g3_start_frame(game_zbuffer);
3883 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
3885 // maybe offset the HUD (jitter stuff)
3886 dont_offset = ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER));
3887 HUD_set_offsets(Viewer_obj, !dont_offset);
3889 // for multiplayer clients, call code in Shield.cpp to set up the Shield_hit array. Have to
3890 // do this becaues of the disjointed nature of this system (in terms of setup and execution).
3891 // must be done before ships are rendered
3892 if ( MULTIPLAYER_CLIENT ) {
3893 shield_point_multi_setup();
3896 if ( Game_subspace_effect ) {
3897 stars_draw(0,0,0,1);
3899 stars_draw(1,1,1,0);
3902 obj_render_all(obj_render);
3903 beam_render_all(); // render all beam weapons
3904 particle_render_all(); // render particles after everything else.
3905 trail_render_all(); // render missilie trails after everything else.
3906 mflash_render_all(); // render all muzzle flashes
3908 // Why do we not show the shield effect in these modes? Seems ok.
3909 //if (!(Viewer_mode & (VM_EXTERNAL | VM_SLEWED | VM_CHASE | VM_DEAD_VIEW))) {
3913 // render nebula lightning
3916 // render local player nebula
3917 neb2_render_player();
3920 ai_debug_render_stuff();
3923 #ifndef RELEASE_REAL
3924 // game_framerate_check();
3928 extern void snd_spew_debug_info();
3929 snd_spew_debug_info();
3932 //================ END OF 3D RENDERING STUFF ====================
3936 if( (Game_detail_flags & DETAIL_FLAG_HUD) && !(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) ) ) {
3937 hud_maybe_clear_head_area();
3938 anim_render_all(0, flFrametime);
3941 extern int Multi_display_netinfo;
3942 if(Multi_display_netinfo){
3943 extern void multi_display_netinfo();
3944 multi_display_netinfo();
3947 game_tst_frame_pre();
3950 do_timing_test(flFrametime);
3954 extern int OO_update_index;
3955 multi_rate_display(OO_update_index, 375, 0);
3960 extern void oo_display();
3967 //#define JOHNS_DEBUG_CODE 1
3969 #ifdef JOHNS_DEBUG_CODE
3970 void john_debug_stuff(vector *eye_pos, matrix *eye_orient)
3972 //if ( keyd_pressed[KEY_LSHIFT] )
3974 ship_subsys *tsys = Players[Player_num].targeted_subobject;
3976 model_subsystem *turret = tsys->system_info;
3978 if (turret->type == SUBSYSTEM_TURRET ) {
3979 vector v.fvec, v.uvec;
3980 object * tobj = &Objects[Players[Player_num].targeted_subobject_parent];
3982 ship_model_start(tobj);
3984 model_find_world_point(eye_pos, &turret->turret_firing_point[0], turret->model_num, turret->turret_gun_sobj, &tobj->orient, &tobj->pos );
3985 model_find_world_dir(&v.fvec, &turret->turret_matrix.v.fvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3986 model_find_world_dir(&v.uvec, &turret->turret_matrix.v.uvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3988 vm_vector_2_matrix( eye_orient, &v.fvec, &v.uvec, NULL );
3990 ship_model_stop(tobj);
4000 // following function for dumping frames for purposes of building trailers.
4003 // function to toggle state of dumping every frame into PCX when playing the game
4004 DCF(dump_frames, "Starts/stop frame dumping at 15 hz")
4008 if ( Debug_dump_frames == 0 ) {
4010 Debug_dump_frames = 15;
4011 Debug_dump_trigger = 0;
4012 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4013 dc_printf( "Frame dumping at 15 hz is now ON\n" );
4016 Debug_dump_frames = 0;
4017 Debug_dump_trigger = 0;
4018 gr_dump_frame_stop();
4019 dc_printf( "Frame dumping is now OFF\n" );
4025 DCF(dump_frames_trigger, "Starts/stop frame dumping at 15 hz")
4029 if ( Debug_dump_frames == 0 ) {
4031 Debug_dump_frames = 15;
4032 Debug_dump_trigger = 1;
4033 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4034 dc_printf( "Frame dumping at 15 hz is now ON\n" );
4037 Debug_dump_frames = 0;
4038 Debug_dump_trigger = 0;
4039 gr_dump_frame_stop();
4040 dc_printf( "Frame dumping is now OFF\n" );
4046 DCF(dump_frames30, "Starts/stop frame dumping at 30 hz")
4050 if ( Debug_dump_frames == 0 ) {
4052 Debug_dump_frames = 30;
4053 Debug_dump_trigger = 0;
4054 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4055 dc_printf( "Frame dumping at 30 hz is now ON\n" );
4058 Debug_dump_frames = 0;
4059 Debug_dump_trigger = 0;
4060 gr_dump_frame_stop();
4061 dc_printf( "Frame dumping is now OFF\n" );
4067 DCF(dump_frames30_trigger, "Starts/stop frame dumping at 30 hz")
4071 if ( Debug_dump_frames == 0 ) {
4073 Debug_dump_frames = 30;
4074 Debug_dump_trigger = 1;
4075 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4076 dc_printf( "Triggered frame dumping at 30 hz is now ON\n" );
4079 Debug_dump_frames = 0;
4080 Debug_dump_trigger = 0;
4081 gr_dump_frame_stop();
4082 dc_printf( "Triggered frame dumping is now OFF\n" );
4088 void game_maybe_dump_frame()
4090 if ( !Debug_dump_frames ){
4094 if( Debug_dump_trigger && !keyd_pressed[KEY_Q] ){
4101 Debug_dump_frame_num++;
4107 extern int Player_dead_state;
4109 // Flip the page and time how long it took.
4110 void game_flip_page_and_time_it()
4115 t1 = timer_get_fixed_seconds();
4117 t2 = timer_get_fixed_seconds();
4120 t = (gr_screen.max_w*gr_screen.max_h*gr_screen.bytes_per_pixel)/1024;
4121 sprintf( transfer_text, NOX("%ld MB/s"), fixmuldiv(t,65,d) );
4128 void game_simulation_frame()
4130 // blow ships up in multiplayer dogfight
4131 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){
4132 // blow up all non-player ships
4133 ship_obj *moveup = GET_FIRST(&Ship_obj_list);
4136 while((moveup != END_OF_LIST(&Ship_obj_list)) && (moveup != NULL)){
4138 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)){
4139 moveup = GET_NEXT(moveup);
4142 shipp = &Ships[Objects[moveup->objnum].instance];
4143 sip = &Ship_info[shipp->ship_info_index];
4145 // only blow up small ships
4146 if((sip->flags & SIF_SMALL_SHIP) && (multi_find_player_by_object(&Objects[moveup->objnum]) < 0) ){
4147 // function to simply explode a ship where it is currently at
4148 ship_self_destruct( &Objects[moveup->objnum] );
4151 moveup = GET_NEXT(moveup);
4157 // process AWACS stuff - do this first thing
4160 // single player, set Player hits_this_frame to 0
4161 if ( !(Game_mode & GM_MULTIPLAYER) && Player ) {
4162 Player->damage_this_burst -= (flFrametime * MAX_BURST_DAMAGE / (0.001f * BURST_DURATION));
4163 Player->damage_this_burst = max(Player->damage_this_burst, 0.0f);
4167 supernova_process();
4168 if(supernova_active() >= 5){
4172 // fire targeting lasers now so that
4173 // 1 - created this frame
4174 // 2 - collide this frame
4175 // 3 - render this frame
4176 // 4 - ignored and deleted next frame
4177 // the basic idea being that because it con be confusing to deal with them on a multi-frame basis, they are only valid for
4179 ship_process_targeting_lasers();
4181 // do this here so that it works for multiplayer
4183 // get viewer direction
4184 int viewer_direction = PHYSICS_VIEWER_REAR;
4186 if(Viewer_mode == 0){
4187 viewer_direction = PHYSICS_VIEWER_FRONT;
4189 if(Viewer_mode & VM_PADLOCK_UP){
4190 viewer_direction = PHYSICS_VIEWER_UP;
4192 else if(Viewer_mode & VM_PADLOCK_REAR){
4193 viewer_direction = PHYSICS_VIEWER_REAR;
4195 else if(Viewer_mode & VM_PADLOCK_LEFT){
4196 viewer_direction = PHYSICS_VIEWER_LEFT;
4198 else if(Viewer_mode & VM_PADLOCK_RIGHT){
4199 viewer_direction = PHYSICS_VIEWER_RIGHT;
4202 physics_set_viewer( &Viewer_obj->phys_info, viewer_direction );
4204 physics_set_viewer( NULL, PHYSICS_VIEWER_FRONT );
4207 #define VM_PADLOCK_UP (1 << 7)
4208 #define VM_PADLOCK_REAR (1 << 8)
4209 #define VM_PADLOCK_LEFT (1 << 9)
4210 #define VM_PADLOCK_RIGHT (1 << 10)
4212 // evaluate mission departures and arrivals before we process all objects.
4213 if ( !(Game_mode & GM_MULTIPLAYER) || ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending()) ) {
4215 // we don't want to evaluate mission stuff when any ingame joiner in multiplayer is receiving
4216 // ships/wing packets.
4217 if ( !((Game_mode & GM_MULTIPLAYER) && (Netgame.flags & NG_FLAG_INGAME_JOINING_CRITICAL)) && !(Game_mode & GM_DEMO_PLAYBACK)){
4218 mission_parse_eval_stuff();
4221 // if we're an observer, move ourselves seperately from the standard physics
4222 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
4223 obj_observer_move(flFrametime);
4226 // move all the objects now
4227 obj_move_all(flFrametime);
4229 // check for cargo reveal (this has an internal timestamp, so only runs every N ms)
4230 // AL: 3-15-98: It was decided to not let AI ships inspect cargo
4231 // ship_check_cargo_all();
4232 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4233 mission_eval_goals();
4237 // always check training objectives, even in multiplayer missions. we need to do this so that the directives gauge works properly on clients
4238 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4239 training_check_objectives();
4242 // do all interpolation now
4243 if ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending() && !(Netgame.flags & NG_FLAG_SERVER_LOST)) {
4244 // client side processing of warping in effect stages
4245 multi_do_client_warp(flFrametime);
4247 // client side movement of an observer
4248 if((Net_player->flags & NETINFO_FLAG_OBSERVER) || (Player_obj->type == OBJ_OBSERVER)){
4249 obj_observer_move(flFrametime);
4252 // move all objects - does interpolation now as well
4253 obj_move_all(flFrametime);
4256 // only process the message queue when the player is "in" the game
4257 if ( !Pre_player_entry ){
4258 message_queue_process(); // process any messages send to the player
4261 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4262 message_maybe_distort(); // maybe distort incoming message if comms damaged
4263 player_repair_frame(flFrametime); // AI objects get repaired in ai_process, called from move code...deal with player.
4264 player_process_pending_praise(); // maybe send off a delayed praise message to the player
4265 player_maybe_play_all_alone_msg(); // mabye tell the player he is all alone
4268 if(!(Game_mode & GM_STANDALONE_SERVER)){
4269 // process some stuff every frame (before frame is rendered)
4270 emp_process_local();
4272 hud_update_frame(); // update hud systems
4274 if (!physics_paused) {
4275 // Move particle system
4276 particle_move_all(flFrametime);
4278 // Move missile trails
4279 trail_move_all(flFrametime);
4281 // process muzzle flashes
4282 mflash_process_all();
4284 // Flash the gun flashes
4285 shipfx_flash_do_frame(flFrametime);
4287 shockwave_move_all(flFrametime); // update all the shockwaves
4290 // subspace missile strikes
4293 obj_snd_do_frame(); // update the object-linked persistant sounds
4294 game_maybe_update_sound_environment();
4295 snd_update_listener(&View_position, &Player_obj->phys_info.vel, &Player_obj->orient);
4297 // AL: debug code used for testing ambient subspace sound (ie when enabling subspace through debug console)
4299 if ( Game_subspace_effect ) {
4300 game_start_subspace_ambient_sound();
4306 // Maybe render and process the dead-popup
4307 void game_maybe_do_dead_popup(float frametime)
4309 if ( popupdead_is_active() ) {
4311 int choice = popupdead_do_frame(frametime);
4313 if ( Game_mode & GM_NORMAL ) {
4317 if(game_do_cd_mission_check(Game_current_mission_filename)){
4318 gameseq_post_event(GS_EVENT_ENTER_GAME);
4320 gameseq_post_event(GS_EVENT_MAIN_MENU);
4325 gameseq_post_event(GS_EVENT_END_GAME);
4330 if(game_do_cd_mission_check(Game_current_mission_filename)){
4331 gameseq_post_event(GS_EVENT_START_GAME);
4333 gameseq_post_event(GS_EVENT_MAIN_MENU);
4337 // this should only happen during a red alert mission
4340 Assert(The_mission.red_alert);
4341 if(!The_mission.red_alert){
4343 if(game_do_cd_mission_check(Game_current_mission_filename)){
4344 gameseq_post_event(GS_EVENT_START_GAME);
4346 gameseq_post_event(GS_EVENT_MAIN_MENU);
4351 // choose the previous mission
4352 mission_campaign_previous_mission();
4354 if(game_do_cd_mission_check(Game_current_mission_filename)){
4355 gameseq_post_event(GS_EVENT_START_GAME);
4357 gameseq_post_event(GS_EVENT_MAIN_MENU);
4368 case POPUPDEAD_DO_MAIN_HALL:
4369 multi_quit_game(PROMPT_NONE,-1);
4372 case POPUPDEAD_DO_RESPAWN:
4373 multi_respawn_normal();
4374 event_music_player_respawn();
4377 case POPUPDEAD_DO_OBSERVER:
4378 multi_respawn_observer();
4379 event_music_player_respawn_as_observer();
4388 if ( leave_popup ) {
4394 // returns true if player is actually in a game_play stats
4395 int game_actually_playing()
4399 state = gameseq_get_state();
4400 if ( (state != GS_STATE_GAME_PLAY) && (state != GS_STATE_DEATH_DIED) && (state != GS_STATE_DEATH_BLEW_UP) )
4406 // Draw the 2D HUD gauges
4407 void game_render_hud_2d()
4409 if ( !(Game_detail_flags & DETAIL_FLAG_HUD) ) {
4413 HUD_render_2d(flFrametime);
4417 // Draw the 3D-dependant HUD gauges
4418 void game_render_hud_3d(vector *eye_pos, matrix *eye_orient)
4420 g3_start_frame(0); // 0 = turn zbuffering off
4421 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
4423 if ( (Game_detail_flags & DETAIL_FLAG_HUD) && (supernova_active() < 3)/* && !(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) )*/ ) {
4424 HUD_render_3d(flFrametime);
4428 game_sunspot_process(flFrametime);
4430 // Diminish the palette effect
4431 game_flash_diminish(flFrametime);
4439 int actually_playing;
4440 fix total_time1, total_time2;
4441 fix render2_time1=0, render2_time2=0;
4442 fix render3_time1=0, render3_time2=0;
4443 fix flip_time1=0, flip_time2=0;
4444 fix clear_time1=0, clear_time2=0;
4450 if (Framerate_delay) {
4451 int start_time = timer_get_milliseconds();
4452 while (timer_get_milliseconds() < start_time + Framerate_delay)
4458 demo_do_frame_start();
4460 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4465 // start timing frame
4466 timing_frame_start();
4468 total_time1 = timer_get_fixed_seconds();
4470 // var to hold which state we are in
4471 actually_playing = game_actually_playing();
4473 if ((!(Game_mode & GM_MULTIPLAYER)) || ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER))) {
4474 if (!(Game_mode & GM_STANDALONE_SERVER)){
4475 Assert( OBJ_INDEX(Player_obj) >= 0 );
4479 if (Missiontime > Entry_delay_time){
4480 Pre_player_entry = 0;
4482 ; //nprintf(("AI", "Framecount = %i, time = %7.3f\n", Framecount, f2fl(Missiontime)));
4485 // Note: These are done even before the player enters, else buffers can overflow.
4486 if (! (Game_mode & GM_STANDALONE_SERVER)){
4490 shield_frame_init();
4492 if ( Player->control_mode != PCM_NORMAL )
4495 if ( !Pre_player_entry && actually_playing ) {
4496 if (! (Game_mode & GM_STANDALONE_SERVER) ) {
4498 if( (!popup_running_state()) && (!popupdead_is_active()) ){
4499 game_process_keys();
4501 // don't read flying controls if we're playing a demo back
4502 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4503 read_player_controls( Player_obj, flFrametime);
4507 // if we're not the master, we may have to send the server-critical ship status button_info bits
4508 if ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER)){
4509 multi_maybe_send_ship_status();
4514 // Reset the whack stuff
4517 // These two lines must be outside of Pre_player_entry code,
4518 // otherwise too many lights are added.
4521 if ((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4525 game_simulation_frame();
4527 // if not actually in a game play state, then return. This condition could only be true in
4528 // a multiplayer game.
4529 if ( !actually_playing ) {
4530 Assert( Game_mode & GM_MULTIPLAYER );
4534 if (!Pre_player_entry) {
4535 if (! (Game_mode & GM_STANDALONE_SERVER)) {
4536 clear_time1 = timer_get_fixed_seconds();
4537 // clear the screen to black
4539 if ( (Game_detail_flags & DETAIL_FLAG_CLEAR) ) {
4543 clear_time2 = timer_get_fixed_seconds();
4544 render3_time1 = timer_get_fixed_seconds();
4545 game_render_frame_setup(&eye_pos, &eye_orient);
4546 game_render_frame( &eye_pos, &eye_orient );
4548 // save the eye position and orientation
4549 if ( Game_mode & GM_MULTIPLAYER ) {
4550 Net_player->s_info.eye_pos = eye_pos;
4551 Net_player->s_info.eye_orient = eye_orient;
4554 hud_show_target_model();
4556 // check to see if we should display the death died popup
4557 if(Game_mode & GM_DEAD_BLEW_UP){
4558 if(Game_mode & GM_MULTIPLAYER){
4559 // catch the situation where we're supposed to be warping out on this transition
4560 if(Net_player->flags & NETINFO_FLAG_WARPING_OUT){
4561 gameseq_post_event(GS_EVENT_DEBRIEF);
4562 } else if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4563 Player_died_popup_wait = -1;
4567 if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4568 Player_died_popup_wait = -1;
4574 // hack - sometimes this seems to slip by in multiplayer. this should guarantee that we catch it
4575 if((Game_mode & GM_MULTIPLAYER) && (Player_multi_died_check != -1) && (Game_mode & GM_DEAD_BLEW_UP) ){
4576 if(fl_abs(time(NULL) - Player_multi_died_check) > 4){
4577 if(!popupdead_is_active()){
4581 Player_multi_died_check = -1;
4585 render3_time2 = timer_get_fixed_seconds();
4586 render2_time1 = timer_get_fixed_seconds();
4589 game_get_framerate();
4590 game_show_framerate();
4592 game_show_time_left();
4594 // Draw the 2D HUD gauges
4595 if(supernova_active() < 3){
4596 game_render_hud_2d();
4599 game_set_view_clip();
4601 // Draw 3D HUD gauges
4602 game_render_hud_3d(&eye_pos, &eye_orient);
4606 render2_time2 = timer_get_fixed_seconds();
4608 // maybe render and process the dead popup
4609 game_maybe_do_dead_popup(flFrametime);
4611 // start timing frame
4612 timing_frame_stop();
4613 // timing_display(30, 10);
4615 // If a regular popup is active, don't flip (popup code flips)
4616 if( !popup_running_state() ){
4617 flip_time1 = timer_get_fixed_seconds();
4618 game_flip_page_and_time_it();
4619 flip_time2 = timer_get_fixed_seconds();
4623 game_maybe_dump_frame(); // used to dump pcx files for building trailers
4626 game_show_standalone_framerate();
4630 game_do_training_checks();
4633 // process lightning (nebula only)
4636 total_time2 = timer_get_fixed_seconds();
4638 // Got some timing numbers
4639 Timing_total = f2fl( total_time2 - total_time1 ) * 1000.0f;
4640 Timing_clear = f2fl( clear_time2 - clear_time1 ) * 1000.0f;
4641 Timing_render2 = f2fl( render2_time2- render2_time1 ) * 1000.0f;
4642 Timing_render3 = f2fl( render3_time2- render3_time1 ) * 1000.0f;
4643 Timing_flip = f2fl( flip_time2 - flip_time1 ) * 1000.0f;
4646 demo_do_frame_end();
4648 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4654 #define MAX_FRAMETIME (F1_0/4) // Frametime gets saturated at this. Changed by MK on 11/1/97.
4655 // Some bug was causing Frametime to always get saturated at 2.0 seconds after the player
4656 // died. This resulted in screwed up death sequences.
4658 fix Last_time = 0; // The absolute time of game at end of last frame (beginning of this frame)
4659 fix Last_delta_time = 0; // While game is paused, this keeps track of how much elapsed in the frame before paused.
4660 static int timer_paused=0;
4661 #if defined(TIMER_TEST) && !defined(NDEBUG)
4662 static int stop_count,start_count;
4663 static int time_stopped,time_started;
4665 int saved_timestamp_ticker = -1;
4667 void game_reset_time()
4669 if((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4673 // Last_time = timer_get_fixed_seconds();
4679 void game_stop_time()
4681 if (timer_paused==0) {
4683 time = timer_get_fixed_seconds();
4684 // Save how much time progressed so far in the frame so we can
4685 // use it when we unpause.
4686 Last_delta_time = time - Last_time;
4688 //mprintf(("Last_time in game_stop_time = %7.3f\n", f2fl(Last_delta_time)));
4689 if (Last_delta_time < 0) {
4690 #if defined(TIMER_TEST) && !defined(NDEBUG)
4691 Int3(); //get Matt!!!!
4693 Last_delta_time = 0;
4695 #if defined(TIMER_TEST) && !defined(NDEBUG)
4696 time_stopped = time;
4699 // Stop the timer_tick stuff...
4700 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4701 saved_timestamp_ticker = timestamp_ticker;
4705 #if defined(TIMER_TEST) && !defined(NDEBUG)
4710 void game_start_time()
4713 Assert(timer_paused >= 0);
4714 if (timer_paused==0) {
4716 time = timer_get_fixed_seconds();
4717 #if defined(TIMER_TEST) && !defined(NDEBUG)
4719 Int3(); //get Matt!!!!
4722 // Take current time, and set it backwards to account for time
4723 // that the frame already executed, so that timer_get_fixed_seconds() - Last_time
4724 // will be correct when it goes to calculate the frametime next
4726 Last_time = time - Last_delta_time;
4727 #if defined(TIMER_TEST) && !defined(NDEBUG)
4728 time_started = time;
4731 // Restore the timer_tick stuff...
4732 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4733 Assert( saved_timestamp_ticker > -1 ); // Called out of order, get JAS
4734 timestamp_ticker = saved_timestamp_ticker;
4735 saved_timestamp_ticker = -1;
4738 #if defined(TIMER_TEST) && !defined(NDEBUG)
4744 void game_set_frametime(int state)
4747 float frame_cap_diff;
4749 thistime = timer_get_fixed_seconds();
4751 if ( Last_time == 0 )
4752 Frametime = F1_0 / 30;
4754 Frametime = thistime - Last_time;
4756 // Frametime = F1_0 / 30;
4758 fix debug_frametime = Frametime; // Just used to display frametime.
4760 // If player hasn't entered mission yet, make frame take 1/4 second.
4761 if ((Pre_player_entry) && (state == GS_STATE_GAME_PLAY))
4764 else if ((Debug_dump_frames) && (state == GS_STATE_GAME_PLAY)) { // note link to above if!!!!!
4766 fix frame_speed = F1_0 / Debug_dump_frames;
4768 if (Frametime > frame_speed ){
4769 nprintf(("warning","slow frame: %x\n",Frametime));
4772 thistime = timer_get_fixed_seconds();
4773 Frametime = thistime - Last_time;
4774 } while (Frametime < frame_speed );
4776 Frametime = frame_speed;
4780 Assert( Framerate_cap > 0 );
4782 // Cap the framerate so it doesn't get too high.
4786 cap = F1_0/Framerate_cap;
4787 if (Frametime < cap) {
4788 thistime = cap - Frametime;
4789 //mprintf(("Sleeping for %6.3f seconds.\n", f2fl(thistime)));
4790 Sleep( (DWORD)(f2fl(thistime) * 1000.0f) );
4792 thistime = timer_get_fixed_seconds();
4796 if((Game_mode & GM_STANDALONE_SERVER) &&
4797 (f2fl(Frametime) < ((float)1.0/(float)Multi_options_g.std_framecap))){
4799 frame_cap_diff = ((float)1.0/(float)Multi_options_g.std_framecap) - f2fl(Frametime);
4800 Sleep((DWORD)(frame_cap_diff*1000));
4802 thistime += fl2f((frame_cap_diff));
4804 Frametime = thistime - Last_time;
4807 // If framerate is too low, cap it.
4808 if (Frametime > MAX_FRAMETIME) {
4810 mprintf(("Frame %2i too long!!: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4812 // to remove warnings in release build
4813 debug_frametime = fl2f(flFrametime);
4815 Frametime = MAX_FRAMETIME;
4818 Frametime = fixmul(Frametime, Game_time_compression);
4820 Last_time = thistime;
4821 //mprintf(("Frame %i, Last_time = %7.3f\n", Framecount, f2fl(Last_time)));
4823 flFrametime = f2fl(Frametime);
4824 //if(!(Game_mode & GM_PLAYING_DEMO)){
4825 timestamp_inc(flFrametime);
4827 /* if ((Framecount > 0) && (Framecount < 10)) {
4828 mprintf(("Frame %2i: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4833 // This is called from game_do_frame(), and from navmap_do_frame()
4834 void game_update_missiontime()
4836 // TODO JAS: Put in if and move this into game_set_frametime,
4837 // fix navmap to call game_stop/start_time
4838 //if ( !timer_paused )
4839 Missiontime += Frametime;
4842 void game_do_frame()
4844 game_set_frametime(GS_STATE_GAME_PLAY);
4845 game_update_missiontime();
4847 if (Game_mode & GM_STANDALONE_SERVER) {
4848 std_multi_set_standalone_missiontime(f2fl(Missiontime));
4851 if ( game_single_step && (last_single_step == game_single_step) ) {
4852 os_set_title( NOX("SINGLE STEP MODE (Pause exits, any other key steps)") );
4853 while( key_checkch() == 0 )
4855 os_set_title( XSTR( "FreeSpace", 171) );
4856 Last_time = timer_get_fixed_seconds();
4859 last_single_step = game_single_step;
4861 if ((gameseq_get_state() == GS_STATE_GAME_PLAY) && Use_mouse_to_fly){
4862 Keep_mouse_centered = 1; // force mouse to center of our window (so we don't hit movement limits)
4866 Keep_mouse_centered = 0;
4867 monitor_update(); // Update monitor variables
4870 void multi_maybe_do_frame()
4872 if ( (Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_IN_MISSION) && !Multi_pause_status){
4877 int Joymouse_button_status = 0;
4879 // Flush all input devices
4887 Joymouse_button_status = 0;
4889 //mprintf(("Game flush!\n" ));
4892 // function for multiplayer only which calls game_do_state_common() when running the
4894 void game_do_dc_networking()
4896 Assert( Game_mode & GM_MULTIPLAYER );
4898 game_do_state_common( gameseq_get_state() );
4901 // Call this whenever in a loop, or when you need to check for a keystroke.
4902 int game_check_key()
4908 // convert keypad enter to normal enter
4909 if ((k & KEY_MASK) == KEY_PADENTER)
4910 k = (k & ~KEY_MASK) | KEY_ENTER;
4915 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4917 #define DEMO_TRAILER_TIMEOUT_MS 45000 // 45 seconds of no input, play trailer
4918 static int Demo_show_trailer_timestamp = 0;
4920 void demo_reset_trailer_timer()
4922 Demo_show_trailer_timestamp = timer_get_milliseconds();
4925 void demo_maybe_show_trailer(int k)
4928 // if key pressed, reset demo trailer timer
4930 demo_reset_trailer_timer();
4934 // if mouse moved, reset demo trailer timer
4937 mouse_get_delta(&dx, &dy);
4938 if ( (dx > 0) || (dy > 0) ) {
4939 demo_reset_trailer_timer();
4943 // if joystick has moved, reset demo trailer timer
4946 joy_get_delta(&dx, &dy);
4947 if ( (dx > 0) || (dy > 0) ) {
4948 demo_reset_trailer_timer();
4952 // NOTE: reseting the trailer timer on mouse/joystick presses is handled in
4953 // the low-level code. Ugly, I know... but was the simplest and most
4956 // if 30 seconds since last demo trailer time reset, launch movie
4957 if ( os_foreground() ) {
4958 int now = timer_get_milliseconds();
4959 if ( (now - Demo_show_trailer_timestamp) > DEMO_TRAILER_TIMEOUT_MS ) {
4960 // if ( (now - Demo_show_trailer_timestamp) > 10000 ) {
4962 movie_play( NOX("fstrailer2.mve") );
4963 demo_reset_trailer_timer();
4971 // same as game_check_key(), except this is used while actually in the game. Since there
4972 // generally are differences between game control keys and general UI keys, makes sense to
4973 // have seperate functions for each case. If you are not checking a game control while in a
4974 // mission, you should probably be using game_check_key() instead.
4979 if (!os_foreground()) {
4984 // If we're in a single player game, pause it.
4985 if (!(Game_mode & GM_MULTIPLAYER)){
4986 if ( (gameseq_get_state() == GS_STATE_GAME_PLAY) && (!popup_active()) && (!popupdead_is_active()) ) {
4987 game_process_pause_key();
4994 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4995 demo_maybe_show_trailer(k);
4998 // Move the mouse cursor with the joystick.
4999 if (os_foreground() && (!Mouse_hidden) && (Use_joy_mouse) ) {
5000 // Move the mouse cursor with the joystick
5004 joy_get_pos( &jx, &jy, &jz, &jr );
5006 dx = fl2i(f2fl(jx)*flFrametime*500.0f);
5007 dy = fl2i(f2fl(jy)*flFrametime*500.0f);
5010 mouse_get_real_pos( &mx, &my );
5011 mouse_set_pos( mx+dx, my+dy );
5016 m = mouse_down(MOUSE_LEFT_BUTTON);
5018 if ( j != Joymouse_button_status ) {
5019 //mprintf(( "Joy went from %d to %d, mouse is %d\n", Joymouse_button_status, j, m ));
5020 Joymouse_button_status = j;
5022 mouse_mark_button( MOUSE_LEFT_BUTTON, 1 );
5023 } else if ( (!j) && (m) ) {
5024 mouse_mark_button( MOUSE_LEFT_BUTTON, 0 );
5029 // if we should be ignoring keys because of some multiplayer situations
5030 if((Game_mode & GM_MULTIPLAYER) && multi_ignore_controls(k)){
5034 // If a popup is running, don't process all the Fn keys
5035 if( popup_active() ) {
5039 state = gameseq_get_state();
5041 // if ( k ) nprintf(( "General", "Key = %x\n", k ));
5044 case KEY_DEBUGGED + KEY_BACKSP:
5049 launch_context_help();
5054 // if (state != GS_STATE_INITIAL_PLAYER_SELECT) {
5056 // don't allow f2 while warping out in multiplayer
5057 if((Game_mode & GM_MULTIPLAYER) && (Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_WARPING_OUT)){
5062 case GS_STATE_INITIAL_PLAYER_SELECT:
5063 case GS_STATE_OPTIONS_MENU:
5064 case GS_STATE_HUD_CONFIG:
5065 case GS_STATE_CONTROL_CONFIG:
5066 case GS_STATE_DEATH_DIED:
5067 case GS_STATE_DEATH_BLEW_UP:
5068 case GS_STATE_VIEW_MEDALS:
5072 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
5079 // hotkey selection screen -- only valid from briefing and beyond.
5081 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
5082 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) ) {
5083 gameseq_post_event( GS_EVENT_HOTKEY_SCREEN );
5089 case KEY_DEBUGGED + KEY_F3:
5090 gameseq_post_event( GS_EVENT_TOGGLE_FULLSCREEN );
5093 case KEY_DEBUGGED + KEY_F4:
5094 gameseq_post_event( GS_EVENT_TOGGLE_GLIDE );
5098 if(Game_mode & GM_MULTIPLAYER){
5099 if((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_MULTI_PAUSED)){
5100 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
5104 if ((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_DEATH_DIED) || (state == GS_STATE_DEATH_BLEW_UP) || (state == GS_STATE_GAME_PAUSED) ) {
5105 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
5111 case KEY_ESC | KEY_SHIFTED:
5112 // make sure to quit properly out of multiplayer
5113 if(Game_mode & GM_MULTIPLAYER){
5114 multi_quit_game(PROMPT_NONE);
5117 gameseq_post_event( GS_EVENT_QUIT_GAME );
5122 case KEY_DEBUGGED + KEY_P:
5125 case KEY_PRINT_SCRN:
5127 static int counter = 0;
5132 sprintf( tmp_name, NOX("screen%02d"), counter );
5134 mprintf(( "Dumping screen to '%s'\n", tmp_name ));
5135 gr_print_screen(tmp_name);
5143 case KEY_SHIFTED | KEY_ENTER: {
5145 #if !defined(NDEBUG)
5147 if ( Game_mode & GM_NORMAL ){
5151 // if we're in multiplayer mode, do some special networking
5152 if(Game_mode & GM_MULTIPLAYER){
5153 debug_console(game_do_dc_networking);
5160 if ( Game_mode & GM_NORMAL )
5174 gameseq_post_event(GS_EVENT_QUIT_GAME);
5177 void apply_physics( float damping, float desired_vel, float initial_vel, float t, float * new_vel, float * delta_pos );
5180 void camera_set_position( vector *pos )
5185 void camera_set_orient( matrix *orient )
5187 Camera_orient = *orient;
5190 void camera_set_velocity( vector *vel, int instantaneous )
5192 Camera_desired_velocity.xyz.x = 0.0f;
5193 Camera_desired_velocity.xyz.y = 0.0f;
5194 Camera_desired_velocity.xyz.z = 0.0f;
5196 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.rvec, vel->xyz.x );
5197 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.uvec, vel->xyz.y );
5198 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.fvec, vel->xyz.z );
5200 if ( instantaneous ) {
5201 Camera_velocity = Camera_desired_velocity;
5209 vector new_vel, delta_pos;
5211 apply_physics( Camera_damping, Camera_desired_velocity.xyz.x, Camera_velocity.xyz.x, flFrametime, &new_vel.xyz.x, &delta_pos.xyz.x );
5212 apply_physics( Camera_damping, Camera_desired_velocity.xyz.y, Camera_velocity.xyz.y, flFrametime, &new_vel.xyz.y, &delta_pos.xyz.y );
5213 apply_physics( Camera_damping, Camera_desired_velocity.xyz.z, Camera_velocity.xyz.z, flFrametime, &new_vel.xyz.z, &delta_pos.xyz.z );
5215 Camera_velocity = new_vel;
5217 // mprintf(( "Camera velocity = %.1f,%.1f, %.1f\n", Camera_velocity.xyz.x, Camera_velocity.xyz.y, Camera_velocity.xyz.z ));
5219 vm_vec_add2( &Camera_pos, &delta_pos );
5221 float ot = Camera_time+0.0f;
5223 Camera_time += flFrametime;
5225 if ( (ot < 0.667f) && ( Camera_time >= 0.667f ) ) {
5228 tmp.xyz.z = 4.739f; // always go this fast forward.
5230 // pick x and y velocities so they are always on a
5231 // circle with a 25 m radius.
5233 float tmp_angle = frand()*PI2;
5235 tmp.xyz.x = 22.0f * (float)sin(tmp_angle);
5236 tmp.xyz.y = -22.0f * (float)cos(tmp_angle);
5238 //mprintf(( "Angle = %.1f, vx=%.1f, vy=%.1f\n", tmp_angle, tmp.xyz.x, tmp.xyz.y ));
5240 //mprintf(( "Changing velocity!\n" ));
5241 camera_set_velocity( &tmp, 0 );
5244 if ( (ot < 3.0f ) && ( Camera_time >= 3.0f ) ) {
5245 vector tmp = { 0.0f, 0.0f, 0.0f };
5246 camera_set_velocity( &tmp, 0 );
5251 void end_demo_campaign_do()
5253 #if defined(FS2_DEMO) || defined(FS1_DEMO)
5254 // show upsell screens
5255 demo_upsell_show_screens();
5256 #elif defined(OEM_BUILD)
5257 // show oem upsell screens
5258 oem_upsell_show_screens();
5261 // drop into main hall
5262 gameseq_post_event( GS_EVENT_MAIN_MENU );
5265 // All code to process events. This is the only place
5266 // that you should change the state of the game.
5267 void game_process_event( int current_state, int event )
5269 mprintf(("Got event %s in state %s\n", GS_event_text[event], GS_state_text[current_state]));
5272 case GS_EVENT_SIMULATOR_ROOM:
5273 gameseq_set_state(GS_STATE_SIMULATOR_ROOM);
5276 case GS_EVENT_MAIN_MENU:
5277 gameseq_set_state(GS_STATE_MAIN_MENU);
5280 case GS_EVENT_OPTIONS_MENU:
5281 gameseq_push_state( GS_STATE_OPTIONS_MENU );
5284 case GS_EVENT_BARRACKS_MENU:
5285 gameseq_set_state(GS_STATE_BARRACKS_MENU);
5288 case GS_EVENT_TECH_MENU:
5289 gameseq_set_state(GS_STATE_TECH_MENU);
5292 case GS_EVENT_TRAINING_MENU:
5293 gameseq_set_state(GS_STATE_TRAINING_MENU);
5296 case GS_EVENT_START_GAME:
5297 Select_default_ship = 0;
5298 Player_multi_died_check = -1;
5299 gameseq_set_state(GS_STATE_CMD_BRIEF);
5302 case GS_EVENT_START_BRIEFING:
5303 gameseq_set_state(GS_STATE_BRIEFING);
5306 case GS_EVENT_DEBRIEF:
5307 // did we end the campaign in the main freespace 2 single player campaign?
5309 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !stricmp(Campaign.filename, "freespace")) {
5311 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !stricmp(Campaign.filename, "freespace2")) {
5313 gameseq_post_event(GS_EVENT_END_CAMPAIGN);
5315 gameseq_set_state(GS_STATE_DEBRIEF);
5318 Player_multi_died_check = -1;
5321 case GS_EVENT_SHIP_SELECTION:
5322 gameseq_set_state( GS_STATE_SHIP_SELECT );
5325 case GS_EVENT_WEAPON_SELECTION:
5326 gameseq_set_state( GS_STATE_WEAPON_SELECT );
5329 case GS_EVENT_ENTER_GAME:
5331 // maybe start recording a demo
5333 demo_start_record("test.fsd");
5337 if (Game_mode & GM_MULTIPLAYER) {
5338 // if we're respawning, make sure we change the view mode so that the hud shows up
5339 if (current_state == GS_STATE_DEATH_BLEW_UP) {
5343 gameseq_set_state(GS_STATE_GAME_PLAY);
5345 gameseq_set_state(GS_STATE_GAME_PLAY, 1);
5348 Player_multi_died_check = -1;
5350 // clear multiplayer button info
5351 extern button_info Multi_ship_status_bi;
5352 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
5354 Start_time = f2fl(timer_get_approx_seconds());
5356 mprintf(("Entering game at time = %7.3f\n", Start_time));
5360 case GS_EVENT_START_GAME_QUICK:
5361 Select_default_ship = 1;
5362 gameseq_post_event(GS_EVENT_ENTER_GAME);
5366 case GS_EVENT_END_GAME:
5367 if ( (current_state == GS_STATE_GAME_PLAY) || (current_state == GS_STATE_DEATH_DIED) ||
5368 (current_state == GS_STATE_DEATH_BLEW_UP) || (current_state == GS_STATE_DEBRIEF) || (current_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) {
5369 gameseq_set_state(GS_STATE_MAIN_MENU);
5374 Player_multi_died_check = -1;
5377 case GS_EVENT_QUIT_GAME:
5378 main_hall_stop_music();
5379 main_hall_stop_ambient();
5380 gameseq_set_state(GS_STATE_QUIT_GAME);
5382 Player_multi_died_check = -1;
5385 case GS_EVENT_GAMEPLAY_HELP:
5386 gameseq_push_state( GS_STATE_GAMEPLAY_HELP );
5389 case GS_EVENT_PAUSE_GAME:
5390 gameseq_push_state(GS_STATE_GAME_PAUSED);
5393 case GS_EVENT_DEBUG_PAUSE_GAME:
5394 gameseq_push_state(GS_STATE_DEBUG_PAUSED);
5397 case GS_EVENT_TRAINING_PAUSE:
5398 gameseq_push_state(GS_STATE_TRAINING_PAUSED);
5401 case GS_EVENT_PREVIOUS_STATE:
5402 gameseq_pop_state();
5405 case GS_EVENT_TOGGLE_FULLSCREEN:
5406 #ifndef HARDWARE_ONLY
5408 if ( gr_screen.mode == GR_SOFTWARE ) {
5409 gr_init( GR_640, GR_DIRECTDRAW );
5410 } else if ( gr_screen.mode == GR_DIRECTDRAW ) {
5411 gr_init( GR_640, GR_SOFTWARE );
5417 case GS_EVENT_TOGGLE_GLIDE:
5419 if ( gr_screen.mode != GR_GLIDE ) {
5420 gr_init( GR_640, GR_GLIDE );
5422 gr_init( GR_640, GR_SOFTWARE );
5427 case GS_EVENT_LOAD_MISSION_MENU:
5428 gameseq_set_state(GS_STATE_LOAD_MISSION_MENU);
5431 case GS_EVENT_MISSION_LOG_SCROLLBACK:
5432 gameseq_push_state( GS_STATE_MISSION_LOG_SCROLLBACK );
5435 case GS_EVENT_HUD_CONFIG:
5436 gameseq_push_state( GS_STATE_HUD_CONFIG );
5439 case GS_EVENT_CONTROL_CONFIG:
5440 gameseq_push_state( GS_STATE_CONTROL_CONFIG );
5443 case GS_EVENT_DEATH_DIED:
5444 gameseq_set_state( GS_STATE_DEATH_DIED );
5447 case GS_EVENT_DEATH_BLEW_UP:
5448 if ( current_state == GS_STATE_DEATH_DIED ) {
5449 gameseq_set_state( GS_STATE_DEATH_BLEW_UP );
5450 event_music_player_death();
5452 // multiplayer clients set their extra check here
5453 if(Game_mode & GM_MULTIPLAYER){
5454 // set the multi died absolute last chance check
5455 Player_multi_died_check = time(NULL);
5458 mprintf(( "Ignoring GS_EVENT_DEATH_BLEW_UP because we're in state %d\n", current_state ));
5462 case GS_EVENT_NEW_CAMPAIGN:
5463 if (!mission_load_up_campaign()){
5464 readyroom_continue_campaign();
5467 Player_multi_died_check = -1;
5470 case GS_EVENT_CAMPAIGN_CHEAT:
5471 if (!mission_load_up_campaign()){
5473 // bash campaign value
5474 extern char Main_hall_campaign_cheat[512];
5477 // look for the mission
5478 for(idx=0; idx<Campaign.num_missions; idx++){
5479 if(!stricmp(Campaign.missions[idx].name, Main_hall_campaign_cheat)){
5480 Campaign.next_mission = idx;
5481 Campaign.prev_mission = idx - 1;
5488 readyroom_continue_campaign();
5491 Player_multi_died_check = -1;
5494 case GS_EVENT_CAMPAIGN_ROOM:
5495 gameseq_set_state(GS_STATE_CAMPAIGN_ROOM);
5498 case GS_EVENT_CMD_BRIEF:
5499 gameseq_set_state(GS_STATE_CMD_BRIEF);
5502 case GS_EVENT_RED_ALERT:
5503 gameseq_set_state(GS_STATE_RED_ALERT);
5506 case GS_EVENT_CREDITS:
5507 gameseq_set_state( GS_STATE_CREDITS );
5510 case GS_EVENT_VIEW_MEDALS:
5511 gameseq_push_state( GS_STATE_VIEW_MEDALS );
5514 case GS_EVENT_SHOW_GOALS:
5515 gameseq_push_state( GS_STATE_SHOW_GOALS ); // use push_state() since we might get to this screen through a variety of states
5518 case GS_EVENT_HOTKEY_SCREEN:
5519 gameseq_push_state( GS_STATE_HOTKEY_SCREEN ); // use push_state() since we might get to this screen through a variety of states
5522 // multiplayer stuff follow these comments
5524 case GS_EVENT_MULTI_JOIN_GAME:
5525 gameseq_set_state( GS_STATE_MULTI_JOIN_GAME );
5528 case GS_EVENT_MULTI_HOST_SETUP:
5529 gameseq_set_state( GS_STATE_MULTI_HOST_SETUP );
5532 case GS_EVENT_MULTI_CLIENT_SETUP:
5533 gameseq_set_state( GS_STATE_MULTI_CLIENT_SETUP );
5536 case GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN:
5537 gameseq_set_state(GS_STATE_VIEW_CUTSCENES);
5540 case GS_EVENT_MULTI_STD_WAIT:
5541 gameseq_set_state( GS_STATE_MULTI_STD_WAIT );
5544 case GS_EVENT_STANDALONE_MAIN:
5545 gameseq_set_state( GS_STATE_STANDALONE_MAIN );
5548 case GS_EVENT_MULTI_PAUSE:
5549 gameseq_push_state( GS_STATE_MULTI_PAUSED );
5552 case GS_EVENT_INGAME_PRE_JOIN:
5553 gameseq_set_state( GS_STATE_INGAME_PRE_JOIN );
5556 case GS_EVENT_EVENT_DEBUG:
5557 gameseq_push_state(GS_STATE_EVENT_DEBUG);
5560 // Start a warpout where player automatically goes 70 no matter what
5561 // and can't cancel out of it.
5562 case GS_EVENT_PLAYER_WARPOUT_START_FORCED:
5563 Warpout_forced = 1; // If non-zero, bash the player to speed and go through effect
5565 // Same code as in GS_EVENT_PLAYER_WARPOUT_START only ignores current mode
5566 Player->saved_viewer_mode = Viewer_mode;
5567 Player->control_mode = PCM_WARPOUT_STAGE1;
5568 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5569 Warpout_time = 0.0f; // Start timer!
5572 case GS_EVENT_PLAYER_WARPOUT_START:
5573 if ( Player->control_mode != PCM_NORMAL ) {
5574 mprintf(( "Player isn't in normal mode; cannot warp out.\n" ));
5576 Player->saved_viewer_mode = Viewer_mode;
5577 Player->control_mode = PCM_WARPOUT_STAGE1;
5578 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5579 Warpout_time = 0.0f; // Start timer!
5580 Warpout_forced = 0; // If non-zero, bash the player to speed and go through effect
5584 case GS_EVENT_PLAYER_WARPOUT_STOP:
5585 if ( Player->control_mode != PCM_NORMAL ) {
5586 if ( !Warpout_forced ) { // cannot cancel forced warpout
5587 Player->control_mode = PCM_NORMAL;
5588 Viewer_mode = Player->saved_viewer_mode;
5589 hud_subspace_notify_abort();
5590 mprintf(( "Player put back to normal mode.\n" ));
5591 if ( Warpout_sound > -1 ) {
5592 snd_stop( Warpout_sound );
5599 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE1: // player ship got up to speed
5600 if ( Player->control_mode != PCM_WARPOUT_STAGE1 ) {
5601 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5602 mprintf(( "Player put back to normal mode, because of invalid sequence in stage1.\n" ));
5604 mprintf(( "Hit target speed. Starting warp effect and moving to stage 2!\n" ));
5605 shipfx_warpout_start( Player_obj );
5606 Player->control_mode = PCM_WARPOUT_STAGE2;
5607 Player->saved_viewer_mode = Viewer_mode;
5608 Viewer_mode |= VM_WARP_CHASE;
5610 vector tmp = Player_obj->pos;
5612 ship_get_eye( &tmp, &tmp_m, Player_obj );
5613 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.rvec, 0.0f );
5614 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.uvec, 0.952f );
5615 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.fvec, -1.782f );
5617 camera_set_position( &tmp );
5618 camera_set_orient( &Player_obj->orient );
5619 vector tmp_vel = { 0.0f, 5.1919f, 14.7f };
5621 //mprintf(( "Rad = %.1f\n", Player_obj->radius ));
5622 camera_set_velocity( &tmp_vel, 1);
5626 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE2: // player ship got into the warp effect
5627 if ( Player->control_mode != PCM_WARPOUT_STAGE2 ) {
5628 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5629 mprintf(( "Player put back to normal mode, because of invalid sequence in stage2.\n" ));
5631 mprintf(( "Hit warp effect. Moving to stage 3!\n" ));
5632 Player->control_mode = PCM_WARPOUT_STAGE3;
5636 case GS_EVENT_PLAYER_WARPOUT_DONE: // player ship got through the warp effect
5637 mprintf(( "Player warped out. Going to debriefing!\n" ));
5638 Player->control_mode = PCM_NORMAL;
5639 Viewer_mode = Player->saved_viewer_mode;
5642 // we have a special debriefing screen for multiplayer furballs
5643 if((Game_mode & GM_MULTIPLAYER) && (The_mission.game_type & MISSION_TYPE_MULTI_DOGFIGHT)){
5644 gameseq_post_event(GS_EVENT_MULTI_DOGFIGHT_DEBRIEF);
5646 // do the normal debriefing for all other situations
5648 gameseq_post_event(GS_EVENT_DEBRIEF);
5652 case GS_EVENT_STANDALONE_POSTGAME:
5653 gameseq_set_state(GS_STATE_STANDALONE_POSTGAME);
5656 case GS_EVENT_INITIAL_PLAYER_SELECT:
5657 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5660 case GS_EVENT_GAME_INIT:
5661 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
5662 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5664 // see if the command line option has been set to use the last pilot, and act acoordingly
5665 if( player_select_get_last_pilot() ) {
5666 // always enter the main menu -- do the automatic network startup stuff elsewhere
5667 // so that we still have valid checks for networking modes, etc.
5668 gameseq_set_state(GS_STATE_MAIN_MENU);
5670 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5675 case GS_EVENT_MULTI_MISSION_SYNC:
5676 gameseq_set_state(GS_STATE_MULTI_MISSION_SYNC);
5679 case GS_EVENT_MULTI_START_GAME:
5680 gameseq_set_state(GS_STATE_MULTI_START_GAME);
5683 case GS_EVENT_MULTI_HOST_OPTIONS:
5684 gameseq_set_state(GS_STATE_MULTI_HOST_OPTIONS);
5687 case GS_EVENT_MULTI_DOGFIGHT_DEBRIEF:
5688 gameseq_set_state(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
5691 case GS_EVENT_TEAM_SELECT:
5692 gameseq_set_state(GS_STATE_TEAM_SELECT);
5695 case GS_EVENT_END_CAMPAIGN:
5696 gameseq_set_state(GS_STATE_END_OF_CAMPAIGN);
5699 case GS_EVENT_END_DEMO:
5700 gameseq_set_state(GS_STATE_END_DEMO);
5703 case GS_EVENT_LOOP_BRIEF:
5704 gameseq_set_state(GS_STATE_LOOP_BRIEF);
5713 // Called when a state is being left.
5714 // The current state is still at old_state, but as soon as
5715 // this function leaves, then the current state will become
5716 // new state. You should never try to change the state
5717 // in here... if you think you need to, you probably really
5718 // need to post an event, not change the state.
5719 void game_leave_state( int old_state, int new_state )
5721 int end_mission = 1;
5723 switch (new_state) {
5724 case GS_STATE_GAME_PAUSED:
5725 case GS_STATE_DEBUG_PAUSED:
5726 case GS_STATE_OPTIONS_MENU:
5727 case GS_STATE_CONTROL_CONFIG:
5728 case GS_STATE_MISSION_LOG_SCROLLBACK:
5729 case GS_STATE_DEATH_DIED:
5730 case GS_STATE_SHOW_GOALS:
5731 case GS_STATE_HOTKEY_SCREEN:
5732 case GS_STATE_MULTI_PAUSED:
5733 case GS_STATE_TRAINING_PAUSED:
5734 case GS_STATE_EVENT_DEBUG:
5735 case GS_STATE_GAMEPLAY_HELP:
5736 end_mission = 0; // these events shouldn't end a mission
5740 switch (old_state) {
5741 case GS_STATE_BRIEFING:
5742 brief_stop_voices();
5743 if ( (new_state != GS_STATE_OPTIONS_MENU) && (new_state != GS_STATE_WEAPON_SELECT)
5744 && (new_state != GS_STATE_SHIP_SELECT) && (new_state != GS_STATE_HOTKEY_SCREEN)
5745 && (new_state != GS_STATE_TEAM_SELECT) ){
5746 common_select_close();
5747 if ( new_state == GS_STATE_MAIN_MENU ) {
5748 freespace_stop_mission();
5752 // COMMAND LINE OPTION
5753 if (Cmdline_multi_stream_chat_to_file){
5754 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5755 cfclose(Multi_chat_stream);
5759 case GS_STATE_DEBRIEF:
5760 if ( (new_state != GS_STATE_VIEW_MEDALS) && (new_state != GS_STATE_OPTIONS_MENU) ) {
5765 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
5766 multi_df_debrief_close();
5769 case GS_STATE_LOAD_MISSION_MENU:
5770 mission_load_menu_close();
5773 case GS_STATE_SIMULATOR_ROOM:
5777 case GS_STATE_CAMPAIGN_ROOM:
5778 campaign_room_close();
5781 case GS_STATE_CMD_BRIEF:
5782 if (new_state == GS_STATE_OPTIONS_MENU) {
5787 if (new_state == GS_STATE_MAIN_MENU)
5788 freespace_stop_mission();
5793 case GS_STATE_RED_ALERT:
5797 case GS_STATE_SHIP_SELECT:
5798 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_WEAPON_SELECT &&
5799 new_state != GS_STATE_HOTKEY_SCREEN &&
5800 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5801 common_select_close();
5802 if ( new_state == GS_STATE_MAIN_MENU ) {
5803 freespace_stop_mission();
5808 case GS_STATE_WEAPON_SELECT:
5809 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5810 new_state != GS_STATE_HOTKEY_SCREEN &&
5811 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5812 common_select_close();
5813 if ( new_state == GS_STATE_MAIN_MENU ) {
5814 freespace_stop_mission();
5819 case GS_STATE_TEAM_SELECT:
5820 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5821 new_state != GS_STATE_HOTKEY_SCREEN &&
5822 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_WEAPON_SELECT) {
5823 common_select_close();
5824 if ( new_state == GS_STATE_MAIN_MENU ) {
5825 freespace_stop_mission();
5830 case GS_STATE_MAIN_MENU:
5831 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
5838 case GS_STATE_OPTIONS_MENU:
5839 //game_start_time();
5840 if(new_state == GS_STATE_MULTI_JOIN_GAME){
5841 multi_join_clear_game_list();
5843 options_menu_close();
5846 case GS_STATE_BARRACKS_MENU:
5847 if(new_state != GS_STATE_VIEW_MEDALS){
5852 case GS_STATE_MISSION_LOG_SCROLLBACK:
5853 hud_scrollback_close();
5856 case GS_STATE_TRAINING_MENU:
5857 training_menu_close();
5860 case GS_STATE_GAME_PLAY:
5861 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
5862 player_save_target_and_weapon_link_prefs();
5863 game_stop_looped_sounds();
5866 sound_env_disable();
5867 joy_ff_stop_effects();
5869 // stop game time under certain conditions
5870 if ( end_mission || (Game_mode & GM_NORMAL) || ((Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MULTI_PAUSED)) ){
5875 // shut down any recording or playing demos
5880 // when in multiplayer and going back to the main menu, send a leave game packet
5881 // right away (before calling stop mission). stop_mission was taking to long to
5882 // close mission down and I want people to get notified ASAP.
5883 if ( (Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MAIN_MENU) ){
5884 multi_quit_game(PROMPT_NONE);
5887 freespace_stop_mission();
5888 Game_time_compression = F1_0;
5892 case GS_STATE_TECH_MENU:
5896 case GS_STATE_TRAINING_PAUSED:
5897 Training_num_lines = 0;
5898 // fall through to GS_STATE_GAME_PAUSED
5900 case GS_STATE_GAME_PAUSED:
5902 if ( end_mission ) {
5907 case GS_STATE_DEBUG_PAUSED:
5910 pause_debug_close();
5914 case GS_STATE_HUD_CONFIG:
5918 // join/start a game
5919 case GS_STATE_MULTI_JOIN_GAME:
5920 if(new_state != GS_STATE_OPTIONS_MENU){
5921 multi_join_game_close();
5925 case GS_STATE_MULTI_HOST_SETUP:
5926 case GS_STATE_MULTI_CLIENT_SETUP:
5927 // if this is just the host going into the options screen, don't do anything
5928 if((new_state == GS_STATE_MULTI_HOST_OPTIONS) || (new_state == GS_STATE_OPTIONS_MENU)){
5932 // close down the proper state
5933 if(old_state == GS_STATE_MULTI_HOST_SETUP){
5934 multi_create_game_close();
5936 multi_game_client_setup_close();
5939 // COMMAND LINE OPTION
5940 if (Cmdline_multi_stream_chat_to_file){
5941 if( (new_state != GS_STATE_TEAM_SELECT) && (Multi_chat_stream!=NULL) ) {
5942 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5943 cfclose(Multi_chat_stream);
5948 case GS_STATE_CONTROL_CONFIG:
5949 control_config_close();
5952 case GS_STATE_DEATH_DIED:
5953 Game_mode &= ~GM_DEAD_DIED;
5955 // early end while respawning or blowing up in a multiplayer game
5956 if((Game_mode & GM_MULTIPLAYER) && ((new_state == GS_STATE_DEBRIEF) || (new_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) ){
5958 freespace_stop_mission();
5962 case GS_STATE_DEATH_BLEW_UP:
5963 Game_mode &= ~GM_DEAD_BLEW_UP;
5965 // for single player, we might reload mission, etc. For multiplayer, look at my new state
5966 // to determine if I should do anything.
5967 if ( !(Game_mode & GM_MULTIPLAYER) ) {
5969 freespace_stop_mission();
5972 // if we are not respawing as an observer or as a player, our new state will not
5973 // be gameplay state.
5974 if ( (new_state != GS_STATE_GAME_PLAY) && (new_state != GS_STATE_MULTI_PAUSED) ) {
5975 game_stop_time(); // hasn't been called yet!!
5976 freespace_stop_mission();
5982 case GS_STATE_CREDITS:
5986 case GS_STATE_VIEW_MEDALS:
5990 case GS_STATE_SHOW_GOALS:
5991 mission_show_goals_close();
5994 case GS_STATE_HOTKEY_SCREEN:
5995 if ( new_state != GS_STATE_OPTIONS_MENU ) {
5996 mission_hotkey_close();
6000 case GS_STATE_MULTI_MISSION_SYNC:
6001 // if we're moving into the options menu, don't do anything
6002 if(new_state == GS_STATE_OPTIONS_MENU){
6006 Assert( Game_mode & GM_MULTIPLAYER );
6008 if ( new_state == GS_STATE_GAME_PLAY ){
6009 // palette_restore_palette();
6011 // change a couple of flags to indicate our state!!!
6012 Net_player->state = NETPLAYER_STATE_IN_MISSION;
6013 send_netplayer_update_packet();
6015 // set the game mode
6016 Game_mode |= GM_IN_MISSION;
6020 case GS_STATE_VIEW_CUTSCENES:
6021 cutscenes_screen_close();
6024 case GS_STATE_MULTI_STD_WAIT:
6025 multi_standalone_wait_close();
6028 case GS_STATE_STANDALONE_MAIN:
6029 standalone_main_close();
6030 if(new_state == GS_STATE_MULTI_STD_WAIT){
6031 init_multiplayer_stats();
6035 case GS_STATE_MULTI_PAUSED:
6036 // if ( end_mission ){
6041 case GS_STATE_INGAME_PRE_JOIN:
6042 multi_ingame_select_close();
6045 case GS_STATE_STANDALONE_POSTGAME:
6046 multi_standalone_postgame_close();
6049 case GS_STATE_INITIAL_PLAYER_SELECT:
6050 player_select_close();
6053 case GS_STATE_MULTI_START_GAME:
6054 multi_start_game_close();
6057 case GS_STATE_MULTI_HOST_OPTIONS:
6058 multi_host_options_close();
6061 case GS_STATE_END_OF_CAMPAIGN:
6062 mission_campaign_end_close();
6065 case GS_STATE_LOOP_BRIEF:
6071 // Called when a state is being entered.
6072 // The current state is set to the state we're entering at
6073 // this point, and old_state is set to the state we're coming
6074 // from. You should never try to change the state
6075 // in here... if you think you need to, you probably really
6076 // need to post an event, not change the state.
6078 void game_enter_state( int old_state, int new_state )
6080 switch (new_state) {
6081 case GS_STATE_MAIN_MENU:
6082 // in multiplayer mode, be sure that we are not doing networking anymore.
6083 if ( Game_mode & GM_MULTIPLAYER ) {
6084 Assert( Net_player != NULL );
6085 Net_player->flags &= ~NETINFO_FLAG_DO_NETWORKING;
6088 Game_time_compression = F1_0;
6090 // determine which ship this guy is currently based on
6091 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
6094 if (Player->on_bastion) {
6102 case GS_STATE_BRIEFING:
6103 main_hall_stop_music();
6104 main_hall_stop_ambient();
6106 if (Game_mode & GM_NORMAL) {
6107 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
6108 // MWA: or from options or hotkey screens
6109 // JH: or if the command brief state already did this
6110 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
6111 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT)
6112 && (old_state != GS_STATE_CMD_BRIEF) ) {
6113 if ( !game_start_mission() ) // this should put us into a new state on failure!
6117 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
6118 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
6119 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6121 Game_time_compression = F1_0;
6123 if ( red_alert_mission() ) {
6124 gameseq_post_event(GS_EVENT_RED_ALERT);
6131 case GS_STATE_DEBRIEF:
6132 game_stop_looped_sounds();
6133 mission_goal_fail_incomplete(); // fail all incomplete goals before entering debriefing
6134 if ( (old_state != GS_STATE_VIEW_MEDALS) && (old_state != GS_STATE_OPTIONS_MENU) ){
6139 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6140 multi_df_debrief_init();
6143 case GS_STATE_LOAD_MISSION_MENU:
6144 mission_load_menu_init();
6147 case GS_STATE_SIMULATOR_ROOM:
6151 case GS_STATE_CAMPAIGN_ROOM:
6152 campaign_room_init();
6155 case GS_STATE_RED_ALERT:
6156 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6160 case GS_STATE_CMD_BRIEF: {
6161 int team_num = 0; // team number used as index for which cmd brief to use.
6163 if (old_state == GS_STATE_OPTIONS_MENU) {
6167 main_hall_stop_music();
6168 main_hall_stop_ambient();
6170 if (Game_mode & GM_NORMAL) {
6171 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
6172 // MWA: or from options or hotkey screens
6173 // JH: or if the command brief state already did this
6174 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
6175 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT) ) {
6176 if ( !game_start_mission() ) // this should put us into a new state on failure!
6181 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
6182 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
6183 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6185 cmd_brief_init(team_num);
6191 case GS_STATE_SHIP_SELECT:
6195 case GS_STATE_WEAPON_SELECT:
6196 weapon_select_init();
6199 case GS_STATE_TEAM_SELECT:
6203 case GS_STATE_GAME_PAUSED:
6208 case GS_STATE_DEBUG_PAUSED:
6209 // game_stop_time();
6210 // os_set_title("FreeSpace - PAUSED");
6213 case GS_STATE_TRAINING_PAUSED:
6220 case GS_STATE_OPTIONS_MENU:
6222 options_menu_init();
6225 case GS_STATE_GAME_PLAY:
6226 // coming from the gameplay state or the main menu, we might need to load the mission
6227 if ( (Game_mode & GM_NORMAL) && ((old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_GAME_PLAY) || (old_state == GS_STATE_DEATH_BLEW_UP)) ) {
6228 if ( !game_start_mission() ) // this should put us into a new state.
6233 // if we are coming from the briefing, ship select, weapons loadout, or main menu (in the
6234 // case of quick start), then do bitmap loads, etc Don't do any of the loading stuff
6235 // if we are in multiplayer -- this stuff is all handled in the multi-wait section
6236 if ( !(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_BRIEFING) || (old_state == GS_STATE_SHIP_SELECT) ||
6237 (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) ) {
6238 // JAS: Used to do all paging here.
6242 HUD_printf("Skill level is set to ** %s **", Skill_level_names(Game_skill_level));
6246 main_hall_stop_music();
6247 main_hall_stop_ambient();
6248 event_music_first_pattern(); // start the first pattern
6251 // special code that restores player ship selection and weapons loadout when doing a quick start
6252 if ( !(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_DEATH_BLEW_UP) || (old_state == GS_STATE_GAME_PLAY) ) {
6253 if ( !stricmp(Player_loadout.filename, Game_current_mission_filename) ) {
6254 wss_direct_restore_loadout();
6258 // single-player, quick-start after just died... we need to set weapon linking and kick off the event music
6259 if (!(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_DEATH_BLEW_UP) ) {
6260 event_music_first_pattern(); // start the first pattern
6263 if ( !(Game_mode & GM_STANDALONE_SERVER) && (old_state != GS_STATE_GAME_PAUSED) && (old_state != GS_STATE_MULTI_PAUSED) ) {
6264 event_music_first_pattern(); // start the first pattern
6266 player_restore_target_and_weapon_link_prefs();
6268 Game_mode |= GM_IN_MISSION;
6271 // required to truely make mouse deltas zeroed in debug mouse code
6272 void mouse_force_pos(int x, int y);
6273 if (!Is_standalone) {
6274 mouse_force_pos(gr_screen.max_w / 2, gr_screen.max_h / 2);
6280 // only start time if in single player, or coming from multi wait state
6283 (Game_mode & GM_NORMAL) &&
6284 (old_state != GS_STATE_VIEW_CUTSCENES)
6286 (Game_mode & GM_MULTIPLAYER) && (
6287 (old_state == GS_STATE_MULTI_PAUSED) ||
6288 (old_state == GS_STATE_MULTI_MISSION_SYNC)
6294 // when coming from the multi paused state, reset the timestamps
6295 if ( (Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_MULTI_PAUSED) ){
6296 multi_reset_timestamps();
6299 if ((Game_mode & GM_MULTIPLAYER) && (old_state != GS_STATE_DEATH_BLEW_UP) ) {
6300 // initialize all object update details
6301 multi_oo_gameplay_init();
6304 // under certain circumstances, the server should reset the object update rate limiting stuff
6305 if( ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)) &&
6306 (old_state == GS_STATE_MULTI_PAUSED) || (old_state == GS_STATE_MULTI_MISSION_SYNC) ){
6308 // reinitialize the rate limiting system for all clients
6309 multi_oo_rate_init_all();
6312 // multiplayer clients should always re-initialize their control info rate limiting system
6313 if((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)){
6314 multi_oo_rate_init_all();
6318 if(Game_mode & GM_MULTIPLAYER){
6319 multi_ping_reset_players();
6322 Game_subspace_effect = 0;
6323 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
6324 Game_subspace_effect = 1;
6325 if( !(Game_mode & GM_STANDALONE_SERVER) ){
6326 game_start_subspace_ambient_sound();
6330 sound_env_set(&Game_sound_env);
6331 joy_ff_mission_init(Ship_info[Player_ship->ship_info_index].rotation_time);
6333 // clear multiplayer button info i
6334 extern button_info Multi_ship_status_bi;
6335 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
6338 case GS_STATE_HUD_CONFIG:
6342 case GS_STATE_MULTI_JOIN_GAME:
6343 multi_join_clear_game_list();
6345 if (old_state != GS_STATE_OPTIONS_MENU) {
6346 multi_join_game_init();
6351 case GS_STATE_MULTI_HOST_SETUP:
6352 // don't reinitialize if we're coming back from the host options screen
6353 if ((old_state != GS_STATE_MULTI_HOST_OPTIONS) && (old_state != GS_STATE_OPTIONS_MENU)) {
6354 multi_create_game_init();
6359 case GS_STATE_MULTI_CLIENT_SETUP:
6360 if (old_state != GS_STATE_OPTIONS_MENU) {
6361 multi_game_client_setup_init();
6366 case GS_STATE_CONTROL_CONFIG:
6367 control_config_init();
6370 case GS_STATE_TECH_MENU:
6374 case GS_STATE_BARRACKS_MENU:
6375 if(old_state != GS_STATE_VIEW_MEDALS){
6380 case GS_STATE_MISSION_LOG_SCROLLBACK:
6381 hud_scrollback_init();
6384 case GS_STATE_DEATH_DIED:
6385 Player_died_time = timestamp(10);
6387 if(!(Game_mode & GM_MULTIPLAYER)){
6388 player_show_death_message();
6390 Game_mode |= GM_DEAD_DIED;
6393 case GS_STATE_DEATH_BLEW_UP:
6394 if ( !popupdead_is_active() ) {
6395 Player_ai->target_objnum = -1;
6398 // stop any local EMP effect
6401 Players[Player_num].flags &= ~PLAYER_FLAGS_AUTO_TARGETING; // Prevent immediate switch to a hostile ship.
6402 Game_mode |= GM_DEAD_BLEW_UP;
6403 Show_viewing_from_self = 0;
6405 // timestamp how long we should wait before displaying the died popup
6406 if ( !popupdead_is_active() ) {
6407 Player_died_popup_wait = timestamp(PLAYER_DIED_POPUP_WAIT);
6411 case GS_STATE_GAMEPLAY_HELP:
6412 gameplay_help_init();
6415 case GS_STATE_CREDITS:
6416 main_hall_stop_music();
6417 main_hall_stop_ambient();
6421 case GS_STATE_VIEW_MEDALS:
6422 medal_main_init(Player);
6425 case GS_STATE_SHOW_GOALS:
6426 mission_show_goals_init();
6429 case GS_STATE_HOTKEY_SCREEN:
6430 mission_hotkey_init();
6433 case GS_STATE_MULTI_MISSION_SYNC:
6434 // if we're coming from the options screen, don't do any
6435 if(old_state == GS_STATE_OPTIONS_MENU){
6439 switch(Multi_sync_mode){
6440 case MULTI_SYNC_PRE_BRIEFING:
6441 // if moving from game forming to the team select state
6444 case MULTI_SYNC_POST_BRIEFING:
6445 // if moving from briefing into the mission itself
6448 // tell everyone that we're now loading data
6449 Net_player->state = NETPLAYER_STATE_DATA_LOAD;
6450 send_netplayer_update_packet();
6452 // JAS: Used to do all paging here!!!!
6454 Net_player->state = NETPLAYER_STATE_WAITING;
6455 send_netplayer_update_packet();
6457 Game_time_compression = F1_0;
6459 case MULTI_SYNC_INGAME:
6465 case GS_STATE_VIEW_CUTSCENES:
6466 cutscenes_screen_init();
6469 case GS_STATE_MULTI_STD_WAIT:
6470 multi_standalone_wait_init();
6473 case GS_STATE_STANDALONE_MAIN:
6474 // don't initialize if we're coming from one of these 2 states unless there are no
6475 // players left (reset situation)
6476 if((old_state != GS_STATE_STANDALONE_POSTGAME) || multi_endgame_ending()){
6477 standalone_main_init();
6481 case GS_STATE_MULTI_PAUSED:
6485 case GS_STATE_INGAME_PRE_JOIN:
6486 multi_ingame_select_init();
6489 case GS_STATE_STANDALONE_POSTGAME:
6490 multi_standalone_postgame_init();
6493 case GS_STATE_INITIAL_PLAYER_SELECT:
6494 player_select_init();
6497 case GS_STATE_MULTI_START_GAME:
6498 multi_start_game_init();
6501 case GS_STATE_MULTI_HOST_OPTIONS:
6502 multi_host_options_init();
6505 case GS_STATE_END_OF_CAMPAIGN:
6506 mission_campaign_end_init();
6509 case GS_STATE_LOOP_BRIEF:
6516 // do stuff that may need to be done regardless of state
6517 void game_do_state_common(int state,int no_networking)
6519 game_maybe_draw_mouse(flFrametime); // determine if to draw the mouse this frame
6520 snd_do_frame(); // update sound system
6521 event_music_do_frame(); // music needs to play across many states
6523 multi_log_process();
6525 if (no_networking) {
6529 // maybe do a multiplayer frame based on game mode and state type
6530 if (Game_mode & GM_MULTIPLAYER) {
6532 case GS_STATE_OPTIONS_MENU:
6533 case GS_STATE_GAMEPLAY_HELP:
6534 case GS_STATE_HOTKEY_SCREEN:
6535 case GS_STATE_HUD_CONFIG:
6536 case GS_STATE_CONTROL_CONFIG:
6537 case GS_STATE_MISSION_LOG_SCROLLBACK:
6538 case GS_STATE_SHOW_GOALS:
6539 case GS_STATE_VIEW_CUTSCENES:
6540 case GS_STATE_EVENT_DEBUG:
6541 multi_maybe_do_frame();
6545 game_do_networking();
6549 // Called once a frame.
6550 // You should never try to change the state
6551 // in here... if you think you need to, you probably really
6552 // need to post an event, not change the state.
6553 int Game_do_state_should_skip = 0;
6554 void game_do_state(int state)
6556 // always lets the do_state_common() function determine if the state should be skipped
6557 Game_do_state_should_skip = 0;
6559 // legal to set the should skip state anywhere in this function
6560 game_do_state_common(state); // do stuff that may need to be done regardless of state
6562 if(Game_do_state_should_skip){
6567 case GS_STATE_MAIN_MENU:
6568 game_set_frametime(GS_STATE_MAIN_MENU);
6569 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
6572 main_hall_do(flFrametime);
6576 case GS_STATE_OPTIONS_MENU:
6577 game_set_frametime(GS_STATE_OPTIONS_MENU);
6578 options_menu_do_frame(flFrametime);
6581 case GS_STATE_BARRACKS_MENU:
6582 game_set_frametime(GS_STATE_BARRACKS_MENU);
6583 barracks_do_frame(flFrametime);
6586 case GS_STATE_TRAINING_MENU:
6587 game_set_frametime(GS_STATE_TRAINING_MENU);
6588 training_menu_do_frame(flFrametime);
6591 case GS_STATE_TECH_MENU:
6592 game_set_frametime(GS_STATE_TECH_MENU);
6593 techroom_do_frame(flFrametime);
6596 case GS_STATE_GAMEPLAY_HELP:
6597 game_set_frametime(GS_STATE_GAMEPLAY_HELP);
6598 gameplay_help_do_frame(flFrametime);
6601 case GS_STATE_GAME_PLAY: // do stuff that should be done during gameplay
6605 case GS_STATE_GAME_PAUSED:
6609 case GS_STATE_DEBUG_PAUSED:
6611 game_set_frametime(GS_STATE_DEBUG_PAUSED);
6616 case GS_STATE_TRAINING_PAUSED:
6617 game_training_pause_do();
6620 case GS_STATE_LOAD_MISSION_MENU:
6621 game_set_frametime(GS_STATE_LOAD_MISSION_MENU);
6622 mission_load_menu_do();
6625 case GS_STATE_BRIEFING:
6626 game_set_frametime(GS_STATE_BRIEFING);
6627 brief_do_frame(flFrametime);
6630 case GS_STATE_DEBRIEF:
6631 game_set_frametime(GS_STATE_DEBRIEF);
6632 debrief_do_frame(flFrametime);
6635 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6636 game_set_frametime(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
6637 multi_df_debrief_do();
6640 case GS_STATE_SHIP_SELECT:
6641 game_set_frametime(GS_STATE_SHIP_SELECT);
6642 ship_select_do(flFrametime);
6645 case GS_STATE_WEAPON_SELECT:
6646 game_set_frametime(GS_STATE_WEAPON_SELECT);
6647 weapon_select_do(flFrametime);
6650 case GS_STATE_MISSION_LOG_SCROLLBACK:
6651 game_set_frametime(GS_STATE_MISSION_LOG_SCROLLBACK);
6652 hud_scrollback_do_frame(flFrametime);
6655 case GS_STATE_HUD_CONFIG:
6656 game_set_frametime(GS_STATE_HUD_CONFIG);
6657 hud_config_do_frame(flFrametime);
6660 case GS_STATE_MULTI_JOIN_GAME:
6661 game_set_frametime(GS_STATE_MULTI_JOIN_GAME);
6662 multi_join_game_do_frame();
6665 case GS_STATE_MULTI_HOST_SETUP:
6666 game_set_frametime(GS_STATE_MULTI_HOST_SETUP);
6667 multi_create_game_do();
6670 case GS_STATE_MULTI_CLIENT_SETUP:
6671 game_set_frametime(GS_STATE_MULTI_CLIENT_SETUP);
6672 multi_game_client_setup_do_frame();
6675 case GS_STATE_CONTROL_CONFIG:
6676 game_set_frametime(GS_STATE_CONTROL_CONFIG);
6677 control_config_do_frame(flFrametime);
6680 case GS_STATE_DEATH_DIED:
6684 case GS_STATE_DEATH_BLEW_UP:
6688 case GS_STATE_SIMULATOR_ROOM:
6689 game_set_frametime(GS_STATE_SIMULATOR_ROOM);
6690 sim_room_do_frame(flFrametime);
6693 case GS_STATE_CAMPAIGN_ROOM:
6694 game_set_frametime(GS_STATE_CAMPAIGN_ROOM);
6695 campaign_room_do_frame(flFrametime);
6698 case GS_STATE_RED_ALERT:
6699 game_set_frametime(GS_STATE_RED_ALERT);
6700 red_alert_do_frame(flFrametime);
6703 case GS_STATE_CMD_BRIEF:
6704 game_set_frametime(GS_STATE_CMD_BRIEF);
6705 cmd_brief_do_frame(flFrametime);
6708 case GS_STATE_CREDITS:
6709 game_set_frametime(GS_STATE_CREDITS);
6710 credits_do_frame(flFrametime);
6713 case GS_STATE_VIEW_MEDALS:
6714 game_set_frametime(GS_STATE_VIEW_MEDALS);
6718 case GS_STATE_SHOW_GOALS:
6719 game_set_frametime(GS_STATE_SHOW_GOALS);
6720 mission_show_goals_do_frame(flFrametime);
6723 case GS_STATE_HOTKEY_SCREEN:
6724 game_set_frametime(GS_STATE_HOTKEY_SCREEN);
6725 mission_hotkey_do_frame(flFrametime);
6728 case GS_STATE_VIEW_CUTSCENES:
6729 game_set_frametime(GS_STATE_VIEW_CUTSCENES);
6730 cutscenes_screen_do_frame();
6733 case GS_STATE_MULTI_STD_WAIT:
6734 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6735 multi_standalone_wait_do();
6738 case GS_STATE_STANDALONE_MAIN:
6739 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6740 standalone_main_do();
6743 case GS_STATE_MULTI_PAUSED:
6744 game_set_frametime(GS_STATE_MULTI_PAUSED);
6748 case GS_STATE_TEAM_SELECT:
6749 game_set_frametime(GS_STATE_TEAM_SELECT);
6753 case GS_STATE_INGAME_PRE_JOIN:
6754 game_set_frametime(GS_STATE_INGAME_PRE_JOIN);
6755 multi_ingame_select_do();
6758 case GS_STATE_EVENT_DEBUG:
6760 game_set_frametime(GS_STATE_EVENT_DEBUG);
6761 game_show_event_debug(flFrametime);
6765 case GS_STATE_STANDALONE_POSTGAME:
6766 game_set_frametime(GS_STATE_STANDALONE_POSTGAME);
6767 multi_standalone_postgame_do();
6770 case GS_STATE_INITIAL_PLAYER_SELECT:
6771 game_set_frametime(GS_STATE_INITIAL_PLAYER_SELECT);
6775 case GS_STATE_MULTI_MISSION_SYNC:
6776 game_set_frametime(GS_STATE_MULTI_MISSION_SYNC);
6780 case GS_STATE_MULTI_START_GAME:
6781 game_set_frametime(GS_STATE_MULTI_START_GAME);
6782 multi_start_game_do();
6785 case GS_STATE_MULTI_HOST_OPTIONS:
6786 game_set_frametime(GS_STATE_MULTI_HOST_OPTIONS);
6787 multi_host_options_do();
6790 case GS_STATE_END_OF_CAMPAIGN:
6791 mission_campaign_end_do();
6794 case GS_STATE_END_DEMO:
6795 game_set_frametime(GS_STATE_END_DEMO);
6796 end_demo_campaign_do();
6799 case GS_STATE_LOOP_BRIEF:
6800 game_set_frametime(GS_STATE_LOOP_BRIEF);
6804 } // end switch(gs_current_state)
6808 // return 0 if there is enough RAM to run FreeSpace, otherwise return -1
6809 int game_do_ram_check(int ram_in_bytes)
6811 if ( ram_in_bytes < 30*1024*1024 ) {
6812 int allowed_to_run = 1;
6813 if ( ram_in_bytes < 25*1024*1024 ) {
6818 int Freespace_total_ram_MB;
6819 Freespace_total_ram_MB = fl2i(ram_in_bytes/(1024*1024));
6821 if ( allowed_to_run ) {
6823 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);
6828 msgbox_rval = MessageBox( NULL, tmp, XSTR( "Not Enough RAM", 194), MB_OKCANCEL );
6829 if ( msgbox_rval == IDCANCEL ) {
6836 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);
6838 MessageBox( NULL, tmp, XSTR( "Not Enough RAM", 194), MB_OK );
6849 // Check if there is a freespace.exe in the /update directory (relative to where fs.exe is installed).
6850 // If so, copy it over and remove the update directory.
6851 void game_maybe_update_launcher(char *exe_dir)
6854 char src_filename[MAX_PATH];
6855 char dest_filename[MAX_PATH];
6857 strcpy(src_filename, exe_dir);
6858 strcat(src_filename, NOX("\\update\\freespace.exe"));
6860 strcpy(dest_filename, exe_dir);
6861 strcat(dest_filename, NOX("\\freespace.exe"));
6863 // see if src_filename exists
6865 fp = fopen(src_filename, "rb");
6871 SetFileAttributes(dest_filename, FILE_ATTRIBUTE_NORMAL);
6873 // copy updated freespace.exe to freespace exe dir
6874 if ( CopyFile(src_filename, dest_filename, 0) == 0 ) {
6875 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 );
6879 // delete the file in the update directory
6880 DeleteFile(src_filename);
6882 // safe to assume directory is empty, since freespace.exe should only be the file ever in the update dir
6883 char update_dir[MAX_PATH];
6884 strcpy(update_dir, exe_dir);
6885 strcat(update_dir, NOX("\\update"));
6886 RemoveDirectory(update_dir);
6892 void game_spew_pof_info_sub(int model_num, polymodel *pm, int sm, CFILE *out, int *out_total, int *out_destroyed_total)
6896 int sub_total_destroyed = 0;
6900 // get the total for all his children
6901 for (i=pm->submodel[sm].first_child; i>-1; i = pm->submodel[i].next_sibling ) {
6902 game_spew_pof_info_sub(model_num, pm, i, out, &sub_total, &sub_total_destroyed);
6905 // find the # of faces for this _individual_ object
6906 total = submodel_get_num_polys(model_num, sm);
6907 if(strstr(pm->submodel[sm].name, "-destroyed")){
6908 sub_total_destroyed = total;
6912 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[sm].name, total);
6915 *out_total += total + sub_total;
6916 *out_destroyed_total += sub_total_destroyed;
6919 #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);
6920 void game_spew_pof_info()
6922 char *pof_list[1000];
6925 int idx, model_num, i, j;
6927 int total, root_total, model_total, destroyed_total, counted;
6931 num_files = cf_get_file_list(1000, pof_list, CF_TYPE_MODELS, "*.pof");
6933 // spew info on all the pofs
6939 out = cfopen("pofspew.txt", "wt", CFILE_NORMAL, CF_TYPE_DATA);
6944 for(idx=0; idx<num_files; idx++, counted++){
6945 sprintf(str, "%s.pof", pof_list[idx]);
6946 model_num = model_load(str, 0, NULL);
6948 pm = model_get(model_num);
6950 // if we have a real model
6955 // go through and print all raw submodels
6956 cfputs("RAW\n", out);
6959 for (i=0; i<pm->n_models; i++) {
6960 total = submodel_get_num_polys(model_num, i);
6962 model_total += total;
6963 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[i].name, total);
6966 sprintf(str, "Model total %d\n", model_total);
6969 // now go through and do it by LOD
6970 cfputs("BY LOD\n\n", out);
6971 for(i=0; i<pm->n_detail_levels; i++){
6972 sprintf(str, "LOD %d\n", i);
6976 root_total = submodel_get_num_polys(model_num, pm->detail[i] );
6978 destroyed_total = 0;
6979 for (j=pm->submodel[pm->detail[i]].first_child; j>-1; j = pm->submodel[j].next_sibling ) {
6980 game_spew_pof_info_sub(model_num, pm, j, out, &total, &destroyed_total);
6983 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[pm->detail[i]].name, root_total);
6986 sprintf(str, "TOTAL: %d\n", total + root_total);
6988 sprintf(str, "TOTAL not counting destroyed faces %d\n", (total + root_total) - destroyed_total);
6990 sprintf(str, "TOTAL destroyed faces %d\n\n", destroyed_total);
6993 cfputs("------------------------------------------------------------------------\n\n", out);
6997 if(counted >= MAX_POLYGON_MODELS - 5){
7010 game_spew_pof_info();
7013 int PASCAL WinMainSub(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
7018 // Don't let more than one instance of Freespace run.
7019 HWND hwnd = FindWindow( NOX( "FreeSpaceClass" ), NULL );
7021 SetForegroundWindow(hwnd);
7026 // Find out how much RAM is on this machine
7029 ms.dwLength = sizeof(MEMORYSTATUS);
7030 GlobalMemoryStatus(&ms);
7031 Freespace_total_ram = ms.dwTotalPhys;
7033 if ( game_do_ram_check(Freespace_total_ram) == -1 ) {
7037 if ( ms.dwTotalVirtual < 1024 ) {
7038 MessageBox( NULL, XSTR( "FreeSpace requires virtual memory to run.\r\n", 196), XSTR( "No Virtual Memory", 197), MB_OK );
7042 if (!vm_init(24*1024*1024)) {
7043 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 );
7047 char *tmp_mem = (char *) malloc(16 * 1024 * 1024);
7049 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);
7057 /* this code doesn't work, and we will hit an error about being unable to load the direct draw
7058 dll before we get here anyway if it's not installed (unless we load it manually, which doesn't
7059 seem worth bothering with.
7063 lResult = RegOpenKeyEx(
7064 HKEY_LOCAL_MACHINE, // Where it is
7065 "Software\\Microsoft\\DirectX", // name of key
7066 NULL, // DWORD reserved
7067 KEY_QUERY_VALUE, // Allows all changes
7068 &hKey // Location to store key
7071 if (lResult == ERROR_SUCCESS) {
7073 DWORD dwType, dwLen;
7076 lResult = RegQueryValueEx(
7077 hKey, // Handle to key
7078 "Version", // The values name
7079 NULL, // DWORD reserved
7080 &dwType, // What kind it is
7081 (ubyte *) version, // value to set
7082 &dwLen // How many bytes to set
7085 if (lResult == ERROR_SUCCESS) {
7086 dx_version = atoi(strstr(version, ".") + 1);
7090 DWORD dwType, dwLen;
7093 lResult = RegQueryValueEx(
7094 hKey, // Handle to key
7095 "InstalledVersion", // The values name
7096 NULL, // DWORD reserved
7097 &dwType, // What kind it is
7098 (ubyte *) &val, // value to set
7099 &dwLen // How many bytes to set
7102 if (lResult == ERROR_SUCCESS) {
7110 if (dx_version < 3) {
7111 MessageBox(NULL, "DirectX 3.0 or higher is required and wasn't detected. You can get the\n"
7112 "latest version of DirectX at:\n\n"
7113 "http://www.microsoft.com/msdownload/directx/dxf/enduser5.0/default.htm", "DirectX required", MB_OK);
7115 MessageBox(NULL, "DirectX 3.0 or higher is required and wasn't detected. You can install\n"
7116 "DirectX 5.2 by pressing the 'Install DirectX' button on the FreeSpace Launcher", "DirectX required", MB_OK);
7121 //=====================================================
7122 // Make sure we're running in the right directory.
7126 if ( GetModuleFileName( hInst, exe_dir, 1023 ) > 0 ) {
7127 char *p = exe_dir + strlen(exe_dir);
7129 // chop off the filename
7130 while( (p>exe_dir) && (*p!='\\') && (*p!='/') && (*p!=':') ) {
7136 if ( strlen(exe_dir) > 0 ) {
7137 SetCurrentDirectory(exe_dir);
7140 // check for updated freespace.exe
7141 game_maybe_update_launcher(exe_dir);
7149 extern void windebug_memwatch_init();
7150 windebug_memwatch_init();
7154 parse_cmdline(szCmdLine);
7156 #ifdef STANDALONE_ONLY_BUILD
7158 nprintf(("Network", "Standalone running"));
7161 nprintf(("Network", "Standalone running"));
7169 // maybe spew pof stuff
7170 if(Cmdline_spew_pof_info){
7171 game_spew_pof_info();
7176 // non-demo, non-standalone, play the intro movie
7182 // to avoid crashes on debug build
7183 for (i=0; i<5; i++) {
7187 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) ){
7189 #if defined(OEM_BUILD)
7190 game_do_cd_check_specific(FS_CDROM_VOLUME_1, 1);
7192 game_do_cd_check_specific(FS_CDROM_VOLUME_2, 2);
7193 #endif // defined(OEM_BUILD)
7196 for (int i=0; i<5; i++) {
7197 if (plist[i] != NULL) {
7202 #endif // RELEASE_REAL
7205 if ( !Is_standalone ) {
7207 // release -- movies always play
7210 // 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
7211 movie_play( NOX("intro.mve"), 0 );
7213 // debug version, movie will only play with -showmovies
7214 #elif !defined(NDEBUG)
7216 movie_play( NOX("intro.mve"), 0);
7219 if ( Cmdline_show_movies )
7220 movie_play( NOX("intro.mve"), 0 );
7229 gameseq_post_event(GS_EVENT_STANDALONE_MAIN);
7231 gameseq_post_event(GS_EVENT_GAME_INIT); // start the game rolling -- check for default pilot, or go to the pilot select screen
7235 // only important for non THREADED mode
7238 state = gameseq_process_events();
7239 if ( state == GS_STATE_QUIT_GAME ){
7244 #if defined(FS2_DEMO) || defined(FS1_DEMO)
7246 demo_upsell_show_screens();
7248 #elif defined(OEM_BUILD)
7249 // show upsell screens on exit
7250 oem_upsell_show_screens();
7257 int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
7263 result = WinMainSub(hInst, hPrev, szCmdLine, nCmdShow);
7265 __except(RecordExceptionInfo(GetExceptionInformation(), "Freespace 2 Main Thread"))
7267 // Do nothing here - RecordExceptionInfo() has already done
7268 // everything that is needed. Actually this code won't even
7269 // get called unless you return EXCEPTION_EXECUTE_HANDLER from
7270 // the __except clause.
7274 nprintf(("WinMain", "exceptions shall fall through"));
7276 result = WinMainSub(hInst, hPrev, szCmdLine, nCmdShow);
7282 // launcher the fslauncher program on exit
7283 void game_launch_launcher_on_exit()
7287 PROCESS_INFORMATION pi;
7288 char cmd_line[2048];
7289 char original_path[1024] = "";
7291 memset( &si, 0, sizeof(STARTUPINFO) );
7295 _getcwd(original_path, 1023);
7297 // set up command line
7298 strcpy(cmd_line, original_path);
7299 strcat(cmd_line, "\\");
7300 strcat(cmd_line, LAUNCHER_FNAME);
7301 strcat(cmd_line, " -straight_to_update");
7303 BOOL ret = CreateProcess( NULL, // pointer to name of executable module
7304 cmd_line, // pointer to command line string
7305 NULL, // pointer to process security attributes
7306 NULL, // pointer to thread security attributes
7307 FALSE, // handle inheritance flag
7308 CREATE_DEFAULT_ERROR_MODE, // creation flags
7309 NULL, // pointer to new environment block
7310 NULL, // pointer to current directory name
7311 &si, // pointer to STARTUPINFO
7312 &pi // pointer to PROCESS_INFORMATION
7314 // to eliminate build warnings
7324 // This function is called when FreeSpace terminates normally.
7326 void game_shutdown(void)
7332 // don't ever flip a page on the standalone!
7333 if(!(Game_mode & GM_STANDALONE_SERVER)){
7339 // if the player has left the "player select" screen and quit the game without actually choosing
7340 // a player, Player will be NULL, in which case we shouldn't write the player file out!
7341 if (!(Game_mode & GM_STANDALONE_SERVER) && (Player!=NULL) && !Is_standalone){
7345 // load up common multiplayer icons
7346 multi_unload_common_icons();
7348 shockwave_close(); // release any memory used by shockwave system
7349 fireball_close(); // free fireball system
7350 ship_close(); // free any memory that was allocated for the ships
7351 weapon_close(); // free any memory that was allocated for the weapons
7352 hud_free_scrollback_list();// free space allocated to store hud messages in hud scrollback
7353 unload_animating_pointer();// frees the frames used for the animating mouse pointer
7354 bm_unload_all(); // free bitmaps
7355 mission_campaign_close(); // close out the campaign stuff
7356 mission_campaign_shutdown(); // get anything that mission_campaign_close can't do
7357 multi_voice_close(); // close down multiplayer voice (including freeing buffers, etc)
7359 #ifdef MULTI_USE_LAG
7363 // the menu close functions will unload the bitmaps if they were displayed during the game
7364 #if !defined(PRESS_TOUR_BUILD) && !defined(PD_BUILD)
7367 context_help_close(); // close out help system
7368 training_menu_close();
7369 lcl_close(); // be sure localization is closed out
7372 // free left-over memory from parsed tables
7373 cutscene_tbl_close();
7375 scoring_tbl_close();
7376 player_tips_close();
7378 extern void joy_close();
7381 audiostream_close();
7383 event_music_close();
7387 // HACKITY HACK HACK
7388 // if this flag is set, we should be firing up the launcher when exiting freespace
7389 extern int Multi_update_fireup_launcher_on_exit;
7390 if(Multi_update_fireup_launcher_on_exit){
7391 game_launch_launcher_on_exit();
7395 // game_stop_looped_sounds()
7397 // This function will call the appropriate stop looped sound functions for those
7398 // modules which use looping sounds. It is not enough just to stop a looping sound
7399 // at the DirectSound level, the game is keeping track of looping sounds, and this
7400 // function is used to inform the game that looping sounds are being halted.
7402 void game_stop_looped_sounds()
7404 hud_stop_looped_locking_sounds();
7405 hud_stop_looped_engine_sounds();
7406 afterburner_stop_sounds();
7407 player_stop_looped_sounds();
7408 obj_snd_stop_all(); // stop all object-linked persistant sounds
7409 game_stop_subspace_ambient_sound();
7410 snd_stop(Radar_static_looping);
7411 Radar_static_looping = -1;
7412 snd_stop(Target_static_looping);
7413 shipfx_stop_engine_wash_sound();
7414 Target_static_looping = -1;
7417 //////////////////////////////////////////////////////////////////////////
7419 // Code for supporting an animating mouse pointer
7422 //////////////////////////////////////////////////////////////////////////
7424 typedef struct animating_obj
7433 static animating_obj Animating_mouse;
7435 // ----------------------------------------------------------------------------
7436 // init_animating_pointer()
7438 // Called by load_animating_pointer() to ensure the Animating_mouse struct
7439 // gets properly initialized
7441 void init_animating_pointer()
7443 Animating_mouse.first_frame = -1;
7444 Animating_mouse.num_frames = 0;
7445 Animating_mouse.current_frame = -1;
7446 Animating_mouse.time = 0.0f;
7447 Animating_mouse.elapsed_time = 0.0f;
7450 // ----------------------------------------------------------------------------
7451 // load_animating_pointer()
7453 // Called at game init to load in the frames for the animating mouse pointer
7455 // input: filename => filename of animation file that holds the animation
7457 void load_animating_pointer(char *filename, int dx, int dy)
7462 init_animating_pointer();
7464 am = &Animating_mouse;
7465 am->first_frame = bm_load_animation(filename, &am->num_frames, &fps);
7466 if ( am->first_frame == -1 )
7467 Error(LOCATION, "Could not load animation %s for the mouse pointer\n", filename);
7468 am->current_frame = 0;
7469 am->time = am->num_frames / i2fl(fps);
7472 // ----------------------------------------------------------------------------
7473 // unload_animating_pointer()
7475 // Called at game shutdown to free the memory used to store the animation frames
7477 void unload_animating_pointer()
7482 am = &Animating_mouse;
7483 for ( i = 0; i < am->num_frames; i++ ) {
7484 Assert( (am->first_frame+i) >= 0 );
7485 bm_release(am->first_frame + i);
7488 am->first_frame = -1;
7490 am->current_frame = -1;
7493 // draw the correct frame of the game mouse... called from game_maybe_draw_mouse()
7494 void game_render_mouse(float frametime)
7499 // if animating cursor exists, play the next frame
7500 am = &Animating_mouse;
7501 if ( am->first_frame != -1 ) {
7502 mouse_get_pos(&mx, &my);
7503 am->elapsed_time += frametime;
7504 am->current_frame = fl2i( ( am->elapsed_time / am->time ) * (am->num_frames-1) );
7505 if ( am->current_frame >= am->num_frames ) {
7506 am->current_frame = 0;
7507 am->elapsed_time = 0.0f;
7509 gr_set_cursor_bitmap(am->first_frame + am->current_frame);
7513 // ----------------------------------------------------------------------------
7514 // game_maybe_draw_mouse()
7516 // determines whether to draw the mouse pointer at all, and what frame of
7517 // animation to use if the mouse is animating
7519 // Sets mouse.cpp globals Mouse_hidden and Mouse_moved based on the state of the game.
7521 // input: frametime => elapsed frame time in seconds since last call
7523 void game_maybe_draw_mouse(float frametime)
7527 game_state = gameseq_get_state();
7529 switch ( game_state ) {
7530 case GS_STATE_GAME_PAUSED:
7531 // case GS_STATE_MULTI_PAUSED:
7532 case GS_STATE_GAME_PLAY:
7533 case GS_STATE_DEATH_DIED:
7534 case GS_STATE_DEATH_BLEW_UP:
7535 if ( popup_active() || popupdead_is_active() ) {
7547 if ( !Mouse_hidden )
7548 game_render_mouse(frametime);
7552 void game_do_training_checks()
7556 waypoint_list *wplp;
7558 if (Training_context & TRAINING_CONTEXT_SPEED) {
7559 s = (int) Player_obj->phys_info.fspeed;
7560 if ((s >= Training_context_speed_min) && (s <= Training_context_speed_max)) {
7561 if (!Training_context_speed_set) {
7562 Training_context_speed_set = 1;
7563 Training_context_speed_timestamp = timestamp();
7567 Training_context_speed_set = 0;
7570 if (Training_context & TRAINING_CONTEXT_FLY_PATH) {
7571 wplp = &Waypoint_lists[Training_context_path];
7572 if (wplp->count > Training_context_goal_waypoint) {
7573 i = Training_context_goal_waypoint;
7575 d = vm_vec_dist(&wplp->waypoints[i], &Player_obj->pos);
7576 if (d <= Training_context_distance) {
7577 Training_context_at_waypoint = i;
7578 if (Training_context_goal_waypoint == i) {
7579 Training_context_goal_waypoint++;
7580 snd_play(&Snds[SND_CARGO_REVEAL], 0.0f);
7587 if (i == wplp->count)
7590 } while (i != Training_context_goal_waypoint);
7594 if ((Players_target == UNINITIALIZED) || (Player_ai->target_objnum != Players_target) || (Player_ai->targeted_subsys != Players_targeted_subsys)) {
7595 Players_target = Player_ai->target_objnum;
7596 Players_targeted_subsys = Player_ai->targeted_subsys;
7597 Players_target_timestamp = timestamp();
7601 /////////// Following is for event debug view screen
7605 #define EVENT_DEBUG_MAX 5000
7606 #define EVENT_DEBUG_EVENT 0x8000
7608 int Event_debug_index[EVENT_DEBUG_MAX];
7611 void game_add_event_debug_index(int n, int indent)
7613 if (ED_count < EVENT_DEBUG_MAX)
7614 Event_debug_index[ED_count++] = n | (indent << 16);
7617 void game_add_event_debug_sexp(int n, int indent)
7622 if (Sexp_nodes[n].first >= 0) {
7623 game_add_event_debug_sexp(Sexp_nodes[n].first, indent);
7624 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7628 game_add_event_debug_index(n, indent);
7629 if (Sexp_nodes[n].subtype == SEXP_ATOM_OPERATOR)
7630 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent + 1);
7632 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7635 void game_event_debug_init()
7640 for (e=0; e<Num_mission_events; e++) {
7641 game_add_event_debug_index(e | EVENT_DEBUG_EVENT, 0);
7642 game_add_event_debug_sexp(Mission_events[e].formula, 1);
7646 void game_show_event_debug(float frametime)
7650 int font_height, font_width;
7652 static int scroll_offset = 0;
7654 k = game_check_key();
7660 if (scroll_offset < 0)
7670 scroll_offset -= 20;
7671 if (scroll_offset < 0)
7676 scroll_offset += 20; // not font-independent, hard-coded since I counted the lines!
7680 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
7686 gr_set_color_fast(&Color_bright);
7688 gr_printf(0x8000, 5, NOX("EVENT DEBUG VIEW"));
7690 gr_set_color_fast(&Color_normal);
7692 gr_get_string_size(&font_width, &font_height, NOX("test"));
7693 y_max = gr_screen.max_h - font_height - 5;
7697 while (k < ED_count) {
7698 if (y_index > y_max)
7701 z = Event_debug_index[k];
7702 if (z & EVENT_DEBUG_EVENT) {
7704 sprintf(buf, NOX("%s%s (%s) %s%d %d"), (Mission_events[z].flags & MEF_CURRENT) ? NOX("* ") : "",
7705 Mission_events[z].name, Mission_events[z].result ? NOX("True") : NOX("False"),
7706 (Mission_events[z].chain_delay < 0) ? "" : NOX("x "),
7707 Mission_events[z].repeat_count, Mission_events[z].interval);
7715 strcat(buf, Sexp_nodes[z & 0x7fff].text);
7716 switch (Sexp_nodes[z & 0x7fff].value) {
7718 strcat(buf, NOX(" (True)"));
7722 strcat(buf, NOX(" (False)"));
7725 case SEXP_KNOWN_TRUE:
7726 strcat(buf, NOX(" (Always true)"));
7729 case SEXP_KNOWN_FALSE:
7730 strcat(buf, NOX(" (Always false)"));
7733 case SEXP_CANT_EVAL:
7734 strcat(buf, NOX(" (Can't eval)"));
7738 case SEXP_NAN_FOREVER:
7739 strcat(buf, NOX(" (Not a number)"));
7744 gr_printf(10, y_index, buf);
7745 y_index += font_height;
7759 extern int Tmap_npixels;
7762 int Tmap_num_too_big = 0;
7763 int Num_models_needing_splitting = 0;
7765 void Time_model( int modelnum )
7767 // mprintf(( "Timing ship '%s'\n", si->name ));
7769 vector eye_pos, model_pos;
7770 matrix eye_orient, model_orient;
7772 polymodel *pm = model_get( modelnum );
7774 int l = strlen(pm->filename);
7776 if ( (l == '/') || (l=='\\') || (l==':')) {
7782 char *pof_file = &pm->filename[l];
7784 int model_needs_splitting = 0;
7786 //fprintf( Texture_fp, "Model: %s\n", pof_file );
7788 for (i=0; i<pm->n_textures; i++ ) {
7789 char filename[1024];
7792 int bmp_num = pm->original_textures[i];
7793 if ( bmp_num > -1 ) {
7794 bm_get_palette(pm->original_textures[i], pal, filename );
7796 bm_get_info( pm->original_textures[i],&w, &h );
7799 if ( (w > 512) || (h > 512) ) {
7800 fprintf( Texture_fp, "%s\t%s\t%d\t%d\n", pof_file, filename, w, h );
7802 model_needs_splitting++;
7805 //fprintf( Texture_fp, "\tTexture %d is bogus\n", i );
7809 if ( model_needs_splitting ) {
7810 Num_models_needing_splitting++;
7812 eye_orient = model_orient = vmd_identity_matrix;
7813 eye_pos = model_pos = vmd_zero_vector;
7815 eye_pos.xyz.z = -pm->rad*2.0f;
7817 vector eye_to_model;
7819 vm_vec_sub( &eye_to_model, &model_pos, &eye_pos );
7820 vm_vector_2_matrix( &eye_orient, &eye_to_model, NULL, NULL );
7822 fix t1 = timer_get_fixed_seconds();
7825 ta.p = ta.b = ta.h = 0.0f;
7832 int bitmaps_used_this_frame, bitmaps_new_this_frame;
7834 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7836 modelstats_num_polys = modelstats_num_verts = 0;
7838 while( ta.h < PI2 ) {
7841 vm_angles_2_matrix(&m1, &ta );
7842 vm_matrix_x_matrix( &model_orient, &vmd_identity_matrix, &m1 );
7849 g3_set_view_matrix( &eye_pos, &eye_orient, Viewer_zoom );
7851 model_clear_instance( modelnum );
7852 model_set_detail_level(0); // use highest detail level
7853 model_render( modelnum, &model_orient, &model_pos, MR_LOCK_DETAIL); //|MR_NO_POLYS );
7861 int k = key_inkey();
7862 if ( k == KEY_ESC ) {
7867 fix t2 = timer_get_fixed_seconds();
7869 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7870 //bitmaps_used_this_frame /= framecount;
7872 modelstats_num_polys /= framecount;
7873 modelstats_num_verts /= framecount;
7876 Tmap_npixels /=framecount;
7879 mprintf(( "'%s' is %.2f FPS\n", pof_file, i2fl(framecount)/f2fl(t2-t1) ));
7881 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 );
7883 fprintf( Time_fp, "\"%s\"\t%.0f\t%d\t%d\t%d\n", pof_file, i2fl(framecount)/f2fl(t2-t1), bitmaps_used_this_frame, modelstats_num_polys, modelstats_num_verts );
7885 // 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 );
7891 int Time_models = 0;
7892 DCF_BOOL( time_models, Time_models );
7894 void Do_model_timings_test()
7898 if ( !Time_models ) return;
7900 mprintf(( "Timing models!\n" ));
7904 ubyte model_used[MAX_POLYGON_MODELS];
7905 int model_id[MAX_POLYGON_MODELS];
7906 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7911 for (i=0; i<Num_ship_types; i++ ) {
7912 Ship_info[i].modelnum = model_load( Ship_info[i].pof_file, 0, NULL );
7914 model_used[Ship_info[i].modelnum%MAX_POLYGON_MODELS]++;
7915 model_id[Ship_info[i].modelnum%MAX_POLYGON_MODELS] = Ship_info[i].modelnum;
7918 Texture_fp = fopen( NOX("ShipTextures.txt"), "wt" );
7919 if ( !Texture_fp ) return;
7921 Time_fp = fopen( NOX("ShipTimings.txt"), "wt" );
7922 if ( !Time_fp ) return;
7924 fprintf( Time_fp, "Name\tFPS\tTRAM\tPolys\tVerts\tPixels\n" );
7925 // fprintf( Time_fp, "FPS\tTRAM\tPolys\tVerts\tPixels\n" );
7927 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7928 if ( model_used[i] ) {
7929 Time_model( model_id[i] );
7933 fprintf( Texture_fp, "Number too big: %d\n", Tmap_num_too_big );
7934 fprintf( Texture_fp, "Number of models needing splitting: %d\n", Num_models_needing_splitting );
7943 // Call this function when you want to inform the player that a feature is not
7944 // enabled in the DEMO version of FreSpace
7945 void game_feature_not_in_demo_popup()
7947 popup(PF_USE_AFFIRMATIVE_ICON|PF_BODY_BIG, 1, POPUP_OK, XSTR( "Sorry, this feature is available only in the retail version", 200));
7950 // format the specified time (fixed point) into a nice string
7951 void game_format_time(fix m_time,char *time_str)
7954 int hours,minutes,seconds;
7957 mtime = f2fl(m_time);
7959 // get the hours, minutes and seconds
7960 hours = (int)(mtime / 3600.0f);
7962 mtime -= (3600.0f * (float)hours);
7964 seconds = (int)mtime%60;
7965 minutes = (int)mtime/60;
7967 // print the hour if necessary
7969 sprintf(time_str,XSTR( "%d:", 201),hours);
7970 // if there are less than 10 minutes, print a leading 0
7972 strcpy(tmp,NOX("0"));
7973 strcat(time_str,tmp);
7977 // print the minutes
7979 sprintf(tmp,XSTR( "%d:", 201),minutes);
7980 strcat(time_str,tmp);
7982 sprintf(time_str,XSTR( "%d:", 201),minutes);
7985 // print the seconds
7987 strcpy(tmp,NOX("0"));
7988 strcat(time_str,tmp);
7990 sprintf(tmp,"%d",seconds);
7991 strcat(time_str,tmp);
7994 // Stuff version string in *str.
7995 void get_version_string(char *str)
7998 if ( FS_VERSION_BUILD == 0 ) {
7999 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
8001 sprintf(str,"v%d.%02d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD );
8004 #if defined (FS2_DEMO) || defined(FS1_DEMO)
8006 #elif defined (OEM_BUILD)
8007 strcat(str, " (OEM)");
8013 char myname[_MAX_PATH];
8014 int namelen, major, minor, build, waste;
8015 unsigned int buf_size;
8021 // Find my EXE file name
8022 hMod = GetModuleHandle(NULL);
8023 namelen = GetModuleFileName( hMod, myname, _MAX_PATH );
8025 version_size = GetFileVersionInfoSize(myname, &bogus_handle );
8026 infop = (char *)malloc(version_size);
8027 result = GetFileVersionInfo( myname, 0, version_size, (LPVOID)infop );
8029 // get the product version
8030 result = VerQueryValue((LPVOID)infop, TEXT("\\StringFileInfo\\040904b0\\ProductVersion"), &bufp, &buf_size );
8031 sscanf( (char *)bufp, "%d, %d, %d, %d", &major, &minor, &build, &waste );
8033 sprintf(str,"Dv%d.%02d",major, minor);
8035 sprintf(str,"v%d.%02d",major, minor);
8040 void get_version_string_short(char *str)
8042 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
8045 // ----------------------------------------------------------------
8047 // OEM UPSELL SCREENS BEGIN
8049 // ----------------------------------------------------------------
8050 #if defined(OEM_BUILD)
8052 #define NUM_OEM_UPSELL_SCREENS 3
8053 #define OEM_UPSELL_SCREEN_DELAY 10000
8055 static int Oem_upsell_bitmaps_loaded = 0;
8056 static int Oem_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS];
8057 static int Oem_upsell_screen_number = 0;
8058 static int Oem_upsell_show_next_bitmap_time;
8061 static char *Oem_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS] =
8074 static int Oem_normal_cursor = -1;
8075 static int Oem_web_cursor = -1;
8076 //#define OEM_UPSELL_URL "http://www.interplay-store.com/"
8077 #define OEM_UPSELL_URL "http://www.interplay.com/cgi-bin/oemlinks.pl/pid=483421&cid=18384"
8079 void oem_upsell_next_screen()
8081 Oem_upsell_screen_number++;
8082 if ( Oem_upsell_screen_number == (NUM_OEM_UPSELL_SCREENS-1) ) {
8083 // extra long delay, mouse shown on last upsell
8084 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY*2;
8088 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
8092 void oem_upsell_load_bitmaps()
8096 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
8097 Oem_upsell_bitmaps[gr_screen.res][i] = bm_load(Oem_upsell_bitmap_filenames[gr_screen.res][i]);
8101 void oem_upsell_unload_bitmaps()
8105 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
8106 if(Oem_upsell_bitmaps[gr_screen.res][i] >= 0){
8107 bm_unload(Oem_upsell_bitmaps[gr_screen.res][i]);
8112 Oem_upsell_bitmaps_loaded = 0;
8115 // clickable hotspot on 3rd OEM upsell screen
8116 static int Oem_upsell3_button_coords[GR_NUM_RESOLUTIONS][4] = {
8118 28, 350, 287, 96 // x, y, w, h
8121 45, 561, 460, 152 // x, y, w, h
8125 void oem_upsell_show_screens()
8127 int current_time, k;
8130 if ( !Oem_upsell_bitmaps_loaded ) {
8131 oem_upsell_load_bitmaps();
8132 Oem_upsell_bitmaps_loaded = 1;
8135 // may use upsell screens more than once
8136 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
8137 Oem_upsell_screen_number = 0;
8143 int nframes; // used to pass, not really needed (should be 1)
8144 Oem_normal_cursor = gr_get_cursor_bitmap();
8145 Oem_web_cursor = bm_load_animation("cursorweb", &nframes);
8146 Assert(Oem_web_cursor >= 0);
8147 if (Oem_web_cursor < 0) {
8148 Oem_web_cursor = Oem_normal_cursor;
8153 //oem_reset_trailer_timer();
8155 current_time = timer_get_milliseconds();
8160 // advance screen on keypress or timeout
8161 if (( k > 0 ) || (mouse_up_count(MOUSE_LEFT_BUTTON) > 0) || (current_time > Oem_upsell_show_next_bitmap_time)) {
8162 oem_upsell_next_screen();
8165 // check if we are done
8166 if ( Oem_upsell_screen_number >= NUM_OEM_UPSELL_SCREENS ) {
8167 Oem_upsell_screen_number--;
8170 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] < 0 ) {
8175 // show me the upsell
8176 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] >= 0 ) {
8177 gr_set_bitmap(Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number]);
8181 // if this is the 3rd upsell, make it clickable, d00d
8182 if ( Oem_upsell_screen_number == NUM_OEM_UPSELL_SCREENS-1 ) {
8184 int button_state = mouse_get_pos(&mx, &my);
8185 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])
8186 && (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]) )
8189 gr_set_cursor_bitmap(Oem_web_cursor); //, GR_CURSOR_LOCK);
8192 if (button_state & MOUSE_LEFT_BUTTON) {
8194 multi_pxo_url(OEM_UPSELL_URL);
8198 // switch cursor back to normal one
8199 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
8204 if (gameseq_get_state() != GS_STATE_END_DEMO) {
8214 oem_upsell_unload_bitmaps();
8216 // switch cursor back to normal one
8217 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
8221 #endif // defined(OEM_BUILD)
8222 // ----------------------------------------------------------------
8224 // OEM UPSELL SCREENS END
8226 // ----------------------------------------------------------------
8230 // ----------------------------------------------------------------
8232 // DEMO UPSELL SCREENS BEGIN
8234 // ----------------------------------------------------------------
8236 #if defined(FS2_DEMO) || defined(FS1_DEMO)
8239 #define NUM_DEMO_UPSELL_SCREENS 2
8241 #define NUM_DEMO_UPSELL_SCREENS 4
8243 #define DEMO_UPSELL_SCREEN_DELAY 3000
8245 static int Demo_upsell_bitmaps_loaded = 0;
8246 static int Demo_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS];
8247 static int Demo_upsell_screen_number = 0;
8248 static int Demo_upsell_show_next_bitmap_time;
8251 static char *Demo_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS] =
8277 void demo_upsell_next_screen()
8279 Demo_upsell_screen_number++;
8280 if ( Demo_upsell_screen_number == (NUM_DEMO_UPSELL_SCREENS-1) ) {
8281 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY*4;
8283 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
8287 if ( Demo_upsell_screen_number < NUM_DEMO_UPSELL_SCREENS ) {
8288 if ( Demo_upsell_bitmap_filenames[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
8289 #ifndef HARDWARE_ONLY
8290 palette_use_bm_palette(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8297 void demo_upsell_load_bitmaps()
8301 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8302 Demo_upsell_bitmaps[gr_screen.res][i] = bm_load(Demo_upsell_bitmap_filenames[gr_screen.res][i]);
8306 void demo_upsell_unload_bitmaps()
8310 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8311 if(Demo_upsell_bitmaps[gr_screen.res][i] >= 0){
8312 bm_unload(Demo_upsell_bitmaps[gr_screen.res][i]);
8317 Demo_upsell_bitmaps_loaded = 0;
8320 void demo_upsell_show_screens()
8322 int current_time, k;
8325 if ( !Demo_upsell_bitmaps_loaded ) {
8326 demo_upsell_load_bitmaps();
8327 Demo_upsell_bitmaps_loaded = 1;
8330 // may use upsell screens more than once
8331 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
8332 Demo_upsell_screen_number = 0;
8339 demo_reset_trailer_timer();
8341 current_time = timer_get_milliseconds();
8348 // don't time out, wait for keypress
8350 if ( current_time > Demo_upsell_show_next_bitmap_time ) {
8351 demo_upsell_next_screen();
8356 demo_upsell_next_screen();
8359 if ( Demo_upsell_screen_number >= NUM_DEMO_UPSELL_SCREENS ) {
8360 Demo_upsell_screen_number--;
8363 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] < 0 ) {
8368 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
8369 gr_set_bitmap(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8374 if (gameseq_get_state() != GS_STATE_END_DEMO) {
8384 demo_upsell_unload_bitmaps();
8389 // ----------------------------------------------------------------
8391 // DEMO UPSELL SCREENS END
8393 // ----------------------------------------------------------------
8396 // ----------------------------------------------------------------
8398 // Subspace Ambient Sound START
8400 // ----------------------------------------------------------------
8402 static int Subspace_ambient_left_channel = -1;
8403 static int Subspace_ambient_right_channel = -1;
8406 void game_start_subspace_ambient_sound()
8408 if ( Subspace_ambient_left_channel < 0 ) {
8409 Subspace_ambient_left_channel = snd_play_looping(&Snds[SND_SUBSPACE_LEFT_CHANNEL], -1.0f);
8412 if ( Subspace_ambient_right_channel < 0 ) {
8413 Subspace_ambient_right_channel = snd_play_looping(&Snds[SND_SUBSPACE_RIGHT_CHANNEL], 1.0f);
8417 void game_stop_subspace_ambient_sound()
8419 if ( Subspace_ambient_left_channel >= 0 ) {
8420 snd_stop(Subspace_ambient_left_channel);
8421 Subspace_ambient_left_channel = -1;
8424 if ( Subspace_ambient_right_channel >= 0 ) {
8425 snd_stop(Subspace_ambient_right_channel);
8426 Subspace_ambient_right_channel = -1;
8430 // ----------------------------------------------------------------
8432 // Subspace Ambient Sound END
8434 // ----------------------------------------------------------------
8436 // ----------------------------------------------------------------
8438 // CDROM detection code START
8440 // ----------------------------------------------------------------
8442 #define CD_SIZE_72_MINUTE_MAX (697000000)
8444 uint game_get_cd_used_space(char *path)
8448 char use_path[512] = "";
8449 char sub_path[512] = "";
8450 WIN32_FIND_DATA find;
8453 // recurse through all files and directories
8454 strcpy(use_path, path);
8455 strcat(use_path, "*.*");
8456 find_handle = FindFirstFile(use_path, &find);
8459 if(find_handle == INVALID_HANDLE_VALUE){
8465 // subdirectory. make sure to ignore . and ..
8466 if((find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && stricmp(find.cFileName, ".") && stricmp(find.cFileName, "..")){
8468 strcpy(sub_path, path);
8469 strcat(sub_path, find.cFileName);
8470 strcat(sub_path, "\\");
8471 total += game_get_cd_used_space(sub_path);
8473 total += (uint)find.nFileSizeLow;
8475 } while(FindNextFile(find_handle, &find));
8478 FindClose(find_handle);
8490 // if volume_name is non-null, the CD name must match that
8491 int find_freespace_cd(char *volume_name)
8494 char oldpath[MAX_PATH];
8498 int volume_match = 0;
8502 GetCurrentDirectory(MAX_PATH, oldpath);
8504 for (i = 0; i < 26; i++)
8510 path[0] = (char)('A'+i);
8511 if (GetDriveType(path) == DRIVE_CDROM) {
8513 if ( GetVolumeInformation(path, volume, 256, NULL, NULL, NULL, NULL, 0) == TRUE ) {
8514 nprintf(("CD", "CD volume: %s\n", volume));
8516 // check for any CD volume
8517 int volume1_present = 0;
8518 int volume2_present = 0;
8519 int volume3_present = 0;
8521 char full_check[512] = "";
8523 // look for setup.exe
8524 strcpy(full_check, path);
8525 strcat(full_check, "setup.exe");
8526 find_handle = _findfirst(full_check, &find);
8527 if(find_handle != -1){
8528 volume1_present = 1;
8529 _findclose(find_handle);
8532 // look for intro.mve
8533 strcpy(full_check, path);
8534 strcat(full_check, "intro.mve");
8535 find_handle = _findfirst(full_check, &find);
8536 if(find_handle != -1){
8537 volume2_present = 1;
8538 _findclose(find_handle);
8541 // look for endpart1.mve
8542 strcpy(full_check, path);
8543 strcat(full_check, "endpart1.mve");
8544 find_handle = _findfirst(full_check, &find);
8545 if(find_handle != -1){
8546 volume3_present = 1;
8547 _findclose(find_handle);
8550 // see if we have the specific CD we're looking for
8551 if ( volume_name ) {
8553 if ( !stricmp(volume_name, FS_CDROM_VOLUME_1) && volume1_present) {
8557 if ( !stricmp(volume_name, FS_CDROM_VOLUME_2) && volume2_present) {
8561 if ( !stricmp(volume_name, FS_CDROM_VOLUME_3) && volume3_present) {
8565 if ( volume1_present || volume2_present || volume3_present ) {
8570 // 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
8571 if ( volume_match ){
8573 // 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
8574 if(volume2_present || volume3_present) {
8575 // first step - check to make sure its a cdrom
8576 if(GetDriveType(path) != DRIVE_CDROM){
8580 #if !defined(OEM_BUILD)
8581 // oem not on 80 min cds, so dont check tha size
8583 uint used_space = game_get_cd_used_space(path);
8584 if(used_space < CD_SIZE_72_MINUTE_MAX){
8587 #endif // !defined(OEM_BUILD)
8595 #endif // RELEASE_REAL
8601 SetCurrentDirectory(oldpath);
8610 int set_cdrom_path(int drive_num)
8614 if (drive_num < 0) { //no CD
8616 // strcpy(CDROM_dir,"j:\\FreeSpaceCD\\"); //set directory
8619 strcpy(Game_CDROM_dir,""); //set directory
8623 sprintf(Game_CDROM_dir,NOX("%c:\\"), 'a' + drive_num ); //set directory
8639 i = find_freespace_cd();
8641 rval = set_cdrom_path(i);
8645 nprintf(("CD", "Using %s for FreeSpace CD\n", CDROM_dir));
8647 nprintf(("CD", "FreeSpace CD not found\n"));
8655 int Last_cd_label_found = 0;
8656 char Last_cd_label[256];
8658 int game_cd_changed()
8665 if ( strlen(Game_CDROM_dir) == 0 ) {
8669 found = GetVolumeInformation(Game_CDROM_dir, label, 256, NULL, NULL, NULL, NULL, 0);
8671 if ( found != Last_cd_label_found ) {
8672 Last_cd_label_found = found;
8674 mprintf(( "CD '%s' was inserted\n", label ));
8677 mprintf(( "CD '%s' was removed\n", Last_cd_label ));
8681 if ( Last_cd_label_found ) {
8682 if ( !stricmp( Last_cd_label, label )) {
8683 //mprintf(( "CD didn't change\n" ));
8685 mprintf(( "CD was changed from '%s' to '%s'\n", Last_cd_label, label ));
8689 // none found before, none found now.
8690 //mprintf(( "still no CD...\n" ));
8694 Last_cd_label_found = found;
8696 strcpy( Last_cd_label, label );
8698 strcpy( Last_cd_label, "" );
8709 // check if _any_ FreeSpace2 CDs are in the drive
8710 // return: 1 => CD now in drive
8711 // 0 => Could not find CD, they refuse to put it in the drive
8712 int game_do_cd_check(char *volume_name)
8714 #if !defined(GAME_CD_CHECK)
8720 int num_attempts = 0;
8721 int refresh_files = 0;
8723 int path_set_ok, popup_rval;
8725 cd_drive_num = find_freespace_cd(volume_name);
8726 path_set_ok = set_cdrom_path(cd_drive_num);
8727 if ( path_set_ok ) {
8729 if ( refresh_files ) {
8741 // no CD found, so prompt user
8742 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR( "FreeSpace 2 CD not found\n\nInsert a FreeSpace 2 CD to continue", 202));
8744 if ( popup_rval != 1 ) {
8749 if ( num_attempts++ > 5 ) {
8760 // check if _any_ FreeSpace2 CDs are in the drive
8761 // return: 1 => CD now in drive
8762 // 0 => Could not find CD, they refuse to put it in the drive
8763 int game_do_cd_check_specific(char *volume_name, int cdnum)
8768 int num_attempts = 0;
8769 int refresh_files = 0;
8771 int path_set_ok, popup_rval;
8773 cd_drive_num = find_freespace_cd(volume_name);
8774 path_set_ok = set_cdrom_path(cd_drive_num);
8775 if ( path_set_ok ) {
8777 if ( refresh_files ) {
8788 // no CD found, so prompt user
8789 #if defined(DVD_MESSAGE_HACK)
8790 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert DVD", 1468));
8792 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert CD %d", 1468), cdnum);
8795 if ( popup_rval != 1 ) {
8800 if ( num_attempts++ > 5 ) {
8810 // only need to do this in RELEASE_REAL
8811 int game_do_cd_mission_check(char *filename)
8817 fs_builtin_mission *m = game_find_builtin_mission(filename);
8819 // check for changed CD
8820 if(game_cd_changed()){
8825 if((Game_mode & GM_MULTIPLAYER) || Is_standalone){
8829 // not builtin, so do a general check (any FS2 CD will do)
8831 return game_do_cd_check();
8834 // does not have any CD requirement, do a general check
8835 if(strlen(m->cd_volume) <= 0){
8836 return game_do_cd_check();
8840 if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_1)){
8842 } else if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_2)){
8845 } else if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_3)){
8849 return game_do_cd_check();
8852 // did we find the cd?
8853 if(find_freespace_cd(m->cd_volume) >= 0){
8857 // make sure the volume exists
8858 int num_attempts = 0;
8859 int refresh_files = 0;
8861 int path_set_ok, popup_rval;
8863 cd_drive_num = find_freespace_cd(m->cd_volume);
8864 path_set_ok = set_cdrom_path(cd_drive_num);
8865 if ( path_set_ok ) {
8867 if ( refresh_files ) {
8874 // no CD found, so prompt user
8875 #if defined(DVD_MESSAGE_HACK)
8876 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert DVD", 1468));
8878 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert CD %d", 1468), cd_num);
8882 if ( popup_rval != 1 ) {
8887 if ( num_attempts++ > 5 ) {
8899 // ----------------------------------------------------------------
8901 // CDROM detection code END
8903 // ----------------------------------------------------------------
8905 // ----------------------------------------------------------------
8907 // Language Autodetection stuff
8910 // this layout order must match Lcl_languages in localize.cpp in order for the
8911 // correct language to be detected
8912 int Lang_auto_detect_checksums[LCL_NUM_LANGUAGES] = {
8914 1366105450, // English
8916 589986744, // English
8918 -1132430286, // German
8920 -1131728960, // Polish
8923 // default setting is "-1" to use config file with English as fall back
8924 // DO NOT change the default setting here or something uncouth might happen
8925 // in the localization code
8931 // try and open the file to verify
8932 CFILE *detect = cfopen("font01.vf", "rb");
8934 // will use default setting if something went wrong
8939 // get the long checksum of the file
8941 cfseek(detect, 0, SEEK_SET);
8942 cf_chksum_long(detect, &file_checksum);
8946 // now compare the checksum/filesize against known #'s
8947 for (idx=0; idx<LCL_NUM_LANGUAGES; idx++) {
8948 if (Lang_auto_detect_checksums[idx] == (int)file_checksum) {
8953 // notify if a match was not found, include detected checksum
8954 printf("ERROR: Unknown Language Checksum: %i\n", (int)file_checksum);
8955 printf("Using default language...\n\n");
8961 // End Auto Lang stuff
8963 // ----------------------------------------------------------------
8965 // ----------------------------------------------------------------
8966 // SHIPS TBL VERIFICATION STUFF
8969 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
8970 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
8971 #define NUM_SHIPS_TBL_CHECKSUMS 3
8973 #define NUM_SHIPS_TBL_CHECKSUMS 1
8977 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8978 1696074201, // FS2 demo
8981 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8982 1603375034, // FS1 DEMO
8985 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8986 -129679197, // FS1 Full 1.06 (US)
8987 7762567, // FS1 SilentThreat
8988 1555372475 // FS1 Full 1.06 (German)
8992 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8993 -463907578, // US - beta 1
8994 1696074201, // FS2 demo
8997 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8998 // -1022810006, // 1.0 FULL
8999 -1254285366 // 1.2 FULL (German)
9003 void verify_ships_tbl()
9007 Game_ships_tbl_valid = 1;
9013 // detect if the packfile exists
9014 CFILE *detect = cfopen("ships.tbl", "rb");
9015 Game_ships_tbl_valid = 0;
9019 Game_ships_tbl_valid = 0;
9023 // get the long checksum of the file
9025 cfseek(detect, 0, SEEK_SET);
9026 cf_chksum_long(detect, &file_checksum);
9030 // now compare the checksum/filesize against known #'s
9031 for(idx=0; idx<NUM_SHIPS_TBL_CHECKSUMS; idx++){
9032 if(Game_ships_tbl_checksums[idx] == (int)file_checksum){
9033 Game_ships_tbl_valid = 1;
9040 DCF(shipspew, "display the checksum for the current ships.tbl")
9043 CFILE *detect = cfopen("ships.tbl", "rb");
9044 // get the long checksum of the file
9046 cfseek(detect, 0, SEEK_SET);
9047 cf_chksum_long(detect, &file_checksum);
9050 dc_printf("%d", file_checksum);
9053 // ----------------------------------------------------------------
9054 // WEAPONS TBL VERIFICATION STUFF
9057 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
9058 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
9059 #define NUM_WEAPONS_TBL_CHECKSUMS 3
9061 #define NUM_WEAPONS_TBL_CHECKSUMS 1
9065 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9066 -266420030, // demo 1
9069 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9070 -1246928725, // FS1 DEMO
9073 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9074 -834598107, // FS1 1.06 Full (US)
9075 -1652231417, // FS1 SilentThreat
9076 720209793 // FS1 1.06 Full (German)
9080 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9081 141718090, // US - beta 1
9082 -266420030, // demo 1
9085 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9086 // 399297860, // 1.0 FULL
9087 -553984927 // 1.2 FULL (german)
9091 void verify_weapons_tbl()
9095 Game_weapons_tbl_valid = 1;
9101 // detect if the packfile exists
9102 CFILE *detect = cfopen("weapons.tbl", "rb");
9103 Game_weapons_tbl_valid = 0;
9107 Game_weapons_tbl_valid = 0;
9111 // get the long checksum of the file
9113 cfseek(detect, 0, SEEK_SET);
9114 cf_chksum_long(detect, &file_checksum);
9118 // now compare the checksum/filesize against known #'s
9119 for(idx=0; idx<NUM_WEAPONS_TBL_CHECKSUMS; idx++){
9120 if(Game_weapons_tbl_checksums[idx] == (int)file_checksum){
9121 Game_weapons_tbl_valid = 1;
9128 DCF(wepspew, "display the checksum for the current weapons.tbl")
9131 CFILE *detect = cfopen("weapons.tbl", "rb");
9132 // get the long checksum of the file
9134 cfseek(detect, 0, SEEK_SET);
9135 cf_chksum_long(detect, &file_checksum);
9138 dc_printf("%d", file_checksum);
9141 // if the game is running using hacked data
9142 int game_hacked_data()
9145 if(!Game_weapons_tbl_valid || !Game_ships_tbl_valid){
9153 void display_title_screen()
9155 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
9156 ///int title_bitmap;
9159 int title_bitmap = bm_load(Game_demo_title_screen_fname[gr_screen.res]);
9160 if (title_bitmap == -1) {
9166 if((gr_screen.mode == GR_DIRECT3D) && (Gr_bitmap_poly)){
9167 extern void d3d_start_frame();
9173 gr_set_bitmap(title_bitmap);
9180 if((gr_screen.mode == GR_DIRECT3D) && (Gr_bitmap_poly)){
9181 extern void d3d_stop_frame();
9189 bm_unload(title_bitmap);
9190 #endif // FS2_DEMO || OEM_BUILD || FS1_DEMO
9193 // return true if the game is running with "low memory", which is less than 48MB
9194 bool game_using_low_mem()
9196 if (Use_low_mem == 0) {