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.34 2003/08/09 03:18:03 taylor
19 * fix tips popup not having any tips
21 * Revision 1.33 2003/08/03 15:57:00 taylor
22 * simpler mouse usage; default ini settings in os_init(); cleanup
24 * Revision 1.32 2003/06/19 11:51:41 taylor
25 * adjustments to memory leak fixes
27 * Revision 1.31 2003/06/11 18:30:32 taylor
30 * Revision 1.30 2003/06/03 04:00:39 taylor
31 * Polish language support (Janusz Dziemidowicz)
33 * Revision 1.29 2003/05/25 02:30:42 taylor
36 * Revision 1.28 2003/05/18 03:55:30 taylor
37 * automatic language selection support
39 * Revision 1.27 2003/03/03 04:54:44 theoddone33
40 * Commit Taylor's ShowFPS fix
42 * Revision 1.26 2003/02/20 17:41:07 theoddone33
43 * Userdir patch from Taylor Richards
45 * Revision 1.25 2003/01/30 19:54:10 relnev
46 * ini config option for the frames per second counter (Taylor Richards)
48 * Revision 1.24 2002/08/31 01:39:13 theoddone33
49 * Speed up the renderer a tad
51 * Revision 1.23 2002/08/04 02:31:00 relnev
52 * make numlock not overlap with pause
54 * Revision 1.22 2002/08/02 23:07:03 relnev
55 * don't access the mouse in standalone mode
57 * Revision 1.21 2002/07/28 05:05:08 relnev
58 * removed some old stuff
60 * Revision 1.20 2002/07/24 00:20:41 relnev
63 * Revision 1.19 2002/06/17 06:33:08 relnev
64 * ryan's struct patch for gcc 2.95
66 * Revision 1.18 2002/06/16 04:46:33 relnev
67 * set up correct checksums for demo
69 * Revision 1.17 2002/06/09 04:41:17 relnev
70 * added copyright header
72 * Revision 1.16 2002/06/09 03:16:04 relnev
75 * removed unneeded asm, old sdl 2d setup.
77 * fixed crash caused by opengl_get_region.
79 * Revision 1.15 2002/06/05 08:05:28 relnev
80 * stub/warning removal.
82 * reworked the sound code.
84 * Revision 1.14 2002/06/05 04:03:32 relnev
85 * finished cfilesystem.
87 * removed some old code.
89 * fixed mouse save off-by-one.
93 * Revision 1.13 2002/06/02 04:26:34 relnev
96 * Revision 1.12 2002/06/02 00:31:35 relnev
97 * implemented osregistry
99 * Revision 1.11 2002/06/01 09:00:34 relnev
100 * silly debug memmanager
102 * Revision 1.10 2002/06/01 07:12:32 relnev
103 * a few NDEBUG updates.
105 * removed a few warnings.
107 * Revision 1.9 2002/05/31 03:05:59 relnev
110 * Revision 1.8 2002/05/29 02:52:32 theoddone33
111 * Enable OpenGL renderer
113 * Revision 1.7 2002/05/28 08:52:03 relnev
114 * implemented two assembly stubs.
116 * cleaned up a few warnings.
118 * added a little demo hackery to make it progress a little farther.
120 * Revision 1.6 2002/05/28 06:28:20 theoddone33
121 * Filesystem mods, actually reads some data files now
123 * Revision 1.5 2002/05/28 04:07:28 theoddone33
124 * New graphics stubbing arrangement
126 * Revision 1.4 2002/05/27 22:46:52 theoddone33
127 * Remove more undefined symbols
129 * Revision 1.3 2002/05/26 23:31:18 relnev
130 * added a few files that needed to be compiled
132 * freespace.cpp: now compiles
134 * Revision 1.2 2002/05/07 03:16:44 theoddone33
135 * The Great Newline Fix
137 * Revision 1.1.1.1 2002/05/03 03:28:09 root
141 * 201 6/16/00 3:15p Jefff
142 * sim of the year dvd version changes, a few german soty localization
145 * 200 11/03/99 11:06a Jefff
148 * 199 10/26/99 5:07p Jamest
149 * fixed jeffs dumb debug code
151 * 198 10/25/99 5:53p Jefff
152 * call control_config_common_init() on startup
154 * 197 10/14/99 10:18a Daveb
155 * Fixed incorrect CD checking problem on standalone server.
157 * 196 10/13/99 9:22a Daveb
158 * Fixed Fred jumpnode placing bug. Fixed 1024 glide tiled texture problem
159 * related to movies. Fixed launcher spawning from PXO screen.
161 * 195 10/06/99 11:05a Jefff
162 * new oem upsell 3 hotspot coords
164 * 194 10/06/99 10:31a Jefff
167 * 193 10/01/99 9:10a Daveb
170 * 192 9/15/99 4:57a Dave
171 * Updated ships.tbl checksum
173 * 191 9/15/99 3:58a Dave
174 * Removed framerate warning at all times.
176 * 190 9/15/99 3:16a Dave
177 * Remove mt-011.fs2 from the builtin mission list.
179 * 189 9/15/99 1:45a Dave
180 * Don't init joystick on standalone. Fixed campaign mode on standalone.
181 * Fixed no-score-report problem in TvT
183 * 188 9/14/99 6:08a Dave
184 * Updated (final) single, multi, and campaign list.
186 * 187 9/14/99 3:26a Dave
187 * Fixed laser fogging problem in nebula (D3D)> Fixed multiplayer
188 * respawn-too-early problem. Made a few crash points safe.
190 * 186 9/13/99 4:52p Dave
193 * 185 9/12/99 8:09p Dave
194 * Fixed problem where skip-training button would cause mission messages
195 * not to get paged out for the current mission.
197 * 184 9/10/99 11:53a Dave
198 * Shutdown graphics before sound to eliminate apparent lockups when
199 * Directsound decides to be lame. Fix TOPMOST problem with D3D windows.
201 * 183 9/09/99 11:40p Dave
202 * Handle an Assert() in beam code. Added supernova sounds. Play the right
203 * 2 end movies properly, based upon what the player did in the mission.
205 * 182 9/08/99 10:29p Dave
206 * Make beam sound pausing and unpausing much safer.
208 * 181 9/08/99 10:01p Dave
209 * Make sure game won't run in a drive's root directory. Make sure
210 * standalone routes suqad war messages properly to the host.
212 * 180 9/08/99 3:22p Dave
213 * Updated builtin mission list.
215 * 179 9/08/99 12:01p Jefff
216 * fixed Game_builtin_mission_list typo on Training-2.fs2
218 * 178 9/08/99 9:48a Andsager
219 * Add force feedback for engine wash.
221 * 177 9/07/99 4:01p Dave
222 * Fixed up a string.tbl paroblem (self destruct message). Make sure IPX
223 * does everything properly (setting up address when binding). Remove
224 * black rectangle background from UI_INPUTBOX.
226 * 176 9/13/99 2:40a Dave
227 * Comment in full 80 minute CD check for RELEASE_REAL builds.
229 * 175 9/06/99 6:38p Dave
230 * Improved CD detection code.
232 * 174 9/06/99 1:30a Dave
233 * Intermediate checkin. Started on enforcing CD-in-drive to play the
236 * 173 9/06/99 1:16a Dave
237 * Make sure the user sees the intro movie.
239 * 172 9/04/99 8:00p Dave
240 * Fixed up 1024 and 32 bit movie support.
242 * 171 9/03/99 1:32a Dave
243 * CD checking by act. Added support to play 2 cutscenes in a row
244 * seamlessly. Fixed super low level cfile bug related to files in the
245 * root directory of a CD. Added cheat code to set campaign mission # in
248 * 170 9/01/99 10:49p Dave
249 * Added nice SquadWar checkbox to the client join wait screen.
251 * 169 9/01/99 10:14a Dave
254 * 168 8/29/99 4:51p Dave
255 * Fixed damaged checkin.
257 * 167 8/29/99 4:18p Andsager
258 * New "burst" limit for friendly damage. Also credit more damage done
259 * against large friendly ships.
261 * 166 8/27/99 6:38p Alanl
262 * crush the blasted repeating messages bug
264 * 164 8/26/99 9:09p Dave
265 * Force framerate check in everything but a RELEASE_REAL build.
267 * 163 8/26/99 9:45a Dave
268 * First pass at easter eggs and cheats.
270 * 162 8/24/99 8:55p Dave
271 * Make sure nondimming pixels work properly in tech menu.
273 * 161 8/24/99 1:49a Dave
274 * Fixed client-side afterburner stuttering. Added checkbox for no version
275 * checking on PXO join. Made button info passing more friendly between
278 * 160 8/22/99 5:53p Dave
279 * Scoring fixes. Added self destruct key. Put callsigns in the logfile
280 * instead of ship designations for multiplayer players.
282 * 159 8/22/99 1:19p Dave
283 * Fixed up http proxy code. Cleaned up scoring code. Reverse the order in
284 * which d3d cards are detected.
286 * 158 8/20/99 2:09p Dave
287 * PXO banner cycling.
289 * 157 8/19/99 10:59a Dave
290 * Packet loss detection.
292 * 156 8/19/99 10:12a Alanl
293 * preload mission-specific messages on machines greater than 48MB
295 * 155 8/16/99 4:04p Dave
296 * Big honking checkin.
298 * 154 8/11/99 5:54p Dave
299 * Fixed collision problem. Fixed standalone ghost problem.
301 * 153 8/10/99 7:59p Jefff
304 * 152 8/10/99 6:54p Dave
305 * Mad optimizations. Added paging to the nebula effect.
307 * 151 8/10/99 3:44p Jefff
308 * loads Intelligence information on startup
310 * 150 8/09/99 3:47p Dave
311 * Fixed incorrect nebula regeneration. Default HUD to low-contrast in
312 * non-nebula missions.
314 * 149 8/09/99 2:21p Andsager
315 * Fix patching from multiplayer direct to launcher update tab.
317 * 148 8/09/99 10:36a Dave
318 * Version info for game.
320 * 147 8/06/99 9:46p Dave
321 * Hopefully final changes for the demo.
323 * 146 8/06/99 3:34p Andsager
324 * Make title version info "(D)" -> "D" show up nicely
326 * 145 8/06/99 2:59p Adamp
327 * Fixed NT launcher/update problem.
329 * 144 8/06/99 1:52p Dave
330 * Bumped up MAX_BITMAPS for the demo.
332 * 143 8/06/99 12:17p Andsager
333 * Demo: down to just 1 demo dog
335 * 142 8/05/99 9:39p Dave
336 * Yet another new checksum.
338 * 141 8/05/99 6:19p Dave
339 * New demo checksums.
341 * 140 8/05/99 5:31p Andsager
342 * Up demo version 1.01
344 * 139 8/05/99 4:22p Andsager
345 * No time limit on upsell screens. Reverse order of display of upsell
348 * 138 8/05/99 4:17p Dave
349 * Tweaks to client interpolation.
351 * 137 8/05/99 3:52p Danw
353 * 136 8/05/99 3:01p Danw
355 * 135 8/05/99 2:43a Anoop
356 * removed duplicate definition.
358 * 134 8/05/99 2:13a Dave
361 * 133 8/05/99 2:05a Dave
364 * 132 8/05/99 1:22a Andsager
367 * 131 8/04/99 9:51p Andsager
368 * Add title screen to demo
370 * 130 8/04/99 6:47p Jefff
371 * fixed link error resulting from #ifdefs
373 * 129 8/04/99 6:26p Dave
374 * Updated ship tbl checksum.
376 * 128 8/04/99 5:40p Andsager
377 * Add multiple demo dogs
379 * 127 8/04/99 5:36p Andsager
380 * Show upsell screens at end of demo campaign before returning to main
383 * 126 8/04/99 11:42a Danw
384 * tone down EAX reverb
386 * 125 8/04/99 11:23a Dave
387 * Updated demo checksums.
389 * 124 8/03/99 11:02p Dave
390 * Maybe fixed sync problems in multiplayer.
392 * 123 8/03/99 6:21p Jefff
395 * 122 8/03/99 3:44p Andsager
396 * Launch laucher if trying to run FS without first having configured
399 * 121 8/03/99 12:45p Dave
402 * 120 8/02/99 9:13p Dave
405 * 119 7/30/99 10:31p Dave
406 * Added comm menu to the configurable hud files.
408 * 118 7/30/99 5:17p Andsager
409 * first fs2demo checksums
411 * 117 7/29/99 3:09p Anoop
413 * 116 7/29/99 12:05a Dave
414 * Nebula speed optimizations.
416 * 115 7/27/99 8:59a Andsager
417 * Make major, minor version consistent for all builds. Only show major
418 * and minor for launcher update window.
420 * 114 7/26/99 5:50p Dave
421 * Revised ingame join. Better? We'll see....
423 * 113 7/26/99 5:27p Andsager
424 * Add training mission as builtin to demo build
426 * 112 7/24/99 1:54p Dave
427 * Hud text flash gauge. Reworked dead popup to use 4 buttons in red-alert
430 * 111 7/22/99 4:00p Dave
431 * Fixed beam weapon muzzle glow rendering. Externalized hud shield info.
433 * 110 7/21/99 8:10p Dave
434 * First run of supernova effect.
436 * 109 7/20/99 1:49p Dave
437 * Peter Drake build. Fixed some release build warnings.
439 * 108 7/19/99 2:26p Andsager
440 * set demo multiplayer missions
442 * 107 7/18/99 5:19p Dave
443 * Jump node icon. Fixed debris fogging. Framerate warning stuff.
445 * 106 7/16/99 1:50p Dave
446 * 8 bit aabitmaps. yay.
448 * 105 7/15/99 3:07p Dave
449 * 32 bit detection support. Mouse coord commandline.
451 * 104 7/15/99 2:13p Dave
452 * Added 32 bit detection.
454 * 103 7/15/99 9:20a Andsager
455 * FS2_DEMO initial checkin
457 * 102 7/14/99 11:02a Dave
458 * Skill level default back to easy. Blech.
460 * 101 7/09/99 5:54p Dave
461 * Seperated cruiser types into individual types. Added tons of new
462 * briefing icons. Campaign screen.
464 * 100 7/08/99 4:43p Andsager
465 * New check for sparky_hi and print if not found.
467 * 99 7/08/99 10:53a Dave
468 * New multiplayer interpolation scheme. Not 100% done yet, but still
469 * better than the old way.
471 * 98 7/06/99 4:24p Dave
472 * Mid-level checkin. Starting on some potentially cool multiplayer
475 * 97 7/06/99 3:35p Andsager
476 * Allow movie to play before red alert mission.
478 * 96 7/03/99 5:50p Dave
479 * Make rotated bitmaps draw properly in padlock views.
481 * 95 7/02/99 9:55p Dave
482 * Player engine wash sound.
484 * 94 7/02/99 4:30p Dave
485 * Much more sophisticated lightning support.
487 * 93 6/29/99 7:52p Dave
488 * Put in exception handling in FS2.
490 * 92 6/22/99 9:37p Dave
491 * Put in pof spewing.
493 * 91 6/16/99 4:06p Dave
494 * New pilot info popup. Added new draw-bitmap-as-poly function.
496 * 90 6/15/99 1:56p Andsager
497 * For release builds, allow start up in high res only with
500 * 89 6/15/99 9:34a Dave
501 * Fixed key checking in single threaded version of the stamp notification
504 * 88 6/09/99 2:55p Andsager
505 * Allow multiple asteroid subtypes (of large, medium, small) and follow
508 * 87 6/08/99 1:14a Dave
509 * Multi colored hud test.
511 * 86 6/04/99 9:52a Dave
512 * Fixed some rendering problems.
514 * 85 6/03/99 10:15p Dave
515 * Put in temporary main hall screen.
517 * 84 6/02/99 6:18p Dave
518 * Fixed TNT lockup problems! Wheeeee!
520 * 83 6/01/99 3:52p Dave
521 * View footage screen. Fixed xstrings to not display the & symbol. Popup,
522 * dead popup, pxo find player popup, pxo private room popup.
524 * 82 5/26/99 1:28p Jasenw
525 * changed coords for loading ani
527 * 81 5/26/99 11:46a Dave
528 * Added ship-blasting lighting and made the randomization of lighting
529 * much more customizable.
531 * 80 5/24/99 5:45p Dave
532 * Added detail levels to the nebula, with a decent speedup. Split nebula
533 * lightning into its own section.
551 #include "systemvars.h"
556 #include "starfield.h"
557 #include "lighting.h"
562 #include "fireballs.h"
566 #include "floating.h"
567 #include "gamesequence.h"
569 #include "optionsmenu.h"
570 #include "playermenu.h"
571 #include "trainingmenu.h"
572 #include "techmenu.h"
575 #include "hudmessage.h"
577 #include "missiongoals.h"
578 #include "missionparse.h"
583 #include "multiutil.h"
584 #include "multimsgs.h"
588 #include "freespace.h"
589 #include "managepilot.h"
591 #include "contexthelp.h"
594 #include "missionbrief.h"
595 #include "missiondebrief.h"
597 #include "missionshipchoice.h"
599 #include "hudconfig.h"
600 #include "controlsconfig.h"
601 #include "missionmessage.h"
602 #include "missiontraining.h"
604 #include "hudtarget.h"
606 #include "eventmusic.h"
607 #include "animplay.h"
608 #include "missionweaponchoice.h"
609 #include "missionlog.h"
610 #include "audiostr.h"
612 #include "missioncampaign.h"
614 #include "missionhotkey.h"
615 #include "objectsnd.h"
616 #include "cmeasure.h"
618 #include "linklist.h"
619 #include "shockwave.h"
620 #include "afterburner.h"
625 #include "stand_gui.h"
626 #include "pcxutils.h"
627 #include "hudtargetbox.h"
628 #include "multi_xfer.h"
629 #include "hudescort.h"
630 #include "multiutil.h"
633 #include "multiteamselect.h"
636 #include "readyroom.h"
637 #include "mainhallmenu.h"
638 #include "multilag.h"
640 #include "particle.h"
642 #include "multi_ingame.h"
643 #include "snazzyui.h"
644 #include "asteroid.h"
645 #include "popupdead.h"
646 #include "multi_voice.h"
647 #include "missioncmdbrief.h"
648 #include "redalert.h"
649 #include "gameplayhelp.h"
650 #include "multilag.h"
651 #include "staticrand.h"
652 #include "multi_pmsg.h"
653 #include "levelpaging.h"
654 #include "observer.h"
655 #include "multi_pause.h"
656 #include "multi_endgame.h"
657 #include "cutscenes.h"
658 #include "multi_respawn.h"
660 #include "multi_obj.h"
661 #include "multi_log.h"
663 #include "localize.h"
664 #include "osregistry.h"
665 #include "barracks.h"
666 #include "missionpause.h"
668 #include "alphacolors.h"
669 #include "objcollide.h"
672 #include "neblightning.h"
673 #include "shipcontrails.h"
676 #include "multi_dogfight.h"
677 #include "multi_rate.h"
678 #include "muzzleflash.h"
682 #include "mainhalltemp.h"
683 #include "exceptionhandler.h"
687 #include "supernova.h"
688 #include "hudshield.h"
689 // #include "names.h"
691 #include "missionloopbrief.h"
695 #error macro FRED is defined when trying to build release Fred. Please undefine FRED macro in build settings
701 // 1.00.04 5/26/98 MWA -- going final (12 pm)
702 // 1.00.03 5/26/98 MWA -- going final (3 am)
703 // 1.00.02 5/25/98 MWA -- going final
704 // 1.00.01 5/25/98 MWA -- going final
705 // 0.90 5/21/98 MWA -- getting ready for final.
706 // 0.10 4/9/98. Set by MK.
708 // Demo version: (obsolete since DEMO codebase split from tree)
709 // 0.03 4/10/98 AL. Interplay rev
710 // 0.02 4/8/98 MK. Increased when this system was modified.
711 // 0.01 4/7/98? AL. First release to Interplay QA.
714 // 1.00 5/28/98 AL. First release to Interplay QA.
716 void game_level_init(int seed = -1);
717 void game_post_level_init();
718 void game_do_frame();
719 void game_update_missiontime(); // called from game_do_frame() and navmap_do_frame()
720 void game_reset_time();
721 void game_show_framerate(); // draws framerate in lower right corner
723 int Game_no_clear = 0;
725 int Pofview_running = 0;
726 int Nebedit_running = 0;
728 typedef struct big_expl_flash {
729 float max_flash_intensity; // max intensity
730 float cur_flash_intensity; // cur intensity
731 int flash_start; // start time
734 #define FRAME_FILTER 16
736 #define DEFAULT_SKILL_LEVEL 1
737 int Game_skill_level = DEFAULT_SKILL_LEVEL;
739 #define VIEWER_ZOOM_DEFAULT 0.75f // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
740 float Viewer_zoom = VIEWER_ZOOM_DEFAULT;
742 #define EXE_FNAME ("fs2.exe")
743 #define LAUNCHER_FNAME ("freespace2.exe")
745 // JAS: Code for warphole camera.
746 // Needs to be cleaned up.
747 vector Camera_pos = { 0.0f, 0.0f, 0.0f };
748 vector Camera_velocity = { 0.0f, 0.0f, 0.0f };
749 vector Camera_desired_velocity = { 0.0f, 0.0f, 0.0f };
750 matrix Camera_orient = IDENTITY_MATRIX;
751 float Camera_damping = 1.0f;
752 float Camera_time = 0.0f;
753 float Warpout_time = 0.0f;
754 int Warpout_forced = 0; // Set if this is a forced warpout that cannot be cancelled.
755 int Warpout_sound = -1;
757 int Use_joy_mouse = 0;
758 int Use_palette_flash = 1;
760 int Use_fullscreen_at_startup = 0;
762 int Show_area_effect = 0;
763 object *Last_view_target = NULL;
765 int dogfight_blown = 0;
768 float frametimes[FRAME_FILTER];
769 float frametotal = 0.0f;
773 int Show_framerate = 0;
775 int Show_framerate = 1;
778 int Framerate_cap = 120;
781 int Show_target_debug_info = 0;
782 int Show_target_weapons = 0;
786 static int Show_player_pos = 0; // debug console command to show player world pos on HUD
789 int Debug_octant = -1;
791 fix Game_time_compression = F1_0;
793 // if the ships.tbl the player has is valid
794 int Game_ships_tbl_valid = 0;
796 // if the weapons.tbl the player has is valid
797 int Game_weapons_tbl_valid = 0;
801 extern int Player_attacking_enabled;
805 int Pre_player_entry;
807 int Fred_running = 0;
808 char Game_current_mission_filename[MAX_FILENAME_LEN];
809 int game_single_step = 0;
810 int last_single_step=0;
812 extern int MSG_WINDOW_X_START; // used to position mission_time and shields output
813 extern int MSG_WINDOW_Y_START;
814 extern int MSG_WINDOW_HEIGHT;
816 int game_zbuffer = 1;
817 //static int Game_music_paused;
818 static int Game_paused;
822 #define EXPIRE_BAD_CHECKSUM 1
823 #define EXPIRE_BAD_TIME 2
825 extern void ssm_init();
826 extern void ssm_level_init();
827 extern void ssm_process();
829 // static variable to contain the time this version was built
830 // commented out for now until
831 // I figure out how to get the username into the file
832 //LOCAL char freespace_build_time[] = "Compiled on:"__DATE__" "__TIME__" by "__USER__;
834 // defines and variables used for dumping frame for making trailers.
836 int Debug_dump_frames = 0; // Set to 0 to not dump frames, else equal hz to dump. (15 or 30 probably)
837 int Debug_dump_trigger = 0;
838 int Debug_dump_frame_count;
839 int Debug_dump_frame_num = 0;
840 #define DUMP_BUFFER_NUM_FRAMES 1 // store every 15 frames
843 // amount of time to wait after the player has died before we display the death died popup
844 #define PLAYER_DIED_POPUP_WAIT 2500
845 int Player_died_popup_wait = -1;
846 int Player_multi_died_check = -1;
848 // builtin mission list stuff
850 int Game_builtin_mission_count = 6;
851 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
852 { "SPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
853 { "SPDemo-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
854 { "DemoTrain.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
855 { "Demo.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
856 { "MPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
857 { "Demo-DOG-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
859 #elif defined(FS1_DEMO)
860 int Game_builtin_mission_count = 5;
861 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
862 { "btmdemo.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
863 { "demo.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
864 { "demo01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
865 { "demo02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
866 { "demo02b.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
868 #elif defined(PD_BUILD)
869 int Game_builtin_mission_count = 4;
870 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
871 { "sm1-01.fs2", (FSB_FROM_VOLITION), "" },
872 { "sm1-05.fs2", (FSB_FROM_VOLITION), "" },
873 { "sm1-01", (FSB_FROM_VOLITION), "" },
874 { "sm1-05", (FSB_FROM_VOLITION), "" },
876 #elif defined(MULTIPLAYER_BETA)
877 int Game_builtin_mission_count = 17;
878 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
880 { "md-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
881 { "md-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
882 { "md-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
883 { "md-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
884 { "md-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
885 { "md-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
886 { "md-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
887 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
888 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
889 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
890 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
891 { "m-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
892 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
893 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
894 { "templar-03a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
895 { "templar-04a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
896 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
898 #elif defined(OEM_BUILD)
899 int Game_builtin_mission_count = 17;
900 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
901 // oem version - act 1 only
902 { "freespace2oem.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
905 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
906 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
907 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
908 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
909 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
910 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
911 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
912 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
913 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
914 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
915 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
916 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
917 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
918 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
919 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
920 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 }
922 #elif defined(MAKE_FS1)
923 int Game_builtin_mission_count = 125;
924 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
925 // single player campaign
926 { "freespace.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
929 { "sm1-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
930 { "sm1-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
931 { "sm1-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
932 { "sm1-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
933 { "sm1-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
934 { "sm1-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
935 { "sm1-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
936 { "sm1-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
937 { "sm1-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
938 { "sm1-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
941 { "sm2-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
942 { "sm2-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
943 { "sm2-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
944 { "sm2-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
945 { "sm2-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
946 { "sm2-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
947 { "sm2-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
948 { "sm2-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
949 { "sm2-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
950 { "sm2-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
953 { "sm3-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
954 { "sm3-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
955 { "sm3-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
956 { "sm3-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
957 { "sm3-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
958 { "sm3-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
959 { "sm3-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
960 { "sm3-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
961 { "sm3-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
964 { "t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
965 { "v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
966 { "s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
969 { "btm-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
970 { "btm-02.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
971 { "btm-03.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
972 { "btm-04.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
973 { "btm-05.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
976 { "m-hope.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
977 { "m-altair.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
979 { "m-v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
980 { "m-va.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
981 { "m-unstoppable.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
982 { "m-t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
983 { "m-s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
984 { "m-rescue.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
985 { "m-pain.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
986 { "m-orecovery.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
987 { "mm3-01a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
988 { "mm3-02a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
989 { "mm3-03a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
990 { "mm3-04a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
991 { "mm3-05a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
992 { "mm3-06a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
993 { "m-guardduty.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
994 { "m-gate.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
995 { "m-duel.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
996 { "m-convoyassault.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
997 { "m-clash.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
999 // SilentThreat missions
1000 // Main SilentThreat campaign
1001 { "SilentThreat.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN_FILE), "" },
1003 { "md-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1004 { "md-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1005 { "md-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1006 { "md-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1007 { "md-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1008 { "md-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1009 { "md-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1010 { "md-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1011 { "md-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1012 { "md-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1013 { "md-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1014 { "md-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1016 // SilentThreat Part 1 - multi-coop
1017 { "ST-Part1.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1019 { "stmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1020 { "stmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1021 { "stmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1023 // SilentThreat Part 2 - multi-coop
1024 { "ST-Part2.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1026 { "stmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1027 { "stmm-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1028 { "stmm-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1030 // SilentThreat Part 3 - multi-coop
1031 { "ST-Part3.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1033 { "stmm-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1034 { "stmm-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1035 { "stmm-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1037 // SilentThreat Part 4 - multi-coop
1038 { "ST-Part4.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1040 { "stmm-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1041 { "stmm-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1042 { "stmm-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1044 // multiplayer missions
1045 { "mdmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1046 { "mdmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1047 { "mdmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1048 { "mdmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1049 // user supplied missions
1050 { "mdu-02.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1051 { "mdu-03.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1052 { "mdu-04.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1053 { "mdu-05.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1054 { "mdu-06.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1055 { "mdu-07.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1056 { "mdu-08.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1057 { "mdu-09.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1058 { "mdu-10.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1059 { "mdu-11.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1060 { "mdu-12.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1061 { "mdu-13.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1062 { "mdu-14.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1063 { "mdu-15.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1064 { "mdu-16.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1065 { "mdu-17.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1066 { "mdu-18.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1067 { "mdu-19.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1068 { "mdu-20.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1069 { "mdu-21.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1070 { "mdu-22.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1071 { "mdu-23.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1072 { "mdu-24.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1073 { "mdu-25.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1074 { "mdu-26.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1075 { "mdu-27.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1076 { "mdu-28.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1077 { "mdu-29.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1078 { "mdu-30.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1079 { "mdu-31.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1080 { "mdumm-01.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1081 { "mdumm-02.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1084 int Game_builtin_mission_count = 92;
1085 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
1086 // single player campaign
1087 { "freespace2.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
1090 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1091 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1092 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1093 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1094 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1095 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1096 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1097 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1098 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1099 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1100 { "loop1-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1101 { "loop1-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1102 { "loop1-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1103 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1104 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1105 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1106 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1107 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1108 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1111 { "sm2-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1112 { "sm2-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1113 { "sm2-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1114 { "sm2-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1115 { "sm2-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1116 { "sm2-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1117 { "sm2-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1118 { "sm2-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1119 { "sm2-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1120 { "sm2-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1123 { "sm3-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1124 { "sm3-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1125 { "sm3-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1126 { "sm3-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1127 { "sm3-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1128 { "sm3-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1129 { "sm3-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1130 { "sm3-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1131 { "sm3-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1132 { "sm3-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1133 { "loop2-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1134 { "loop2-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1136 // multiplayer missions
1139 { "g-shi.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1140 { "g-ter.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1141 { "g-vas.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1144 { "m-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1145 { "m-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1146 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1147 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1150 { "mdh-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1151 { "mdh-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1152 { "mdh-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1153 { "mdh-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1154 { "mdh-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1155 { "mdh-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1156 { "mdh-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1157 { "mdh-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1158 { "mdh-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1159 { "mdl-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1160 { "mdl-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1161 { "mdl-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1162 { "mdl-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1163 { "mdl-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1164 { "mdl-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1165 { "mdl-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1166 { "mdl-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1167 { "mdl-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1168 { "mdm-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1169 { "mdm-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1170 { "mdm-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1171 { "mdm-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1172 { "mdm-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1173 { "mdm-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1174 { "mdm-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1175 { "mdm-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1176 { "mdm-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1177 { "osdog.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1180 { "mt-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1181 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1182 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1183 { "mt-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1184 { "mt-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1185 { "mt-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1186 { "mt-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1187 { "mt-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1188 { "mt-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1189 { "mt-10.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1192 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1193 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1194 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1195 { "templar-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1196 { "templar-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1201 // Internal function prototypes
1202 void game_maybe_draw_mouse(float frametime);
1203 void init_animating_pointer();
1204 void load_animating_pointer(char *filename, int dx, int dy);
1205 void unload_animating_pointer();
1206 void game_do_training_checks();
1207 void game_shutdown(void);
1208 void game_show_event_debug(float frametime);
1209 void game_event_debug_init();
1211 void demo_upsell_show_screens();
1212 void game_start_subspace_ambient_sound();
1213 void game_stop_subspace_ambient_sound();
1214 void verify_ships_tbl();
1215 void verify_weapons_tbl();
1216 void display_title_screen();
1218 // loading background filenames
1219 static char *Game_loading_bground_fname[GR_NUM_RESOLUTIONS] = {
1220 "LoadingBG", // GR_640
1221 "2_LoadingBG" // GR_1024
1225 static char *Game_loading_ani_fname[GR_NUM_RESOLUTIONS] = {
1226 "Loading.ani", // GR_640
1227 "2_Loading.ani" // GR_1024
1230 #if defined(FS2_DEMO) || defined(FS1_DEMO)
1231 static char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1239 #elif defined(OEM_BUILD)
1240 static char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1250 char Game_CDROM_dir[MAX_PATH_LEN];
1253 // How much RAM is on this machine. Set in WinMain
1254 uint Freespace_total_ram = 0;
1257 float Game_flash_red = 0.0f;
1258 float Game_flash_green = 0.0f;
1259 float Game_flash_blue = 0.0f;
1260 float Sun_spot = 0.0f;
1261 big_expl_flash Big_expl_flash = {0.0f, 0.0f, 0};
1263 // game shudder stuff (in ms)
1264 int Game_shudder_time = -1;
1265 int Game_shudder_total = 0;
1266 float Game_shudder_intensity = 0.0f; // should be between 0.0 and 100.0
1269 sound_env Game_sound_env;
1270 //sound_env Game_default_sound_env = {SND_ENV_AUDITORIUM, 0.25f, 0.35f, 3.0f};
1271 sound_env Game_default_sound_env = {SND_ENV_GENERIC, 0.2F,0.2F,1.0F};
1273 int Game_sound_env_update_timestamp;
1275 // WARPIN CRAP BEGIN --------------------------------------------------------------------------------------------
1278 // WARPIN CRAP END --------------------------------------------------------------------------------------------
1280 fs_builtin_mission *game_find_builtin_mission(char *filename)
1284 // look through all existing builtin missions
1285 for(idx=0; idx<Game_builtin_mission_count; idx++){
1286 if(!stricmp(Game_builtin_mission_list[idx].filename, filename)){
1287 return &Game_builtin_mission_list[idx];
1295 int game_get_default_skill_level()
1297 return DEFAULT_SKILL_LEVEL;
1301 void game_flash_reset()
1303 Game_flash_red = 0.0f;
1304 Game_flash_green = 0.0f;
1305 Game_flash_blue = 0.0f;
1307 Big_expl_flash.max_flash_intensity = 0.0f;
1308 Big_expl_flash.cur_flash_intensity = 0.0f;
1309 Big_expl_flash.flash_start = 0;
1312 float Gf_critical = -1.0f; // framerate we should be above on the average for this mission
1313 float Gf_critical_time = 0.0f; // how much time we've been at the critical framerate
1315 void game_framerate_check_init()
1317 // zero critical time
1318 Gf_critical_time = 0.0f;
1321 if(The_mission.flags & MISSION_FLAG_FULLNEB){
1322 // if this is a glide card
1323 if(gr_screen.mode == GR_GLIDE){
1325 extern GrHwConfiguration hwconfig;
1328 if(hwconfig.SSTs[0].sstBoard.VoodooConfig.fbRam >= 4){
1329 Gf_critical = 15.0f;
1333 Gf_critical = 10.0f;
1338 Gf_critical = 15.0f;
1341 // d3d. only care about good cards here I guess (TNT)
1343 Gf_critical = 15.0f;
1346 // if this is a glide card
1347 if(gr_screen.mode == GR_GLIDE){
1349 extern GrHwConfiguration hwconfig;
1352 if(hwconfig.SSTs[0].sstBoard.VoodooConfig.fbRam >= 4){
1353 Gf_critical = 25.0f;
1357 Gf_critical = 20.0f;
1362 Gf_critical = 25.0f;
1365 // d3d. only care about good cards here I guess (TNT)
1367 Gf_critical = 25.0f;
1372 extern float Framerate;
1373 void game_framerate_check()
1377 // if the current framerate is above the critical level, add frametime
1378 if(Framerate >= Gf_critical){
1379 Gf_critical_time += flFrametime;
1382 if(!Show_framerate){
1386 // display if we're above the critical framerate
1387 if(Framerate < Gf_critical){
1388 gr_set_color_fast(&Color_bright_red);
1389 gr_string(200, y_start, "Framerate warning");
1394 // display our current pct of good frametime
1395 if(f2fl(Missiontime) >= 0.0f){
1396 float pct = (Gf_critical_time / f2fl(Missiontime)) * 100.0f;
1399 gr_set_color_fast(&Color_bright_green);
1401 gr_set_color_fast(&Color_bright_red);
1404 gr_printf(200, y_start, "%d%%", (int)pct);
1411 // Adds a flash effect. These can be positive or negative.
1412 // The range will get capped at around -1 to 1, so stick
1413 // with a range like that.
1414 void game_flash( float r, float g, float b )
1416 Game_flash_red += r;
1417 Game_flash_green += g;
1418 Game_flash_blue += b;
1420 if ( Game_flash_red < -1.0f ) {
1421 Game_flash_red = -1.0f;
1422 } else if ( Game_flash_red > 1.0f ) {
1423 Game_flash_red = 1.0f;
1426 if ( Game_flash_green < -1.0f ) {
1427 Game_flash_green = -1.0f;
1428 } else if ( Game_flash_green > 1.0f ) {
1429 Game_flash_green = 1.0f;
1432 if ( Game_flash_blue < -1.0f ) {
1433 Game_flash_blue = -1.0f;
1434 } else if ( Game_flash_blue > 1.0f ) {
1435 Game_flash_blue = 1.0f;
1440 // Adds a flash for Big Ship explosions
1441 // cap range from 0 to 1
1442 void big_explosion_flash(float flash)
1444 Big_expl_flash.flash_start = timestamp(1);
1448 } else if (flash < 0.0f) {
1452 Big_expl_flash.max_flash_intensity = flash;
1453 Big_expl_flash.cur_flash_intensity = 0.0f;
1456 // Amount to diminish palette towards normal, per second.
1457 #define DIMINISH_RATE 0.75f
1458 #define SUN_DIMINISH_RATE 6.00f
1462 float sn_glare_scale = 1.7f;
1465 dc_get_arg(ARG_FLOAT);
1466 sn_glare_scale = Dc_arg_float;
1469 float Supernova_last_glare = 0.0f;
1470 void game_sunspot_process(float frametime)
1474 float Sun_spot_goal = 0.0f;
1477 sn_stage = supernova_active();
1479 // sunspot differently based on supernova stage
1481 // approaching. player still in control
1484 pct = (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME));
1487 light_get_global_dir(&light_dir, 0);
1489 dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec );
1492 // scale it some more
1493 dot = dot * (0.5f + (pct * 0.5f));
1496 Sun_spot_goal += (dot * sn_glare_scale);
1499 // draw the sun glow
1500 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, 0 ) ) {
1501 // draw the glow for this sun
1502 stars_draw_sun_glow(0);
1505 Supernova_last_glare = Sun_spot_goal;
1508 // camera cut. player not in control. note : at this point camera starts out facing the sun. so we can go nice and bright
1511 Sun_spot_goal = 0.9f;
1512 Sun_spot_goal += (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME)) * 0.1f;
1514 if(Sun_spot_goal > 1.0f){
1515 Sun_spot_goal = 1.0f;
1518 Sun_spot_goal *= sn_glare_scale;
1519 Supernova_last_glare = Sun_spot_goal;
1522 // fade to white. display dead popup
1525 Supernova_last_glare += (2.0f * flFrametime);
1526 if(Supernova_last_glare > 2.0f){
1527 Supernova_last_glare = 2.0f;
1530 Sun_spot_goal = Supernova_last_glare;
1537 // check sunspots for all suns
1538 n_lights = light_get_global_count();
1541 for(idx=0; idx<n_lights; idx++){
1542 //(vector *eye_pos, matrix *eye_orient)
1543 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, idx ) ) {
1546 light_get_global_dir(&light_dir, idx);
1548 float dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec )*0.5f+0.5f;
1550 Sun_spot_goal += (float)pow(dot,85.0f);
1552 // draw the glow for this sun
1553 stars_draw_sun_glow(idx);
1555 Sun_spot_goal = 0.0f;
1561 Sun_spot_goal = 0.0f;
1565 float dec_amount = frametime*SUN_DIMINISH_RATE;
1567 if ( Sun_spot < Sun_spot_goal ) {
1568 Sun_spot += dec_amount;
1569 if ( Sun_spot > Sun_spot_goal ) {
1570 Sun_spot = Sun_spot_goal;
1572 } else if ( Sun_spot > Sun_spot_goal ) {
1573 Sun_spot -= dec_amount;
1574 if ( Sun_spot < Sun_spot_goal ) {
1575 Sun_spot = Sun_spot_goal;
1581 // Call once a frame to diminish the
1582 // flash effect to 0.
1583 void game_flash_diminish(float frametime)
1585 float dec_amount = frametime*DIMINISH_RATE;
1587 if ( Game_flash_red > 0.0f ) {
1588 Game_flash_red -= dec_amount;
1589 if ( Game_flash_red < 0.0f )
1590 Game_flash_red = 0.0f;
1592 Game_flash_red += dec_amount;
1593 if ( Game_flash_red > 0.0f )
1594 Game_flash_red = 0.0f;
1597 if ( Game_flash_green > 0.0f ) {
1598 Game_flash_green -= dec_amount;
1599 if ( Game_flash_green < 0.0f )
1600 Game_flash_green = 0.0f;
1602 Game_flash_green += dec_amount;
1603 if ( Game_flash_green > 0.0f )
1604 Game_flash_green = 0.0f;
1607 if ( Game_flash_blue > 0.0f ) {
1608 Game_flash_blue -= dec_amount;
1609 if ( Game_flash_blue < 0.0f )
1610 Game_flash_blue = 0.0f;
1612 Game_flash_blue += dec_amount;
1613 if ( Game_flash_blue > 0.0f )
1614 Game_flash_blue = 0.0f;
1617 // update big_explosion_cur_flash
1618 #define TIME_UP 1500
1619 #define TIME_DOWN 2500
1620 int duration = TIME_UP + TIME_DOWN;
1621 int time = timestamp_until(Big_expl_flash.flash_start);
1622 if (time > -duration) {
1624 if (time < TIME_UP) {
1625 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * time / (float) TIME_UP;
1628 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * ((float) TIME_DOWN - time) / (float) TIME_DOWN;
1632 if ( Use_palette_flash ) {
1634 // static int or=0, og=0, ob=0;
1636 // Change the 200 to change the color range of colors.
1637 r = fl2i( Game_flash_red*128.0f );
1638 g = fl2i( Game_flash_green*128.0f );
1639 b = fl2i( Game_flash_blue*128.0f );
1641 if ( Sun_spot > 0.0f ) {
1642 r += fl2i(Sun_spot*128.0f);
1643 g += fl2i(Sun_spot*128.0f);
1644 b += fl2i(Sun_spot*128.0f);
1647 if ( Big_expl_flash.cur_flash_intensity > 0.0f ) {
1648 r += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1649 g += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1650 b += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1653 if ( r < 0 ) r = 0; else if ( r > 255 ) r = 255;
1654 if ( g < 0 ) g = 0; else if ( g > 255 ) g = 255;
1655 if ( b < 0 ) b = 0; else if ( b > 255 ) b = 255;
1657 if ( (r!=0) || (g!=0) || (b!=0) ) {
1658 gr_flash( r, g, b );
1660 //mprintf(( "Flash! %d,%d,%d\n", r, g, b ));
1671 void game_level_close()
1673 // De-Initialize the game subsystems
1674 event_music_level_close();
1675 game_stop_looped_sounds();
1677 obj_snd_level_close(); // uninit object-linked persistant sounds
1678 gamesnd_unload_gameplay_sounds(); // unload gameplay sounds from memory
1679 anim_level_close(); // stop and clean up any anim instances
1680 message_mission_shutdown(); // called after anim_level_close() to make sure anim instances are free
1681 shockwave_level_close();
1682 fireball_level_close();
1684 mission_event_shutdown();
1685 asteroid_level_close();
1686 model_cache_reset(); // Reset/free all the model caching stuff
1687 flak_level_close(); // unload flak stuff
1688 neb2_level_close(); // shutdown gaseous nebula stuff
1691 mflash_level_close();
1693 audiostream_unpause_all();
1698 // intializes game stuff and loads the mission. Returns 0 on failure, 1 on success
1699 // input: seed => DEFAULT PARAMETER (value -1). Only set by demo playback code.
1700 void game_level_init(int seed)
1702 // seed the random number generator
1704 // if no seed was passed, seed the generator either from the time value, or from the
1705 // netgame security flags -- ensures that all players in multiplayer game will have the
1706 // same randon number sequence (with static rand functions)
1707 if ( Game_mode & GM_NORMAL ) {
1708 Game_level_seed = time(NULL);
1710 Game_level_seed = Netgame.security;
1713 // mwa 9/17/98 -- maybe this assert isn't needed????
1714 Assert( !(Game_mode & GM_MULTIPLAYER) );
1715 Game_level_seed = seed;
1717 srand( Game_level_seed );
1719 // semirand function needs to get re-initted every time in multiplayer
1720 if ( Game_mode & GM_MULTIPLAYER ){
1726 Key_normal_game = (Game_mode & GM_NORMAL);
1729 Game_shudder_time = -1;
1731 // Initialize the game subsystems
1732 // timestamp_reset(); // Must be inited before everything else
1734 game_reset_time(); // resets time, and resets saved time too
1736 obj_init(); // Must be inited before the other systems
1737 model_free_all(); // Free all existing models
1738 mission_brief_common_init(); // Free all existing briefing/debriefing text
1739 weapon_level_init();
1740 ai_level_init(); // Call this before ship_init() because it reads ai.tbl.
1742 player_level_init();
1743 shipfx_flash_init(); // Init the ship gun flash system.
1744 game_flash_reset(); // Reset the flash effect
1745 particle_init(); // Reset the particle system
1749 shield_hit_init(); // Initialize system for showing shield hits
1750 radar_mission_init();
1751 mission_init_goals();
1754 obj_snd_level_init(); // init object-linked persistant sounds
1756 shockwave_level_init();
1757 afterburner_level_init();
1758 scoring_level_init( &Player->stats );
1760 asteroid_level_init();
1761 control_config_clear_used_status();
1762 collide_ship_ship_sounds_init();
1764 Pre_player_entry = 1; // Means the player has not yet entered.
1765 Entry_delay_time = 0; // Could get overwritten in mission read.
1766 fireball_preload(); // page in warphole bitmaps
1768 flak_level_init(); // initialize flak - bitmaps, etc
1769 ct_level_init(); // initialize ships contrails, etc
1770 awacs_level_init(); // initialize AWACS
1771 beam_level_init(); // initialize beam weapons
1772 mflash_level_init();
1774 supernova_level_init();
1776 // multiplayer dogfight hack
1779 shipfx_engine_wash_level_init();
1783 Last_view_target = NULL;
1788 // campaign wasn't ended
1789 Campaign_ended_in_mission = 0;
1792 // called when a mission is over -- does server specific stuff.
1793 void freespace_stop_mission()
1796 Game_mode &= ~GM_IN_MISSION;
1799 // called at frame interval to process networking stuff
1800 void game_do_networking()
1802 Assert( Net_player != NULL );
1803 if (!(Game_mode & GM_MULTIPLAYER)){
1807 // see if this player should be reading/writing data. Bit is set when at join
1808 // screen onward until quits back to main menu.
1809 if ( !(Net_player->flags & NETINFO_FLAG_DO_NETWORKING) ){
1813 if(gameseq_get_state()!=GS_STATE_MULTI_PAUSED){
1816 multi_pause_do_frame();
1821 // Loads the best palette for this level, based
1822 // on nebula color and hud color. You could just call palette_load_table with
1823 // the appropriate filename, but who wants to do that.
1824 void game_load_palette()
1826 char palette_filename[1024];
1828 // We only use 3 hud colors right now
1830 Assert( HUD_config.main_color >= 0 );
1831 Assert( HUD_config.main_color <= 2 );
1834 Assert( Mission_palette >= 0 );
1835 Assert( Mission_palette <= 98 );
1838 if ( The_mission.flags & MISSION_FLAG_SUBSPACE ) {
1839 strcpy( palette_filename, NOX("gamepalette-subspace") );
1841 sprintf( palette_filename, NOX("gamepalette%d-%02d"), HUD_config.main_color+1, Mission_palette+1 );
1844 mprintf(( "Loading palette %s\n", palette_filename ));
1846 palette_load_table(palette_filename);
1848 strcpy( palette_filename, NOX("gamepalette-subspace") );
1850 mprintf(( "Loading palette %s\n", palette_filename ));
1854 void game_post_level_init()
1856 // Stuff which gets called after mission is loaded. Because player isn't created until
1857 // after mission loads, some things must get initted after the level loads
1859 model_level_post_init();
1862 hud_setup_escort_list();
1863 mission_hotkey_set_defaults(); // set up the default hotkeys (from mission file)
1869 game_event_debug_init();
1872 training_mission_init();
1873 asteroid_create_all();
1875 game_framerate_check_init();
1879 // An estimate as to how high the count passed to game_loading_callback will go.
1880 // This is just a guess, it seems to always be about the same. The count is
1881 // proportional to the code being executed, not the time, so this works good
1882 // for a bar, assuming the code does about the same thing each time you
1883 // load a level. You can find this value by looking at the return value
1884 // of game_busy_callback(NULL), which I conveniently print out to the
1885 // debug output window with the '=== ENDING LOAD ==' stuff.
1886 //#define COUNT_ESTIMATE 3706
1887 #define COUNT_ESTIMATE 1111
1889 int Game_loading_callback_inited = 0;
1891 int Game_loading_background = -1;
1892 anim * Game_loading_ani = NULL;
1893 anim_instance *Game_loading_ani_instance;
1894 int Game_loading_frame=-1;
1896 static int Game_loading_ani_coords[GR_NUM_RESOLUTIONS][2] = {
1898 #if defined(FS1_DEMO)
1900 #elif defined(MAKE_FS1)
1911 // This gets called 10x per second and count is the number of times
1912 // game_busy() has been called since the current callback function
1914 void game_loading_callback(int count)
1916 game_do_networking();
1918 Assert( Game_loading_callback_inited==1 );
1919 Assert( Game_loading_ani != NULL );
1921 int framenum = ((Game_loading_ani->total_frames*count) / COUNT_ESTIMATE)+1;
1922 if ( framenum > Game_loading_ani->total_frames-1 ) {
1923 framenum = Game_loading_ani->total_frames-1;
1924 } else if ( framenum < 0 ) {
1929 while ( Game_loading_frame < framenum ) {
1930 Game_loading_frame++;
1931 cbitmap = anim_get_next_frame(Game_loading_ani_instance);
1935 if ( cbitmap > -1 ) {
1936 if ( Game_loading_background > -1 ) {
1937 gr_set_bitmap( Game_loading_background );
1941 //mprintf(( "Showing frame %d/%d [ Bitmap=%d ]\n", Game_loading_frame , Game_loading_ani->total_frames, cbitmap ));
1942 gr_set_bitmap( cbitmap );
1943 gr_bitmap(Game_loading_ani_coords[gr_screen.res][0],Game_loading_ani_coords[gr_screen.res][1]);
1945 bm_release(cbitmap);
1951 void game_loading_callback_init()
1953 Assert( Game_loading_callback_inited==0 );
1955 Game_loading_background = bm_load(Game_loading_bground_fname[gr_screen.res]);
1957 common_set_interface_palette("InterfacePalette"); // set the interface palette
1961 Game_loading_ani = anim_load( Game_loading_ani_fname[gr_screen.res]);
1962 Assert( Game_loading_ani != NULL );
1963 Game_loading_ani_instance = init_anim_instance(Game_loading_ani, 16);
1964 Assert( Game_loading_ani_instance != NULL );
1965 Game_loading_frame = -1;
1967 Game_loading_callback_inited = 1;
1969 game_busy_callback( game_loading_callback, (COUNT_ESTIMATE/Game_loading_ani->total_frames)+1 );
1974 void game_loading_callback_close()
1976 Assert( Game_loading_callback_inited==1 );
1978 // Make sure bar shows all the way over.
1979 game_loading_callback(COUNT_ESTIMATE);
1981 int real_count = game_busy_callback( NULL );
1984 Game_loading_callback_inited = 0;
1987 mprintf(( "=================== ENDING LOAD ================\n" ));
1988 mprintf(( "Real count = %d, Estimated count = %d\n", real_count, COUNT_ESTIMATE ));
1989 mprintf(( "================================================\n" ));
1991 // to remove warnings in release build
1995 free_anim_instance(Game_loading_ani_instance);
1996 Game_loading_ani_instance = NULL;
1997 anim_free(Game_loading_ani);
1998 Game_loading_ani = NULL;
2000 bm_release( Game_loading_background );
2001 common_free_interface_palette(); // restore game palette
2002 Game_loading_background = -1;
2004 gr_set_font( FONT1 );
2007 // Update the sound environment (ie change EAX settings based on proximity to large ships)
2009 void game_maybe_update_sound_environment()
2011 // do nothing for now
2014 // Assign the sound environment for the game, based on the current mission
2016 void game_assign_sound_environment()
2019 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
2020 Game_sound_env.id = SND_ENV_DRUGGED;
2021 Game_sound_env.volume = 0.800f;
2022 Game_sound_env.damping = 1.188f;
2023 Game_sound_env.decay = 6.392f;
2025 } else if (Num_asteroids > 30) {
2026 Game_sound_env.id = SND_ENV_AUDITORIUM;
2027 Game_sound_env.volume = 0.603f;
2028 Game_sound_env.damping = 0.5f;
2029 Game_sound_env.decay = 4.279f;
2032 Game_sound_env = Game_default_sound_env;
2036 Game_sound_env = Game_default_sound_env;
2037 Game_sound_env_update_timestamp = timestamp(1);
2040 // function which gets called before actually entering the mission. It is broken down into a funciton
2041 // since it will get called in one place from a single player game and from another place for
2042 // a multiplayer game
2043 void freespace_mission_load_stuff()
2045 // called if we're not on a freespace dedicated (non rendering, no pilot) server
2046 // IE : we _don't_ want to load any sounds or bitmap/texture info on this machine.
2047 if(!(Game_mode & GM_STANDALONE_SERVER)){
2049 mprintf(( "=================== STARTING LEVEL DATA LOAD ==================\n" ));
2051 game_loading_callback_init();
2053 event_music_level_init(); // preloads the first 2 seconds for each event music track
2056 gamesnd_unload_interface_sounds(); // unload interface sounds from memory
2059 gamesnd_preload_common_sounds(); // load in sounds that are expected to play
2062 ship_assign_sound_all(); // assign engine sounds to ships
2063 game_assign_sound_environment(); // assign the sound environment for this mission
2066 // call function in missionparse.cpp to fixup player/ai stuff.
2067 mission_parse_fixup_players();
2070 // Load in all the bitmaps for this level
2075 game_loading_callback_close();
2077 // the only thing we need to call on the standalone for now.
2079 // call function in missionparse.cpp to fixup player/ai stuff.
2080 mission_parse_fixup_players();
2082 // Load in all the bitmaps for this level
2088 uint load_mission_load;
2089 uint load_post_level_init;
2090 uint load_mission_stuff;
2092 // tells the server to load the mission and initialize structures
2093 int game_start_mission()
2095 mprintf(( "=================== STARTING LEVEL LOAD ==================\n" ));
2097 load_gl_init = time(NULL);
2099 load_gl_init = time(NULL) - load_gl_init;
2101 if (Game_mode & GM_MULTIPLAYER) {
2102 Player->flags |= PLAYER_FLAGS_IS_MULTI;
2104 // clear multiplayer stats
2105 init_multiplayer_stats();
2108 load_mission_load = time(NULL);
2109 if (mission_load()) {
2110 if ( !(Game_mode & GM_MULTIPLAYER) ) {
2111 popup(PF_BODY_BIG, 1, POPUP_OK, XSTR( "Attempt to load the mission failed", 169));
2112 gameseq_post_event(GS_EVENT_MAIN_MENU);
2114 multi_quit_game(PROMPT_NONE, MULTI_END_NOTIFY_NONE, MULTI_END_ERROR_LOAD_FAIL);
2119 load_mission_load = time(NULL) - load_mission_load;
2121 // If this is a red alert mission in campaign mode, bash wingman status
2122 if ( (Game_mode & GM_CAMPAIGN_MODE) && red_alert_mission() ) {
2123 red_alert_bash_wingman_status();
2126 // the standalone server in multiplayer doesn't do any rendering, so we will not even bother loading the palette
2127 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
2128 mprintf(( "=================== LOADING GAME PALETTE ================\n" ));
2130 game_load_palette();
2134 load_post_level_init = time(NULL);
2135 game_post_level_init();
2136 load_post_level_init = time(NULL) - load_post_level_init;
2140 void Do_model_timings_test();
2141 Do_model_timings_test();
2145 load_mission_stuff = time(NULL);
2146 freespace_mission_load_stuff();
2147 load_mission_stuff = time(NULL) - load_mission_stuff;
2152 int Interface_framerate = 0;
2155 DCF_BOOL( mouse_control, Use_mouse_to_fly )
2156 DCF_BOOL( show_framerate, Show_framerate )
2157 DCF_BOOL( show_target_debug_info, Show_target_debug_info )
2158 DCF_BOOL( show_target_weapons, Show_target_weapons )
2159 DCF_BOOL( lead_target_cheat, Players[Player_num].lead_target_cheat )
2160 DCF_BOOL( sound, Sound_enabled )
2161 DCF_BOOL( zbuffer, game_zbuffer )
2162 DCF_BOOL( shield_system, New_shield_system )
2163 DCF_BOOL( show_shield_mesh, Show_shield_mesh)
2164 DCF_BOOL( player_attacking, Player_attacking_enabled )
2165 DCF_BOOL( show_waypoints, Show_waypoints )
2166 DCF_BOOL( show_area_effect, Show_area_effect )
2167 DCF_BOOL( show_net_stats, Show_net_stats )
2168 DCF_BOOL( log, Log_debug_output_to_file )
2169 DCF_BOOL( training_msg_method, Training_msg_method )
2170 DCF_BOOL( show_player_pos, Show_player_pos )
2171 DCF_BOOL(i_framerate, Interface_framerate )
2173 DCF(show_mem,"Toggles showing mem usage")
2176 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2177 if ( Dc_arg_type & ARG_TRUE ) Show_mem = 1;
2178 else if ( Dc_arg_type & ARG_FALSE ) Show_mem = 0;
2179 else if ( Dc_arg_type & ARG_NONE ) Show_mem ^= 1;
2185 if ( Dc_help ) dc_printf( "Usage: Show_mem\nSets show_mem to true or false. If nothing passed, then toggles it.\n" );
2187 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2188 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2192 DCF(show_cpu,"Toggles showing cpu usage")
2195 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2196 if ( Dc_arg_type & ARG_TRUE ) Show_cpu = 1;
2197 else if ( Dc_arg_type & ARG_FALSE ) Show_cpu = 0;
2198 else if ( Dc_arg_type & ARG_NONE ) Show_cpu ^= 1;
2204 if ( Dc_help ) dc_printf( "Usage: Show_cpu\nSets show_cpu to true or false. If nothing passed, then toggles it.\n" );
2206 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2207 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2214 // AL 4-8-98: always allow players to display their framerate
2217 DCF_BOOL( show_framerate, Show_framerate )
2224 DCF(use_joy_mouse,"Makes joystick move mouse cursor")
2227 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2228 if ( Dc_arg_type & ARG_TRUE ) Use_joy_mouse = 1;
2229 else if ( Dc_arg_type & ARG_FALSE ) Use_joy_mouse = 0;
2230 else if ( Dc_arg_type & ARG_NONE ) Use_joy_mouse ^= 1;
2232 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" );
2233 if ( Dc_status ) dc_printf( "use_joy_mouse is %s\n", (Use_joy_mouse?"TRUE":"FALSE") );
2235 os_config_write_uint( NULL, NOX("JoystickMovesCursor"), Use_joy_mouse );
2238 DCF(palette_flash,"Toggles palette flash effect on/off")
2241 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2242 if ( Dc_arg_type & ARG_TRUE ) Use_palette_flash = 1;
2243 else if ( Dc_arg_type & ARG_FALSE ) Use_palette_flash = 0;
2244 else if ( Dc_arg_type & ARG_NONE ) Use_palette_flash ^= 1;
2246 if ( Dc_help ) dc_printf( "Usage: palette_flash [bool]\nSets palette_flash to true or false. If nothing passed, then toggles it.\n" );
2247 if ( Dc_status ) dc_printf( "palette_flash is %s\n", (Use_palette_flash?"TRUE":"FALSE") );
2250 int Use_low_mem = 0;
2252 DCF(low_mem,"Uses low memory settings regardless of RAM")
2255 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2256 if ( Dc_arg_type & ARG_TRUE ) Use_low_mem = 1;
2257 else if ( Dc_arg_type & ARG_FALSE ) Use_low_mem = 0;
2258 else if ( Dc_arg_type & ARG_NONE ) Use_low_mem ^= 1;
2260 if ( Dc_help ) dc_printf( "Usage: low_mem [bool]\nSets low_mem to true or false. If nothing passed, then toggles it.\n" );
2261 if ( Dc_status ) dc_printf( "low_mem is %s\n", (Use_low_mem?"TRUE":"FALSE") );
2263 os_config_write_uint( NULL, NOX("LowMem"), Use_low_mem );
2269 DCF(force_fullscreen, "Forces game to startup in fullscreen mode")
2272 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2273 if ( Dc_arg_type & ARG_TRUE ) Use_fullscreen_at_startup = 1;
2274 else if ( Dc_arg_type & ARG_FALSE ) Use_fullscreen_at_startup = 0;
2275 else if ( Dc_arg_type & ARG_NONE ) Use_fullscreen_at_startup ^= 1;
2277 if ( Dc_help ) dc_printf( "Usage: force_fullscreen [bool]\nSets force_fullscreen to true or false. If nothing passed, then toggles it.\n" );
2278 if ( Dc_status ) dc_printf( "force_fullscreen is %s\n", (Use_fullscreen_at_startup?"TRUE":"FALSE") );
2279 os_config_write_uint( NULL, NOX("ForceFullscreen"), Use_fullscreen_at_startup );
2283 int Framerate_delay = 0;
2285 float Freespace_gamma = 1.0f;
2287 DCF(gamma,"Sets Gamma factor")
2290 dc_get_arg(ARG_FLOAT|ARG_NONE);
2291 if ( Dc_arg_type & ARG_FLOAT ) {
2292 Freespace_gamma = Dc_arg_float;
2294 dc_printf( "Gamma reset to 1.0f\n" );
2295 Freespace_gamma = 1.0f;
2297 if ( Freespace_gamma < 0.1f ) {
2298 Freespace_gamma = 0.1f;
2299 } else if ( Freespace_gamma > 5.0f ) {
2300 Freespace_gamma = 5.0f;
2302 gr_set_gamma(Freespace_gamma);
2304 char tmp_gamma_string[32];
2305 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2306 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2310 dc_printf( "Usage: gamma <float>\n" );
2311 dc_printf( "Sets gamma in range 1-3, no argument resets to default 1.2\n" );
2312 Dc_status = 0; // don't print status if help is printed. Too messy.
2316 dc_printf( "Gamma = %.2f\n", Freespace_gamma );
2325 Game_current_mission_filename[0] = 0;
2327 // seed the random number generator
2328 Game_init_seed = time(NULL);
2329 srand( Game_init_seed );
2331 Framerate_delay = 0;
2337 extern void bm_init();
2343 // Initialize the timer before the os
2351 GetCurrentDirectory(1024, whee);
2354 getcwd (whee, 1024);
2357 strcat(whee, EXE_FNAME);
2359 //Initialize the libraries
2360 s1 = timer_get_milliseconds();
2361 if(cfile_init(whee, Game_CDROM_dir)){ // initialize before calling any cfopen stuff!!!
2364 e1 = timer_get_milliseconds();
2366 // time a bunch of cfopens
2368 s2 = timer_get_milliseconds();
2370 for(int idx=0; idx<10000; idx++){
2371 whee = cfopen("capital01.pof", "rb", CFILE_NORMAL, CF_TYPE_MODELS);
2376 //cf_exist("capital01.pof", CF_TYPE_MODELS);
2378 e2 = timer_get_milliseconds();
2381 if (Is_standalone) {
2382 std_init_standalone();
2384 os_init( Osreg_class_name, Osreg_app_name );
2385 os_set_title(Osreg_title);
2388 // initialize localization module. Make sure this is down AFTER initialzing OS.
2389 // int t1 = timer_get_milliseconds();
2390 lcl_init( detect_lang() );
2392 // mprintf(("LCL_INIT() TOOK %d MS\n", timer_get_milliseconds()-t1));
2394 // verify that he has a valid ships.tbl (will Game_ships_tbl_valid if so)
2397 // verify that he has a valid weapons.tbl
2398 verify_weapons_tbl();
2400 // Output version numbers to registry for auto patching purposes
2401 os_config_write_uint(NOX("Version"), NOX("Major"), FS_VERSION_MAJOR);
2402 os_config_write_uint(NOX("Version"), NOX("Minor"), FS_VERSION_MINOR);
2403 os_config_write_uint(NOX("Version"), NOX("Build"), FS_VERSION_BUILD);
2405 Use_joy_mouse = 0; //os_config_read_uint( NULL, NOX("JoystickMovesCursor"), 1 );
2406 //Use_palette_flash = os_config_read_uint( NULL, NOX("PaletteFlash"), 0 );
2407 Use_low_mem = os_config_read_uint( NULL, NOX("LowMem"), 0 );
2410 Use_fullscreen_at_startup = os_config_read_uint( NULL, NOX("ForceFullscreen"), 1 );
2413 #if defined (PLAT_UNIX) && defined(RELEASE_REAL)
2414 // show the FPS counter if the config file says so
2415 Show_framerate = os_config_read_uint( NULL, NOX("ShowFPS"), 0 );
2418 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
2419 Asteroids_enabled = 1;
2422 /////////////////////////////
2424 /////////////////////////////
2429 ptr = os_config_read_string(NULL, NOX("Soundcard"), NULL);
2430 mprintf(("soundcard = %s\n", ptr ? ptr : "<nothing>"));
2432 if (!stricmp(ptr, NOX("no sound"))) {
2433 Cmdline_freespace_no_sound = 1;
2435 } else if (!stricmp(ptr, NOX("Aureal A3D"))) {
2437 } else if (!stricmp(ptr, NOX("EAX"))) {
2442 if (!Is_standalone) {
2443 snd_init(use_a3d, use_eax);
2445 /////////////////////////////
2447 /////////////////////////////
2449 ptr = os_config_read_string(NULL, NOX("Videocard"), NULL);
2452 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);
2454 // fire up the UpdateLauncher executable
2456 PROCESS_INFORMATION pi;
2458 memset( &si, 0, sizeof(STARTUPINFO) );
2461 BOOL ret = CreateProcess( LAUNCHER_FNAME, // pointer to name of executable module
2462 NULL, // pointer to command line string
2463 NULL, // pointer to process security attributes
2464 NULL, // pointer to thread security attributes
2465 FALSE, // handle inheritance flag
2466 CREATE_DEFAULT_ERROR_MODE, // creation flags
2467 NULL, // pointer to new environment block
2468 NULL, // pointer to current directory name
2469 &si, // pointer to STARTUPINFO
2470 &pi // pointer to PROCESS_INFORMATION
2473 // If the Launcher could not be started up, let the user know
2475 MessageBox((HWND)os_get_window(), XSTR("The Launcher could not be restarted.", 1450), XSTR("Error", 1451), MB_OK);
2484 if(!stricmp(ptr, "Aucune accélération 3D") || !stricmp(ptr, "Keine 3D-Beschleunigerkarte") || !stricmp(ptr, "No 3D acceleration")){
2486 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);
2494 // check for hi res pack file
2495 int has_sparky_hi = 0;
2497 // check if sparky_hi exists -- access mode 0 means does file exist
2498 #ifndef MAKE_FS1 // shoudn't have it so don't check
2501 if ( _access("sparky_hi_fs2.vp", 0) == 0) {
2504 mprintf(("No sparky_hi_fs2.vp in directory %s\n", dir));
2508 // see if we've got 32 bit in the string
2509 if(strstr(ptr, "32 bit")){
2516 if (!Is_standalone && ptr && (strstr(ptr, NOX("3DFX Glide")))) {
2518 // always 640 for E3
2519 gr_init(GR_640, GR_GLIDE);
2521 // regular or hi-res ?
2523 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2525 if(strstr(ptr, NOX("(1024x768)"))){
2527 gr_init(GR_1024, GR_GLIDE);
2529 gr_init(GR_640, GR_GLIDE);
2532 } else if (!Is_standalone && ptr && (strstr(ptr, NOX("Direct 3D -") ))) {
2534 // always 640 for E3
2536 gr_init(GR_640, GR_DIRECT3D, depth);
2538 // regular or hi-res ?
2540 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2542 if(strstr(ptr, NOX("(1024x768)"))){
2546 gr_init(GR_1024, GR_DIRECT3D, depth);
2550 gr_init(GR_640, GR_DIRECT3D, depth);
2556 if ( Use_fullscreen_at_startup && !Is_standalone) {
2557 gr_init(GR_640, GR_DIRECTDRAW);
2559 gr_init(GR_640, GR_SOFTWARE);
2562 if ( !Is_standalone ) {
2563 gr_init(GR_640, GR_DIRECTDRAW);
2565 gr_init(GR_640, GR_SOFTWARE);
2570 if (!Is_standalone /* && ptr && (strstr(ptr, NOX("OpenGL"))) */) {
2571 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2572 gr_init(GR_1024, GR_OPENGL);
2574 gr_init(GR_640, GR_OPENGL);
2578 gr_init(GR_640, GR_SOFTWARE);
2580 #endif // !PLAT_UNIX
2583 extern int Gr_inited;
2584 if(trying_d3d && !Gr_inited){
2586 extern char Device_init_error[512];
2587 MessageBox( NULL, Device_init_error, "Error intializing Direct3D", MB_OK|MB_TASKMODAL|MB_SETFOREGROUND );
2596 ptr = os_config_read_string(NULL,NOX("Gamma"),NOX("1.80"));
2597 Freespace_gamma = (float)atof(ptr);
2598 if ( Freespace_gamma == 0.0f ) {
2599 Freespace_gamma = 1.80f;
2600 } else if ( Freespace_gamma < 0.1f ) {
2601 Freespace_gamma = 0.1f;
2602 } else if ( Freespace_gamma > 5.0f ) {
2603 Freespace_gamma = 5.0f;
2605 char tmp_gamma_string[32];
2606 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2607 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2609 gr_set_gamma(Freespace_gamma);
2611 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
2614 display_title_screen();
2618 // attempt to load up master tracker registry info (login and password)
2619 Multi_tracker_id = -1;
2621 // pxo login and password
2622 ptr = os_config_read_string(NOX("PXO"),NOX("Login"),NULL);
2624 nprintf(("Network","Error reading in PXO login data\n"));
2625 strcpy(Multi_tracker_login,"");
2627 strcpy(Multi_tracker_login,ptr);
2629 ptr = os_config_read_string(NOX("PXO"),NOX("Password"),NULL);
2631 nprintf(("Network","Error reading PXO password\n"));
2632 strcpy(Multi_tracker_passwd,"");
2634 strcpy(Multi_tracker_passwd,ptr);
2637 // pxo squad name and password
2638 ptr = os_config_read_string(NOX("PXO"),NOX("SquadName"),NULL);
2640 nprintf(("Network","Error reading in PXO squad name\n"));
2641 strcpy(Multi_tracker_squad_name, "");
2643 strcpy(Multi_tracker_squad_name, ptr);
2646 // If less than 48MB of RAM, use low memory model.
2649 (Freespace_total_ram < 48*1024*1024) ||
2652 mprintf(( "Using normal memory settings...\n" ));
2653 bm_set_low_mem(1); // Use every other frame of bitmaps
2655 mprintf(( "Using high memory settings...\n" ));
2656 bm_set_low_mem(0); // Use all frames of bitmaps
2659 // load non-darkening pixel defs
2660 palman_load_pixels();
2662 // hud shield icon stuff
2663 hud_shield_game_init();
2665 control_config_common_init(); // sets up localization stuff in the control config
2671 gamesnd_parse_soundstbl();
2676 // standalone's don't use hte joystick and it seems to sometimes cause them to not get shutdown properly
2681 player_controls_init();
2684 //if(!Is_standalone){
2692 ship_init(); // read in ships.tbl
2694 mission_campaign_init(); // load in the default campaign
2696 // navmap_init(); // init the navigation map system
2697 context_help_init();
2698 techroom_intel_init(); // parse species.tbl, load intel info
2700 psnet_init( Multi_options_g.protocol, Multi_options_g.port ); // initialize the networking code
2701 init_animating_pointer();
2703 mission_brief_common_init(); // Mark all the briefing structures as empty.
2704 gr_font_init(); // loads up all fonts
2706 neb2_init(); // fullneb stuff
2710 player_tips_init(); // helpful tips
2713 // load the list of pilot pic filenames (for barracks and pilot select popup quick reference)
2714 pilot_load_pic_list();
2715 pilot_load_squad_pic_list();
2717 load_animating_pointer(NOX("cursor"), 0, 0);
2719 // initialize alpha colors
2720 alpha_colors_init();
2723 // Game_music_paused = 0;
2730 nprintf(("General", "Ships.tbl is : %s\n", Game_ships_tbl_valid ? "VALID" : "INVALID!!!!"));
2731 nprintf(("General", "Weapons.tbl is : %s\n", Game_weapons_tbl_valid ? "VALID" : "INVALID!!!!"));
2733 mprintf(("cfile_init() took %d\n", e1 - s1));
2734 // mprintf(("1000 cfopens() took %d\n", e2 - s2));
2737 char transfer_text[128];
2739 float Start_time = 0.0f;
2741 float Framerate = 0.0f;
2743 float Timing_total = 0.0f;
2744 float Timing_render2 = 0.0f;
2745 float Timing_render3 = 0.0f;
2746 float Timing_flip = 0.0f;
2747 float Timing_clear = 0.0f;
2749 MONITOR(NumPolysDrawn);
2755 void game_get_framerate()
2757 char text[128] = "";
2759 if ( frame_int == -1 ) {
2761 for (i=0; i<FRAME_FILTER; i++ ) {
2762 frametimes[i] = 0.0f;
2767 frametotal -= frametimes[frame_int];
2768 frametotal += flFrametime;
2769 frametimes[frame_int] = flFrametime;
2770 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2772 if ( frametotal != 0.0 ) {
2773 if ( Framecount >= FRAME_FILTER )
2774 Framerate = FRAME_FILTER / frametotal;
2776 Framerate = Framecount / frametotal;
2777 sprintf( text, NOX("FPS: %.1f"), Framerate );
2779 sprintf( text, NOX("FPS: ?") );
2783 if (Show_framerate) {
2784 gr_set_color_fast(&HUD_color_debug);
2785 gr_string( 570, 2, text );
2789 void game_show_framerate()
2793 cur_time = f2fl(timer_get_approx_seconds());
2794 if (cur_time - Start_time > 30.0f) {
2795 mprintf(("%i frames executed in %7.3f seconds, %7.3f frames per second.\n", Framecount, cur_time - Start_time, Framecount/(cur_time - Start_time)));
2796 Start_time += 1000.0f;
2799 //mprintf(( "%s\n", text ));
2802 if ( Debug_dump_frames )
2806 // possibly show control checking info
2807 control_check_indicate();
2809 // int bitmaps_used_this_frame, bitmaps_new_this_frame;
2810 // bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
2811 // MONITOR_INC(BmpUsed, bitmaps_used_this_frame);
2812 // MONITOR_INC(BmpNew, bitmaps_new_this_frame);
2815 if ( Show_cpu == 1 ) {
2820 dy = gr_get_font_height() + 1;
2822 gr_set_color_fast(&HUD_color_debug);
2826 extern int D3D_textures_in;
2827 extern int D3D_textures_in_frame;
2828 extern int Glide_textures_in;
2829 extern int Glide_textures_in_frame;
2830 extern int Glide_explosion_vram;
2831 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2833 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame+D3D_textures_in_frame)/1024 );
2835 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2839 // gr_printf( sx, sy, "BPP: %d", gr_screen.bits_per_pixel );
2841 gr_printf( sx, sy, NOX("DMA: %s"), transfer_text );
2843 gr_printf( sx, sy, NOX("POLYP: %d"), modelstats_num_polys );
2845 gr_printf( sx, sy, NOX("POLYD: %d"), modelstats_num_polys_drawn );
2847 gr_printf( sx, sy, NOX("VERTS: %d"), modelstats_num_verts );
2852 extern int Num_pairs; // Number of object pairs that were checked.
2853 gr_printf( sx, sy, NOX("PAIRS: %d"), Num_pairs );
2856 extern int Num_pairs_checked; // What percent of object pairs were checked.
2857 gr_printf( sx, sy, NOX("FVI: %d"), Num_pairs_checked );
2859 Num_pairs_checked = 0;
2863 gr_printf( sx, sy, NOX("Snds: %d"), snd_num_playing() );
2866 if ( Timing_total > 0.01f ) {
2867 gr_printf( sx, sy, NOX("CLEAR: %.0f%%"), Timing_clear*100.0f/Timing_total );
2869 gr_printf( sx, sy, NOX("REND2D: %.0f%%"), Timing_render2*100.0f/Timing_total );
2871 gr_printf( sx, sy, NOX("REND3D: %.0f%%"), Timing_render3*100.0f/Timing_total );
2873 gr_printf( sx, sy, NOX("FLIP: %.0f%%"), Timing_flip*100.0f/Timing_total );
2875 gr_printf( sx, sy, NOX("GAME: %.0f%%"), (Timing_total-(Timing_render2+Timing_render3+Timing_flip+Timing_clear))*100.0f/Timing_total );
2885 dy = gr_get_font_height() + 1;
2887 gr_set_color_fast(&HUD_color_debug);
2890 extern int TotalRam;
2891 gr_printf( sx, sy, NOX("DYN: %d KB\n"), TotalRam/1024 );
2896 extern int Model_ram;
2897 gr_printf( sx, sy, NOX("POF: %d KB\n"), Model_ram/1024 );
2901 gr_printf( sx, sy, NOX("BMP: %d KB\n"), bm_texture_ram/1024 );
2903 gr_printf( sx, sy, NOX("S-SRAM: %d KB\n"), Snd_sram/1024 ); // mem used to store game sound
2905 gr_printf( sx, sy, NOX("S-HRAM: %d KB\n"), Snd_hram/1024 ); // mem used to store game sound
2909 extern int D3D_textures_in;
2910 extern int Glide_textures_in;
2911 extern int Glide_textures_in_frame;
2912 extern int Glide_explosion_vram;
2913 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2915 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame)/1024 );
2917 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2924 if ( Show_player_pos ) {
2928 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));
2931 MONITOR_INC(NumPolys, modelstats_num_polys);
2932 MONITOR_INC(NumPolysDrawn, modelstats_num_polys_drawn );
2933 MONITOR_INC(NumVerts, modelstats_num_verts );
2935 modelstats_num_polys = 0;
2936 modelstats_num_polys_drawn = 0;
2937 modelstats_num_verts = 0;
2938 modelstats_num_sortnorms = 0;
2942 void game_show_standalone_framerate()
2944 float frame_rate=30.0f;
2945 if ( frame_int == -1 ) {
2947 for (i=0; i<FRAME_FILTER; i++ ) {
2948 frametimes[i] = 0.0f;
2953 frametotal -= frametimes[frame_int];
2954 frametotal += flFrametime;
2955 frametimes[frame_int] = flFrametime;
2956 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2958 if ( frametotal != 0.0 ) {
2959 if ( Framecount >= FRAME_FILTER ){
2960 frame_rate = FRAME_FILTER / frametotal;
2962 frame_rate = Framecount / frametotal;
2965 std_set_standalone_fps(frame_rate);
2969 // function to show the time remaining in a mission. Used only when the end-mission sexpression is used
2970 void game_show_time_left()
2974 // mission_end_time is a global from missionparse.cpp that contains the mission time at which the
2975 // mission should end (in fixed seconds). There is code in missionparse.cpp which actually handles
2976 // checking how much time is left
2978 if ( Mission_end_time == -1 ){
2982 diff = f2i(Mission_end_time - Missiontime);
2983 // be sure to bash to 0. diff could be negative on frame that we quit mission
2988 hud_set_default_color();
2989 gr_printf( 5, 40, XSTR( "Mission time remaining: %d seconds", 179), diff );
2992 //========================================================================================
2993 //=================== NEW DEBUG CONSOLE COMMANDS TO REPLACE OLD DEBUG PAUSE MENU =========
2994 //========================================================================================
2998 DCF(ai_pause,"Pauses ai")
3001 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
3002 if ( Dc_arg_type & ARG_TRUE ) ai_paused = 1;
3003 else if ( Dc_arg_type & ARG_FALSE ) ai_paused = 0;
3004 else if ( Dc_arg_type & ARG_NONE ) ai_paused = !ai_paused;
3007 obj_init_all_ships_physics();
3010 if ( Dc_help ) dc_printf( "Usage: ai_paused [bool]\nSets ai_paused to true or false. If nothing passed, then toggles it.\n" );
3011 if ( Dc_status ) dc_printf( "ai_paused is %s\n", (ai_paused?"TRUE":"FALSE") );
3014 DCF(single_step,"Single steps the game")
3017 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
3018 if ( Dc_arg_type & ARG_TRUE ) game_single_step = 1;
3019 else if ( Dc_arg_type & ARG_FALSE ) game_single_step = 0;
3020 else if ( Dc_arg_type & ARG_NONE ) game_single_step = !game_single_step;
3022 last_single_step = 0; // Make so single step waits a frame before stepping
3025 if ( Dc_help ) dc_printf( "Usage: single_step [bool]\nSets single_step to true or false. If nothing passed, then toggles it.\n" );
3026 if ( Dc_status ) dc_printf( "single_step is %s\n", (game_single_step?"TRUE":"FALSE") );
3029 DCF_BOOL(physics_pause, physics_paused)
3030 DCF_BOOL(ai_rendering, Ai_render_debug_flag)
3031 DCF_BOOL(ai_firing, Ai_firing_enabled )
3033 // Create some simple aliases to these commands...
3034 debug_command dc_s("s","shortcut for single_step",dcf_single_step);
3035 debug_command dc_p("p","shortcut for physics_pause", dcf_physics_pause );
3036 debug_command dc_r("r","shortcut for ai_rendering", dcf_ai_rendering );
3037 debug_command dc_f("f","shortcut for ai_firing", dcf_ai_firing);
3038 debug_command dc_a("a","shortcut for ai_pause", dcf_ai_pause);
3041 //========================================================================================
3042 //========================================================================================
3045 void game_training_pause_do()
3049 key = game_check_key();
3051 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
3058 void game_increase_skill_level()
3061 if (Game_skill_level >= NUM_SKILL_LEVELS){
3062 Game_skill_level = 0;
3066 int Player_died_time;
3068 int View_percent = 100;
3071 DCF(view, "Sets the percent of the 3d view to render.")
3074 dc_get_arg(ARG_INT);
3075 if ( (Dc_arg_int >= 5 ) || (Dc_arg_int <= 100) ) {
3076 View_percent = Dc_arg_int;
3078 dc_printf( "Illegal value for view. (Must be from 5-100) \n\n");
3084 dc_printf("Usage: view [n]\nwhere n is percent of view to show (5-100).\n");
3088 dc_printf("View is set to %d%%\n", View_percent );
3093 // Set the clip region for the 3d rendering window
3094 void game_set_view_clip()
3096 if ((Game_mode & GM_DEAD) || (supernova_active() >= 2)) {
3097 // Set the clip region for the letterbox "dead view"
3098 int yborder = gr_screen.max_h/4;
3100 // Numeric constants encouraged by J "pig farmer" S, who shall remain semi-anonymous.
3101 // J.S. I've changed my ways!! See the new "no constants" code!!!
3102 gr_set_clip(0, yborder, gr_screen.max_w, gr_screen.max_h - yborder*2 );
3104 // Set the clip region for normal view
3105 if ( View_percent >= 100 ) {
3108 int xborder, yborder;
3110 if ( View_percent < 5 ) {
3114 float fp = i2fl(View_percent)/100.0f;
3115 int fi = fl2i(fl_sqrt(fp)*100.0f);
3116 if ( fi > 100 ) fi=100;
3118 xborder = ( gr_screen.max_w*(100-fi) )/200;
3119 yborder = ( gr_screen.max_h*(100-fi) )/200;
3121 gr_set_clip(xborder, yborder, gr_screen.max_w-xborder*2,gr_screen.max_h-yborder*2 );
3127 void show_debug_stuff()
3130 int laser_count = 0, missile_count = 0;
3132 for (i=0; i<MAX_OBJECTS; i++) {
3133 if (Objects[i].type == OBJ_WEAPON){
3134 if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_LASER){
3136 } else if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_MISSILE){
3142 nprintf(("Mike", "Frame: %i Lasers: %4i, Missiles: %4i\n", Framecount, laser_count, missile_count));
3145 extern int Tool_enabled;
3150 int tst_bitmap = -1;
3152 float tst_offset, tst_offset_total;
3155 void game_tst_frame_pre()
3163 g3_rotate_vertex(&v, &tst_pos);
3164 g3_project_vertex(&v);
3167 if(!((v.sx >= 0) && (v.sx <= gr_screen.max_w) && (v.sy >= 0) && (v.sy <= gr_screen.max_h))){
3171 // big ship? always tst
3173 // within 3000 meters
3174 if( vm_vec_dist_quick(&tst_pos, &Eye_position) <= 3000.0f){
3178 // within 300 meters
3179 if( (vm_vec_dist_quick(&tst_pos, &Eye_position) <= 300.0f) && ((tst_time == 0) || ((time(NULL) - tst_time) >= 10)) ){
3186 void game_tst_frame()
3196 tst_time = time(NULL);
3198 // load the tst bitmap
3199 switch((int)frand_range(0.0f, 3.0)){
3201 tst_bitmap = bm_load("ig_jim");
3203 mprintf(("TST 0\n"));
3207 tst_bitmap = bm_load("ig_kan");
3209 mprintf(("TST 1\n"));
3213 tst_bitmap = bm_load("ig_jim");
3215 mprintf(("TST 2\n"));
3219 tst_bitmap = bm_load("ig_kan");
3221 mprintf(("TST 3\n"));
3230 // get the tst bitmap dimensions
3232 bm_get_info(tst_bitmap, &w, &h);
3235 tst_y = frand_range(0.0f, (float)gr_screen.max_h - h);
3237 snd_play(&Snds[SND_VASUDAN_BUP]);
3239 // tst x and direction
3243 tst_offset_total = (float)w;
3244 tst_offset = (float)w;
3246 tst_x = (float)gr_screen.max_w;
3247 tst_offset_total = (float)-w;
3248 tst_offset = (float)w;
3256 float diff = (tst_offset_total / 0.5f) * flFrametime;
3262 tst_offset -= fl_abs(diff);
3263 } else if(tst_mode == 2){
3266 tst_offset -= fl_abs(diff);
3270 gr_set_bitmap(tst_bitmap);
3271 gr_bitmap((int)tst_x, (int)tst_y);
3274 if(timestamp_elapsed_safe(tst_stamp, 1100)){
3278 // if we passed the switch point
3279 if(tst_offset <= 0.0f){
3284 tst_stamp = timestamp(1000);
3285 tst_offset = fl_abs(tst_offset_total);
3296 void game_tst_mark(object *objp, ship *shipp)
3305 if((objp == NULL) || (shipp == NULL) || (shipp->ship_info_index < 0) || (shipp->ship_info_index >= Num_ship_types)){
3308 sip = &Ship_info[shipp->ship_info_index];
3315 tst_pos = objp->pos;
3316 if(sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)){
3322 extern void render_shields();
3324 void player_repair_frame(float frametime)
3326 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
3328 for(idx=0;idx<MAX_PLAYERS;idx++){
3331 np = &Net_players[idx];
3333 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)){
3335 // don't rearm/repair if the player is dead or dying/departing
3336 if ( !NETPLAYER_IS_DEAD(np) && !(Ships[Objects[np->player->objnum].instance].flags & (SF_DYING|SF_DEPARTING)) ) {
3337 ai_do_repair_frame(&Objects[Net_players[idx].player->objnum],&Ai_info[Ships[Objects[Net_players[idx].player->objnum].instance].ai_index],frametime);
3342 if ( (Player_obj != NULL) && (Player_obj->type == OBJ_SHIP) && !(Game_mode & GM_STANDALONE_SERVER) && (Player_ship != NULL) && !(Player_ship->flags & SF_DYING) ) {
3343 ai_do_repair_frame(Player_obj, &Ai_info[Ships[Player_obj->instance].ai_index], frametime);
3349 #define NUM_FRAMES_TEST 300
3350 #define NUM_MIXED_SOUNDS 16
3351 void do_timing_test(float flFrametime)
3353 static int framecount = 0;
3354 static int test_running = 0;
3355 static float test_time = 0.0f;
3357 static int snds[NUM_MIXED_SOUNDS];
3360 if ( test_running ) {
3362 test_time += flFrametime;
3363 if ( framecount >= NUM_FRAMES_TEST ) {
3365 nprintf(("General", "%d frames took %.3f seconds\n", NUM_FRAMES_TEST, test_time));
3366 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3371 if ( Test_begin == 1 ) {
3377 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3380 // start looping digital sounds
3381 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3382 snds[i] = snd_play_looping( &Snds[i], 0.0f, -1, -1);
3389 DCF(dcf_fov, "Change the field of view")
3392 dc_get_arg(ARG_FLOAT|ARG_NONE);
3393 if ( Dc_arg_type & ARG_NONE ) {
3394 Viewer_zoom = VIEWER_ZOOM_DEFAULT;
3395 dc_printf( "Zoom factor reset\n" );
3397 if ( Dc_arg_type & ARG_FLOAT ) {
3398 if (Dc_arg_float < 0.25f) {
3399 Viewer_zoom = 0.25f;
3400 dc_printf("Zoom factor pinned at 0.25.\n");
3401 } else if (Dc_arg_float > 1.25f) {
3402 Viewer_zoom = 1.25f;
3403 dc_printf("Zoom factor pinned at 1.25.\n");
3405 Viewer_zoom = Dc_arg_float;
3411 dc_printf( "Usage: fov [factor]\nFactor is the zoom factor btwn .25 and 1.25\nNo parameter resets it to default.\n" );
3414 dc_printf("Zoom factor set to %6.3f (original = 0.5, John = 0.75)", Viewer_zoom);
3418 DCF(framerate_cap, "Sets the framerate cap")
3421 dc_get_arg(ARG_INT);
3422 if ( (Dc_arg_int >= 1 ) || (Dc_arg_int <= 120) ) {
3423 Framerate_cap = Dc_arg_int;
3425 dc_printf( "Illegal value for framerate cap. (Must be from 1-120) \n\n");
3431 dc_printf("Usage: framerate_cap [n]\nwhere n is the frames per second to cap framerate at.\n");
3432 dc_printf("If n is 0 or omitted, then the framerate cap is removed\n");
3433 dc_printf("[n] must be from 1 to 120.\n");
3437 if ( Framerate_cap )
3438 dc_printf("Framerate cap is set to %d fps\n", Framerate_cap );
3440 dc_printf("There is no framerate cap currently active.\n");
3444 #define MIN_DIST_TO_DEAD_CAMERA 50.0f
3445 int Show_viewing_from_self = 0;
3447 void say_view_target()
3449 object *view_target;
3451 if ((Viewer_mode & VM_OTHER_SHIP) && (Player_ai->target_objnum != -1))
3452 view_target = &Objects[Player_ai->target_objnum];
3454 view_target = Player_obj;
3456 if (Game_mode & GM_DEAD) {
3457 if (Player_ai->target_objnum != -1)
3458 view_target = &Objects[Player_ai->target_objnum];
3461 if (!(Game_mode & GM_DEAD_DIED) && ((Game_mode & (GM_DEAD_BLEW_UP)) || ((Last_view_target != NULL) && (Last_view_target != view_target)))) {
3462 if (view_target != Player_obj){
3464 char *view_target_name = NULL;
3465 switch(Objects[Player_ai->target_objnum].type) {
3467 view_target_name = Ships[Objects[Player_ai->target_objnum].instance].ship_name;
3470 view_target_name = Weapon_info[Weapons[Objects[Player_ai->target_objnum].instance].weapon_info_index].name;
3471 Viewer_mode &= ~VM_OTHER_SHIP;
3473 case OBJ_JUMP_NODE: {
3474 char jump_node_name[128];
3475 strcpy(jump_node_name, XSTR( "jump node", 184));
3476 view_target_name = jump_node_name;
3477 Viewer_mode &= ~VM_OTHER_SHIP;
3486 if ( view_target_name ) {
3487 HUD_fixed_printf(0.0f, XSTR( "Viewing %s%s\n", 185), (Viewer_mode & VM_OTHER_SHIP) ? XSTR( "from ", 186) : "", view_target_name);
3488 Show_viewing_from_self = 1;
3491 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER) && (Player_obj->type == OBJ_OBSERVER)){
3492 HUD_fixed_printf(2.0f,XSTR( "Viewing from observer\n", 187));
3493 Show_viewing_from_self = 1;
3495 if (Show_viewing_from_self)
3496 HUD_fixed_printf(2.0f, XSTR( "Viewing from self\n", 188));
3501 Last_view_target = view_target;
3505 float Game_hit_x = 0.0f;
3506 float Game_hit_y = 0.0f;
3508 // Reset at the beginning of each frame
3509 void game_whack_reset()
3515 // Apply a 2d whack to the player
3516 void game_whack_apply( float x, float y )
3518 // Do some force feedback
3519 joy_ff_play_dir_effect(x * 80.0f, y * 80.0f);
3525 // mprintf(( "WHACK = %.1f, %.1f\n", Game_hit_x, Game_hit_y ));
3528 // call to apply a "shudder"
3529 void game_shudder_apply(int time, float intensity)
3531 Game_shudder_time = timestamp(time);
3532 Game_shudder_total = time;
3533 Game_shudder_intensity = intensity;
3536 #define FF_SCALE 10000
3537 void apply_hud_shake(matrix *eye_orient)
3539 if (Viewer_obj == Player_obj) {
3540 physics_info *pi = &Player_obj->phys_info;
3548 // Make eye shake due to afterburner
3549 if ( !timestamp_elapsed(pi->afterburner_decay) ) {
3552 dtime = timestamp_until(pi->afterburner_decay);
3556 tangles.p += 0.07f * (float) (r1-RAND_MAX/2)/RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3557 tangles.h += 0.07f * (float) (r2-RAND_MAX/2)/RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3560 // Make eye shake due to engine wash
3562 if (Player_obj->type == OBJ_SHIP && (Ships[Player_obj->instance].wash_intensity > 0) && Wash_on ) {
3565 tangles.p += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r1-RAND_MAX/2)/RAND_MAX;
3566 tangles.h += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r2-RAND_MAX/2)/RAND_MAX;
3568 // get the intensity
3569 float intensity = FF_SCALE * Ships[Player_obj->instance].wash_intensity;
3573 vm_vec_rand_vec_quick(&rand_vec);
3576 joy_ff_play_dir_effect(intensity*rand_vec.xyz.x, intensity*rand_vec.xyz.y);
3580 // make hud shake due to shuddering
3581 if(Game_shudder_time != -1){
3582 // if the timestamp has elapsed
3583 if(timestamp_elapsed(Game_shudder_time)){
3584 Game_shudder_time = -1;
3586 // otherwise apply some shudder
3590 dtime = timestamp_until(Game_shudder_time);
3594 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));
3595 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));
3600 vm_angles_2_matrix(&tm, &tangles);
3601 Assert(vm_vec_mag(&tm.v.fvec) > 0.0f);
3602 Assert(vm_vec_mag(&tm.v.rvec) > 0.0f);
3603 Assert(vm_vec_mag(&tm.v.uvec) > 0.0f);
3604 vm_matrix_x_matrix(&tm2, eye_orient, &tm);
3609 extern void compute_slew_matrix(matrix *orient, angles *a); // TODO: move code to proper place and extern in header file
3611 // Player's velocity just before he blew up. Used to keep camera target moving.
3612 vector Dead_player_last_vel = {1.0f, 1.0f, 1.0f};
3614 // Set eye_pos and eye_orient based on view mode.
3615 void game_render_frame_setup(vector *eye_pos, matrix *eye_orient)
3619 static int last_Viewer_mode = 0;
3620 static int last_Game_mode = 0;
3621 static int last_Viewer_objnum = -1;
3623 // This code is supposed to detect camera "cuts"... like going between
3626 // determine if we need to regenerate the nebula
3627 if( (!(last_Viewer_mode & VM_EXTERNAL) && (Viewer_mode & VM_EXTERNAL)) || // internal to external
3628 ((last_Viewer_mode & VM_EXTERNAL) && !(Viewer_mode & VM_EXTERNAL)) || // external to internal
3629 (!(last_Viewer_mode & VM_DEAD_VIEW) && (Viewer_mode & VM_DEAD_VIEW)) || // non dead-view to dead-view
3630 ((last_Viewer_mode & VM_DEAD_VIEW) && !(Viewer_mode & VM_DEAD_VIEW)) || // dead-view to non dead-view
3631 (!(last_Viewer_mode & VM_WARP_CHASE) && (Viewer_mode & VM_WARP_CHASE)) || // non warp-chase to warp-chase
3632 ((last_Viewer_mode & VM_WARP_CHASE) && !(Viewer_mode & VM_WARP_CHASE)) || // warp-chase to non warp-chase
3633 (!(last_Viewer_mode & VM_OTHER_SHIP) && (Viewer_mode & VM_OTHER_SHIP)) || // non other-ship to other-ship
3634 ((last_Viewer_mode & VM_OTHER_SHIP) && !(Viewer_mode & VM_OTHER_SHIP)) || // other-ship to non-other ship
3635 ((Viewer_mode & VM_OTHER_SHIP) && (last_Viewer_objnum != Player_ai->target_objnum)) // other ship mode, but targets changes
3638 // regenerate the nebula
3642 if ( (last_Viewer_mode != Viewer_mode) || (last_Game_mode != Game_mode) ) {
3643 //mprintf(( "************** Camera cut! ************\n" ));
3644 last_Viewer_mode = Viewer_mode;
3645 last_Game_mode = Game_mode;
3647 // Camera moved. Tell stars & debris to not do blurring.
3653 if ( Viewer_mode & VM_PADLOCK_ANY ) {
3654 player_display_packlock_view();
3657 game_set_view_clip();
3659 if (Game_mode & GM_DEAD) {
3660 vector vec_to_deader, view_pos;
3663 Viewer_mode |= VM_DEAD_VIEW;
3665 if (Player_ai->target_objnum != -1) {
3666 int view_from_player = 1;
3668 if (Viewer_mode & VM_OTHER_SHIP) {
3669 // View from target.
3670 Viewer_obj = &Objects[Player_ai->target_objnum];
3672 last_Viewer_objnum = Player_ai->target_objnum;
3674 if ( Viewer_obj->type == OBJ_SHIP ) {
3675 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3676 view_from_player = 0;
3679 last_Viewer_objnum = -1;
3682 if ( view_from_player ) {
3683 // View target from player ship.
3685 *eye_pos = Player_obj->pos;
3686 vm_vec_normalized_dir(&eye_dir, &Objects[Player_ai->target_objnum].pos, eye_pos);
3687 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3690 dist = vm_vec_normalized_dir(&vec_to_deader, &Player_obj->pos, &Dead_camera_pos);
3692 if (dist < MIN_DIST_TO_DEAD_CAMERA)
3693 dist += flFrametime * 16.0f;
3695 vm_vec_scale(&vec_to_deader, -dist);
3696 vm_vec_add(&Dead_camera_pos, &Player_obj->pos, &vec_to_deader);
3698 view_pos = Player_obj->pos;
3700 if (!(Game_mode & GM_DEAD_BLEW_UP)) {
3701 Viewer_mode &= ~(VM_EXTERNAL | VM_CHASE);
3702 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, 25.0f * flFrametime);
3703 Dead_player_last_vel = Player_obj->phys_info.vel;
3704 //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));
3705 } else if (Player_ai->target_objnum != -1) {
3706 view_pos = Objects[Player_ai->target_objnum].pos;
3708 // Make camera follow explosion, but gradually slow down.
3709 vm_vec_scale_add2(&Player_obj->pos, &Dead_player_last_vel, flFrametime);
3710 view_pos = Player_obj->pos;
3711 vm_vec_scale(&Dead_player_last_vel, 0.99f);
3712 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, min(25.0f, vm_vec_mag_quick(&Dead_player_last_vel)) * flFrametime);
3715 *eye_pos = Dead_camera_pos;
3717 vm_vec_normalized_dir(&eye_dir, &Player_obj->pos, eye_pos);
3719 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3724 // if supernova shockwave
3725 if(supernova_camera_cut()){
3729 // call it dead view
3730 Viewer_mode |= VM_DEAD_VIEW;
3732 // set eye pos and orient
3733 supernova_set_view(eye_pos, eye_orient);
3735 // If already blown up, these other modes can override.
3736 if (!(Game_mode & (GM_DEAD | GM_DEAD_BLEW_UP))) {
3737 Viewer_mode &= ~VM_DEAD_VIEW;
3739 Viewer_obj = Player_obj;
3741 if (Viewer_mode & VM_OTHER_SHIP) {
3742 if (Player_ai->target_objnum != -1){
3743 Viewer_obj = &Objects[Player_ai->target_objnum];
3744 last_Viewer_objnum = Player_ai->target_objnum;
3746 Viewer_mode &= ~VM_OTHER_SHIP;
3747 last_Viewer_objnum = -1;
3750 last_Viewer_objnum = -1;
3753 if (Viewer_mode & VM_EXTERNAL) {
3756 vm_angles_2_matrix(&tm2, &Viewer_external_info.angles);
3757 vm_matrix_x_matrix(&tm, &Viewer_obj->orient, &tm2);
3759 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &tm.v.fvec, 2.0f * Viewer_obj->radius + Viewer_external_info.distance);
3761 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3762 vm_vec_normalize(&eye_dir);
3763 vm_vector_2_matrix(eye_orient, &eye_dir, &Viewer_obj->orient.v.uvec, NULL);
3766 // Modify the orientation based on head orientation.
3767 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3769 } else if ( Viewer_mode & VM_CHASE ) {
3772 if ( Viewer_obj->phys_info.speed < 0.1 )
3773 move_dir = Viewer_obj->orient.v.fvec;
3775 move_dir = Viewer_obj->phys_info.vel;
3776 vm_vec_normalize(&move_dir);
3779 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &move_dir, -3.0f * Viewer_obj->radius - Viewer_chase_info.distance);
3780 vm_vec_scale_add2(eye_pos, &Viewer_obj->orient.v.uvec, 0.75f * Viewer_obj->radius);
3781 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3782 vm_vec_normalize(&eye_dir);
3784 // JAS: I added the following code because if you slew up using
3785 // Descent-style physics, eye_dir and Viewer_obj->orient.v.uvec are
3786 // equal, which causes a zero-length vector in the vm_vector_2_matrix
3787 // call because the up and the forward vector are the same. I fixed
3788 // it by adding in a fraction of the right vector all the time to the
3790 vector tmp_up = Viewer_obj->orient.v.uvec;
3791 vm_vec_scale_add2( &tmp_up, &Viewer_obj->orient.v.rvec, 0.00001f );
3793 vm_vector_2_matrix(eye_orient, &eye_dir, &tmp_up, NULL);
3796 // Modify the orientation based on head orientation.
3797 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3798 } else if ( Viewer_mode & VM_WARP_CHASE ) {
3799 *eye_pos = Camera_pos;
3801 ship * shipp = &Ships[Player_obj->instance];
3803 vm_vec_sub(&eye_dir, &shipp->warp_effect_pos, eye_pos);
3804 vm_vec_normalize(&eye_dir);
3805 vm_vector_2_matrix(eye_orient, &eye_dir, &Player_obj->orient.v.uvec, NULL);
3808 // get an eye position based upon the correct type of object
3809 switch(Viewer_obj->type){
3811 // make a call to get the eye point for the player object
3812 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3815 // make a call to get the eye point for the player object
3816 observer_get_eye( eye_pos, eye_orient, Viewer_obj );
3822 #ifdef JOHNS_DEBUG_CODE
3823 john_debug_stuff(&eye_pos, &eye_orient);
3829 apply_hud_shake(eye_orient);
3831 // setup neb2 rendering
3832 neb2_render_setup(eye_pos, eye_orient);
3836 extern void ai_debug_render_stuff();
3839 int Game_subspace_effect = 0;
3840 DCF_BOOL( subspace, Game_subspace_effect );
3842 // Does everything needed to render a frame
3843 void game_render_frame( vector * eye_pos, matrix * eye_orient )
3847 g3_start_frame(game_zbuffer);
3848 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
3850 // maybe offset the HUD (jitter stuff)
3851 dont_offset = ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER));
3852 HUD_set_offsets(Viewer_obj, !dont_offset);
3854 // for multiplayer clients, call code in Shield.cpp to set up the Shield_hit array. Have to
3855 // do this becaues of the disjointed nature of this system (in terms of setup and execution).
3856 // must be done before ships are rendered
3857 if ( MULTIPLAYER_CLIENT ) {
3858 shield_point_multi_setup();
3861 if ( Game_subspace_effect ) {
3862 stars_draw(0,0,0,1);
3864 stars_draw(1,1,1,0);
3867 obj_render_all(obj_render);
3868 beam_render_all(); // render all beam weapons
3869 particle_render_all(); // render particles after everything else.
3870 trail_render_all(); // render missilie trails after everything else.
3871 mflash_render_all(); // render all muzzle flashes
3873 // Why do we not show the shield effect in these modes? Seems ok.
3874 //if (!(Viewer_mode & (VM_EXTERNAL | VM_SLEWED | VM_CHASE | VM_DEAD_VIEW))) {
3878 // render nebula lightning
3881 // render local player nebula
3882 neb2_render_player();
3885 ai_debug_render_stuff();
3888 #ifndef RELEASE_REAL
3889 // game_framerate_check();
3893 extern void snd_spew_debug_info();
3894 snd_spew_debug_info();
3897 //================ END OF 3D RENDERING STUFF ====================
3901 if( (Game_detail_flags & DETAIL_FLAG_HUD) && !(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) ) ) {
3902 hud_maybe_clear_head_area();
3903 anim_render_all(0, flFrametime);
3906 extern int Multi_display_netinfo;
3907 if(Multi_display_netinfo){
3908 extern void multi_display_netinfo();
3909 multi_display_netinfo();
3912 game_tst_frame_pre();
3915 do_timing_test(flFrametime);
3919 extern int OO_update_index;
3920 multi_rate_display(OO_update_index, 375, 0);
3925 extern void oo_display();
3932 //#define JOHNS_DEBUG_CODE 1
3934 #ifdef JOHNS_DEBUG_CODE
3935 void john_debug_stuff(vector *eye_pos, matrix *eye_orient)
3937 //if ( keyd_pressed[KEY_LSHIFT] )
3939 ship_subsys *tsys = Players[Player_num].targeted_subobject;
3941 model_subsystem *turret = tsys->system_info;
3943 if (turret->type == SUBSYSTEM_TURRET ) {
3944 vector v.fvec, v.uvec;
3945 object * tobj = &Objects[Players[Player_num].targeted_subobject_parent];
3947 ship_model_start(tobj);
3949 model_find_world_point(eye_pos, &turret->turret_firing_point[0], turret->model_num, turret->turret_gun_sobj, &tobj->orient, &tobj->pos );
3950 model_find_world_dir(&v.fvec, &turret->turret_matrix.v.fvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3951 model_find_world_dir(&v.uvec, &turret->turret_matrix.v.uvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3953 vm_vector_2_matrix( eye_orient, &v.fvec, &v.uvec, NULL );
3955 ship_model_stop(tobj);
3965 // following function for dumping frames for purposes of building trailers.
3968 // function to toggle state of dumping every frame into PCX when playing the game
3969 DCF(dump_frames, "Starts/stop frame dumping at 15 hz")
3973 if ( Debug_dump_frames == 0 ) {
3975 Debug_dump_frames = 15;
3976 Debug_dump_trigger = 0;
3977 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3978 dc_printf( "Frame dumping at 15 hz is now ON\n" );
3981 Debug_dump_frames = 0;
3982 Debug_dump_trigger = 0;
3983 gr_dump_frame_stop();
3984 dc_printf( "Frame dumping is now OFF\n" );
3990 DCF(dump_frames_trigger, "Starts/stop frame dumping at 15 hz")
3994 if ( Debug_dump_frames == 0 ) {
3996 Debug_dump_frames = 15;
3997 Debug_dump_trigger = 1;
3998 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3999 dc_printf( "Frame dumping at 15 hz is now ON\n" );
4002 Debug_dump_frames = 0;
4003 Debug_dump_trigger = 0;
4004 gr_dump_frame_stop();
4005 dc_printf( "Frame dumping is now OFF\n" );
4011 DCF(dump_frames30, "Starts/stop frame dumping at 30 hz")
4015 if ( Debug_dump_frames == 0 ) {
4017 Debug_dump_frames = 30;
4018 Debug_dump_trigger = 0;
4019 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4020 dc_printf( "Frame dumping at 30 hz is now ON\n" );
4023 Debug_dump_frames = 0;
4024 Debug_dump_trigger = 0;
4025 gr_dump_frame_stop();
4026 dc_printf( "Frame dumping is now OFF\n" );
4032 DCF(dump_frames30_trigger, "Starts/stop frame dumping at 30 hz")
4036 if ( Debug_dump_frames == 0 ) {
4038 Debug_dump_frames = 30;
4039 Debug_dump_trigger = 1;
4040 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4041 dc_printf( "Triggered frame dumping at 30 hz is now ON\n" );
4044 Debug_dump_frames = 0;
4045 Debug_dump_trigger = 0;
4046 gr_dump_frame_stop();
4047 dc_printf( "Triggered frame dumping is now OFF\n" );
4053 void game_maybe_dump_frame()
4055 if ( !Debug_dump_frames ){
4059 if( Debug_dump_trigger && !keyd_pressed[KEY_Q] ){
4066 Debug_dump_frame_num++;
4072 extern int Player_dead_state;
4074 // Flip the page and time how long it took.
4075 void game_flip_page_and_time_it()
4080 t1 = timer_get_fixed_seconds();
4082 t2 = timer_get_fixed_seconds();
4085 t = (gr_screen.max_w*gr_screen.max_h*gr_screen.bytes_per_pixel)/1024;
4086 sprintf( transfer_text, NOX("%ld MB/s"), fixmuldiv(t,65,d) );
4093 void game_simulation_frame()
4095 // blow ships up in multiplayer dogfight
4096 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){
4097 // blow up all non-player ships
4098 ship_obj *moveup = GET_FIRST(&Ship_obj_list);
4101 while((moveup != END_OF_LIST(&Ship_obj_list)) && (moveup != NULL)){
4103 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)){
4104 moveup = GET_NEXT(moveup);
4107 shipp = &Ships[Objects[moveup->objnum].instance];
4108 sip = &Ship_info[shipp->ship_info_index];
4110 // only blow up small ships
4111 if((sip->flags & SIF_SMALL_SHIP) && (multi_find_player_by_object(&Objects[moveup->objnum]) < 0) ){
4112 // function to simply explode a ship where it is currently at
4113 ship_self_destruct( &Objects[moveup->objnum] );
4116 moveup = GET_NEXT(moveup);
4122 // process AWACS stuff - do this first thing
4125 // single player, set Player hits_this_frame to 0
4126 if ( !(Game_mode & GM_MULTIPLAYER) && Player ) {
4127 Player->damage_this_burst -= (flFrametime * MAX_BURST_DAMAGE / (0.001f * BURST_DURATION));
4128 Player->damage_this_burst = max(Player->damage_this_burst, 0.0f);
4132 supernova_process();
4133 if(supernova_active() >= 5){
4137 // fire targeting lasers now so that
4138 // 1 - created this frame
4139 // 2 - collide this frame
4140 // 3 - render this frame
4141 // 4 - ignored and deleted next frame
4142 // the basic idea being that because it con be confusing to deal with them on a multi-frame basis, they are only valid for
4144 ship_process_targeting_lasers();
4146 // do this here so that it works for multiplayer
4148 // get viewer direction
4149 int viewer_direction = PHYSICS_VIEWER_REAR;
4151 if(Viewer_mode == 0){
4152 viewer_direction = PHYSICS_VIEWER_FRONT;
4154 if(Viewer_mode & VM_PADLOCK_UP){
4155 viewer_direction = PHYSICS_VIEWER_UP;
4157 else if(Viewer_mode & VM_PADLOCK_REAR){
4158 viewer_direction = PHYSICS_VIEWER_REAR;
4160 else if(Viewer_mode & VM_PADLOCK_LEFT){
4161 viewer_direction = PHYSICS_VIEWER_LEFT;
4163 else if(Viewer_mode & VM_PADLOCK_RIGHT){
4164 viewer_direction = PHYSICS_VIEWER_RIGHT;
4167 physics_set_viewer( &Viewer_obj->phys_info, viewer_direction );
4169 physics_set_viewer( NULL, PHYSICS_VIEWER_FRONT );
4172 #define VM_PADLOCK_UP (1 << 7)
4173 #define VM_PADLOCK_REAR (1 << 8)
4174 #define VM_PADLOCK_LEFT (1 << 9)
4175 #define VM_PADLOCK_RIGHT (1 << 10)
4177 // evaluate mission departures and arrivals before we process all objects.
4178 if ( !(Game_mode & GM_MULTIPLAYER) || ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending()) ) {
4180 // we don't want to evaluate mission stuff when any ingame joiner in multiplayer is receiving
4181 // ships/wing packets.
4182 if ( !((Game_mode & GM_MULTIPLAYER) && (Netgame.flags & NG_FLAG_INGAME_JOINING_CRITICAL)) && !(Game_mode & GM_DEMO_PLAYBACK)){
4183 mission_parse_eval_stuff();
4186 // if we're an observer, move ourselves seperately from the standard physics
4187 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
4188 obj_observer_move(flFrametime);
4191 // move all the objects now
4192 obj_move_all(flFrametime);
4194 // check for cargo reveal (this has an internal timestamp, so only runs every N ms)
4195 // AL: 3-15-98: It was decided to not let AI ships inspect cargo
4196 // ship_check_cargo_all();
4197 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4198 mission_eval_goals();
4202 // always check training objectives, even in multiplayer missions. we need to do this so that the directives gauge works properly on clients
4203 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4204 training_check_objectives();
4207 // do all interpolation now
4208 if ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending() && !(Netgame.flags & NG_FLAG_SERVER_LOST)) {
4209 // client side processing of warping in effect stages
4210 multi_do_client_warp(flFrametime);
4212 // client side movement of an observer
4213 if((Net_player->flags & NETINFO_FLAG_OBSERVER) || (Player_obj->type == OBJ_OBSERVER)){
4214 obj_observer_move(flFrametime);
4217 // move all objects - does interpolation now as well
4218 obj_move_all(flFrametime);
4221 // only process the message queue when the player is "in" the game
4222 if ( !Pre_player_entry ){
4223 message_queue_process(); // process any messages send to the player
4226 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4227 message_maybe_distort(); // maybe distort incoming message if comms damaged
4228 player_repair_frame(flFrametime); // AI objects get repaired in ai_process, called from move code...deal with player.
4229 player_process_pending_praise(); // maybe send off a delayed praise message to the player
4230 player_maybe_play_all_alone_msg(); // mabye tell the player he is all alone
4233 if(!(Game_mode & GM_STANDALONE_SERVER)){
4234 // process some stuff every frame (before frame is rendered)
4235 emp_process_local();
4237 hud_update_frame(); // update hud systems
4239 if (!physics_paused) {
4240 // Move particle system
4241 particle_move_all(flFrametime);
4243 // Move missile trails
4244 trail_move_all(flFrametime);
4246 // process muzzle flashes
4247 mflash_process_all();
4249 // Flash the gun flashes
4250 shipfx_flash_do_frame(flFrametime);
4252 shockwave_move_all(flFrametime); // update all the shockwaves
4255 // subspace missile strikes
4258 obj_snd_do_frame(); // update the object-linked persistant sounds
4259 game_maybe_update_sound_environment();
4260 snd_update_listener(&View_position, &Player_obj->phys_info.vel, &Player_obj->orient);
4262 // AL: debug code used for testing ambient subspace sound (ie when enabling subspace through debug console)
4264 if ( Game_subspace_effect ) {
4265 game_start_subspace_ambient_sound();
4271 // Maybe render and process the dead-popup
4272 void game_maybe_do_dead_popup(float frametime)
4274 if ( popupdead_is_active() ) {
4276 int choice = popupdead_do_frame(frametime);
4278 if ( Game_mode & GM_NORMAL ) {
4282 if(game_do_cd_mission_check(Game_current_mission_filename)){
4283 gameseq_post_event(GS_EVENT_ENTER_GAME);
4285 gameseq_post_event(GS_EVENT_MAIN_MENU);
4290 gameseq_post_event(GS_EVENT_END_GAME);
4295 if(game_do_cd_mission_check(Game_current_mission_filename)){
4296 gameseq_post_event(GS_EVENT_START_GAME);
4298 gameseq_post_event(GS_EVENT_MAIN_MENU);
4302 // this should only happen during a red alert mission
4305 Assert(The_mission.red_alert);
4306 if(!The_mission.red_alert){
4308 if(game_do_cd_mission_check(Game_current_mission_filename)){
4309 gameseq_post_event(GS_EVENT_START_GAME);
4311 gameseq_post_event(GS_EVENT_MAIN_MENU);
4316 // choose the previous mission
4317 mission_campaign_previous_mission();
4319 if(game_do_cd_mission_check(Game_current_mission_filename)){
4320 gameseq_post_event(GS_EVENT_START_GAME);
4322 gameseq_post_event(GS_EVENT_MAIN_MENU);
4333 case POPUPDEAD_DO_MAIN_HALL:
4334 multi_quit_game(PROMPT_NONE,-1);
4337 case POPUPDEAD_DO_RESPAWN:
4338 multi_respawn_normal();
4339 event_music_player_respawn();
4342 case POPUPDEAD_DO_OBSERVER:
4343 multi_respawn_observer();
4344 event_music_player_respawn_as_observer();
4353 if ( leave_popup ) {
4359 // returns true if player is actually in a game_play stats
4360 int game_actually_playing()
4364 state = gameseq_get_state();
4365 if ( (state != GS_STATE_GAME_PLAY) && (state != GS_STATE_DEATH_DIED) && (state != GS_STATE_DEATH_BLEW_UP) )
4371 // Draw the 2D HUD gauges
4372 void game_render_hud_2d()
4374 if ( !(Game_detail_flags & DETAIL_FLAG_HUD) ) {
4378 HUD_render_2d(flFrametime);
4382 // Draw the 3D-dependant HUD gauges
4383 void game_render_hud_3d(vector *eye_pos, matrix *eye_orient)
4385 g3_start_frame(0); // 0 = turn zbuffering off
4386 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
4388 if ( (Game_detail_flags & DETAIL_FLAG_HUD) && (supernova_active() < 3)/* && !(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) )*/ ) {
4389 HUD_render_3d(flFrametime);
4393 game_sunspot_process(flFrametime);
4395 // Diminish the palette effect
4396 game_flash_diminish(flFrametime);
4404 int actually_playing;
4405 fix total_time1, total_time2;
4406 fix render2_time1=0, render2_time2=0;
4407 fix render3_time1=0, render3_time2=0;
4408 fix flip_time1=0, flip_time2=0;
4409 fix clear_time1=0, clear_time2=0;
4415 if (Framerate_delay) {
4416 int start_time = timer_get_milliseconds();
4417 while (timer_get_milliseconds() < start_time + Framerate_delay)
4423 demo_do_frame_start();
4425 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4430 // start timing frame
4431 timing_frame_start();
4433 total_time1 = timer_get_fixed_seconds();
4435 // var to hold which state we are in
4436 actually_playing = game_actually_playing();
4438 if ((!(Game_mode & GM_MULTIPLAYER)) || ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER))) {
4439 if (!(Game_mode & GM_STANDALONE_SERVER)){
4440 Assert( OBJ_INDEX(Player_obj) >= 0 );
4444 if (Missiontime > Entry_delay_time){
4445 Pre_player_entry = 0;
4447 ; //nprintf(("AI", "Framecount = %i, time = %7.3f\n", Framecount, f2fl(Missiontime)));
4450 // Note: These are done even before the player enters, else buffers can overflow.
4451 if (! (Game_mode & GM_STANDALONE_SERVER)){
4455 shield_frame_init();
4457 if ( Player->control_mode != PCM_NORMAL )
4460 if ( !Pre_player_entry && actually_playing ) {
4461 if (! (Game_mode & GM_STANDALONE_SERVER) ) {
4463 if( (!popup_running_state()) && (!popupdead_is_active()) ){
4464 game_process_keys();
4466 // don't read flying controls if we're playing a demo back
4467 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4468 read_player_controls( Player_obj, flFrametime);
4472 // if we're not the master, we may have to send the server-critical ship status button_info bits
4473 if ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER)){
4474 multi_maybe_send_ship_status();
4479 // Reset the whack stuff
4482 // These two lines must be outside of Pre_player_entry code,
4483 // otherwise too many lights are added.
4486 if ((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4490 game_simulation_frame();
4492 // if not actually in a game play state, then return. This condition could only be true in
4493 // a multiplayer game.
4494 if ( !actually_playing ) {
4495 Assert( Game_mode & GM_MULTIPLAYER );
4499 if (!Pre_player_entry) {
4500 if (! (Game_mode & GM_STANDALONE_SERVER)) {
4501 clear_time1 = timer_get_fixed_seconds();
4502 // clear the screen to black
4504 if ( (Game_detail_flags & DETAIL_FLAG_CLEAR) ) {
4508 clear_time2 = timer_get_fixed_seconds();
4509 render3_time1 = timer_get_fixed_seconds();
4510 game_render_frame_setup(&eye_pos, &eye_orient);
4511 game_render_frame( &eye_pos, &eye_orient );
4513 // save the eye position and orientation
4514 if ( Game_mode & GM_MULTIPLAYER ) {
4515 Net_player->s_info.eye_pos = eye_pos;
4516 Net_player->s_info.eye_orient = eye_orient;
4519 hud_show_target_model();
4521 // check to see if we should display the death died popup
4522 if(Game_mode & GM_DEAD_BLEW_UP){
4523 if(Game_mode & GM_MULTIPLAYER){
4524 // catch the situation where we're supposed to be warping out on this transition
4525 if(Net_player->flags & NETINFO_FLAG_WARPING_OUT){
4526 gameseq_post_event(GS_EVENT_DEBRIEF);
4527 } else if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4528 Player_died_popup_wait = -1;
4532 if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4533 Player_died_popup_wait = -1;
4539 // hack - sometimes this seems to slip by in multiplayer. this should guarantee that we catch it
4540 if((Game_mode & GM_MULTIPLAYER) && (Player_multi_died_check != -1) && (Game_mode & GM_DEAD_BLEW_UP) ){
4541 if(fl_abs(time(NULL) - Player_multi_died_check) > 4){
4542 if(!popupdead_is_active()){
4546 Player_multi_died_check = -1;
4550 render3_time2 = timer_get_fixed_seconds();
4551 render2_time1 = timer_get_fixed_seconds();
4554 game_get_framerate();
4555 game_show_framerate();
4557 game_show_time_left();
4559 // Draw the 2D HUD gauges
4560 if(supernova_active() < 3){
4561 game_render_hud_2d();
4564 game_set_view_clip();
4566 // Draw 3D HUD gauges
4567 game_render_hud_3d(&eye_pos, &eye_orient);
4571 render2_time2 = timer_get_fixed_seconds();
4573 // maybe render and process the dead popup
4574 game_maybe_do_dead_popup(flFrametime);
4576 // start timing frame
4577 timing_frame_stop();
4578 // timing_display(30, 10);
4580 // If a regular popup is active, don't flip (popup code flips)
4581 if( !popup_running_state() ){
4582 flip_time1 = timer_get_fixed_seconds();
4583 game_flip_page_and_time_it();
4584 flip_time2 = timer_get_fixed_seconds();
4588 game_maybe_dump_frame(); // used to dump pcx files for building trailers
4591 game_show_standalone_framerate();
4595 game_do_training_checks();
4598 // process lightning (nebula only)
4601 total_time2 = timer_get_fixed_seconds();
4603 // Got some timing numbers
4604 Timing_total = f2fl( total_time2 - total_time1 ) * 1000.0f;
4605 Timing_clear = f2fl( clear_time2 - clear_time1 ) * 1000.0f;
4606 Timing_render2 = f2fl( render2_time2- render2_time1 ) * 1000.0f;
4607 Timing_render3 = f2fl( render3_time2- render3_time1 ) * 1000.0f;
4608 Timing_flip = f2fl( flip_time2 - flip_time1 ) * 1000.0f;
4611 demo_do_frame_end();
4613 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4619 #define MAX_FRAMETIME (F1_0/4) // Frametime gets saturated at this. Changed by MK on 11/1/97.
4620 // Some bug was causing Frametime to always get saturated at 2.0 seconds after the player
4621 // died. This resulted in screwed up death sequences.
4623 fix Last_time = 0; // The absolute time of game at end of last frame (beginning of this frame)
4624 fix Last_delta_time = 0; // While game is paused, this keeps track of how much elapsed in the frame before paused.
4625 static int timer_paused=0;
4626 #if defined(TIMER_TEST) && !defined(NDEBUG)
4627 static int stop_count,start_count;
4628 static int time_stopped,time_started;
4630 int saved_timestamp_ticker = -1;
4632 void game_reset_time()
4634 if((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4638 // Last_time = timer_get_fixed_seconds();
4644 void game_stop_time()
4646 if (timer_paused==0) {
4648 time = timer_get_fixed_seconds();
4649 // Save how much time progressed so far in the frame so we can
4650 // use it when we unpause.
4651 Last_delta_time = time - Last_time;
4653 //mprintf(("Last_time in game_stop_time = %7.3f\n", f2fl(Last_delta_time)));
4654 if (Last_delta_time < 0) {
4655 #if defined(TIMER_TEST) && !defined(NDEBUG)
4656 Int3(); //get Matt!!!!
4658 Last_delta_time = 0;
4660 #if defined(TIMER_TEST) && !defined(NDEBUG)
4661 time_stopped = time;
4664 // Stop the timer_tick stuff...
4665 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4666 saved_timestamp_ticker = timestamp_ticker;
4670 #if defined(TIMER_TEST) && !defined(NDEBUG)
4675 void game_start_time()
4678 Assert(timer_paused >= 0);
4679 if (timer_paused==0) {
4681 time = timer_get_fixed_seconds();
4682 #if defined(TIMER_TEST) && !defined(NDEBUG)
4684 Int3(); //get Matt!!!!
4687 // Take current time, and set it backwards to account for time
4688 // that the frame already executed, so that timer_get_fixed_seconds() - Last_time
4689 // will be correct when it goes to calculate the frametime next
4691 Last_time = time - Last_delta_time;
4692 #if defined(TIMER_TEST) && !defined(NDEBUG)
4693 time_started = time;
4696 // Restore the timer_tick stuff...
4697 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4698 Assert( saved_timestamp_ticker > -1 ); // Called out of order, get JAS
4699 timestamp_ticker = saved_timestamp_ticker;
4700 saved_timestamp_ticker = -1;
4703 #if defined(TIMER_TEST) && !defined(NDEBUG)
4709 void game_set_frametime(int state)
4712 float frame_cap_diff;
4714 thistime = timer_get_fixed_seconds();
4716 if ( Last_time == 0 )
4717 Frametime = F1_0 / 30;
4719 Frametime = thistime - Last_time;
4721 // Frametime = F1_0 / 30;
4723 fix debug_frametime = Frametime; // Just used to display frametime.
4725 // If player hasn't entered mission yet, make frame take 1/4 second.
4726 if ((Pre_player_entry) && (state == GS_STATE_GAME_PLAY))
4729 else if ((Debug_dump_frames) && (state == GS_STATE_GAME_PLAY)) { // note link to above if!!!!!
4731 fix frame_speed = F1_0 / Debug_dump_frames;
4733 if (Frametime > frame_speed ){
4734 nprintf(("warning","slow frame: %x\n",Frametime));
4737 thistime = timer_get_fixed_seconds();
4738 Frametime = thistime - Last_time;
4739 } while (Frametime < frame_speed );
4741 Frametime = frame_speed;
4745 Assert( Framerate_cap > 0 );
4747 // Cap the framerate so it doesn't get too high.
4751 cap = F1_0/Framerate_cap;
4752 if (Frametime < cap) {
4753 thistime = cap - Frametime;
4754 //mprintf(("Sleeping for %6.3f seconds.\n", f2fl(thistime)));
4755 Sleep( DWORD(f2fl(thistime) * 1000.0f) );
4757 thistime = timer_get_fixed_seconds();
4761 if((Game_mode & GM_STANDALONE_SERVER) &&
4762 (f2fl(Frametime) < ((float)1.0/(float)Multi_options_g.std_framecap))){
4764 frame_cap_diff = ((float)1.0/(float)Multi_options_g.std_framecap) - f2fl(Frametime);
4765 Sleep((DWORD)(frame_cap_diff*1000));
4767 thistime += fl2f((frame_cap_diff));
4769 Frametime = thistime - Last_time;
4772 // If framerate is too low, cap it.
4773 if (Frametime > MAX_FRAMETIME) {
4775 mprintf(("Frame %2i too long!!: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4777 // to remove warnings in release build
4778 debug_frametime = fl2f(flFrametime);
4780 Frametime = MAX_FRAMETIME;
4783 Frametime = fixmul(Frametime, Game_time_compression);
4785 Last_time = thistime;
4786 //mprintf(("Frame %i, Last_time = %7.3f\n", Framecount, f2fl(Last_time)));
4788 flFrametime = f2fl(Frametime);
4789 //if(!(Game_mode & GM_PLAYING_DEMO)){
4790 timestamp_inc(flFrametime);
4792 /* if ((Framecount > 0) && (Framecount < 10)) {
4793 mprintf(("Frame %2i: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4798 // This is called from game_do_frame(), and from navmap_do_frame()
4799 void game_update_missiontime()
4801 // TODO JAS: Put in if and move this into game_set_frametime,
4802 // fix navmap to call game_stop/start_time
4803 //if ( !timer_paused )
4804 Missiontime += Frametime;
4807 void game_do_frame()
4809 game_set_frametime(GS_STATE_GAME_PLAY);
4810 game_update_missiontime();
4812 if (Game_mode & GM_STANDALONE_SERVER) {
4813 std_multi_set_standalone_missiontime(f2fl(Missiontime));
4816 if ( game_single_step && (last_single_step == game_single_step) ) {
4817 os_set_title( NOX("SINGLE STEP MODE (Pause exits, any other key steps)") );
4818 while( key_checkch() == 0 )
4820 os_set_title( XSTR( "FreeSpace", 171) );
4821 Last_time = timer_get_fixed_seconds();
4824 last_single_step = game_single_step;
4826 if ((gameseq_get_state() == GS_STATE_GAME_PLAY) && Use_mouse_to_fly){
4827 Keep_mouse_centered = 1; // force mouse to center of our window (so we don't hit movement limits)
4831 Keep_mouse_centered = 0;
4832 monitor_update(); // Update monitor variables
4835 void multi_maybe_do_frame()
4837 if ( (Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_IN_MISSION) && !Multi_pause_status){
4842 int Joymouse_button_status = 0;
4844 // Flush all input devices
4852 Joymouse_button_status = 0;
4854 //mprintf(("Game flush!\n" ));
4857 // function for multiplayer only which calls game_do_state_common() when running the
4859 void game_do_dc_networking()
4861 Assert( Game_mode & GM_MULTIPLAYER );
4863 game_do_state_common( gameseq_get_state() );
4866 // Call this whenever in a loop, or when you need to check for a keystroke.
4867 int game_check_key()
4873 // convert keypad enter to normal enter
4874 if ((k & KEY_MASK) == KEY_PADENTER)
4875 k = (k & ~KEY_MASK) | KEY_ENTER;
4880 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4882 #define DEMO_TRAILER_TIMEOUT_MS 45000 // 45 seconds of no input, play trailer
4883 static int Demo_show_trailer_timestamp = 0;
4885 void demo_reset_trailer_timer()
4887 Demo_show_trailer_timestamp = timer_get_milliseconds();
4890 void demo_maybe_show_trailer(int k)
4893 // if key pressed, reset demo trailer timer
4895 demo_reset_trailer_timer();
4899 // if mouse moved, reset demo trailer timer
4902 mouse_get_delta(&dx, &dy);
4903 if ( (dx > 0) || (dy > 0) ) {
4904 demo_reset_trailer_timer();
4908 // if joystick has moved, reset demo trailer timer
4911 joy_get_delta(&dx, &dy);
4912 if ( (dx > 0) || (dy > 0) ) {
4913 demo_reset_trailer_timer();
4917 // NOTE: reseting the trailer timer on mouse/joystick presses is handled in
4918 // the low-level code. Ugly, I know... but was the simplest and most
4921 // if 30 seconds since last demo trailer time reset, launch movie
4922 if ( os_foreground() ) {
4923 int now = timer_get_milliseconds();
4924 if ( (now - Demo_show_trailer_timestamp) > DEMO_TRAILER_TIMEOUT_MS ) {
4925 // if ( (now - Demo_show_trailer_timestamp) > 10000 ) {
4927 movie_play( NOX("fstrailer2.mve") );
4928 demo_reset_trailer_timer();
4936 // same as game_check_key(), except this is used while actually in the game. Since there
4937 // generally are differences between game control keys and general UI keys, makes sense to
4938 // have seperate functions for each case. If you are not checking a game control while in a
4939 // mission, you should probably be using game_check_key() instead.
4944 if (!os_foreground()) {
4949 // If we're in a single player game, pause it.
4950 if (!(Game_mode & GM_MULTIPLAYER)){
4951 if ( (gameseq_get_state() == GS_STATE_GAME_PLAY) && (!popup_active()) && (!popupdead_is_active()) ) {
4952 game_process_pause_key();
4959 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4960 demo_maybe_show_trailer(k);
4963 // Move the mouse cursor with the joystick.
4964 if (os_foreground() && (!Mouse_hidden) && (Use_joy_mouse) ) {
4965 // Move the mouse cursor with the joystick
4969 joy_get_pos( &jx, &jy, &jz, &jr );
4971 dx = fl2i(f2fl(jx)*flFrametime*500.0f);
4972 dy = fl2i(f2fl(jy)*flFrametime*500.0f);
4975 mouse_get_real_pos( &mx, &my );
4976 mouse_set_pos( mx+dx, my+dy );
4981 m = mouse_down(MOUSE_LEFT_BUTTON);
4983 if ( j != Joymouse_button_status ) {
4984 //mprintf(( "Joy went from %d to %d, mouse is %d\n", Joymouse_button_status, j, m ));
4985 Joymouse_button_status = j;
4987 mouse_mark_button( MOUSE_LEFT_BUTTON, 1 );
4988 } else if ( (!j) && (m) ) {
4989 mouse_mark_button( MOUSE_LEFT_BUTTON, 0 );
4994 // if we should be ignoring keys because of some multiplayer situations
4995 if((Game_mode & GM_MULTIPLAYER) && multi_ignore_controls(k)){
4999 // If a popup is running, don't process all the Fn keys
5000 if( popup_active() ) {
5004 state = gameseq_get_state();
5006 // if ( k ) nprintf(( "General", "Key = %x\n", k ));
5009 case KEY_DEBUGGED + KEY_BACKSP:
5014 launch_context_help();
5019 // if (state != GS_STATE_INITIAL_PLAYER_SELECT) {
5021 // don't allow f2 while warping out in multiplayer
5022 if((Game_mode & GM_MULTIPLAYER) && (Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_WARPING_OUT)){
5027 case GS_STATE_INITIAL_PLAYER_SELECT:
5028 case GS_STATE_OPTIONS_MENU:
5029 case GS_STATE_HUD_CONFIG:
5030 case GS_STATE_CONTROL_CONFIG:
5031 case GS_STATE_DEATH_DIED:
5032 case GS_STATE_DEATH_BLEW_UP:
5033 case GS_STATE_VIEW_MEDALS:
5037 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
5044 // hotkey selection screen -- only valid from briefing and beyond.
5046 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
5047 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) ) {
5048 gameseq_post_event( GS_EVENT_HOTKEY_SCREEN );
5054 case KEY_DEBUGGED + KEY_F3:
5055 gameseq_post_event( GS_EVENT_TOGGLE_FULLSCREEN );
5058 case KEY_DEBUGGED + KEY_F4:
5059 gameseq_post_event( GS_EVENT_TOGGLE_GLIDE );
5063 if(Game_mode & GM_MULTIPLAYER){
5064 if((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_MULTI_PAUSED)){
5065 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
5069 if ((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_DEATH_DIED) || (state == GS_STATE_DEATH_BLEW_UP) || (state == GS_STATE_GAME_PAUSED) ) {
5070 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
5076 case KEY_ESC | KEY_SHIFTED:
5077 // make sure to quit properly out of multiplayer
5078 if(Game_mode & GM_MULTIPLAYER){
5079 multi_quit_game(PROMPT_NONE);
5082 gameseq_post_event( GS_EVENT_QUIT_GAME );
5087 case KEY_DEBUGGED + KEY_P:
5090 case KEY_PRINT_SCRN:
5092 static int counter = 0;
5097 sprintf( tmp_name, NOX("screen%02d"), counter );
5099 mprintf(( "Dumping screen to '%s'\n", tmp_name ));
5100 gr_print_screen(tmp_name);
5108 case KEY_SHIFTED | KEY_ENTER: {
5110 #if !defined(NDEBUG)
5112 if ( Game_mode & GM_NORMAL ){
5116 // if we're in multiplayer mode, do some special networking
5117 if(Game_mode & GM_MULTIPLAYER){
5118 debug_console(game_do_dc_networking);
5125 if ( Game_mode & GM_NORMAL )
5139 gameseq_post_event(GS_EVENT_QUIT_GAME);
5142 void apply_physics( float damping, float desired_vel, float initial_vel, float t, float * new_vel, float * delta_pos );
5145 void camera_set_position( vector *pos )
5150 void camera_set_orient( matrix *orient )
5152 Camera_orient = *orient;
5155 void camera_set_velocity( vector *vel, int instantaneous )
5157 Camera_desired_velocity.xyz.x = 0.0f;
5158 Camera_desired_velocity.xyz.y = 0.0f;
5159 Camera_desired_velocity.xyz.z = 0.0f;
5161 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.rvec, vel->xyz.x );
5162 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.uvec, vel->xyz.y );
5163 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.fvec, vel->xyz.z );
5165 if ( instantaneous ) {
5166 Camera_velocity = Camera_desired_velocity;
5174 vector new_vel, delta_pos;
5176 apply_physics( Camera_damping, Camera_desired_velocity.xyz.x, Camera_velocity.xyz.x, flFrametime, &new_vel.xyz.x, &delta_pos.xyz.x );
5177 apply_physics( Camera_damping, Camera_desired_velocity.xyz.y, Camera_velocity.xyz.y, flFrametime, &new_vel.xyz.y, &delta_pos.xyz.y );
5178 apply_physics( Camera_damping, Camera_desired_velocity.xyz.z, Camera_velocity.xyz.z, flFrametime, &new_vel.xyz.z, &delta_pos.xyz.z );
5180 Camera_velocity = new_vel;
5182 // mprintf(( "Camera velocity = %.1f,%.1f, %.1f\n", Camera_velocity.xyz.x, Camera_velocity.xyz.y, Camera_velocity.xyz.z ));
5184 vm_vec_add2( &Camera_pos, &delta_pos );
5186 float ot = Camera_time+0.0f;
5188 Camera_time += flFrametime;
5190 if ( (ot < 0.667f) && ( Camera_time >= 0.667f ) ) {
5193 tmp.xyz.z = 4.739f; // always go this fast forward.
5195 // pick x and y velocities so they are always on a
5196 // circle with a 25 m radius.
5198 float tmp_angle = frand()*PI2;
5200 tmp.xyz.x = 22.0f * (float)sin(tmp_angle);
5201 tmp.xyz.y = -22.0f * (float)cos(tmp_angle);
5203 //mprintf(( "Angle = %.1f, vx=%.1f, vy=%.1f\n", tmp_angle, tmp.xyz.x, tmp.xyz.y ));
5205 //mprintf(( "Changing velocity!\n" ));
5206 camera_set_velocity( &tmp, 0 );
5209 if ( (ot < 3.0f ) && ( Camera_time >= 3.0f ) ) {
5210 vector tmp = { 0.0f, 0.0f, 0.0f };
5211 camera_set_velocity( &tmp, 0 );
5216 void end_demo_campaign_do()
5218 #if defined(FS2_DEMO) || defined(FS1_DEMO)
5219 // show upsell screens
5220 demo_upsell_show_screens();
5221 #elif defined(OEM_BUILD)
5222 // show oem upsell screens
5223 oem_upsell_show_screens();
5226 // drop into main hall
5227 gameseq_post_event( GS_EVENT_MAIN_MENU );
5230 // All code to process events. This is the only place
5231 // that you should change the state of the game.
5232 void game_process_event( int current_state, int event )
5234 mprintf(("Got event %s in state %s\n", GS_event_text[event], GS_state_text[current_state]));
5237 case GS_EVENT_SIMULATOR_ROOM:
5238 gameseq_set_state(GS_STATE_SIMULATOR_ROOM);
5241 case GS_EVENT_MAIN_MENU:
5242 gameseq_set_state(GS_STATE_MAIN_MENU);
5245 case GS_EVENT_OPTIONS_MENU:
5246 gameseq_push_state( GS_STATE_OPTIONS_MENU );
5249 case GS_EVENT_BARRACKS_MENU:
5250 gameseq_set_state(GS_STATE_BARRACKS_MENU);
5253 case GS_EVENT_TECH_MENU:
5254 gameseq_set_state(GS_STATE_TECH_MENU);
5257 case GS_EVENT_TRAINING_MENU:
5258 gameseq_set_state(GS_STATE_TRAINING_MENU);
5261 case GS_EVENT_START_GAME:
5262 Select_default_ship = 0;
5263 Player_multi_died_check = -1;
5264 gameseq_set_state(GS_STATE_CMD_BRIEF);
5267 case GS_EVENT_START_BRIEFING:
5268 gameseq_set_state(GS_STATE_BRIEFING);
5271 case GS_EVENT_DEBRIEF:
5272 // did we end the campaign in the main freespace 2 single player campaign?
5274 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !stricmp(Campaign.filename, "freespace")) {
5276 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !stricmp(Campaign.filename, "freespace2")) {
5278 gameseq_post_event(GS_EVENT_END_CAMPAIGN);
5280 gameseq_set_state(GS_STATE_DEBRIEF);
5283 Player_multi_died_check = -1;
5286 case GS_EVENT_SHIP_SELECTION:
5287 gameseq_set_state( GS_STATE_SHIP_SELECT );
5290 case GS_EVENT_WEAPON_SELECTION:
5291 gameseq_set_state( GS_STATE_WEAPON_SELECT );
5294 case GS_EVENT_ENTER_GAME:
5296 // maybe start recording a demo
5298 demo_start_record("test.fsd");
5302 if (Game_mode & GM_MULTIPLAYER) {
5303 // if we're respawning, make sure we change the view mode so that the hud shows up
5304 if (current_state == GS_STATE_DEATH_BLEW_UP) {
5308 gameseq_set_state(GS_STATE_GAME_PLAY);
5310 gameseq_set_state(GS_STATE_GAME_PLAY, 1);
5313 Player_multi_died_check = -1;
5315 // clear multiplayer button info
5316 extern button_info Multi_ship_status_bi;
5317 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
5319 Start_time = f2fl(timer_get_approx_seconds());
5321 mprintf(("Entering game at time = %7.3f\n", Start_time));
5325 case GS_EVENT_START_GAME_QUICK:
5326 Select_default_ship = 1;
5327 gameseq_post_event(GS_EVENT_ENTER_GAME);
5331 case GS_EVENT_END_GAME:
5332 if ( (current_state == GS_STATE_GAME_PLAY) || (current_state == GS_STATE_DEATH_DIED) ||
5333 (current_state == GS_STATE_DEATH_BLEW_UP) || (current_state == GS_STATE_DEBRIEF) || (current_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) {
5334 gameseq_set_state(GS_STATE_MAIN_MENU);
5339 Player_multi_died_check = -1;
5342 case GS_EVENT_QUIT_GAME:
5343 main_hall_stop_music();
5344 main_hall_stop_ambient();
5345 gameseq_set_state(GS_STATE_QUIT_GAME);
5347 Player_multi_died_check = -1;
5350 case GS_EVENT_GAMEPLAY_HELP:
5351 gameseq_push_state( GS_STATE_GAMEPLAY_HELP );
5354 case GS_EVENT_PAUSE_GAME:
5355 gameseq_push_state(GS_STATE_GAME_PAUSED);
5358 case GS_EVENT_DEBUG_PAUSE_GAME:
5359 gameseq_push_state(GS_STATE_DEBUG_PAUSED);
5362 case GS_EVENT_TRAINING_PAUSE:
5363 gameseq_push_state(GS_STATE_TRAINING_PAUSED);
5366 case GS_EVENT_PREVIOUS_STATE:
5367 gameseq_pop_state();
5370 case GS_EVENT_TOGGLE_FULLSCREEN:
5371 #ifndef HARDWARE_ONLY
5373 if ( gr_screen.mode == GR_SOFTWARE ) {
5374 gr_init( GR_640, GR_DIRECTDRAW );
5375 } else if ( gr_screen.mode == GR_DIRECTDRAW ) {
5376 gr_init( GR_640, GR_SOFTWARE );
5382 case GS_EVENT_TOGGLE_GLIDE:
5384 if ( gr_screen.mode != GR_GLIDE ) {
5385 gr_init( GR_640, GR_GLIDE );
5387 gr_init( GR_640, GR_SOFTWARE );
5392 case GS_EVENT_LOAD_MISSION_MENU:
5393 gameseq_set_state(GS_STATE_LOAD_MISSION_MENU);
5396 case GS_EVENT_MISSION_LOG_SCROLLBACK:
5397 gameseq_push_state( GS_STATE_MISSION_LOG_SCROLLBACK );
5400 case GS_EVENT_HUD_CONFIG:
5401 gameseq_push_state( GS_STATE_HUD_CONFIG );
5404 case GS_EVENT_CONTROL_CONFIG:
5405 gameseq_push_state( GS_STATE_CONTROL_CONFIG );
5408 case GS_EVENT_DEATH_DIED:
5409 gameseq_set_state( GS_STATE_DEATH_DIED );
5412 case GS_EVENT_DEATH_BLEW_UP:
5413 if ( current_state == GS_STATE_DEATH_DIED ) {
5414 gameseq_set_state( GS_STATE_DEATH_BLEW_UP );
5415 event_music_player_death();
5417 // multiplayer clients set their extra check here
5418 if(Game_mode & GM_MULTIPLAYER){
5419 // set the multi died absolute last chance check
5420 Player_multi_died_check = time(NULL);
5423 mprintf(( "Ignoring GS_EVENT_DEATH_BLEW_UP because we're in state %d\n", current_state ));
5427 case GS_EVENT_NEW_CAMPAIGN:
5428 if (!mission_load_up_campaign()){
5429 readyroom_continue_campaign();
5432 Player_multi_died_check = -1;
5435 case GS_EVENT_CAMPAIGN_CHEAT:
5436 if (!mission_load_up_campaign()){
5438 // bash campaign value
5439 extern char Main_hall_campaign_cheat[512];
5442 // look for the mission
5443 for(idx=0; idx<Campaign.num_missions; idx++){
5444 if(!stricmp(Campaign.missions[idx].name, Main_hall_campaign_cheat)){
5445 Campaign.next_mission = idx;
5446 Campaign.prev_mission = idx - 1;
5453 readyroom_continue_campaign();
5456 Player_multi_died_check = -1;
5459 case GS_EVENT_CAMPAIGN_ROOM:
5460 gameseq_set_state(GS_STATE_CAMPAIGN_ROOM);
5463 case GS_EVENT_CMD_BRIEF:
5464 gameseq_set_state(GS_STATE_CMD_BRIEF);
5467 case GS_EVENT_RED_ALERT:
5468 gameseq_set_state(GS_STATE_RED_ALERT);
5471 case GS_EVENT_CREDITS:
5472 gameseq_set_state( GS_STATE_CREDITS );
5475 case GS_EVENT_VIEW_MEDALS:
5476 gameseq_push_state( GS_STATE_VIEW_MEDALS );
5479 case GS_EVENT_SHOW_GOALS:
5480 gameseq_push_state( GS_STATE_SHOW_GOALS ); // use push_state() since we might get to this screen through a variety of states
5483 case GS_EVENT_HOTKEY_SCREEN:
5484 gameseq_push_state( GS_STATE_HOTKEY_SCREEN ); // use push_state() since we might get to this screen through a variety of states
5487 // multiplayer stuff follow these comments
5489 case GS_EVENT_MULTI_JOIN_GAME:
5490 gameseq_set_state( GS_STATE_MULTI_JOIN_GAME );
5493 case GS_EVENT_MULTI_HOST_SETUP:
5494 gameseq_set_state( GS_STATE_MULTI_HOST_SETUP );
5497 case GS_EVENT_MULTI_CLIENT_SETUP:
5498 gameseq_set_state( GS_STATE_MULTI_CLIENT_SETUP );
5501 case GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN:
5502 gameseq_set_state(GS_STATE_VIEW_CUTSCENES);
5505 case GS_EVENT_MULTI_STD_WAIT:
5506 gameseq_set_state( GS_STATE_MULTI_STD_WAIT );
5509 case GS_EVENT_STANDALONE_MAIN:
5510 gameseq_set_state( GS_STATE_STANDALONE_MAIN );
5513 case GS_EVENT_MULTI_PAUSE:
5514 gameseq_push_state( GS_STATE_MULTI_PAUSED );
5517 case GS_EVENT_INGAME_PRE_JOIN:
5518 gameseq_set_state( GS_STATE_INGAME_PRE_JOIN );
5521 case GS_EVENT_EVENT_DEBUG:
5522 gameseq_push_state(GS_STATE_EVENT_DEBUG);
5525 // Start a warpout where player automatically goes 70 no matter what
5526 // and can't cancel out of it.
5527 case GS_EVENT_PLAYER_WARPOUT_START_FORCED:
5528 Warpout_forced = 1; // If non-zero, bash the player to speed and go through effect
5530 // Same code as in GS_EVENT_PLAYER_WARPOUT_START only ignores current mode
5531 Player->saved_viewer_mode = Viewer_mode;
5532 Player->control_mode = PCM_WARPOUT_STAGE1;
5533 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5534 Warpout_time = 0.0f; // Start timer!
5537 case GS_EVENT_PLAYER_WARPOUT_START:
5538 if ( Player->control_mode != PCM_NORMAL ) {
5539 mprintf(( "Player isn't in normal mode; cannot warp out.\n" ));
5541 Player->saved_viewer_mode = Viewer_mode;
5542 Player->control_mode = PCM_WARPOUT_STAGE1;
5543 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5544 Warpout_time = 0.0f; // Start timer!
5545 Warpout_forced = 0; // If non-zero, bash the player to speed and go through effect
5549 case GS_EVENT_PLAYER_WARPOUT_STOP:
5550 if ( Player->control_mode != PCM_NORMAL ) {
5551 if ( !Warpout_forced ) { // cannot cancel forced warpout
5552 Player->control_mode = PCM_NORMAL;
5553 Viewer_mode = Player->saved_viewer_mode;
5554 hud_subspace_notify_abort();
5555 mprintf(( "Player put back to normal mode.\n" ));
5556 if ( Warpout_sound > -1 ) {
5557 snd_stop( Warpout_sound );
5564 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE1: // player ship got up to speed
5565 if ( Player->control_mode != PCM_WARPOUT_STAGE1 ) {
5566 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5567 mprintf(( "Player put back to normal mode, because of invalid sequence in stage1.\n" ));
5569 mprintf(( "Hit target speed. Starting warp effect and moving to stage 2!\n" ));
5570 shipfx_warpout_start( Player_obj );
5571 Player->control_mode = PCM_WARPOUT_STAGE2;
5572 Player->saved_viewer_mode = Viewer_mode;
5573 Viewer_mode |= VM_WARP_CHASE;
5575 vector tmp = Player_obj->pos;
5577 ship_get_eye( &tmp, &tmp_m, Player_obj );
5578 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.rvec, 0.0f );
5579 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.uvec, 0.952f );
5580 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.fvec, -1.782f );
5582 camera_set_position( &tmp );
5583 camera_set_orient( &Player_obj->orient );
5584 vector tmp_vel = { 0.0f, 5.1919f, 14.7f };
5586 //mprintf(( "Rad = %.1f\n", Player_obj->radius ));
5587 camera_set_velocity( &tmp_vel, 1);
5591 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE2: // player ship got into the warp effect
5592 if ( Player->control_mode != PCM_WARPOUT_STAGE2 ) {
5593 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5594 mprintf(( "Player put back to normal mode, because of invalid sequence in stage2.\n" ));
5596 mprintf(( "Hit warp effect. Moving to stage 3!\n" ));
5597 Player->control_mode = PCM_WARPOUT_STAGE3;
5601 case GS_EVENT_PLAYER_WARPOUT_DONE: // player ship got through the warp effect
5602 mprintf(( "Player warped out. Going to debriefing!\n" ));
5603 Player->control_mode = PCM_NORMAL;
5604 Viewer_mode = Player->saved_viewer_mode;
5607 // we have a special debriefing screen for multiplayer furballs
5608 if((Game_mode & GM_MULTIPLAYER) && (The_mission.game_type & MISSION_TYPE_MULTI_DOGFIGHT)){
5609 gameseq_post_event(GS_EVENT_MULTI_DOGFIGHT_DEBRIEF);
5611 // do the normal debriefing for all other situations
5613 gameseq_post_event(GS_EVENT_DEBRIEF);
5617 case GS_EVENT_STANDALONE_POSTGAME:
5618 gameseq_set_state(GS_STATE_STANDALONE_POSTGAME);
5621 case GS_EVENT_INITIAL_PLAYER_SELECT:
5622 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5625 case GS_EVENT_GAME_INIT:
5626 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
5627 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5629 // see if the command line option has been set to use the last pilot, and act acoordingly
5630 if( player_select_get_last_pilot() ) {
5631 // always enter the main menu -- do the automatic network startup stuff elsewhere
5632 // so that we still have valid checks for networking modes, etc.
5633 gameseq_set_state(GS_STATE_MAIN_MENU);
5635 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5640 case GS_EVENT_MULTI_MISSION_SYNC:
5641 gameseq_set_state(GS_STATE_MULTI_MISSION_SYNC);
5644 case GS_EVENT_MULTI_START_GAME:
5645 gameseq_set_state(GS_STATE_MULTI_START_GAME);
5648 case GS_EVENT_MULTI_HOST_OPTIONS:
5649 gameseq_set_state(GS_STATE_MULTI_HOST_OPTIONS);
5652 case GS_EVENT_MULTI_DOGFIGHT_DEBRIEF:
5653 gameseq_set_state(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
5656 case GS_EVENT_TEAM_SELECT:
5657 gameseq_set_state(GS_STATE_TEAM_SELECT);
5660 case GS_EVENT_END_CAMPAIGN:
5661 gameseq_set_state(GS_STATE_END_OF_CAMPAIGN);
5664 case GS_EVENT_END_DEMO:
5665 gameseq_set_state(GS_STATE_END_DEMO);
5668 case GS_EVENT_LOOP_BRIEF:
5669 gameseq_set_state(GS_STATE_LOOP_BRIEF);
5678 // Called when a state is being left.
5679 // The current state is still at old_state, but as soon as
5680 // this function leaves, then the current state will become
5681 // new state. You should never try to change the state
5682 // in here... if you think you need to, you probably really
5683 // need to post an event, not change the state.
5684 void game_leave_state( int old_state, int new_state )
5686 int end_mission = 1;
5688 switch (new_state) {
5689 case GS_STATE_GAME_PAUSED:
5690 case GS_STATE_DEBUG_PAUSED:
5691 case GS_STATE_OPTIONS_MENU:
5692 case GS_STATE_CONTROL_CONFIG:
5693 case GS_STATE_MISSION_LOG_SCROLLBACK:
5694 case GS_STATE_DEATH_DIED:
5695 case GS_STATE_SHOW_GOALS:
5696 case GS_STATE_HOTKEY_SCREEN:
5697 case GS_STATE_MULTI_PAUSED:
5698 case GS_STATE_TRAINING_PAUSED:
5699 case GS_STATE_EVENT_DEBUG:
5700 case GS_STATE_GAMEPLAY_HELP:
5701 end_mission = 0; // these events shouldn't end a mission
5705 switch (old_state) {
5706 case GS_STATE_BRIEFING:
5707 brief_stop_voices();
5708 if ( (new_state != GS_STATE_OPTIONS_MENU) && (new_state != GS_STATE_WEAPON_SELECT)
5709 && (new_state != GS_STATE_SHIP_SELECT) && (new_state != GS_STATE_HOTKEY_SCREEN)
5710 && (new_state != GS_STATE_TEAM_SELECT) ){
5711 common_select_close();
5712 if ( new_state == GS_STATE_MAIN_MENU ) {
5713 freespace_stop_mission();
5717 // COMMAND LINE OPTION
5718 if (Cmdline_multi_stream_chat_to_file){
5719 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5720 cfclose(Multi_chat_stream);
5724 case GS_STATE_DEBRIEF:
5725 if ( (new_state != GS_STATE_VIEW_MEDALS) && (new_state != GS_STATE_OPTIONS_MENU) ) {
5730 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
5731 multi_df_debrief_close();
5734 case GS_STATE_LOAD_MISSION_MENU:
5735 mission_load_menu_close();
5738 case GS_STATE_SIMULATOR_ROOM:
5742 case GS_STATE_CAMPAIGN_ROOM:
5743 campaign_room_close();
5746 case GS_STATE_CMD_BRIEF:
5747 if (new_state == GS_STATE_OPTIONS_MENU) {
5752 if (new_state == GS_STATE_MAIN_MENU)
5753 freespace_stop_mission();
5758 case GS_STATE_RED_ALERT:
5762 case GS_STATE_SHIP_SELECT:
5763 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_WEAPON_SELECT &&
5764 new_state != GS_STATE_HOTKEY_SCREEN &&
5765 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5766 common_select_close();
5767 if ( new_state == GS_STATE_MAIN_MENU ) {
5768 freespace_stop_mission();
5773 case GS_STATE_WEAPON_SELECT:
5774 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5775 new_state != GS_STATE_HOTKEY_SCREEN &&
5776 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5777 common_select_close();
5778 if ( new_state == GS_STATE_MAIN_MENU ) {
5779 freespace_stop_mission();
5784 case GS_STATE_TEAM_SELECT:
5785 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5786 new_state != GS_STATE_HOTKEY_SCREEN &&
5787 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_WEAPON_SELECT) {
5788 common_select_close();
5789 if ( new_state == GS_STATE_MAIN_MENU ) {
5790 freespace_stop_mission();
5795 case GS_STATE_MAIN_MENU:
5796 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
5803 case GS_STATE_OPTIONS_MENU:
5804 //game_start_time();
5805 if(new_state == GS_STATE_MULTI_JOIN_GAME){
5806 multi_join_clear_game_list();
5808 options_menu_close();
5811 case GS_STATE_BARRACKS_MENU:
5812 if(new_state != GS_STATE_VIEW_MEDALS){
5817 case GS_STATE_MISSION_LOG_SCROLLBACK:
5818 hud_scrollback_close();
5821 case GS_STATE_TRAINING_MENU:
5822 training_menu_close();
5825 case GS_STATE_GAME_PLAY:
5826 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
5827 player_save_target_and_weapon_link_prefs();
5828 game_stop_looped_sounds();
5831 sound_env_disable();
5832 joy_ff_stop_effects();
5834 // stop game time under certain conditions
5835 if ( end_mission || (Game_mode & GM_NORMAL) || ((Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MULTI_PAUSED)) ){
5840 // shut down any recording or playing demos
5845 // when in multiplayer and going back to the main menu, send a leave game packet
5846 // right away (before calling stop mission). stop_mission was taking to long to
5847 // close mission down and I want people to get notified ASAP.
5848 if ( (Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MAIN_MENU) ){
5849 multi_quit_game(PROMPT_NONE);
5852 freespace_stop_mission();
5853 Game_time_compression = F1_0;
5857 case GS_STATE_TECH_MENU:
5861 case GS_STATE_TRAINING_PAUSED:
5862 Training_num_lines = 0;
5863 // fall through to GS_STATE_GAME_PAUSED
5865 case GS_STATE_GAME_PAUSED:
5867 if ( end_mission ) {
5872 case GS_STATE_DEBUG_PAUSED:
5875 pause_debug_close();
5879 case GS_STATE_HUD_CONFIG:
5883 // join/start a game
5884 case GS_STATE_MULTI_JOIN_GAME:
5885 if(new_state != GS_STATE_OPTIONS_MENU){
5886 multi_join_game_close();
5890 case GS_STATE_MULTI_HOST_SETUP:
5891 case GS_STATE_MULTI_CLIENT_SETUP:
5892 // if this is just the host going into the options screen, don't do anything
5893 if((new_state == GS_STATE_MULTI_HOST_OPTIONS) || (new_state == GS_STATE_OPTIONS_MENU)){
5897 // close down the proper state
5898 if(old_state == GS_STATE_MULTI_HOST_SETUP){
5899 multi_create_game_close();
5901 multi_game_client_setup_close();
5904 // COMMAND LINE OPTION
5905 if (Cmdline_multi_stream_chat_to_file){
5906 if( (new_state != GS_STATE_TEAM_SELECT) && (Multi_chat_stream!=NULL) ) {
5907 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5908 cfclose(Multi_chat_stream);
5913 case GS_STATE_CONTROL_CONFIG:
5914 control_config_close();
5917 case GS_STATE_DEATH_DIED:
5918 Game_mode &= ~GM_DEAD_DIED;
5920 // early end while respawning or blowing up in a multiplayer game
5921 if((Game_mode & GM_MULTIPLAYER) && ((new_state == GS_STATE_DEBRIEF) || (new_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) ){
5923 freespace_stop_mission();
5927 case GS_STATE_DEATH_BLEW_UP:
5928 Game_mode &= ~GM_DEAD_BLEW_UP;
5930 // for single player, we might reload mission, etc. For multiplayer, look at my new state
5931 // to determine if I should do anything.
5932 if ( !(Game_mode & GM_MULTIPLAYER) ) {
5934 freespace_stop_mission();
5937 // if we are not respawing as an observer or as a player, our new state will not
5938 // be gameplay state.
5939 if ( (new_state != GS_STATE_GAME_PLAY) && (new_state != GS_STATE_MULTI_PAUSED) ) {
5940 game_stop_time(); // hasn't been called yet!!
5941 freespace_stop_mission();
5947 case GS_STATE_CREDITS:
5951 case GS_STATE_VIEW_MEDALS:
5955 case GS_STATE_SHOW_GOALS:
5956 mission_show_goals_close();
5959 case GS_STATE_HOTKEY_SCREEN:
5960 if ( new_state != GS_STATE_OPTIONS_MENU ) {
5961 mission_hotkey_close();
5965 case GS_STATE_MULTI_MISSION_SYNC:
5966 // if we're moving into the options menu, don't do anything
5967 if(new_state == GS_STATE_OPTIONS_MENU){
5971 Assert( Game_mode & GM_MULTIPLAYER );
5973 if ( new_state == GS_STATE_GAME_PLAY ){
5974 // palette_restore_palette();
5976 // change a couple of flags to indicate our state!!!
5977 Net_player->state = NETPLAYER_STATE_IN_MISSION;
5978 send_netplayer_update_packet();
5980 // set the game mode
5981 Game_mode |= GM_IN_MISSION;
5985 case GS_STATE_VIEW_CUTSCENES:
5986 cutscenes_screen_close();
5989 case GS_STATE_MULTI_STD_WAIT:
5990 multi_standalone_wait_close();
5993 case GS_STATE_STANDALONE_MAIN:
5994 standalone_main_close();
5995 if(new_state == GS_STATE_MULTI_STD_WAIT){
5996 init_multiplayer_stats();
6000 case GS_STATE_MULTI_PAUSED:
6001 // if ( end_mission ){
6006 case GS_STATE_INGAME_PRE_JOIN:
6007 multi_ingame_select_close();
6010 case GS_STATE_STANDALONE_POSTGAME:
6011 multi_standalone_postgame_close();
6014 case GS_STATE_INITIAL_PLAYER_SELECT:
6015 player_select_close();
6018 case GS_STATE_MULTI_START_GAME:
6019 multi_start_game_close();
6022 case GS_STATE_MULTI_HOST_OPTIONS:
6023 multi_host_options_close();
6026 case GS_STATE_END_OF_CAMPAIGN:
6027 mission_campaign_end_close();
6030 case GS_STATE_LOOP_BRIEF:
6036 // Called when a state is being entered.
6037 // The current state is set to the state we're entering at
6038 // this point, and old_state is set to the state we're coming
6039 // from. You should never try to change the state
6040 // in here... if you think you need to, you probably really
6041 // need to post an event, not change the state.
6043 void game_enter_state( int old_state, int new_state )
6045 switch (new_state) {
6046 case GS_STATE_MAIN_MENU:
6047 // in multiplayer mode, be sure that we are not doing networking anymore.
6048 if ( Game_mode & GM_MULTIPLAYER ) {
6049 Assert( Net_player != NULL );
6050 Net_player->flags &= ~NETINFO_FLAG_DO_NETWORKING;
6053 Game_time_compression = F1_0;
6055 // determine which ship this guy is currently based on
6056 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
6059 if (Player->on_bastion) {
6067 case GS_STATE_BRIEFING:
6068 main_hall_stop_music();
6069 main_hall_stop_ambient();
6071 if (Game_mode & GM_NORMAL) {
6072 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
6073 // MWA: or from options or hotkey screens
6074 // JH: or if the command brief state already did this
6075 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
6076 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT)
6077 && (old_state != GS_STATE_CMD_BRIEF) ) {
6078 if ( !game_start_mission() ) // this should put us into a new state on failure!
6082 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
6083 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
6084 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6086 Game_time_compression = F1_0;
6088 if ( red_alert_mission() ) {
6089 gameseq_post_event(GS_EVENT_RED_ALERT);
6096 case GS_STATE_DEBRIEF:
6097 game_stop_looped_sounds();
6098 mission_goal_fail_incomplete(); // fail all incomplete goals before entering debriefing
6099 if ( (old_state != GS_STATE_VIEW_MEDALS) && (old_state != GS_STATE_OPTIONS_MENU) ){
6104 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6105 multi_df_debrief_init();
6108 case GS_STATE_LOAD_MISSION_MENU:
6109 mission_load_menu_init();
6112 case GS_STATE_SIMULATOR_ROOM:
6116 case GS_STATE_CAMPAIGN_ROOM:
6117 campaign_room_init();
6120 case GS_STATE_RED_ALERT:
6121 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6125 case GS_STATE_CMD_BRIEF: {
6126 int team_num = 0; // team number used as index for which cmd brief to use.
6128 if (old_state == GS_STATE_OPTIONS_MENU) {
6132 main_hall_stop_music();
6133 main_hall_stop_ambient();
6135 if (Game_mode & GM_NORMAL) {
6136 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
6137 // MWA: or from options or hotkey screens
6138 // JH: or if the command brief state already did this
6139 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
6140 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT) ) {
6141 if ( !game_start_mission() ) // this should put us into a new state on failure!
6146 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
6147 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
6148 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6150 cmd_brief_init(team_num);
6156 case GS_STATE_SHIP_SELECT:
6160 case GS_STATE_WEAPON_SELECT:
6161 weapon_select_init();
6164 case GS_STATE_TEAM_SELECT:
6168 case GS_STATE_GAME_PAUSED:
6173 case GS_STATE_DEBUG_PAUSED:
6174 // game_stop_time();
6175 // os_set_title("FreeSpace - PAUSED");
6178 case GS_STATE_TRAINING_PAUSED:
6185 case GS_STATE_OPTIONS_MENU:
6187 options_menu_init();
6190 case GS_STATE_GAME_PLAY:
6191 // coming from the gameplay state or the main menu, we might need to load the mission
6192 if ( (Game_mode & GM_NORMAL) && ((old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_GAME_PLAY) || (old_state == GS_STATE_DEATH_BLEW_UP)) ) {
6193 if ( !game_start_mission() ) // this should put us into a new state.
6198 // if we are coming from the briefing, ship select, weapons loadout, or main menu (in the
6199 // case of quick start), then do bitmap loads, etc Don't do any of the loading stuff
6200 // if we are in multiplayer -- this stuff is all handled in the multi-wait section
6201 if ( !(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_BRIEFING) || (old_state == GS_STATE_SHIP_SELECT) ||
6202 (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) ) {
6203 // JAS: Used to do all paging here.
6207 HUD_printf("Skill level is set to ** %s **", Skill_level_names(Game_skill_level));
6211 main_hall_stop_music();
6212 main_hall_stop_ambient();
6213 event_music_first_pattern(); // start the first pattern
6216 // special code that restores player ship selection and weapons loadout when doing a quick start
6217 if ( !(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_DEATH_BLEW_UP) || (old_state == GS_STATE_GAME_PLAY) ) {
6218 if ( !stricmp(Player_loadout.filename, Game_current_mission_filename) ) {
6219 wss_direct_restore_loadout();
6223 // single-player, quick-start after just died... we need to set weapon linking and kick off the event music
6224 if (!(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_DEATH_BLEW_UP) ) {
6225 event_music_first_pattern(); // start the first pattern
6228 if ( !(Game_mode & GM_STANDALONE_SERVER) && (old_state != GS_STATE_GAME_PAUSED) && (old_state != GS_STATE_MULTI_PAUSED) ) {
6229 event_music_first_pattern(); // start the first pattern
6231 player_restore_target_and_weapon_link_prefs();
6233 Game_mode |= GM_IN_MISSION;
6236 // required to truely make mouse deltas zeroed in debug mouse code
6237 void mouse_force_pos(int x, int y);
6238 if (!Is_standalone) {
6239 mouse_force_pos(gr_screen.max_w / 2, gr_screen.max_h / 2);
6245 // only start time if in single player, or coming from multi wait state
6248 (Game_mode & GM_NORMAL) &&
6249 (old_state != GS_STATE_VIEW_CUTSCENES)
6251 (Game_mode & GM_MULTIPLAYER) && (
6252 (old_state == GS_STATE_MULTI_PAUSED) ||
6253 (old_state == GS_STATE_MULTI_MISSION_SYNC)
6259 // when coming from the multi paused state, reset the timestamps
6260 if ( (Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_MULTI_PAUSED) ){
6261 multi_reset_timestamps();
6264 if ((Game_mode & GM_MULTIPLAYER) && (old_state != GS_STATE_DEATH_BLEW_UP) ) {
6265 // initialize all object update details
6266 multi_oo_gameplay_init();
6269 // under certain circumstances, the server should reset the object update rate limiting stuff
6270 if( ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)) &&
6271 (old_state == GS_STATE_MULTI_PAUSED) || (old_state == GS_STATE_MULTI_MISSION_SYNC) ){
6273 // reinitialize the rate limiting system for all clients
6274 multi_oo_rate_init_all();
6277 // multiplayer clients should always re-initialize their control info rate limiting system
6278 if((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)){
6279 multi_oo_rate_init_all();
6283 if(Game_mode & GM_MULTIPLAYER){
6284 multi_ping_reset_players();
6287 Game_subspace_effect = 0;
6288 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
6289 Game_subspace_effect = 1;
6290 if( !(Game_mode & GM_STANDALONE_SERVER) ){
6291 game_start_subspace_ambient_sound();
6295 sound_env_set(&Game_sound_env);
6296 joy_ff_mission_init(Ship_info[Player_ship->ship_info_index].rotation_time);
6298 // clear multiplayer button info i
6299 extern button_info Multi_ship_status_bi;
6300 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
6303 case GS_STATE_HUD_CONFIG:
6307 case GS_STATE_MULTI_JOIN_GAME:
6308 multi_join_clear_game_list();
6310 if (old_state != GS_STATE_OPTIONS_MENU) {
6311 multi_join_game_init();
6316 case GS_STATE_MULTI_HOST_SETUP:
6317 // don't reinitialize if we're coming back from the host options screen
6318 if ((old_state != GS_STATE_MULTI_HOST_OPTIONS) && (old_state != GS_STATE_OPTIONS_MENU)) {
6319 multi_create_game_init();
6324 case GS_STATE_MULTI_CLIENT_SETUP:
6325 if (old_state != GS_STATE_OPTIONS_MENU) {
6326 multi_game_client_setup_init();
6331 case GS_STATE_CONTROL_CONFIG:
6332 control_config_init();
6335 case GS_STATE_TECH_MENU:
6339 case GS_STATE_BARRACKS_MENU:
6340 if(old_state != GS_STATE_VIEW_MEDALS){
6345 case GS_STATE_MISSION_LOG_SCROLLBACK:
6346 hud_scrollback_init();
6349 case GS_STATE_DEATH_DIED:
6350 Player_died_time = timestamp(10);
6352 if(!(Game_mode & GM_MULTIPLAYER)){
6353 player_show_death_message();
6355 Game_mode |= GM_DEAD_DIED;
6358 case GS_STATE_DEATH_BLEW_UP:
6359 if ( !popupdead_is_active() ) {
6360 Player_ai->target_objnum = -1;
6363 // stop any local EMP effect
6366 Players[Player_num].flags &= ~PLAYER_FLAGS_AUTO_TARGETING; // Prevent immediate switch to a hostile ship.
6367 Game_mode |= GM_DEAD_BLEW_UP;
6368 Show_viewing_from_self = 0;
6370 // timestamp how long we should wait before displaying the died popup
6371 if ( !popupdead_is_active() ) {
6372 Player_died_popup_wait = timestamp(PLAYER_DIED_POPUP_WAIT);
6376 case GS_STATE_GAMEPLAY_HELP:
6377 gameplay_help_init();
6380 case GS_STATE_CREDITS:
6381 main_hall_stop_music();
6382 main_hall_stop_ambient();
6386 case GS_STATE_VIEW_MEDALS:
6387 medal_main_init(Player);
6390 case GS_STATE_SHOW_GOALS:
6391 mission_show_goals_init();
6394 case GS_STATE_HOTKEY_SCREEN:
6395 mission_hotkey_init();
6398 case GS_STATE_MULTI_MISSION_SYNC:
6399 // if we're coming from the options screen, don't do any
6400 if(old_state == GS_STATE_OPTIONS_MENU){
6404 switch(Multi_sync_mode){
6405 case MULTI_SYNC_PRE_BRIEFING:
6406 // if moving from game forming to the team select state
6409 case MULTI_SYNC_POST_BRIEFING:
6410 // if moving from briefing into the mission itself
6413 // tell everyone that we're now loading data
6414 Net_player->state = NETPLAYER_STATE_DATA_LOAD;
6415 send_netplayer_update_packet();
6417 // JAS: Used to do all paging here!!!!
6419 Net_player->state = NETPLAYER_STATE_WAITING;
6420 send_netplayer_update_packet();
6422 Game_time_compression = F1_0;
6424 case MULTI_SYNC_INGAME:
6430 case GS_STATE_VIEW_CUTSCENES:
6431 cutscenes_screen_init();
6434 case GS_STATE_MULTI_STD_WAIT:
6435 multi_standalone_wait_init();
6438 case GS_STATE_STANDALONE_MAIN:
6439 // don't initialize if we're coming from one of these 2 states unless there are no
6440 // players left (reset situation)
6441 if((old_state != GS_STATE_STANDALONE_POSTGAME) || multi_endgame_ending()){
6442 standalone_main_init();
6446 case GS_STATE_MULTI_PAUSED:
6450 case GS_STATE_INGAME_PRE_JOIN:
6451 multi_ingame_select_init();
6454 case GS_STATE_STANDALONE_POSTGAME:
6455 multi_standalone_postgame_init();
6458 case GS_STATE_INITIAL_PLAYER_SELECT:
6459 player_select_init();
6462 case GS_STATE_MULTI_START_GAME:
6463 multi_start_game_init();
6466 case GS_STATE_MULTI_HOST_OPTIONS:
6467 multi_host_options_init();
6470 case GS_STATE_END_OF_CAMPAIGN:
6471 mission_campaign_end_init();
6474 case GS_STATE_LOOP_BRIEF:
6481 // do stuff that may need to be done regardless of state
6482 void game_do_state_common(int state,int no_networking)
6484 game_maybe_draw_mouse(flFrametime); // determine if to draw the mouse this frame
6485 snd_do_frame(); // update sound system
6486 event_music_do_frame(); // music needs to play across many states
6488 multi_log_process();
6490 if (no_networking) {
6494 // maybe do a multiplayer frame based on game mode and state type
6495 if (Game_mode & GM_MULTIPLAYER) {
6497 case GS_STATE_OPTIONS_MENU:
6498 case GS_STATE_GAMEPLAY_HELP:
6499 case GS_STATE_HOTKEY_SCREEN:
6500 case GS_STATE_HUD_CONFIG:
6501 case GS_STATE_CONTROL_CONFIG:
6502 case GS_STATE_MISSION_LOG_SCROLLBACK:
6503 case GS_STATE_SHOW_GOALS:
6504 case GS_STATE_VIEW_CUTSCENES:
6505 case GS_STATE_EVENT_DEBUG:
6506 multi_maybe_do_frame();
6510 game_do_networking();
6514 // Called once a frame.
6515 // You should never try to change the state
6516 // in here... if you think you need to, you probably really
6517 // need to post an event, not change the state.
6518 int Game_do_state_should_skip = 0;
6519 void game_do_state(int state)
6521 // always lets the do_state_common() function determine if the state should be skipped
6522 Game_do_state_should_skip = 0;
6524 // legal to set the should skip state anywhere in this function
6525 game_do_state_common(state); // do stuff that may need to be done regardless of state
6527 if(Game_do_state_should_skip){
6532 case GS_STATE_MAIN_MENU:
6533 game_set_frametime(GS_STATE_MAIN_MENU);
6534 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
6537 main_hall_do(flFrametime);
6541 case GS_STATE_OPTIONS_MENU:
6542 game_set_frametime(GS_STATE_OPTIONS_MENU);
6543 options_menu_do_frame(flFrametime);
6546 case GS_STATE_BARRACKS_MENU:
6547 game_set_frametime(GS_STATE_BARRACKS_MENU);
6548 barracks_do_frame(flFrametime);
6551 case GS_STATE_TRAINING_MENU:
6552 game_set_frametime(GS_STATE_TRAINING_MENU);
6553 training_menu_do_frame(flFrametime);
6556 case GS_STATE_TECH_MENU:
6557 game_set_frametime(GS_STATE_TECH_MENU);
6558 techroom_do_frame(flFrametime);
6561 case GS_STATE_GAMEPLAY_HELP:
6562 game_set_frametime(GS_STATE_GAMEPLAY_HELP);
6563 gameplay_help_do_frame(flFrametime);
6566 case GS_STATE_GAME_PLAY: // do stuff that should be done during gameplay
6570 case GS_STATE_GAME_PAUSED:
6574 case GS_STATE_DEBUG_PAUSED:
6576 game_set_frametime(GS_STATE_DEBUG_PAUSED);
6581 case GS_STATE_TRAINING_PAUSED:
6582 game_training_pause_do();
6585 case GS_STATE_LOAD_MISSION_MENU:
6586 game_set_frametime(GS_STATE_LOAD_MISSION_MENU);
6587 mission_load_menu_do();
6590 case GS_STATE_BRIEFING:
6591 game_set_frametime(GS_STATE_BRIEFING);
6592 brief_do_frame(flFrametime);
6595 case GS_STATE_DEBRIEF:
6596 game_set_frametime(GS_STATE_DEBRIEF);
6597 debrief_do_frame(flFrametime);
6600 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6601 game_set_frametime(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
6602 multi_df_debrief_do();
6605 case GS_STATE_SHIP_SELECT:
6606 game_set_frametime(GS_STATE_SHIP_SELECT);
6607 ship_select_do(flFrametime);
6610 case GS_STATE_WEAPON_SELECT:
6611 game_set_frametime(GS_STATE_WEAPON_SELECT);
6612 weapon_select_do(flFrametime);
6615 case GS_STATE_MISSION_LOG_SCROLLBACK:
6616 game_set_frametime(GS_STATE_MISSION_LOG_SCROLLBACK);
6617 hud_scrollback_do_frame(flFrametime);
6620 case GS_STATE_HUD_CONFIG:
6621 game_set_frametime(GS_STATE_HUD_CONFIG);
6622 hud_config_do_frame(flFrametime);
6625 case GS_STATE_MULTI_JOIN_GAME:
6626 game_set_frametime(GS_STATE_MULTI_JOIN_GAME);
6627 multi_join_game_do_frame();
6630 case GS_STATE_MULTI_HOST_SETUP:
6631 game_set_frametime(GS_STATE_MULTI_HOST_SETUP);
6632 multi_create_game_do();
6635 case GS_STATE_MULTI_CLIENT_SETUP:
6636 game_set_frametime(GS_STATE_MULTI_CLIENT_SETUP);
6637 multi_game_client_setup_do_frame();
6640 case GS_STATE_CONTROL_CONFIG:
6641 game_set_frametime(GS_STATE_CONTROL_CONFIG);
6642 control_config_do_frame(flFrametime);
6645 case GS_STATE_DEATH_DIED:
6649 case GS_STATE_DEATH_BLEW_UP:
6653 case GS_STATE_SIMULATOR_ROOM:
6654 game_set_frametime(GS_STATE_SIMULATOR_ROOM);
6655 sim_room_do_frame(flFrametime);
6658 case GS_STATE_CAMPAIGN_ROOM:
6659 game_set_frametime(GS_STATE_CAMPAIGN_ROOM);
6660 campaign_room_do_frame(flFrametime);
6663 case GS_STATE_RED_ALERT:
6664 game_set_frametime(GS_STATE_RED_ALERT);
6665 red_alert_do_frame(flFrametime);
6668 case GS_STATE_CMD_BRIEF:
6669 game_set_frametime(GS_STATE_CMD_BRIEF);
6670 cmd_brief_do_frame(flFrametime);
6673 case GS_STATE_CREDITS:
6674 game_set_frametime(GS_STATE_CREDITS);
6675 credits_do_frame(flFrametime);
6678 case GS_STATE_VIEW_MEDALS:
6679 game_set_frametime(GS_STATE_VIEW_MEDALS);
6683 case GS_STATE_SHOW_GOALS:
6684 game_set_frametime(GS_STATE_SHOW_GOALS);
6685 mission_show_goals_do_frame(flFrametime);
6688 case GS_STATE_HOTKEY_SCREEN:
6689 game_set_frametime(GS_STATE_HOTKEY_SCREEN);
6690 mission_hotkey_do_frame(flFrametime);
6693 case GS_STATE_VIEW_CUTSCENES:
6694 game_set_frametime(GS_STATE_VIEW_CUTSCENES);
6695 cutscenes_screen_do_frame();
6698 case GS_STATE_MULTI_STD_WAIT:
6699 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6700 multi_standalone_wait_do();
6703 case GS_STATE_STANDALONE_MAIN:
6704 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6705 standalone_main_do();
6708 case GS_STATE_MULTI_PAUSED:
6709 game_set_frametime(GS_STATE_MULTI_PAUSED);
6713 case GS_STATE_TEAM_SELECT:
6714 game_set_frametime(GS_STATE_TEAM_SELECT);
6718 case GS_STATE_INGAME_PRE_JOIN:
6719 game_set_frametime(GS_STATE_INGAME_PRE_JOIN);
6720 multi_ingame_select_do();
6723 case GS_STATE_EVENT_DEBUG:
6725 game_set_frametime(GS_STATE_EVENT_DEBUG);
6726 game_show_event_debug(flFrametime);
6730 case GS_STATE_STANDALONE_POSTGAME:
6731 game_set_frametime(GS_STATE_STANDALONE_POSTGAME);
6732 multi_standalone_postgame_do();
6735 case GS_STATE_INITIAL_PLAYER_SELECT:
6736 game_set_frametime(GS_STATE_INITIAL_PLAYER_SELECT);
6740 case GS_STATE_MULTI_MISSION_SYNC:
6741 game_set_frametime(GS_STATE_MULTI_MISSION_SYNC);
6745 case GS_STATE_MULTI_START_GAME:
6746 game_set_frametime(GS_STATE_MULTI_START_GAME);
6747 multi_start_game_do();
6750 case GS_STATE_MULTI_HOST_OPTIONS:
6751 game_set_frametime(GS_STATE_MULTI_HOST_OPTIONS);
6752 multi_host_options_do();
6755 case GS_STATE_END_OF_CAMPAIGN:
6756 mission_campaign_end_do();
6759 case GS_STATE_END_DEMO:
6760 game_set_frametime(GS_STATE_END_DEMO);
6761 end_demo_campaign_do();
6764 case GS_STATE_LOOP_BRIEF:
6765 game_set_frametime(GS_STATE_LOOP_BRIEF);
6769 } // end switch(gs_current_state)
6773 // return 0 if there is enough RAM to run FreeSpace, otherwise return -1
6774 int game_do_ram_check(int ram_in_bytes)
6776 if ( ram_in_bytes < 30*1024*1024 ) {
6777 int allowed_to_run = 1;
6778 if ( ram_in_bytes < 25*1024*1024 ) {
6783 int Freespace_total_ram_MB;
6784 Freespace_total_ram_MB = fl2i(ram_in_bytes/(1024*1024));
6786 if ( allowed_to_run ) {
6788 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);
6793 msgbox_rval = MessageBox( NULL, tmp, XSTR( "Not Enough RAM", 194), MB_OKCANCEL );
6794 if ( msgbox_rval == IDCANCEL ) {
6801 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);
6803 MessageBox( NULL, tmp, XSTR( "Not Enough RAM", 194), MB_OK );
6814 // Check if there is a freespace.exe in the /update directory (relative to where fs.exe is installed).
6815 // If so, copy it over and remove the update directory.
6816 void game_maybe_update_launcher(char *exe_dir)
6819 char src_filename[MAX_PATH];
6820 char dest_filename[MAX_PATH];
6822 strcpy(src_filename, exe_dir);
6823 strcat(src_filename, NOX("\\update\\freespace.exe"));
6825 strcpy(dest_filename, exe_dir);
6826 strcat(dest_filename, NOX("\\freespace.exe"));
6828 // see if src_filename exists
6830 fp = fopen(src_filename, "rb");
6836 SetFileAttributes(dest_filename, FILE_ATTRIBUTE_NORMAL);
6838 // copy updated freespace.exe to freespace exe dir
6839 if ( CopyFile(src_filename, dest_filename, 0) == 0 ) {
6840 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 );
6844 // delete the file in the update directory
6845 DeleteFile(src_filename);
6847 // safe to assume directory is empty, since freespace.exe should only be the file ever in the update dir
6848 char update_dir[MAX_PATH];
6849 strcpy(update_dir, exe_dir);
6850 strcat(update_dir, NOX("\\update"));
6851 RemoveDirectory(update_dir);
6857 void game_spew_pof_info_sub(int model_num, polymodel *pm, int sm, CFILE *out, int *out_total, int *out_destroyed_total)
6861 int sub_total_destroyed = 0;
6865 // get the total for all his children
6866 for (i=pm->submodel[sm].first_child; i>-1; i = pm->submodel[i].next_sibling ) {
6867 game_spew_pof_info_sub(model_num, pm, i, out, &sub_total, &sub_total_destroyed);
6870 // find the # of faces for this _individual_ object
6871 total = submodel_get_num_polys(model_num, sm);
6872 if(strstr(pm->submodel[sm].name, "-destroyed")){
6873 sub_total_destroyed = total;
6877 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[sm].name, total);
6880 *out_total += total + sub_total;
6881 *out_destroyed_total += sub_total_destroyed;
6884 #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);
6885 void game_spew_pof_info()
6887 char *pof_list[1000];
6890 int idx, model_num, i, j;
6892 int total, root_total, model_total, destroyed_total, counted;
6896 num_files = cf_get_file_list(1000, pof_list, CF_TYPE_MODELS, "*.pof");
6898 // spew info on all the pofs
6904 out = cfopen("pofspew.txt", "wt", CFILE_NORMAL, CF_TYPE_DATA);
6909 for(idx=0; idx<num_files; idx++, counted++){
6910 sprintf(str, "%s.pof", pof_list[idx]);
6911 model_num = model_load(str, 0, NULL);
6913 pm = model_get(model_num);
6915 // if we have a real model
6920 // go through and print all raw submodels
6921 cfputs("RAW\n", out);
6924 for (i=0; i<pm->n_models; i++) {
6925 total = submodel_get_num_polys(model_num, i);
6927 model_total += total;
6928 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[i].name, total);
6931 sprintf(str, "Model total %d\n", model_total);
6934 // now go through and do it by LOD
6935 cfputs("BY LOD\n\n", out);
6936 for(i=0; i<pm->n_detail_levels; i++){
6937 sprintf(str, "LOD %d\n", i);
6941 root_total = submodel_get_num_polys(model_num, pm->detail[i] );
6943 destroyed_total = 0;
6944 for (j=pm->submodel[pm->detail[i]].first_child; j>-1; j = pm->submodel[j].next_sibling ) {
6945 game_spew_pof_info_sub(model_num, pm, j, out, &total, &destroyed_total);
6948 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[pm->detail[i]].name, root_total);
6951 sprintf(str, "TOTAL: %d\n", total + root_total);
6953 sprintf(str, "TOTAL not counting destroyed faces %d\n", (total + root_total) - destroyed_total);
6955 sprintf(str, "TOTAL destroyed faces %d\n\n", destroyed_total);
6958 cfputs("------------------------------------------------------------------------\n\n", out);
6962 if(counted >= MAX_POLYGON_MODELS - 5){
6975 game_spew_pof_info();
6978 int PASCAL WinMainSub(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
6983 // Don't let more than one instance of Freespace run.
6984 HWND hwnd = FindWindow( NOX( "FreeSpaceClass" ), NULL );
6986 SetForegroundWindow(hwnd);
6991 // Find out how much RAM is on this machine
6994 ms.dwLength = sizeof(MEMORYSTATUS);
6995 GlobalMemoryStatus(&ms);
6996 Freespace_total_ram = ms.dwTotalPhys;
6998 if ( game_do_ram_check(Freespace_total_ram) == -1 ) {
7002 if ( ms.dwTotalVirtual < 1024 ) {
7003 MessageBox( NULL, XSTR( "FreeSpace requires virtual memory to run.\r\n", 196), XSTR( "No Virtual Memory", 197), MB_OK );
7007 if (!vm_init(24*1024*1024)) {
7008 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 );
7012 char *tmp_mem = (char *) malloc(16 * 1024 * 1024);
7014 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);
7022 /* this code doesn't work, and we will hit an error about being unable to load the direct draw
7023 dll before we get here anyway if it's not installed (unless we load it manually, which doesn't
7024 seem worth bothering with.
7028 lResult = RegOpenKeyEx(
7029 HKEY_LOCAL_MACHINE, // Where it is
7030 "Software\\Microsoft\\DirectX", // name of key
7031 NULL, // DWORD reserved
7032 KEY_QUERY_VALUE, // Allows all changes
7033 &hKey // Location to store key
7036 if (lResult == ERROR_SUCCESS) {
7038 DWORD dwType, dwLen;
7041 lResult = RegQueryValueEx(
7042 hKey, // Handle to key
7043 "Version", // The values name
7044 NULL, // DWORD reserved
7045 &dwType, // What kind it is
7046 (ubyte *) version, // value to set
7047 &dwLen // How many bytes to set
7050 if (lResult == ERROR_SUCCESS) {
7051 dx_version = atoi(strstr(version, ".") + 1);
7055 DWORD dwType, dwLen;
7058 lResult = RegQueryValueEx(
7059 hKey, // Handle to key
7060 "InstalledVersion", // The values name
7061 NULL, // DWORD reserved
7062 &dwType, // What kind it is
7063 (ubyte *) &val, // value to set
7064 &dwLen // How many bytes to set
7067 if (lResult == ERROR_SUCCESS) {
7075 if (dx_version < 3) {
7076 MessageBox(NULL, "DirectX 3.0 or higher is required and wasn't detected. You can get the\n"
7077 "latest version of DirectX at:\n\n"
7078 "http://www.microsoft.com/msdownload/directx/dxf/enduser5.0/default.htm", "DirectX required", MB_OK);
7080 MessageBox(NULL, "DirectX 3.0 or higher is required and wasn't detected. You can install\n"
7081 "DirectX 5.2 by pressing the 'Install DirectX' button on the FreeSpace Launcher", "DirectX required", MB_OK);
7086 //=====================================================
7087 // Make sure we're running in the right directory.
7091 if ( GetModuleFileName( hInst, exe_dir, 1023 ) > 0 ) {
7092 char *p = exe_dir + strlen(exe_dir);
7094 // chop off the filename
7095 while( (p>exe_dir) && (*p!='\\') && (*p!='/') && (*p!=':') ) {
7101 if ( strlen(exe_dir) > 0 ) {
7102 SetCurrentDirectory(exe_dir);
7105 // check for updated freespace.exe
7106 game_maybe_update_launcher(exe_dir);
7114 extern void windebug_memwatch_init();
7115 windebug_memwatch_init();
7119 parse_cmdline(szCmdLine);
7121 #ifdef STANDALONE_ONLY_BUILD
7123 nprintf(("Network", "Standalone running"));
7126 nprintf(("Network", "Standalone running"));
7134 // maybe spew pof stuff
7135 if(Cmdline_spew_pof_info){
7136 game_spew_pof_info();
7141 // non-demo, non-standalone, play the intro movie
7147 // to avoid crashes on debug build
7148 for (i=0; i<5; i++) {
7152 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) ){
7154 #if defined(OEM_BUILD)
7155 game_do_cd_check_specific(FS_CDROM_VOLUME_1, 1);
7157 game_do_cd_check_specific(FS_CDROM_VOLUME_2, 2);
7158 #endif // defined(OEM_BUILD)
7161 for (int i=0; i<5; i++) {
7162 if (plist[i] != NULL) {
7167 #endif // RELEASE_REAL
7170 if ( !Is_standalone ) {
7172 // release -- movies always play
7175 // 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
7176 movie_play( NOX("intro.mve"), 0 );
7178 // debug version, movie will only play with -showmovies
7179 #elif !defined(NDEBUG)
7181 movie_play( NOX("intro.mve"), 0);
7184 if ( Cmdline_show_movies )
7185 movie_play( NOX("intro.mve"), 0 );
7194 gameseq_post_event(GS_EVENT_STANDALONE_MAIN);
7196 gameseq_post_event(GS_EVENT_GAME_INIT); // start the game rolling -- check for default pilot, or go to the pilot select screen
7200 // only important for non THREADED mode
7203 state = gameseq_process_events();
7204 if ( state == GS_STATE_QUIT_GAME ){
7209 #if defined(FS2_DEMO) || defined(FS1_DEMO)
7211 demo_upsell_show_screens();
7213 #elif defined(OEM_BUILD)
7214 // show upsell screens on exit
7215 oem_upsell_show_screens();
7222 int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
7228 result = WinMainSub(hInst, hPrev, szCmdLine, nCmdShow);
7230 __except(RecordExceptionInfo(GetExceptionInformation(), "Freespace 2 Main Thread"))
7232 // Do nothing here - RecordExceptionInfo() has already done
7233 // everything that is needed. Actually this code won't even
7234 // get called unless you return EXCEPTION_EXECUTE_HANDLER from
7235 // the __except clause.
7239 nprintf(("WinMain", "exceptions shall fall through"));
7241 result = WinMainSub(hInst, hPrev, szCmdLine, nCmdShow);
7247 // launcher the fslauncher program on exit
7248 void game_launch_launcher_on_exit()
7252 PROCESS_INFORMATION pi;
7253 char cmd_line[2048];
7254 char original_path[1024] = "";
7256 memset( &si, 0, sizeof(STARTUPINFO) );
7260 _getcwd(original_path, 1023);
7262 // set up command line
7263 strcpy(cmd_line, original_path);
7264 strcat(cmd_line, "\\");
7265 strcat(cmd_line, LAUNCHER_FNAME);
7266 strcat(cmd_line, " -straight_to_update");
7268 BOOL ret = CreateProcess( NULL, // pointer to name of executable module
7269 cmd_line, // pointer to command line string
7270 NULL, // pointer to process security attributes
7271 NULL, // pointer to thread security attributes
7272 FALSE, // handle inheritance flag
7273 CREATE_DEFAULT_ERROR_MODE, // creation flags
7274 NULL, // pointer to new environment block
7275 NULL, // pointer to current directory name
7276 &si, // pointer to STARTUPINFO
7277 &pi // pointer to PROCESS_INFORMATION
7279 // to eliminate build warnings
7289 // This function is called when FreeSpace terminates normally.
7291 void game_shutdown(void)
7297 // don't ever flip a page on the standalone!
7298 if(!(Game_mode & GM_STANDALONE_SERVER)){
7304 // if the player has left the "player select" screen and quit the game without actually choosing
7305 // a player, Player will be NULL, in which case we shouldn't write the player file out!
7306 if (!(Game_mode & GM_STANDALONE_SERVER) && (Player!=NULL) && !Is_standalone){
7310 // load up common multiplayer icons
7311 multi_unload_common_icons();
7313 shockwave_close(); // release any memory used by shockwave system
7314 fireball_close(); // free fireball system
7315 ship_close(); // free any memory that was allocated for the ships
7316 weapon_close(); // free any memory that was allocated for the weapons
7317 hud_free_scrollback_list();// free space allocated to store hud messages in hud scrollback
7318 unload_animating_pointer();// frees the frames used for the animating mouse pointer
7319 bm_unload_all(); // free bitmaps
7320 mission_campaign_close(); // close out the campaign stuff
7321 mission_campaign_shutdown(); // get anything that mission_campaign_close can't do
7322 multi_voice_close(); // close down multiplayer voice (including freeing buffers, etc)
7324 #ifdef MULTI_USE_LAG
7328 // the menu close functions will unload the bitmaps if they were displayed during the game
7329 #if !defined(PRESS_TOUR_BUILD) && !defined(PD_BUILD)
7332 context_help_close(); // close out help system
7333 training_menu_close();
7334 lcl_close(); // be sure localization is closed out
7337 // free left-over memory from parsed tables
7338 cutscene_tbl_close();
7340 scoring_tbl_close();
7341 player_tips_close();
7343 extern void joy_close();
7346 audiostream_close();
7348 event_music_close();
7352 // HACKITY HACK HACK
7353 // if this flag is set, we should be firing up the launcher when exiting freespace
7354 extern int Multi_update_fireup_launcher_on_exit;
7355 if(Multi_update_fireup_launcher_on_exit){
7356 game_launch_launcher_on_exit();
7360 // game_stop_looped_sounds()
7362 // This function will call the appropriate stop looped sound functions for those
7363 // modules which use looping sounds. It is not enough just to stop a looping sound
7364 // at the DirectSound level, the game is keeping track of looping sounds, and this
7365 // function is used to inform the game that looping sounds are being halted.
7367 void game_stop_looped_sounds()
7369 hud_stop_looped_locking_sounds();
7370 hud_stop_looped_engine_sounds();
7371 afterburner_stop_sounds();
7372 player_stop_looped_sounds();
7373 obj_snd_stop_all(); // stop all object-linked persistant sounds
7374 game_stop_subspace_ambient_sound();
7375 snd_stop(Radar_static_looping);
7376 Radar_static_looping = -1;
7377 snd_stop(Target_static_looping);
7378 shipfx_stop_engine_wash_sound();
7379 Target_static_looping = -1;
7382 //////////////////////////////////////////////////////////////////////////
7384 // Code for supporting an animating mouse pointer
7387 //////////////////////////////////////////////////////////////////////////
7389 typedef struct animating_obj
7398 static animating_obj Animating_mouse;
7400 // ----------------------------------------------------------------------------
7401 // init_animating_pointer()
7403 // Called by load_animating_pointer() to ensure the Animating_mouse struct
7404 // gets properly initialized
7406 void init_animating_pointer()
7408 Animating_mouse.first_frame = -1;
7409 Animating_mouse.num_frames = 0;
7410 Animating_mouse.current_frame = -1;
7411 Animating_mouse.time = 0.0f;
7412 Animating_mouse.elapsed_time = 0.0f;
7415 // ----------------------------------------------------------------------------
7416 // load_animating_pointer()
7418 // Called at game init to load in the frames for the animating mouse pointer
7420 // input: filename => filename of animation file that holds the animation
7422 void load_animating_pointer(char *filename, int dx, int dy)
7427 init_animating_pointer();
7429 am = &Animating_mouse;
7430 am->first_frame = bm_load_animation(filename, &am->num_frames, &fps);
7431 if ( am->first_frame == -1 )
7432 Error(LOCATION, "Could not load animation %s for the mouse pointer\n", filename);
7433 am->current_frame = 0;
7434 am->time = am->num_frames / i2fl(fps);
7437 // ----------------------------------------------------------------------------
7438 // unload_animating_pointer()
7440 // Called at game shutdown to free the memory used to store the animation frames
7442 void unload_animating_pointer()
7447 am = &Animating_mouse;
7448 for ( i = 0; i < am->num_frames; i++ ) {
7449 Assert( (am->first_frame+i) >= 0 );
7450 bm_release(am->first_frame + i);
7453 am->first_frame = -1;
7455 am->current_frame = -1;
7458 // draw the correct frame of the game mouse... called from game_maybe_draw_mouse()
7459 void game_render_mouse(float frametime)
7464 // if animating cursor exists, play the next frame
7465 am = &Animating_mouse;
7466 if ( am->first_frame != -1 ) {
7467 mouse_get_pos(&mx, &my);
7468 am->elapsed_time += frametime;
7469 am->current_frame = fl2i( ( am->elapsed_time / am->time ) * (am->num_frames-1) );
7470 if ( am->current_frame >= am->num_frames ) {
7471 am->current_frame = 0;
7472 am->elapsed_time = 0.0f;
7474 gr_set_cursor_bitmap(am->first_frame + am->current_frame);
7478 // ----------------------------------------------------------------------------
7479 // game_maybe_draw_mouse()
7481 // determines whether to draw the mouse pointer at all, and what frame of
7482 // animation to use if the mouse is animating
7484 // Sets mouse.cpp globals Mouse_hidden and Mouse_moved based on the state of the game.
7486 // input: frametime => elapsed frame time in seconds since last call
7488 void game_maybe_draw_mouse(float frametime)
7492 game_state = gameseq_get_state();
7494 switch ( game_state ) {
7495 case GS_STATE_GAME_PAUSED:
7496 // case GS_STATE_MULTI_PAUSED:
7497 case GS_STATE_GAME_PLAY:
7498 case GS_STATE_DEATH_DIED:
7499 case GS_STATE_DEATH_BLEW_UP:
7500 if ( popup_active() || popupdead_is_active() ) {
7512 if ( !Mouse_hidden )
7513 game_render_mouse(frametime);
7517 void game_do_training_checks()
7521 waypoint_list *wplp;
7523 if (Training_context & TRAINING_CONTEXT_SPEED) {
7524 s = (int) Player_obj->phys_info.fspeed;
7525 if ((s >= Training_context_speed_min) && (s <= Training_context_speed_max)) {
7526 if (!Training_context_speed_set) {
7527 Training_context_speed_set = 1;
7528 Training_context_speed_timestamp = timestamp();
7532 Training_context_speed_set = 0;
7535 if (Training_context & TRAINING_CONTEXT_FLY_PATH) {
7536 wplp = &Waypoint_lists[Training_context_path];
7537 if (wplp->count > Training_context_goal_waypoint) {
7538 i = Training_context_goal_waypoint;
7540 d = vm_vec_dist(&wplp->waypoints[i], &Player_obj->pos);
7541 if (d <= Training_context_distance) {
7542 Training_context_at_waypoint = i;
7543 if (Training_context_goal_waypoint == i) {
7544 Training_context_goal_waypoint++;
7545 snd_play(&Snds[SND_CARGO_REVEAL], 0.0f);
7552 if (i == wplp->count)
7555 } while (i != Training_context_goal_waypoint);
7559 if ((Players_target == UNINITIALIZED) || (Player_ai->target_objnum != Players_target) || (Player_ai->targeted_subsys != Players_targeted_subsys)) {
7560 Players_target = Player_ai->target_objnum;
7561 Players_targeted_subsys = Player_ai->targeted_subsys;
7562 Players_target_timestamp = timestamp();
7566 /////////// Following is for event debug view screen
7570 #define EVENT_DEBUG_MAX 5000
7571 #define EVENT_DEBUG_EVENT 0x8000
7573 int Event_debug_index[EVENT_DEBUG_MAX];
7576 void game_add_event_debug_index(int n, int indent)
7578 if (ED_count < EVENT_DEBUG_MAX)
7579 Event_debug_index[ED_count++] = n | (indent << 16);
7582 void game_add_event_debug_sexp(int n, int indent)
7587 if (Sexp_nodes[n].first >= 0) {
7588 game_add_event_debug_sexp(Sexp_nodes[n].first, indent);
7589 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7593 game_add_event_debug_index(n, indent);
7594 if (Sexp_nodes[n].subtype == SEXP_ATOM_OPERATOR)
7595 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent + 1);
7597 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7600 void game_event_debug_init()
7605 for (e=0; e<Num_mission_events; e++) {
7606 game_add_event_debug_index(e | EVENT_DEBUG_EVENT, 0);
7607 game_add_event_debug_sexp(Mission_events[e].formula, 1);
7611 void game_show_event_debug(float frametime)
7615 int font_height, font_width;
7617 static int scroll_offset = 0;
7619 k = game_check_key();
7625 if (scroll_offset < 0)
7635 scroll_offset -= 20;
7636 if (scroll_offset < 0)
7641 scroll_offset += 20; // not font-independent, hard-coded since I counted the lines!
7645 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
7651 gr_set_color_fast(&Color_bright);
7653 gr_printf(0x8000, 5, NOX("EVENT DEBUG VIEW"));
7655 gr_set_color_fast(&Color_normal);
7657 gr_get_string_size(&font_width, &font_height, NOX("test"));
7658 y_max = gr_screen.max_h - font_height - 5;
7662 while (k < ED_count) {
7663 if (y_index > y_max)
7666 z = Event_debug_index[k];
7667 if (z & EVENT_DEBUG_EVENT) {
7669 sprintf(buf, NOX("%s%s (%s) %s%d %d"), (Mission_events[z].flags & MEF_CURRENT) ? NOX("* ") : "",
7670 Mission_events[z].name, Mission_events[z].result ? NOX("True") : NOX("False"),
7671 (Mission_events[z].chain_delay < 0) ? "" : NOX("x "),
7672 Mission_events[z].repeat_count, Mission_events[z].interval);
7680 strcat(buf, Sexp_nodes[z & 0x7fff].text);
7681 switch (Sexp_nodes[z & 0x7fff].value) {
7683 strcat(buf, NOX(" (True)"));
7687 strcat(buf, NOX(" (False)"));
7690 case SEXP_KNOWN_TRUE:
7691 strcat(buf, NOX(" (Always true)"));
7694 case SEXP_KNOWN_FALSE:
7695 strcat(buf, NOX(" (Always false)"));
7698 case SEXP_CANT_EVAL:
7699 strcat(buf, NOX(" (Can't eval)"));
7703 case SEXP_NAN_FOREVER:
7704 strcat(buf, NOX(" (Not a number)"));
7709 gr_printf(10, y_index, buf);
7710 y_index += font_height;
7723 extern int Tmap_npixels;
7725 int Tmap_num_too_big = 0;
7726 int Num_models_needing_splitting = 0;
7728 void Time_model( int modelnum )
7730 // mprintf(( "Timing ship '%s'\n", si->name ));
7732 vector eye_pos, model_pos;
7733 matrix eye_orient, model_orient;
7735 polymodel *pm = model_get( modelnum );
7737 int l = strlen(pm->filename);
7739 if ( (l == '/') || (l=='\\') || (l==':')) {
7745 char *pof_file = &pm->filename[l];
7747 int model_needs_splitting = 0;
7749 //fprintf( Texture_fp, "Model: %s\n", pof_file );
7751 for (i=0; i<pm->n_textures; i++ ) {
7752 char filename[1024];
7755 int bmp_num = pm->original_textures[i];
7756 if ( bmp_num > -1 ) {
7757 bm_get_palette(pm->original_textures[i], pal, filename );
7759 bm_get_info( pm->original_textures[i],&w, &h );
7762 if ( (w > 512) || (h > 512) ) {
7763 fprintf( Texture_fp, "%s\t%s\t%d\t%d\n", pof_file, filename, w, h );
7765 model_needs_splitting++;
7768 //fprintf( Texture_fp, "\tTexture %d is bogus\n", i );
7772 if ( model_needs_splitting ) {
7773 Num_models_needing_splitting++;
7775 eye_orient = model_orient = vmd_identity_matrix;
7776 eye_pos = model_pos = vmd_zero_vector;
7778 eye_pos.xyz.z = -pm->rad*2.0f;
7780 vector eye_to_model;
7782 vm_vec_sub( &eye_to_model, &model_pos, &eye_pos );
7783 vm_vector_2_matrix( &eye_orient, &eye_to_model, NULL, NULL );
7785 fix t1 = timer_get_fixed_seconds();
7788 ta.p = ta.b = ta.h = 0.0f;
7793 int bitmaps_used_this_frame, bitmaps_new_this_frame;
7795 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7797 modelstats_num_polys = modelstats_num_verts = 0;
7799 while( ta.h < PI2 ) {
7802 vm_angles_2_matrix(&m1, &ta );
7803 vm_matrix_x_matrix( &model_orient, &vmd_identity_matrix, &m1 );
7810 g3_set_view_matrix( &eye_pos, &eye_orient, Viewer_zoom );
7812 model_clear_instance( modelnum );
7813 model_set_detail_level(0); // use highest detail level
7814 model_render( modelnum, &model_orient, &model_pos, MR_LOCK_DETAIL); //|MR_NO_POLYS );
7822 int k = key_inkey();
7823 if ( k == KEY_ESC ) {
7828 fix t2 = timer_get_fixed_seconds();
7830 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7831 //bitmaps_used_this_frame /= framecount;
7833 modelstats_num_polys /= framecount;
7834 modelstats_num_verts /= framecount;
7836 Tmap_npixels /=framecount;
7839 mprintf(( "'%s' is %.2f FPS\n", pof_file, i2fl(framecount)/f2fl(t2-t1) ));
7840 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 );
7841 // 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 );
7847 int Time_models = 0;
7848 DCF_BOOL( time_models, Time_models );
7850 void Do_model_timings_test()
7854 if ( !Time_models ) return;
7856 mprintf(( "Timing models!\n" ));
7860 ubyte model_used[MAX_POLYGON_MODELS];
7861 int model_id[MAX_POLYGON_MODELS];
7862 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7867 for (i=0; i<Num_ship_types; i++ ) {
7868 Ship_info[i].modelnum = model_load( Ship_info[i].pof_file, 0, NULL );
7870 model_used[Ship_info[i].modelnum%MAX_POLYGON_MODELS]++;
7871 model_id[Ship_info[i].modelnum%MAX_POLYGON_MODELS] = Ship_info[i].modelnum;
7874 Texture_fp = fopen( NOX("ShipTextures.txt"), "wt" );
7875 if ( !Texture_fp ) return;
7877 Time_fp = fopen( NOX("ShipTimings.txt"), "wt" );
7878 if ( !Time_fp ) return;
7880 fprintf( Time_fp, "Name\tFPS\tTRAM\tPolys\tVerts\tPixels\n" );
7881 // fprintf( Time_fp, "FPS\tTRAM\tPolys\tVerts\tPixels\n" );
7883 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7884 if ( model_used[i] ) {
7885 Time_model( model_id[i] );
7889 fprintf( Texture_fp, "Number too big: %d\n", Tmap_num_too_big );
7890 fprintf( Texture_fp, "Number of models needing splitting: %d\n", Num_models_needing_splitting );
7899 // Call this function when you want to inform the player that a feature is not
7900 // enabled in the DEMO version of FreSpace
7901 void game_feature_not_in_demo_popup()
7903 popup(PF_USE_AFFIRMATIVE_ICON|PF_BODY_BIG, 1, POPUP_OK, XSTR( "Sorry, this feature is available only in the retail version", 200));
7906 // format the specified time (fixed point) into a nice string
7907 void game_format_time(fix m_time,char *time_str)
7910 int hours,minutes,seconds;
7913 mtime = f2fl(m_time);
7915 // get the hours, minutes and seconds
7916 hours = (int)(mtime / 3600.0f);
7918 mtime -= (3600.0f * (float)hours);
7920 seconds = (int)mtime%60;
7921 minutes = (int)mtime/60;
7923 // print the hour if necessary
7925 sprintf(time_str,XSTR( "%d:", 201),hours);
7926 // if there are less than 10 minutes, print a leading 0
7928 strcpy(tmp,NOX("0"));
7929 strcat(time_str,tmp);
7933 // print the minutes
7935 sprintf(tmp,XSTR( "%d:", 201),minutes);
7936 strcat(time_str,tmp);
7938 sprintf(time_str,XSTR( "%d:", 201),minutes);
7941 // print the seconds
7943 strcpy(tmp,NOX("0"));
7944 strcat(time_str,tmp);
7946 sprintf(tmp,"%d",seconds);
7947 strcat(time_str,tmp);
7950 // Stuff version string in *str.
7951 void get_version_string(char *str)
7954 if ( FS_VERSION_BUILD == 0 ) {
7955 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
7957 sprintf(str,"v%d.%02d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD );
7960 #if defined (FS2_DEMO) || defined(FS1_DEMO)
7962 #elif defined (OEM_BUILD)
7963 strcat(str, " (OEM)");
7969 char myname[_MAX_PATH];
7970 int namelen, major, minor, build, waste;
7971 unsigned int buf_size;
7977 // Find my EXE file name
7978 hMod = GetModuleHandle(NULL);
7979 namelen = GetModuleFileName( hMod, myname, _MAX_PATH );
7981 version_size = GetFileVersionInfoSize(myname, &bogus_handle );
7982 infop = (char *)malloc(version_size);
7983 result = GetFileVersionInfo( myname, 0, version_size, (LPVOID)infop );
7985 // get the product version
7986 result = VerQueryValue((LPVOID)infop, TEXT("\\StringFileInfo\\040904b0\\ProductVersion"), &bufp, &buf_size );
7987 sscanf( (char *)bufp, "%d, %d, %d, %d", &major, &minor, &build, &waste );
7989 sprintf(str,"Dv%d.%02d",major, minor);
7991 sprintf(str,"v%d.%02d",major, minor);
7996 void get_version_string_short(char *str)
7998 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
8001 // ----------------------------------------------------------------
8003 // OEM UPSELL SCREENS BEGIN
8005 // ----------------------------------------------------------------
8006 #if defined(OEM_BUILD)
8008 #define NUM_OEM_UPSELL_SCREENS 3
8009 #define OEM_UPSELL_SCREEN_DELAY 10000
8011 static int Oem_upsell_bitmaps_loaded = 0;
8012 static int Oem_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS];
8013 static int Oem_upsell_screen_number = 0;
8014 static int Oem_upsell_show_next_bitmap_time;
8017 static char *Oem_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS] =
8030 static int Oem_normal_cursor = -1;
8031 static int Oem_web_cursor = -1;
8032 //#define OEM_UPSELL_URL "http://www.interplay-store.com/"
8033 #define OEM_UPSELL_URL "http://www.interplay.com/cgi-bin/oemlinks.pl/pid=483421&cid=18384"
8035 void oem_upsell_next_screen()
8037 Oem_upsell_screen_number++;
8038 if ( Oem_upsell_screen_number == (NUM_OEM_UPSELL_SCREENS-1) ) {
8039 // extra long delay, mouse shown on last upsell
8040 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY*2;
8044 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
8048 void oem_upsell_load_bitmaps()
8052 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
8053 Oem_upsell_bitmaps[gr_screen.res][i] = bm_load(Oem_upsell_bitmap_filenames[gr_screen.res][i]);
8057 void oem_upsell_unload_bitmaps()
8061 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
8062 if(Oem_upsell_bitmaps[gr_screen.res][i] >= 0){
8063 bm_unload(Oem_upsell_bitmaps[gr_screen.res][i]);
8068 Oem_upsell_bitmaps_loaded = 0;
8071 // clickable hotspot on 3rd OEM upsell screen
8072 static int Oem_upsell3_button_coords[GR_NUM_RESOLUTIONS][4] = {
8074 28, 350, 287, 96 // x, y, w, h
8077 45, 561, 460, 152 // x, y, w, h
8081 void oem_upsell_show_screens()
8083 int current_time, k;
8086 if ( !Oem_upsell_bitmaps_loaded ) {
8087 oem_upsell_load_bitmaps();
8088 Oem_upsell_bitmaps_loaded = 1;
8091 // may use upsell screens more than once
8092 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
8093 Oem_upsell_screen_number = 0;
8099 int nframes; // used to pass, not really needed (should be 1)
8100 Oem_normal_cursor = gr_get_cursor_bitmap();
8101 Oem_web_cursor = bm_load_animation("cursorweb", &nframes);
8102 Assert(Oem_web_cursor >= 0);
8103 if (Oem_web_cursor < 0) {
8104 Oem_web_cursor = Oem_normal_cursor;
8109 //oem_reset_trailer_timer();
8111 current_time = timer_get_milliseconds();
8116 // advance screen on keypress or timeout
8117 if (( k > 0 ) || (mouse_up_count(MOUSE_LEFT_BUTTON) > 0) || (current_time > Oem_upsell_show_next_bitmap_time)) {
8118 oem_upsell_next_screen();
8121 // check if we are done
8122 if ( Oem_upsell_screen_number >= NUM_OEM_UPSELL_SCREENS ) {
8123 Oem_upsell_screen_number--;
8126 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] < 0 ) {
8131 // show me the upsell
8132 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] >= 0 ) {
8133 gr_set_bitmap(Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number]);
8137 // if this is the 3rd upsell, make it clickable, d00d
8138 if ( Oem_upsell_screen_number == NUM_OEM_UPSELL_SCREENS-1 ) {
8140 int button_state = mouse_get_pos(&mx, &my);
8141 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])
8142 && (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]) )
8145 gr_set_cursor_bitmap(Oem_web_cursor); //, GR_CURSOR_LOCK);
8148 if (button_state & MOUSE_LEFT_BUTTON) {
8150 multi_pxo_url(OEM_UPSELL_URL);
8154 // switch cursor back to normal one
8155 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
8160 if (gameseq_get_state() != GS_STATE_END_DEMO) {
8170 oem_upsell_unload_bitmaps();
8172 // switch cursor back to normal one
8173 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
8177 #endif // defined(OEM_BUILD)
8178 // ----------------------------------------------------------------
8180 // OEM UPSELL SCREENS END
8182 // ----------------------------------------------------------------
8186 // ----------------------------------------------------------------
8188 // DEMO UPSELL SCREENS BEGIN
8190 // ----------------------------------------------------------------
8192 #if defined(FS2_DEMO) || defined(FS1_DEMO)
8195 #define NUM_DEMO_UPSELL_SCREENS 2
8197 #define NUM_DEMO_UPSELL_SCREENS 4
8199 #define DEMO_UPSELL_SCREEN_DELAY 3000
8201 static int Demo_upsell_bitmaps_loaded = 0;
8202 static int Demo_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS];
8203 static int Demo_upsell_screen_number = 0;
8204 static int Demo_upsell_show_next_bitmap_time;
8207 static char *Demo_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS] =
8233 void demo_upsell_next_screen()
8235 Demo_upsell_screen_number++;
8236 if ( Demo_upsell_screen_number == (NUM_DEMO_UPSELL_SCREENS-1) ) {
8237 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY*4;
8239 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
8243 if ( Demo_upsell_screen_number < NUM_DEMO_UPSELL_SCREENS ) {
8244 if ( Demo_upsell_bitmap_filenames[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
8245 #ifndef HARDWARE_ONLY
8246 palette_use_bm_palette(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8253 void demo_upsell_load_bitmaps()
8257 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8258 Demo_upsell_bitmaps[gr_screen.res][i] = bm_load(Demo_upsell_bitmap_filenames[gr_screen.res][i]);
8262 void demo_upsell_unload_bitmaps()
8266 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8267 if(Demo_upsell_bitmaps[gr_screen.res][i] >= 0){
8268 bm_unload(Demo_upsell_bitmaps[gr_screen.res][i]);
8273 Demo_upsell_bitmaps_loaded = 0;
8276 void demo_upsell_show_screens()
8278 int current_time, k;
8281 if ( !Demo_upsell_bitmaps_loaded ) {
8282 demo_upsell_load_bitmaps();
8283 Demo_upsell_bitmaps_loaded = 1;
8286 // may use upsell screens more than once
8287 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
8288 Demo_upsell_screen_number = 0;
8295 demo_reset_trailer_timer();
8297 current_time = timer_get_milliseconds();
8304 // don't time out, wait for keypress
8306 if ( current_time > Demo_upsell_show_next_bitmap_time ) {
8307 demo_upsell_next_screen();
8312 demo_upsell_next_screen();
8315 if ( Demo_upsell_screen_number >= NUM_DEMO_UPSELL_SCREENS ) {
8316 Demo_upsell_screen_number--;
8319 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] < 0 ) {
8324 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
8325 gr_set_bitmap(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8330 if (gameseq_get_state() != GS_STATE_END_DEMO) {
8340 demo_upsell_unload_bitmaps();
8345 // ----------------------------------------------------------------
8347 // DEMO UPSELL SCREENS END
8349 // ----------------------------------------------------------------
8352 // ----------------------------------------------------------------
8354 // Subspace Ambient Sound START
8356 // ----------------------------------------------------------------
8358 static int Subspace_ambient_left_channel = -1;
8359 static int Subspace_ambient_right_channel = -1;
8362 void game_start_subspace_ambient_sound()
8364 if ( Subspace_ambient_left_channel < 0 ) {
8365 Subspace_ambient_left_channel = snd_play_looping(&Snds[SND_SUBSPACE_LEFT_CHANNEL], -1.0f);
8368 if ( Subspace_ambient_right_channel < 0 ) {
8369 Subspace_ambient_right_channel = snd_play_looping(&Snds[SND_SUBSPACE_RIGHT_CHANNEL], 1.0f);
8373 void game_stop_subspace_ambient_sound()
8375 if ( Subspace_ambient_left_channel >= 0 ) {
8376 snd_stop(Subspace_ambient_left_channel);
8377 Subspace_ambient_left_channel = -1;
8380 if ( Subspace_ambient_right_channel >= 0 ) {
8381 snd_stop(Subspace_ambient_right_channel);
8382 Subspace_ambient_right_channel = -1;
8386 // ----------------------------------------------------------------
8388 // Subspace Ambient Sound END
8390 // ----------------------------------------------------------------
8392 // ----------------------------------------------------------------
8394 // CDROM detection code START
8396 // ----------------------------------------------------------------
8398 #define CD_SIZE_72_MINUTE_MAX (697000000)
8400 uint game_get_cd_used_space(char *path)
8404 char use_path[512] = "";
8405 char sub_path[512] = "";
8406 WIN32_FIND_DATA find;
8409 // recurse through all files and directories
8410 strcpy(use_path, path);
8411 strcat(use_path, "*.*");
8412 find_handle = FindFirstFile(use_path, &find);
8415 if(find_handle == INVALID_HANDLE_VALUE){
8421 // subdirectory. make sure to ignore . and ..
8422 if((find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && stricmp(find.cFileName, ".") && stricmp(find.cFileName, "..")){
8424 strcpy(sub_path, path);
8425 strcat(sub_path, find.cFileName);
8426 strcat(sub_path, "\\");
8427 total += game_get_cd_used_space(sub_path);
8429 total += (uint)find.nFileSizeLow;
8431 } while(FindNextFile(find_handle, &find));
8434 FindClose(find_handle);
8446 // if volume_name is non-null, the CD name must match that
8447 int find_freespace_cd(char *volume_name)
8450 char oldpath[MAX_PATH];
8454 int volume_match = 0;
8458 GetCurrentDirectory(MAX_PATH, oldpath);
8460 for (i = 0; i < 26; i++)
8466 path[0] = (char)('A'+i);
8467 if (GetDriveType(path) == DRIVE_CDROM) {
8469 if ( GetVolumeInformation(path, volume, 256, NULL, NULL, NULL, NULL, 0) == TRUE ) {
8470 nprintf(("CD", "CD volume: %s\n", volume));
8472 // check for any CD volume
8473 int volume1_present = 0;
8474 int volume2_present = 0;
8475 int volume3_present = 0;
8477 char full_check[512] = "";
8479 // look for setup.exe
8480 strcpy(full_check, path);
8481 strcat(full_check, "setup.exe");
8482 find_handle = _findfirst(full_check, &find);
8483 if(find_handle != -1){
8484 volume1_present = 1;
8485 _findclose(find_handle);
8488 // look for intro.mve
8489 strcpy(full_check, path);
8490 strcat(full_check, "intro.mve");
8491 find_handle = _findfirst(full_check, &find);
8492 if(find_handle != -1){
8493 volume2_present = 1;
8494 _findclose(find_handle);
8497 // look for endpart1.mve
8498 strcpy(full_check, path);
8499 strcat(full_check, "endpart1.mve");
8500 find_handle = _findfirst(full_check, &find);
8501 if(find_handle != -1){
8502 volume3_present = 1;
8503 _findclose(find_handle);
8506 // see if we have the specific CD we're looking for
8507 if ( volume_name ) {
8509 if ( !stricmp(volume_name, FS_CDROM_VOLUME_1) && volume1_present) {
8513 if ( !stricmp(volume_name, FS_CDROM_VOLUME_2) && volume2_present) {
8517 if ( !stricmp(volume_name, FS_CDROM_VOLUME_3) && volume3_present) {
8521 if ( volume1_present || volume2_present || volume3_present ) {
8526 // 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
8527 if ( volume_match ){
8529 // 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
8530 if(volume2_present || volume3_present) {
8531 // first step - check to make sure its a cdrom
8532 if(GetDriveType(path) != DRIVE_CDROM){
8536 #if !defined(OEM_BUILD)
8537 // oem not on 80 min cds, so dont check tha size
8539 uint used_space = game_get_cd_used_space(path);
8540 if(used_space < CD_SIZE_72_MINUTE_MAX){
8543 #endif // !defined(OEM_BUILD)
8551 #endif // RELEASE_REAL
8557 SetCurrentDirectory(oldpath);
8566 int set_cdrom_path(int drive_num)
8570 if (drive_num < 0) { //no CD
8572 // strcpy(CDROM_dir,"j:\\FreeSpaceCD\\"); //set directory
8575 strcpy(Game_CDROM_dir,""); //set directory
8579 sprintf(Game_CDROM_dir,NOX("%c:\\"), 'a' + drive_num ); //set directory
8595 i = find_freespace_cd();
8597 rval = set_cdrom_path(i);
8601 nprintf(("CD", "Using %s for FreeSpace CD\n", CDROM_dir));
8603 nprintf(("CD", "FreeSpace CD not found\n"));
8611 int Last_cd_label_found = 0;
8612 char Last_cd_label[256];
8614 int game_cd_changed()
8621 if ( strlen(Game_CDROM_dir) == 0 ) {
8625 found = GetVolumeInformation(Game_CDROM_dir, label, 256, NULL, NULL, NULL, NULL, 0);
8627 if ( found != Last_cd_label_found ) {
8628 Last_cd_label_found = found;
8630 mprintf(( "CD '%s' was inserted\n", label ));
8633 mprintf(( "CD '%s' was removed\n", Last_cd_label ));
8637 if ( Last_cd_label_found ) {
8638 if ( !stricmp( Last_cd_label, label )) {
8639 //mprintf(( "CD didn't change\n" ));
8641 mprintf(( "CD was changed from '%s' to '%s'\n", Last_cd_label, label ));
8645 // none found before, none found now.
8646 //mprintf(( "still no CD...\n" ));
8650 Last_cd_label_found = found;
8652 strcpy( Last_cd_label, label );
8654 strcpy( Last_cd_label, "" );
8665 // check if _any_ FreeSpace2 CDs are in the drive
8666 // return: 1 => CD now in drive
8667 // 0 => Could not find CD, they refuse to put it in the drive
8668 int game_do_cd_check(char *volume_name)
8670 #if !defined(GAME_CD_CHECK)
8676 int num_attempts = 0;
8677 int refresh_files = 0;
8679 int path_set_ok, popup_rval;
8681 cd_drive_num = find_freespace_cd(volume_name);
8682 path_set_ok = set_cdrom_path(cd_drive_num);
8683 if ( path_set_ok ) {
8685 if ( refresh_files ) {
8697 // no CD found, so prompt user
8698 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR( "FreeSpace 2 CD not found\n\nInsert a FreeSpace 2 CD to continue", 202));
8700 if ( popup_rval != 1 ) {
8705 if ( num_attempts++ > 5 ) {
8716 // check if _any_ FreeSpace2 CDs are in the drive
8717 // return: 1 => CD now in drive
8718 // 0 => Could not find CD, they refuse to put it in the drive
8719 int game_do_cd_check_specific(char *volume_name, int cdnum)
8724 int num_attempts = 0;
8725 int refresh_files = 0;
8727 int path_set_ok, popup_rval;
8729 cd_drive_num = find_freespace_cd(volume_name);
8730 path_set_ok = set_cdrom_path(cd_drive_num);
8731 if ( path_set_ok ) {
8733 if ( refresh_files ) {
8744 // no CD found, so prompt user
8745 #if defined(DVD_MESSAGE_HACK)
8746 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert DVD", 1468));
8748 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert CD %d", 1468), cdnum);
8751 if ( popup_rval != 1 ) {
8756 if ( num_attempts++ > 5 ) {
8766 // only need to do this in RELEASE_REAL
8767 int game_do_cd_mission_check(char *filename)
8773 fs_builtin_mission *m = game_find_builtin_mission(filename);
8775 // check for changed CD
8776 if(game_cd_changed()){
8781 if((Game_mode & GM_MULTIPLAYER) || Is_standalone){
8785 // not builtin, so do a general check (any FS2 CD will do)
8787 return game_do_cd_check();
8790 // does not have any CD requirement, do a general check
8791 if(strlen(m->cd_volume) <= 0){
8792 return game_do_cd_check();
8796 if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_1)){
8798 } else if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_2)){
8801 } else if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_3)){
8805 return game_do_cd_check();
8808 // did we find the cd?
8809 if(find_freespace_cd(m->cd_volume) >= 0){
8813 // make sure the volume exists
8814 int num_attempts = 0;
8815 int refresh_files = 0;
8817 int path_set_ok, popup_rval;
8819 cd_drive_num = find_freespace_cd(m->cd_volume);
8820 path_set_ok = set_cdrom_path(cd_drive_num);
8821 if ( path_set_ok ) {
8823 if ( refresh_files ) {
8830 // no CD found, so prompt user
8831 #if defined(DVD_MESSAGE_HACK)
8832 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert DVD", 1468));
8834 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert CD %d", 1468), cd_num);
8838 if ( popup_rval != 1 ) {
8843 if ( num_attempts++ > 5 ) {
8855 // ----------------------------------------------------------------
8857 // CDROM detection code END
8859 // ----------------------------------------------------------------
8861 // ----------------------------------------------------------------
8863 // Language Autodetection stuff
8866 // this layout order must match Lcl_languages in localize.cpp in order for the
8867 // correct language to be detected
8868 int Lang_auto_detect_checksums[LCL_NUM_LANGUAGES] = {
8870 1366105450, // English
8872 589986744, // English
8874 -1132430286, // German
8876 -1131728960, // Polish
8879 // default setting is "-1" to use config file with English as fall back
8880 // DO NOT change the default setting here or something uncouth might happen
8881 // in the localization code
8887 // try and open the file to verify
8888 CFILE *detect = cfopen("font01.vf", "rb");
8890 // will use default setting if something went wrong
8895 // get the long checksum of the file
8897 cfseek(detect, 0, SEEK_SET);
8898 cf_chksum_long(detect, &file_checksum);
8902 // now compare the checksum/filesize against known #'s
8903 for (idx=0; idx<LCL_NUM_LANGUAGES; idx++) {
8904 if (Lang_auto_detect_checksums[idx] == (int)file_checksum) {
8909 // notify if a match was not found, include detected checksum
8910 printf("ERROR: Unknown Language Checksum: %i\n", (int)file_checksum);
8911 printf("Using default language...\n\n");
8917 // End Auto Lang stuff
8919 // ----------------------------------------------------------------
8921 // ----------------------------------------------------------------
8922 // SHIPS TBL VERIFICATION STUFF
8925 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
8926 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
8927 #define NUM_SHIPS_TBL_CHECKSUMS 3
8929 #define NUM_SHIPS_TBL_CHECKSUMS 1
8933 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8934 1696074201, // FS2 demo
8937 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8938 1603375034, // FS1 DEMO
8941 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8942 -129679197, // FS1 Full 1.06 (US)
8943 7762567, // FS1 SilentThreat
8944 1555372475 // FS1 Full 1.06 (German)
8948 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8949 -463907578, // US - beta 1
8950 1696074201, // FS2 demo
8953 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8954 // -1022810006, // 1.0 FULL
8955 -1254285366 // 1.2 FULL (German)
8959 void verify_ships_tbl()
8963 Game_ships_tbl_valid = 1;
8969 // detect if the packfile exists
8970 CFILE *detect = cfopen("ships.tbl", "rb");
8971 Game_ships_tbl_valid = 0;
8975 Game_ships_tbl_valid = 0;
8979 // get the long checksum of the file
8981 cfseek(detect, 0, SEEK_SET);
8982 cf_chksum_long(detect, &file_checksum);
8986 // now compare the checksum/filesize against known #'s
8987 for(idx=0; idx<NUM_SHIPS_TBL_CHECKSUMS; idx++){
8988 if(Game_ships_tbl_checksums[idx] == (int)file_checksum){
8989 Game_ships_tbl_valid = 1;
8996 DCF(shipspew, "display the checksum for the current ships.tbl")
8999 CFILE *detect = cfopen("ships.tbl", "rb");
9000 // get the long checksum of the file
9002 cfseek(detect, 0, SEEK_SET);
9003 cf_chksum_long(detect, &file_checksum);
9006 dc_printf("%d", file_checksum);
9009 // ----------------------------------------------------------------
9010 // WEAPONS TBL VERIFICATION STUFF
9013 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
9014 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
9015 #define NUM_WEAPONS_TBL_CHECKSUMS 3
9017 #define NUM_WEAPONS_TBL_CHECKSUMS 1
9021 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9022 -266420030, // demo 1
9025 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9026 -1246928725, // FS1 DEMO
9029 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9030 -834598107, // FS1 1.06 Full (US)
9031 -1652231417, // FS1 SilentThreat
9032 720209793 // FS1 1.06 Full (German)
9036 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9037 141718090, // US - beta 1
9038 -266420030, // demo 1
9041 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9042 // 399297860, // 1.0 FULL
9043 -553984927 // 1.2 FULL (german)
9047 void verify_weapons_tbl()
9051 Game_weapons_tbl_valid = 1;
9057 // detect if the packfile exists
9058 CFILE *detect = cfopen("weapons.tbl", "rb");
9059 Game_weapons_tbl_valid = 0;
9063 Game_weapons_tbl_valid = 0;
9067 // get the long checksum of the file
9069 cfseek(detect, 0, SEEK_SET);
9070 cf_chksum_long(detect, &file_checksum);
9074 // now compare the checksum/filesize against known #'s
9075 for(idx=0; idx<NUM_WEAPONS_TBL_CHECKSUMS; idx++){
9076 if(Game_weapons_tbl_checksums[idx] == (int)file_checksum){
9077 Game_weapons_tbl_valid = 1;
9084 DCF(wepspew, "display the checksum for the current weapons.tbl")
9087 CFILE *detect = cfopen("weapons.tbl", "rb");
9088 // get the long checksum of the file
9090 cfseek(detect, 0, SEEK_SET);
9091 cf_chksum_long(detect, &file_checksum);
9094 dc_printf("%d", file_checksum);
9097 // if the game is running using hacked data
9098 int game_hacked_data()
9101 if(!Game_weapons_tbl_valid || !Game_ships_tbl_valid){
9109 void display_title_screen()
9111 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
9112 ///int title_bitmap;
9115 int title_bitmap = bm_load(Game_demo_title_screen_fname[gr_screen.res]);
9116 if (title_bitmap == -1) {
9122 if((gr_screen.mode == GR_DIRECT3D) && (Gr_bitmap_poly)){
9123 extern void d3d_start_frame();
9129 gr_set_bitmap(title_bitmap);
9136 if((gr_screen.mode == GR_DIRECT3D) && (Gr_bitmap_poly)){
9137 extern void d3d_stop_frame();
9145 bm_unload(title_bitmap);
9146 #endif // FS2_DEMO || OEM_BUILD || FS1_DEMO
9149 // return true if the game is running with "low memory", which is less than 48MB
9150 bool game_using_low_mem()
9152 if (Use_low_mem == 0) {