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.28 2003/05/18 03:55:30 taylor
19 * automatic language selection support
21 * Revision 1.27 2003/03/03 04:54:44 theoddone33
22 * Commit Taylor's ShowFPS fix
24 * Revision 1.26 2003/02/20 17:41:07 theoddone33
25 * Userdir patch from Taylor Richards
27 * Revision 1.25 2003/01/30 19:54:10 relnev
28 * ini config option for the frames per second counter (Taylor Richards)
30 * Revision 1.24 2002/08/31 01:39:13 theoddone33
31 * Speed up the renderer a tad
33 * Revision 1.23 2002/08/04 02:31:00 relnev
34 * make numlock not overlap with pause
36 * Revision 1.22 2002/08/02 23:07:03 relnev
37 * don't access the mouse in standalone mode
39 * Revision 1.21 2002/07/28 05:05:08 relnev
40 * removed some old stuff
42 * Revision 1.20 2002/07/24 00:20:41 relnev
45 * Revision 1.19 2002/06/17 06:33:08 relnev
46 * ryan's struct patch for gcc 2.95
48 * Revision 1.18 2002/06/16 04:46:33 relnev
49 * set up correct checksums for demo
51 * Revision 1.17 2002/06/09 04:41:17 relnev
52 * added copyright header
54 * Revision 1.16 2002/06/09 03:16:04 relnev
57 * removed unneeded asm, old sdl 2d setup.
59 * fixed crash caused by opengl_get_region.
61 * Revision 1.15 2002/06/05 08:05:28 relnev
62 * stub/warning removal.
64 * reworked the sound code.
66 * Revision 1.14 2002/06/05 04:03:32 relnev
67 * finished cfilesystem.
69 * removed some old code.
71 * fixed mouse save off-by-one.
75 * Revision 1.13 2002/06/02 04:26:34 relnev
78 * Revision 1.12 2002/06/02 00:31:35 relnev
79 * implemented osregistry
81 * Revision 1.11 2002/06/01 09:00:34 relnev
82 * silly debug memmanager
84 * Revision 1.10 2002/06/01 07:12:32 relnev
85 * a few NDEBUG updates.
87 * removed a few warnings.
89 * Revision 1.9 2002/05/31 03:05:59 relnev
92 * Revision 1.8 2002/05/29 02:52:32 theoddone33
93 * Enable OpenGL renderer
95 * Revision 1.7 2002/05/28 08:52:03 relnev
96 * implemented two assembly stubs.
98 * cleaned up a few warnings.
100 * added a little demo hackery to make it progress a little farther.
102 * Revision 1.6 2002/05/28 06:28:20 theoddone33
103 * Filesystem mods, actually reads some data files now
105 * Revision 1.5 2002/05/28 04:07:28 theoddone33
106 * New graphics stubbing arrangement
108 * Revision 1.4 2002/05/27 22:46:52 theoddone33
109 * Remove more undefined symbols
111 * Revision 1.3 2002/05/26 23:31:18 relnev
112 * added a few files that needed to be compiled
114 * freespace.cpp: now compiles
116 * Revision 1.2 2002/05/07 03:16:44 theoddone33
117 * The Great Newline Fix
119 * Revision 1.1.1.1 2002/05/03 03:28:09 root
123 * 201 6/16/00 3:15p Jefff
124 * sim of the year dvd version changes, a few german soty localization
127 * 200 11/03/99 11:06a Jefff
130 * 199 10/26/99 5:07p Jamest
131 * fixed jeffs dumb debug code
133 * 198 10/25/99 5:53p Jefff
134 * call control_config_common_init() on startup
136 * 197 10/14/99 10:18a Daveb
137 * Fixed incorrect CD checking problem on standalone server.
139 * 196 10/13/99 9:22a Daveb
140 * Fixed Fred jumpnode placing bug. Fixed 1024 glide tiled texture problem
141 * related to movies. Fixed launcher spawning from PXO screen.
143 * 195 10/06/99 11:05a Jefff
144 * new oem upsell 3 hotspot coords
146 * 194 10/06/99 10:31a Jefff
149 * 193 10/01/99 9:10a Daveb
152 * 192 9/15/99 4:57a Dave
153 * Updated ships.tbl checksum
155 * 191 9/15/99 3:58a Dave
156 * Removed framerate warning at all times.
158 * 190 9/15/99 3:16a Dave
159 * Remove mt-011.fs2 from the builtin mission list.
161 * 189 9/15/99 1:45a Dave
162 * Don't init joystick on standalone. Fixed campaign mode on standalone.
163 * Fixed no-score-report problem in TvT
165 * 188 9/14/99 6:08a Dave
166 * Updated (final) single, multi, and campaign list.
168 * 187 9/14/99 3:26a Dave
169 * Fixed laser fogging problem in nebula (D3D)> Fixed multiplayer
170 * respawn-too-early problem. Made a few crash points safe.
172 * 186 9/13/99 4:52p Dave
175 * 185 9/12/99 8:09p Dave
176 * Fixed problem where skip-training button would cause mission messages
177 * not to get paged out for the current mission.
179 * 184 9/10/99 11:53a Dave
180 * Shutdown graphics before sound to eliminate apparent lockups when
181 * Directsound decides to be lame. Fix TOPMOST problem with D3D windows.
183 * 183 9/09/99 11:40p Dave
184 * Handle an Assert() in beam code. Added supernova sounds. Play the right
185 * 2 end movies properly, based upon what the player did in the mission.
187 * 182 9/08/99 10:29p Dave
188 * Make beam sound pausing and unpausing much safer.
190 * 181 9/08/99 10:01p Dave
191 * Make sure game won't run in a drive's root directory. Make sure
192 * standalone routes suqad war messages properly to the host.
194 * 180 9/08/99 3:22p Dave
195 * Updated builtin mission list.
197 * 179 9/08/99 12:01p Jefff
198 * fixed Game_builtin_mission_list typo on Training-2.fs2
200 * 178 9/08/99 9:48a Andsager
201 * Add force feedback for engine wash.
203 * 177 9/07/99 4:01p Dave
204 * Fixed up a string.tbl paroblem (self destruct message). Make sure IPX
205 * does everything properly (setting up address when binding). Remove
206 * black rectangle background from UI_INPUTBOX.
208 * 176 9/13/99 2:40a Dave
209 * Comment in full 80 minute CD check for RELEASE_REAL builds.
211 * 175 9/06/99 6:38p Dave
212 * Improved CD detection code.
214 * 174 9/06/99 1:30a Dave
215 * Intermediate checkin. Started on enforcing CD-in-drive to play the
218 * 173 9/06/99 1:16a Dave
219 * Make sure the user sees the intro movie.
221 * 172 9/04/99 8:00p Dave
222 * Fixed up 1024 and 32 bit movie support.
224 * 171 9/03/99 1:32a Dave
225 * CD checking by act. Added support to play 2 cutscenes in a row
226 * seamlessly. Fixed super low level cfile bug related to files in the
227 * root directory of a CD. Added cheat code to set campaign mission # in
230 * 170 9/01/99 10:49p Dave
231 * Added nice SquadWar checkbox to the client join wait screen.
233 * 169 9/01/99 10:14a Dave
236 * 168 8/29/99 4:51p Dave
237 * Fixed damaged checkin.
239 * 167 8/29/99 4:18p Andsager
240 * New "burst" limit for friendly damage. Also credit more damage done
241 * against large friendly ships.
243 * 166 8/27/99 6:38p Alanl
244 * crush the blasted repeating messages bug
246 * 164 8/26/99 9:09p Dave
247 * Force framerate check in everything but a RELEASE_REAL build.
249 * 163 8/26/99 9:45a Dave
250 * First pass at easter eggs and cheats.
252 * 162 8/24/99 8:55p Dave
253 * Make sure nondimming pixels work properly in tech menu.
255 * 161 8/24/99 1:49a Dave
256 * Fixed client-side afterburner stuttering. Added checkbox for no version
257 * checking on PXO join. Made button info passing more friendly between
260 * 160 8/22/99 5:53p Dave
261 * Scoring fixes. Added self destruct key. Put callsigns in the logfile
262 * instead of ship designations for multiplayer players.
264 * 159 8/22/99 1:19p Dave
265 * Fixed up http proxy code. Cleaned up scoring code. Reverse the order in
266 * which d3d cards are detected.
268 * 158 8/20/99 2:09p Dave
269 * PXO banner cycling.
271 * 157 8/19/99 10:59a Dave
272 * Packet loss detection.
274 * 156 8/19/99 10:12a Alanl
275 * preload mission-specific messages on machines greater than 48MB
277 * 155 8/16/99 4:04p Dave
278 * Big honking checkin.
280 * 154 8/11/99 5:54p Dave
281 * Fixed collision problem. Fixed standalone ghost problem.
283 * 153 8/10/99 7:59p Jefff
286 * 152 8/10/99 6:54p Dave
287 * Mad optimizations. Added paging to the nebula effect.
289 * 151 8/10/99 3:44p Jefff
290 * loads Intelligence information on startup
292 * 150 8/09/99 3:47p Dave
293 * Fixed incorrect nebula regeneration. Default HUD to low-contrast in
294 * non-nebula missions.
296 * 149 8/09/99 2:21p Andsager
297 * Fix patching from multiplayer direct to launcher update tab.
299 * 148 8/09/99 10:36a Dave
300 * Version info for game.
302 * 147 8/06/99 9:46p Dave
303 * Hopefully final changes for the demo.
305 * 146 8/06/99 3:34p Andsager
306 * Make title version info "(D)" -> "D" show up nicely
308 * 145 8/06/99 2:59p Adamp
309 * Fixed NT launcher/update problem.
311 * 144 8/06/99 1:52p Dave
312 * Bumped up MAX_BITMAPS for the demo.
314 * 143 8/06/99 12:17p Andsager
315 * Demo: down to just 1 demo dog
317 * 142 8/05/99 9:39p Dave
318 * Yet another new checksum.
320 * 141 8/05/99 6:19p Dave
321 * New demo checksums.
323 * 140 8/05/99 5:31p Andsager
324 * Up demo version 1.01
326 * 139 8/05/99 4:22p Andsager
327 * No time limit on upsell screens. Reverse order of display of upsell
330 * 138 8/05/99 4:17p Dave
331 * Tweaks to client interpolation.
333 * 137 8/05/99 3:52p Danw
335 * 136 8/05/99 3:01p Danw
337 * 135 8/05/99 2:43a Anoop
338 * removed duplicate definition.
340 * 134 8/05/99 2:13a Dave
343 * 133 8/05/99 2:05a Dave
346 * 132 8/05/99 1:22a Andsager
349 * 131 8/04/99 9:51p Andsager
350 * Add title screen to demo
352 * 130 8/04/99 6:47p Jefff
353 * fixed link error resulting from #ifdefs
355 * 129 8/04/99 6:26p Dave
356 * Updated ship tbl checksum.
358 * 128 8/04/99 5:40p Andsager
359 * Add multiple demo dogs
361 * 127 8/04/99 5:36p Andsager
362 * Show upsell screens at end of demo campaign before returning to main
365 * 126 8/04/99 11:42a Danw
366 * tone down EAX reverb
368 * 125 8/04/99 11:23a Dave
369 * Updated demo checksums.
371 * 124 8/03/99 11:02p Dave
372 * Maybe fixed sync problems in multiplayer.
374 * 123 8/03/99 6:21p Jefff
377 * 122 8/03/99 3:44p Andsager
378 * Launch laucher if trying to run FS without first having configured
381 * 121 8/03/99 12:45p Dave
384 * 120 8/02/99 9:13p Dave
387 * 119 7/30/99 10:31p Dave
388 * Added comm menu to the configurable hud files.
390 * 118 7/30/99 5:17p Andsager
391 * first fs2demo checksums
393 * 117 7/29/99 3:09p Anoop
395 * 116 7/29/99 12:05a Dave
396 * Nebula speed optimizations.
398 * 115 7/27/99 8:59a Andsager
399 * Make major, minor version consistent for all builds. Only show major
400 * and minor for launcher update window.
402 * 114 7/26/99 5:50p Dave
403 * Revised ingame join. Better? We'll see....
405 * 113 7/26/99 5:27p Andsager
406 * Add training mission as builtin to demo build
408 * 112 7/24/99 1:54p Dave
409 * Hud text flash gauge. Reworked dead popup to use 4 buttons in red-alert
412 * 111 7/22/99 4:00p Dave
413 * Fixed beam weapon muzzle glow rendering. Externalized hud shield info.
415 * 110 7/21/99 8:10p Dave
416 * First run of supernova effect.
418 * 109 7/20/99 1:49p Dave
419 * Peter Drake build. Fixed some release build warnings.
421 * 108 7/19/99 2:26p Andsager
422 * set demo multiplayer missions
424 * 107 7/18/99 5:19p Dave
425 * Jump node icon. Fixed debris fogging. Framerate warning stuff.
427 * 106 7/16/99 1:50p Dave
428 * 8 bit aabitmaps. yay.
430 * 105 7/15/99 3:07p Dave
431 * 32 bit detection support. Mouse coord commandline.
433 * 104 7/15/99 2:13p Dave
434 * Added 32 bit detection.
436 * 103 7/15/99 9:20a Andsager
437 * FS2_DEMO initial checkin
439 * 102 7/14/99 11:02a Dave
440 * Skill level default back to easy. Blech.
442 * 101 7/09/99 5:54p Dave
443 * Seperated cruiser types into individual types. Added tons of new
444 * briefing icons. Campaign screen.
446 * 100 7/08/99 4:43p Andsager
447 * New check for sparky_hi and print if not found.
449 * 99 7/08/99 10:53a Dave
450 * New multiplayer interpolation scheme. Not 100% done yet, but still
451 * better than the old way.
453 * 98 7/06/99 4:24p Dave
454 * Mid-level checkin. Starting on some potentially cool multiplayer
457 * 97 7/06/99 3:35p Andsager
458 * Allow movie to play before red alert mission.
460 * 96 7/03/99 5:50p Dave
461 * Make rotated bitmaps draw properly in padlock views.
463 * 95 7/02/99 9:55p Dave
464 * Player engine wash sound.
466 * 94 7/02/99 4:30p Dave
467 * Much more sophisticated lightning support.
469 * 93 6/29/99 7:52p Dave
470 * Put in exception handling in FS2.
472 * 92 6/22/99 9:37p Dave
473 * Put in pof spewing.
475 * 91 6/16/99 4:06p Dave
476 * New pilot info popup. Added new draw-bitmap-as-poly function.
478 * 90 6/15/99 1:56p Andsager
479 * For release builds, allow start up in high res only with
482 * 89 6/15/99 9:34a Dave
483 * Fixed key checking in single threaded version of the stamp notification
486 * 88 6/09/99 2:55p Andsager
487 * Allow multiple asteroid subtypes (of large, medium, small) and follow
490 * 87 6/08/99 1:14a Dave
491 * Multi colored hud test.
493 * 86 6/04/99 9:52a Dave
494 * Fixed some rendering problems.
496 * 85 6/03/99 10:15p Dave
497 * Put in temporary main hall screen.
499 * 84 6/02/99 6:18p Dave
500 * Fixed TNT lockup problems! Wheeeee!
502 * 83 6/01/99 3:52p Dave
503 * View footage screen. Fixed xstrings to not display the & symbol. Popup,
504 * dead popup, pxo find player popup, pxo private room popup.
506 * 82 5/26/99 1:28p Jasenw
507 * changed coords for loading ani
509 * 81 5/26/99 11:46a Dave
510 * Added ship-blasting lighting and made the randomization of lighting
511 * much more customizable.
513 * 80 5/24/99 5:45p Dave
514 * Added detail levels to the nebula, with a decent speedup. Split nebula
515 * lightning into its own section.
533 #include "systemvars.h"
538 #include "starfield.h"
539 #include "lighting.h"
544 #include "fireballs.h"
548 #include "floating.h"
549 #include "gamesequence.h"
551 #include "optionsmenu.h"
552 #include "playermenu.h"
553 #include "trainingmenu.h"
554 #include "techmenu.h"
557 #include "hudmessage.h"
559 #include "missiongoals.h"
560 #include "missionparse.h"
565 #include "multiutil.h"
566 #include "multimsgs.h"
570 #include "freespace.h"
571 #include "managepilot.h"
573 #include "contexthelp.h"
576 #include "missionbrief.h"
577 #include "missiondebrief.h"
579 #include "missionshipchoice.h"
581 #include "hudconfig.h"
582 #include "controlsconfig.h"
583 #include "missionmessage.h"
584 #include "missiontraining.h"
586 #include "hudtarget.h"
588 #include "eventmusic.h"
589 #include "animplay.h"
590 #include "missionweaponchoice.h"
591 #include "missionlog.h"
592 #include "audiostr.h"
594 #include "missioncampaign.h"
596 #include "missionhotkey.h"
597 #include "objectsnd.h"
598 #include "cmeasure.h"
600 #include "linklist.h"
601 #include "shockwave.h"
602 #include "afterburner.h"
607 #include "stand_gui.h"
608 #include "pcxutils.h"
609 #include "hudtargetbox.h"
610 #include "multi_xfer.h"
611 #include "hudescort.h"
612 #include "multiutil.h"
615 #include "multiteamselect.h"
618 #include "readyroom.h"
619 #include "mainhallmenu.h"
620 #include "multilag.h"
622 #include "particle.h"
624 #include "multi_ingame.h"
625 #include "snazzyui.h"
626 #include "asteroid.h"
627 #include "popupdead.h"
628 #include "multi_voice.h"
629 #include "missioncmdbrief.h"
630 #include "redalert.h"
631 #include "gameplayhelp.h"
632 #include "multilag.h"
633 #include "staticrand.h"
634 #include "multi_pmsg.h"
635 #include "levelpaging.h"
636 #include "observer.h"
637 #include "multi_pause.h"
638 #include "multi_endgame.h"
639 #include "cutscenes.h"
640 #include "multi_respawn.h"
642 #include "multi_obj.h"
643 #include "multi_log.h"
645 #include "localize.h"
646 #include "osregistry.h"
647 #include "barracks.h"
648 #include "missionpause.h"
650 #include "alphacolors.h"
651 #include "objcollide.h"
654 #include "neblightning.h"
655 #include "shipcontrails.h"
658 #include "multi_dogfight.h"
659 #include "multi_rate.h"
660 #include "muzzleflash.h"
664 #include "mainhalltemp.h"
665 #include "exceptionhandler.h"
669 #include "supernova.h"
670 #include "hudshield.h"
671 // #include "names.h"
673 #include "missionloopbrief.h"
677 #error macro FRED is defined when trying to build release Fred. Please undefine FRED macro in build settings
683 // 1.00.04 5/26/98 MWA -- going final (12 pm)
684 // 1.00.03 5/26/98 MWA -- going final (3 am)
685 // 1.00.02 5/25/98 MWA -- going final
686 // 1.00.01 5/25/98 MWA -- going final
687 // 0.90 5/21/98 MWA -- getting ready for final.
688 // 0.10 4/9/98. Set by MK.
690 // Demo version: (obsolete since DEMO codebase split from tree)
691 // 0.03 4/10/98 AL. Interplay rev
692 // 0.02 4/8/98 MK. Increased when this system was modified.
693 // 0.01 4/7/98? AL. First release to Interplay QA.
696 // 1.00 5/28/98 AL. First release to Interplay QA.
698 void game_level_init(int seed = -1);
699 void game_post_level_init();
700 void game_do_frame();
701 void game_update_missiontime(); // called from game_do_frame() and navmap_do_frame()
702 void game_reset_time();
703 void game_show_framerate(); // draws framerate in lower right corner
705 int Game_no_clear = 0;
707 int Pofview_running = 0;
708 int Nebedit_running = 0;
710 typedef struct big_expl_flash {
711 float max_flash_intensity; // max intensity
712 float cur_flash_intensity; // cur intensity
713 int flash_start; // start time
716 #define FRAME_FILTER 16
718 #define DEFAULT_SKILL_LEVEL 1
719 int Game_skill_level = DEFAULT_SKILL_LEVEL;
721 #define VIEWER_ZOOM_DEFAULT 0.75f // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
722 float Viewer_zoom = VIEWER_ZOOM_DEFAULT;
724 #define EXE_FNAME ("fs2.exe")
725 #define LAUNCHER_FNAME ("freespace2.exe")
727 // JAS: Code for warphole camera.
728 // Needs to be cleaned up.
729 vector Camera_pos = { 0.0f, 0.0f, 0.0f };
730 vector Camera_velocity = { 0.0f, 0.0f, 0.0f };
731 vector Camera_desired_velocity = { 0.0f, 0.0f, 0.0f };
732 matrix Camera_orient = IDENTITY_MATRIX;
733 float Camera_damping = 1.0f;
734 float Camera_time = 0.0f;
735 float Warpout_time = 0.0f;
736 int Warpout_forced = 0; // Set if this is a forced warpout that cannot be cancelled.
737 int Warpout_sound = -1;
739 int Use_joy_mouse = 0;
740 int Use_palette_flash = 1;
742 int Use_fullscreen_at_startup = 0;
744 int Show_area_effect = 0;
745 object *Last_view_target = NULL;
747 int dogfight_blown = 0;
750 float frametimes[FRAME_FILTER];
751 float frametotal = 0.0f;
755 int Show_framerate = 0;
757 int Show_framerate = 1;
760 int Framerate_cap = 120;
763 int Show_target_debug_info = 0;
764 int Show_target_weapons = 0;
768 static int Show_player_pos = 0; // debug console command to show player world pos on HUD
771 int Debug_octant = -1;
773 fix Game_time_compression = F1_0;
775 // if the ships.tbl the player has is valid
776 int Game_ships_tbl_valid = 0;
778 // if the weapons.tbl the player has is valid
779 int Game_weapons_tbl_valid = 0;
783 extern int Player_attacking_enabled;
787 int Pre_player_entry;
789 int Fred_running = 0;
790 char Game_current_mission_filename[MAX_FILENAME_LEN];
791 int game_single_step = 0;
792 int last_single_step=0;
794 extern int MSG_WINDOW_X_START; // used to position mission_time and shields output
795 extern int MSG_WINDOW_Y_START;
796 extern int MSG_WINDOW_HEIGHT;
798 int game_zbuffer = 1;
799 //static int Game_music_paused;
800 static int Game_paused;
804 #define EXPIRE_BAD_CHECKSUM 1
805 #define EXPIRE_BAD_TIME 2
807 extern void ssm_init();
808 extern void ssm_level_init();
809 extern void ssm_process();
811 // static variable to contain the time this version was built
812 // commented out for now until
813 // I figure out how to get the username into the file
814 //LOCAL char freespace_build_time[] = "Compiled on:"__DATE__" "__TIME__" by "__USER__;
816 // defines and variables used for dumping frame for making trailers.
818 int Debug_dump_frames = 0; // Set to 0 to not dump frames, else equal hz to dump. (15 or 30 probably)
819 int Debug_dump_trigger = 0;
820 int Debug_dump_frame_count;
821 int Debug_dump_frame_num = 0;
822 #define DUMP_BUFFER_NUM_FRAMES 1 // store every 15 frames
825 // amount of time to wait after the player has died before we display the death died popup
826 #define PLAYER_DIED_POPUP_WAIT 2500
827 int Player_died_popup_wait = -1;
828 int Player_multi_died_check = -1;
830 // builtin mission list stuff
832 int Game_builtin_mission_count = 6;
833 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
834 { "SPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
835 { "SPDemo-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
836 { "DemoTrain.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
837 { "Demo.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
838 { "MPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
839 { "Demo-DOG-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
841 #elif defined(PD_BUILD)
842 int Game_builtin_mission_count = 4;
843 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
844 { "sm1-01.fs2", (FSB_FROM_VOLITION), "" },
845 { "sm1-05.fs2", (FSB_FROM_VOLITION), "" },
846 { "sm1-01", (FSB_FROM_VOLITION), "" },
847 { "sm1-05", (FSB_FROM_VOLITION), "" },
849 #elif defined(MULTIPLAYER_BETA)
850 int Game_builtin_mission_count = 17;
851 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
853 { "md-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
854 { "md-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
855 { "md-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
856 { "md-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
857 { "md-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
858 { "md-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
859 { "md-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
860 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
861 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
862 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
863 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
864 { "m-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
865 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
866 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
867 { "templar-03a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
868 { "templar-04a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
869 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
871 #elif defined(OEM_BUILD)
872 int Game_builtin_mission_count = 17;
873 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
874 // oem version - act 1 only
875 { "freespace2oem.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
878 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
879 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
880 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
881 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
882 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
883 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
884 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
885 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
886 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
887 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
888 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
889 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
890 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
891 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
892 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
893 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 }
896 int Game_builtin_mission_count = 92;
897 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
898 // single player campaign
899 { "freespace2.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
902 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
903 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
904 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
905 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
906 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
907 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
908 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
909 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
910 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
911 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
912 { "loop1-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
913 { "loop1-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
914 { "loop1-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
915 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
916 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
917 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
918 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
919 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
920 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
923 { "sm2-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
924 { "sm2-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
925 { "sm2-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
926 { "sm2-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
927 { "sm2-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
928 { "sm2-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
929 { "sm2-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
930 { "sm2-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
931 { "sm2-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
932 { "sm2-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
935 { "sm3-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
936 { "sm3-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
937 { "sm3-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
938 { "sm3-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
939 { "sm3-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
940 { "sm3-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
941 { "sm3-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
942 { "sm3-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
943 { "sm3-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
944 { "sm3-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
945 { "loop2-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
946 { "loop2-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
948 // multiplayer missions
951 { "g-shi.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
952 { "g-ter.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
953 { "g-vas.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
956 { "m-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
957 { "m-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
958 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
959 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
962 { "mdh-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
963 { "mdh-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
964 { "mdh-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
965 { "mdh-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
966 { "mdh-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
967 { "mdh-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
968 { "mdh-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
969 { "mdh-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
970 { "mdh-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
971 { "mdl-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
972 { "mdl-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
973 { "mdl-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
974 { "mdl-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
975 { "mdl-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
976 { "mdl-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
977 { "mdl-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
978 { "mdl-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
979 { "mdl-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
980 { "mdm-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
981 { "mdm-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
982 { "mdm-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
983 { "mdm-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
984 { "mdm-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
985 { "mdm-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
986 { "mdm-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
987 { "mdm-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
988 { "mdm-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
989 { "osdog.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
992 { "mt-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
993 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
994 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
995 { "mt-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
996 { "mt-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
997 { "mt-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
998 { "mt-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
999 { "mt-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1000 { "mt-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1001 { "mt-10.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1004 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1005 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1006 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1007 { "templar-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1008 { "templar-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1013 // Internal function prototypes
1014 void game_maybe_draw_mouse(float frametime);
1015 void init_animating_pointer();
1016 void load_animating_pointer(char *filename, int dx, int dy);
1017 void unload_animating_pointer();
1018 void game_do_training_checks();
1019 void game_shutdown(void);
1020 void game_show_event_debug(float frametime);
1021 void game_event_debug_init();
1023 void demo_upsell_show_screens();
1024 void game_start_subspace_ambient_sound();
1025 void game_stop_subspace_ambient_sound();
1026 void verify_ships_tbl();
1027 void verify_weapons_tbl();
1028 void display_title_screen();
1030 // loading background filenames
1031 static char *Game_loading_bground_fname[GR_NUM_RESOLUTIONS] = {
1032 "LoadingBG", // GR_640
1033 "2_LoadingBG" // GR_1024
1037 static char *Game_loading_ani_fname[GR_NUM_RESOLUTIONS] = {
1038 "Loading.ani", // GR_640
1039 "2_Loading.ani" // GR_1024
1042 #if defined(FS2_DEMO)
1043 static char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1047 #elif defined(OEM_BUILD)
1048 static char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1058 char Game_CDROM_dir[MAX_PATH_LEN];
1061 // How much RAM is on this machine. Set in WinMain
1062 uint Freespace_total_ram = 0;
1065 float Game_flash_red = 0.0f;
1066 float Game_flash_green = 0.0f;
1067 float Game_flash_blue = 0.0f;
1068 float Sun_spot = 0.0f;
1069 big_expl_flash Big_expl_flash = {0.0f, 0.0f, 0};
1071 // game shudder stuff (in ms)
1072 int Game_shudder_time = -1;
1073 int Game_shudder_total = 0;
1074 float Game_shudder_intensity = 0.0f; // should be between 0.0 and 100.0
1077 sound_env Game_sound_env;
1078 //sound_env Game_default_sound_env = {SND_ENV_AUDITORIUM, 0.25f, 0.35f, 3.0f};
1079 sound_env Game_default_sound_env = {SND_ENV_GENERIC, 0.2F,0.2F,1.0F};
1081 int Game_sound_env_update_timestamp;
1083 // WARPIN CRAP BEGIN --------------------------------------------------------------------------------------------
1086 // WARPIN CRAP END --------------------------------------------------------------------------------------------
1088 fs_builtin_mission *game_find_builtin_mission(char *filename)
1092 // look through all existing builtin missions
1093 for(idx=0; idx<Game_builtin_mission_count; idx++){
1094 if(!stricmp(Game_builtin_mission_list[idx].filename, filename)){
1095 return &Game_builtin_mission_list[idx];
1103 int game_get_default_skill_level()
1105 return DEFAULT_SKILL_LEVEL;
1109 void game_flash_reset()
1111 Game_flash_red = 0.0f;
1112 Game_flash_green = 0.0f;
1113 Game_flash_blue = 0.0f;
1115 Big_expl_flash.max_flash_intensity = 0.0f;
1116 Big_expl_flash.cur_flash_intensity = 0.0f;
1117 Big_expl_flash.flash_start = 0;
1120 float Gf_critical = -1.0f; // framerate we should be above on the average for this mission
1121 float Gf_critical_time = 0.0f; // how much time we've been at the critical framerate
1123 void game_framerate_check_init()
1125 // zero critical time
1126 Gf_critical_time = 0.0f;
1129 if(The_mission.flags & MISSION_FLAG_FULLNEB){
1130 // if this is a glide card
1131 if(gr_screen.mode == GR_GLIDE){
1133 extern GrHwConfiguration hwconfig;
1136 if(hwconfig.SSTs[0].sstBoard.VoodooConfig.fbRam >= 4){
1137 Gf_critical = 15.0f;
1141 Gf_critical = 10.0f;
1146 Gf_critical = 15.0f;
1149 // d3d. only care about good cards here I guess (TNT)
1151 Gf_critical = 15.0f;
1154 // if this is a glide card
1155 if(gr_screen.mode == GR_GLIDE){
1157 extern GrHwConfiguration hwconfig;
1160 if(hwconfig.SSTs[0].sstBoard.VoodooConfig.fbRam >= 4){
1161 Gf_critical = 25.0f;
1165 Gf_critical = 20.0f;
1170 Gf_critical = 25.0f;
1173 // d3d. only care about good cards here I guess (TNT)
1175 Gf_critical = 25.0f;
1180 extern float Framerate;
1181 void game_framerate_check()
1185 // if the current framerate is above the critical level, add frametime
1186 if(Framerate >= Gf_critical){
1187 Gf_critical_time += flFrametime;
1190 if(!Show_framerate){
1194 // display if we're above the critical framerate
1195 if(Framerate < Gf_critical){
1196 gr_set_color_fast(&Color_bright_red);
1197 gr_string(200, y_start, "Framerate warning");
1202 // display our current pct of good frametime
1203 if(f2fl(Missiontime) >= 0.0f){
1204 float pct = (Gf_critical_time / f2fl(Missiontime)) * 100.0f;
1207 gr_set_color_fast(&Color_bright_green);
1209 gr_set_color_fast(&Color_bright_red);
1212 gr_printf(200, y_start, "%d%%", (int)pct);
1219 // Adds a flash effect. These can be positive or negative.
1220 // The range will get capped at around -1 to 1, so stick
1221 // with a range like that.
1222 void game_flash( float r, float g, float b )
1224 Game_flash_red += r;
1225 Game_flash_green += g;
1226 Game_flash_blue += b;
1228 if ( Game_flash_red < -1.0f ) {
1229 Game_flash_red = -1.0f;
1230 } else if ( Game_flash_red > 1.0f ) {
1231 Game_flash_red = 1.0f;
1234 if ( Game_flash_green < -1.0f ) {
1235 Game_flash_green = -1.0f;
1236 } else if ( Game_flash_green > 1.0f ) {
1237 Game_flash_green = 1.0f;
1240 if ( Game_flash_blue < -1.0f ) {
1241 Game_flash_blue = -1.0f;
1242 } else if ( Game_flash_blue > 1.0f ) {
1243 Game_flash_blue = 1.0f;
1248 // Adds a flash for Big Ship explosions
1249 // cap range from 0 to 1
1250 void big_explosion_flash(float flash)
1252 Big_expl_flash.flash_start = timestamp(1);
1256 } else if (flash < 0.0f) {
1260 Big_expl_flash.max_flash_intensity = flash;
1261 Big_expl_flash.cur_flash_intensity = 0.0f;
1264 // Amount to diminish palette towards normal, per second.
1265 #define DIMINISH_RATE 0.75f
1266 #define SUN_DIMINISH_RATE 6.00f
1270 float sn_glare_scale = 1.7f;
1273 dc_get_arg(ARG_FLOAT);
1274 sn_glare_scale = Dc_arg_float;
1277 float Supernova_last_glare = 0.0f;
1278 void game_sunspot_process(float frametime)
1282 float Sun_spot_goal = 0.0f;
1285 sn_stage = supernova_active();
1287 // sunspot differently based on supernova stage
1289 // approaching. player still in control
1292 pct = (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME));
1295 light_get_global_dir(&light_dir, 0);
1297 dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec );
1300 // scale it some more
1301 dot = dot * (0.5f + (pct * 0.5f));
1304 Sun_spot_goal += (dot * sn_glare_scale);
1307 // draw the sun glow
1308 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, 0 ) ) {
1309 // draw the glow for this sun
1310 stars_draw_sun_glow(0);
1313 Supernova_last_glare = Sun_spot_goal;
1316 // camera cut. player not in control. note : at this point camera starts out facing the sun. so we can go nice and bright
1319 Sun_spot_goal = 0.9f;
1320 Sun_spot_goal += (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME)) * 0.1f;
1322 if(Sun_spot_goal > 1.0f){
1323 Sun_spot_goal = 1.0f;
1326 Sun_spot_goal *= sn_glare_scale;
1327 Supernova_last_glare = Sun_spot_goal;
1330 // fade to white. display dead popup
1333 Supernova_last_glare += (2.0f * flFrametime);
1334 if(Supernova_last_glare > 2.0f){
1335 Supernova_last_glare = 2.0f;
1338 Sun_spot_goal = Supernova_last_glare;
1345 // check sunspots for all suns
1346 n_lights = light_get_global_count();
1349 for(idx=0; idx<n_lights; idx++){
1350 //(vector *eye_pos, matrix *eye_orient)
1351 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, idx ) ) {
1354 light_get_global_dir(&light_dir, idx);
1356 float dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec )*0.5f+0.5f;
1358 Sun_spot_goal += (float)pow(dot,85.0f);
1360 // draw the glow for this sun
1361 stars_draw_sun_glow(idx);
1363 Sun_spot_goal = 0.0f;
1369 Sun_spot_goal = 0.0f;
1373 float dec_amount = frametime*SUN_DIMINISH_RATE;
1375 if ( Sun_spot < Sun_spot_goal ) {
1376 Sun_spot += dec_amount;
1377 if ( Sun_spot > Sun_spot_goal ) {
1378 Sun_spot = Sun_spot_goal;
1380 } else if ( Sun_spot > Sun_spot_goal ) {
1381 Sun_spot -= dec_amount;
1382 if ( Sun_spot < Sun_spot_goal ) {
1383 Sun_spot = Sun_spot_goal;
1389 // Call once a frame to diminish the
1390 // flash effect to 0.
1391 void game_flash_diminish(float frametime)
1393 float dec_amount = frametime*DIMINISH_RATE;
1395 if ( Game_flash_red > 0.0f ) {
1396 Game_flash_red -= dec_amount;
1397 if ( Game_flash_red < 0.0f )
1398 Game_flash_red = 0.0f;
1400 Game_flash_red += dec_amount;
1401 if ( Game_flash_red > 0.0f )
1402 Game_flash_red = 0.0f;
1405 if ( Game_flash_green > 0.0f ) {
1406 Game_flash_green -= dec_amount;
1407 if ( Game_flash_green < 0.0f )
1408 Game_flash_green = 0.0f;
1410 Game_flash_green += dec_amount;
1411 if ( Game_flash_green > 0.0f )
1412 Game_flash_green = 0.0f;
1415 if ( Game_flash_blue > 0.0f ) {
1416 Game_flash_blue -= dec_amount;
1417 if ( Game_flash_blue < 0.0f )
1418 Game_flash_blue = 0.0f;
1420 Game_flash_blue += dec_amount;
1421 if ( Game_flash_blue > 0.0f )
1422 Game_flash_blue = 0.0f;
1425 // update big_explosion_cur_flash
1426 #define TIME_UP 1500
1427 #define TIME_DOWN 2500
1428 int duration = TIME_UP + TIME_DOWN;
1429 int time = timestamp_until(Big_expl_flash.flash_start);
1430 if (time > -duration) {
1432 if (time < TIME_UP) {
1433 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * time / (float) TIME_UP;
1436 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * ((float) TIME_DOWN - time) / (float) TIME_DOWN;
1440 if ( Use_palette_flash ) {
1442 // static int or=0, og=0, ob=0;
1444 // Change the 200 to change the color range of colors.
1445 r = fl2i( Game_flash_red*128.0f );
1446 g = fl2i( Game_flash_green*128.0f );
1447 b = fl2i( Game_flash_blue*128.0f );
1449 if ( Sun_spot > 0.0f ) {
1450 r += fl2i(Sun_spot*128.0f);
1451 g += fl2i(Sun_spot*128.0f);
1452 b += fl2i(Sun_spot*128.0f);
1455 if ( Big_expl_flash.cur_flash_intensity > 0.0f ) {
1456 r += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1457 g += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1458 b += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1461 if ( r < 0 ) r = 0; else if ( r > 255 ) r = 255;
1462 if ( g < 0 ) g = 0; else if ( g > 255 ) g = 255;
1463 if ( b < 0 ) b = 0; else if ( b > 255 ) b = 255;
1465 if ( (r!=0) || (g!=0) || (b!=0) ) {
1466 gr_flash( r, g, b );
1468 //mprintf(( "Flash! %d,%d,%d\n", r, g, b ));
1479 void game_level_close()
1481 // De-Initialize the game subsystems
1482 message_mission_shutdown();
1483 event_music_level_close();
1484 game_stop_looped_sounds();
1486 obj_snd_level_close(); // uninit object-linked persistant sounds
1487 gamesnd_unload_gameplay_sounds(); // unload gameplay sounds from memory
1488 anim_level_close(); // stop and clean up any anim instances
1489 shockwave_level_close();
1490 fireball_level_close();
1492 mission_event_shutdown();
1493 asteroid_level_close();
1494 model_cache_reset(); // Reset/free all the model caching stuff
1495 flak_level_close(); // unload flak stuff
1496 neb2_level_close(); // shutdown gaseous nebula stuff
1499 mflash_level_close();
1501 audiostream_unpause_all();
1506 // intializes game stuff and loads the mission. Returns 0 on failure, 1 on success
1507 // input: seed => DEFAULT PARAMETER (value -1). Only set by demo playback code.
1508 void game_level_init(int seed)
1510 // seed the random number generator
1512 // if no seed was passed, seed the generator either from the time value, or from the
1513 // netgame security flags -- ensures that all players in multiplayer game will have the
1514 // same randon number sequence (with static rand functions)
1515 if ( Game_mode & GM_NORMAL ) {
1516 Game_level_seed = time(NULL);
1518 Game_level_seed = Netgame.security;
1521 // mwa 9/17/98 -- maybe this assert isn't needed????
1522 Assert( !(Game_mode & GM_MULTIPLAYER) );
1523 Game_level_seed = seed;
1525 srand( Game_level_seed );
1527 // semirand function needs to get re-initted every time in multiplayer
1528 if ( Game_mode & GM_MULTIPLAYER ){
1534 Key_normal_game = (Game_mode & GM_NORMAL);
1537 Game_shudder_time = -1;
1539 // Initialize the game subsystems
1540 // timestamp_reset(); // Must be inited before everything else
1542 game_reset_time(); // resets time, and resets saved time too
1544 obj_init(); // Must be inited before the other systems
1545 model_free_all(); // Free all existing models
1546 mission_brief_common_init(); // Free all existing briefing/debriefing text
1547 weapon_level_init();
1548 ai_level_init(); // Call this before ship_init() because it reads ai.tbl.
1550 player_level_init();
1551 shipfx_flash_init(); // Init the ship gun flash system.
1552 game_flash_reset(); // Reset the flash effect
1553 particle_init(); // Reset the particle system
1557 shield_hit_init(); // Initialize system for showing shield hits
1558 radar_mission_init();
1559 mission_init_goals();
1562 obj_snd_level_init(); // init object-linked persistant sounds
1564 shockwave_level_init();
1565 afterburner_level_init();
1566 scoring_level_init( &Player->stats );
1568 asteroid_level_init();
1569 control_config_clear_used_status();
1570 collide_ship_ship_sounds_init();
1572 Pre_player_entry = 1; // Means the player has not yet entered.
1573 Entry_delay_time = 0; // Could get overwritten in mission read.
1574 fireball_preload(); // page in warphole bitmaps
1576 flak_level_init(); // initialize flak - bitmaps, etc
1577 ct_level_init(); // initialize ships contrails, etc
1578 awacs_level_init(); // initialize AWACS
1579 beam_level_init(); // initialize beam weapons
1580 mflash_level_init();
1582 supernova_level_init();
1584 // multiplayer dogfight hack
1587 shipfx_engine_wash_level_init();
1591 Last_view_target = NULL;
1596 // campaign wasn't ended
1597 Campaign_ended_in_mission = 0;
1600 // called when a mission is over -- does server specific stuff.
1601 void freespace_stop_mission()
1604 Game_mode &= ~GM_IN_MISSION;
1607 // called at frame interval to process networking stuff
1608 void game_do_networking()
1610 Assert( Net_player != NULL );
1611 if (!(Game_mode & GM_MULTIPLAYER)){
1615 // see if this player should be reading/writing data. Bit is set when at join
1616 // screen onward until quits back to main menu.
1617 if ( !(Net_player->flags & NETINFO_FLAG_DO_NETWORKING) ){
1621 if(gameseq_get_state()!=GS_STATE_MULTI_PAUSED){
1624 multi_pause_do_frame();
1629 // Loads the best palette for this level, based
1630 // on nebula color and hud color. You could just call palette_load_table with
1631 // the appropriate filename, but who wants to do that.
1632 void game_load_palette()
1634 char palette_filename[1024];
1636 // We only use 3 hud colors right now
1637 // Assert( HUD_config.color >= 0 );
1638 // Assert( HUD_config.color <= 2 );
1640 Assert( Mission_palette >= 0 );
1641 Assert( Mission_palette <= 98 );
1643 // if ( The_mission.flags & MISSION_FLAG_SUBSPACE ) {
1644 strcpy( palette_filename, NOX("gamepalette-subspace") );
1646 // sprintf( palette_filename, NOX("gamepalette%d-%02d"), HUD_config.color+1, Mission_palette+1 );
1649 mprintf(( "Loading palette %s\n", palette_filename ));
1651 // palette_load_table(palette_filename);
1654 void game_post_level_init()
1656 // Stuff which gets called after mission is loaded. Because player isn't created until
1657 // after mission loads, some things must get initted after the level loads
1659 model_level_post_init();
1662 hud_setup_escort_list();
1663 mission_hotkey_set_defaults(); // set up the default hotkeys (from mission file)
1669 game_event_debug_init();
1672 training_mission_init();
1673 asteroid_create_all();
1675 game_framerate_check_init();
1679 // An estimate as to how high the count passed to game_loading_callback will go.
1680 // This is just a guess, it seems to always be about the same. The count is
1681 // proportional to the code being executed, not the time, so this works good
1682 // for a bar, assuming the code does about the same thing each time you
1683 // load a level. You can find this value by looking at the return value
1684 // of game_busy_callback(NULL), which I conveniently print out to the
1685 // debug output window with the '=== ENDING LOAD ==' stuff.
1686 //#define COUNT_ESTIMATE 3706
1687 #define COUNT_ESTIMATE 1111
1689 int Game_loading_callback_inited = 0;
1691 int Game_loading_background = -1;
1692 anim * Game_loading_ani = NULL;
1693 anim_instance *Game_loading_ani_instance;
1694 int Game_loading_frame=-1;
1696 static int Game_loading_ani_coords[GR_NUM_RESOLUTIONS][2] = {
1705 // This gets called 10x per second and count is the number of times
1706 // game_busy() has been called since the current callback function
1708 void game_loading_callback(int count)
1710 game_do_networking();
1712 Assert( Game_loading_callback_inited==1 );
1713 Assert( Game_loading_ani != NULL );
1715 int framenum = ((Game_loading_ani->total_frames*count) / COUNT_ESTIMATE)+1;
1716 if ( framenum > Game_loading_ani->total_frames-1 ) {
1717 framenum = Game_loading_ani->total_frames-1;
1718 } else if ( framenum < 0 ) {
1723 while ( Game_loading_frame < framenum ) {
1724 Game_loading_frame++;
1725 cbitmap = anim_get_next_frame(Game_loading_ani_instance);
1729 if ( cbitmap > -1 ) {
1730 if ( Game_loading_background > -1 ) {
1731 gr_set_bitmap( Game_loading_background );
1735 //mprintf(( "Showing frame %d/%d [ Bitmap=%d ]\n", Game_loading_frame , Game_loading_ani->total_frames, cbitmap ));
1736 gr_set_bitmap( cbitmap );
1737 gr_bitmap(Game_loading_ani_coords[gr_screen.res][0],Game_loading_ani_coords[gr_screen.res][1]);
1739 bm_release(cbitmap);
1745 void game_loading_callback_init()
1747 Assert( Game_loading_callback_inited==0 );
1749 Game_loading_background = bm_load(Game_loading_bground_fname[gr_screen.res]);
1750 //common_set_interface_palette("InterfacePalette"); // set the interface palette
1753 Game_loading_ani = anim_load( Game_loading_ani_fname[gr_screen.res]);
1754 Assert( Game_loading_ani != NULL );
1755 Game_loading_ani_instance = init_anim_instance(Game_loading_ani, 16);
1756 Assert( Game_loading_ani_instance != NULL );
1757 Game_loading_frame = -1;
1759 Game_loading_callback_inited = 1;
1761 game_busy_callback( game_loading_callback, (COUNT_ESTIMATE/Game_loading_ani->total_frames)+1 );
1766 void game_loading_callback_close()
1768 Assert( Game_loading_callback_inited==1 );
1770 // Make sure bar shows all the way over.
1771 game_loading_callback(COUNT_ESTIMATE);
1773 int real_count = game_busy_callback( NULL );
1776 Game_loading_callback_inited = 0;
1779 mprintf(( "=================== ENDING LOAD ================\n" ));
1780 mprintf(( "Real count = %d, Estimated count = %d\n", real_count, COUNT_ESTIMATE ));
1781 mprintf(( "================================================\n" ));
1783 // to remove warnings in release build
1787 free_anim_instance(Game_loading_ani_instance);
1788 Game_loading_ani_instance = NULL;
1789 anim_free(Game_loading_ani);
1790 Game_loading_ani = NULL;
1792 bm_release( Game_loading_background );
1793 common_free_interface_palette(); // restore game palette
1794 Game_loading_background = -1;
1796 gr_set_font( FONT1 );
1799 // Update the sound environment (ie change EAX settings based on proximity to large ships)
1801 void game_maybe_update_sound_environment()
1803 // do nothing for now
1806 // Assign the sound environment for the game, based on the current mission
1808 void game_assign_sound_environment()
1811 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
1812 Game_sound_env.id = SND_ENV_DRUGGED;
1813 Game_sound_env.volume = 0.800f;
1814 Game_sound_env.damping = 1.188f;
1815 Game_sound_env.decay = 6.392f;
1817 } else if (Num_asteroids > 30) {
1818 Game_sound_env.id = SND_ENV_AUDITORIUM;
1819 Game_sound_env.volume = 0.603f;
1820 Game_sound_env.damping = 0.5f;
1821 Game_sound_env.decay = 4.279f;
1824 Game_sound_env = Game_default_sound_env;
1828 Game_sound_env = Game_default_sound_env;
1829 Game_sound_env_update_timestamp = timestamp(1);
1832 // function which gets called before actually entering the mission. It is broken down into a funciton
1833 // since it will get called in one place from a single player game and from another place for
1834 // a multiplayer game
1835 void freespace_mission_load_stuff()
1837 // called if we're not on a freespace dedicated (non rendering, no pilot) server
1838 // IE : we _don't_ want to load any sounds or bitmap/texture info on this machine.
1839 if(!(Game_mode & GM_STANDALONE_SERVER)){
1841 mprintf(( "=================== STARTING LEVEL DATA LOAD ==================\n" ));
1843 game_loading_callback_init();
1845 event_music_level_init(); // preloads the first 2 seconds for each event music track
1848 gamesnd_unload_interface_sounds(); // unload interface sounds from memory
1851 gamesnd_preload_common_sounds(); // load in sounds that are expected to play
1854 ship_assign_sound_all(); // assign engine sounds to ships
1855 game_assign_sound_environment(); // assign the sound environment for this mission
1858 // call function in missionparse.cpp to fixup player/ai stuff.
1859 mission_parse_fixup_players();
1862 // Load in all the bitmaps for this level
1867 game_loading_callback_close();
1869 // the only thing we need to call on the standalone for now.
1871 // call function in missionparse.cpp to fixup player/ai stuff.
1872 mission_parse_fixup_players();
1874 // Load in all the bitmaps for this level
1880 uint load_mission_load;
1881 uint load_post_level_init;
1882 uint load_mission_stuff;
1884 // tells the server to load the mission and initialize structures
1885 int game_start_mission()
1887 mprintf(( "=================== STARTING LEVEL LOAD ==================\n" ));
1889 load_gl_init = time(NULL);
1891 load_gl_init = time(NULL) - load_gl_init;
1893 if (Game_mode & GM_MULTIPLAYER) {
1894 Player->flags |= PLAYER_FLAGS_IS_MULTI;
1896 // clear multiplayer stats
1897 init_multiplayer_stats();
1900 load_mission_load = time(NULL);
1901 if (mission_load()) {
1902 if ( !(Game_mode & GM_MULTIPLAYER) ) {
1903 popup(PF_BODY_BIG, 1, POPUP_OK, XSTR( "Attempt to load the mission failed", 169));
1904 gameseq_post_event(GS_EVENT_MAIN_MENU);
1906 multi_quit_game(PROMPT_NONE, MULTI_END_NOTIFY_NONE, MULTI_END_ERROR_LOAD_FAIL);
1911 load_mission_load = time(NULL) - load_mission_load;
1913 // If this is a red alert mission in campaign mode, bash wingman status
1914 if ( (Game_mode & GM_CAMPAIGN_MODE) && red_alert_mission() ) {
1915 red_alert_bash_wingman_status();
1918 // the standalone server in multiplayer doesn't do any rendering, so we will not even bother loading the palette
1919 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
1920 mprintf(( "=================== LOADING GAME PALETTE ================\n" ));
1921 // game_load_palette();
1924 load_post_level_init = time(NULL);
1925 game_post_level_init();
1926 load_post_level_init = time(NULL) - load_post_level_init;
1930 void Do_model_timings_test();
1931 Do_model_timings_test();
1935 load_mission_stuff = time(NULL);
1936 freespace_mission_load_stuff();
1937 load_mission_stuff = time(NULL) - load_mission_stuff;
1942 int Interface_framerate = 0;
1945 DCF_BOOL( mouse_control, Use_mouse_to_fly )
1946 DCF_BOOL( show_framerate, Show_framerate )
1947 DCF_BOOL( show_target_debug_info, Show_target_debug_info )
1948 DCF_BOOL( show_target_weapons, Show_target_weapons )
1949 DCF_BOOL( lead_target_cheat, Players[Player_num].lead_target_cheat )
1950 DCF_BOOL( sound, Sound_enabled )
1951 DCF_BOOL( zbuffer, game_zbuffer )
1952 DCF_BOOL( shield_system, New_shield_system )
1953 DCF_BOOL( show_shield_mesh, Show_shield_mesh)
1954 DCF_BOOL( player_attacking, Player_attacking_enabled )
1955 DCF_BOOL( show_waypoints, Show_waypoints )
1956 DCF_BOOL( show_area_effect, Show_area_effect )
1957 DCF_BOOL( show_net_stats, Show_net_stats )
1958 DCF_BOOL( log, Log_debug_output_to_file )
1959 DCF_BOOL( training_msg_method, Training_msg_method )
1960 DCF_BOOL( show_player_pos, Show_player_pos )
1961 DCF_BOOL(i_framerate, Interface_framerate )
1963 DCF(show_mem,"Toggles showing mem usage")
1966 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
1967 if ( Dc_arg_type & ARG_TRUE ) Show_mem = 1;
1968 else if ( Dc_arg_type & ARG_FALSE ) Show_mem = 0;
1969 else if ( Dc_arg_type & ARG_NONE ) Show_mem ^= 1;
1975 if ( Dc_help ) dc_printf( "Usage: Show_mem\nSets show_mem to true or false. If nothing passed, then toggles it.\n" );
1977 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
1978 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
1982 DCF(show_cpu,"Toggles showing cpu usage")
1985 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
1986 if ( Dc_arg_type & ARG_TRUE ) Show_cpu = 1;
1987 else if ( Dc_arg_type & ARG_FALSE ) Show_cpu = 0;
1988 else if ( Dc_arg_type & ARG_NONE ) Show_cpu ^= 1;
1994 if ( Dc_help ) dc_printf( "Usage: Show_cpu\nSets show_cpu to true or false. If nothing passed, then toggles it.\n" );
1996 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
1997 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2004 // AL 4-8-98: always allow players to display their framerate
2007 DCF_BOOL( show_framerate, Show_framerate )
2014 DCF(use_joy_mouse,"Makes joystick move mouse cursor")
2017 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2018 if ( Dc_arg_type & ARG_TRUE ) Use_joy_mouse = 1;
2019 else if ( Dc_arg_type & ARG_FALSE ) Use_joy_mouse = 0;
2020 else if ( Dc_arg_type & ARG_NONE ) Use_joy_mouse ^= 1;
2022 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" );
2023 if ( Dc_status ) dc_printf( "use_joy_mouse is %s\n", (Use_joy_mouse?"TRUE":"FALSE") );
2025 os_config_write_uint( NULL, NOX("JoystickMovesCursor"), Use_joy_mouse );
2028 DCF(palette_flash,"Toggles palette flash effect on/off")
2031 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2032 if ( Dc_arg_type & ARG_TRUE ) Use_palette_flash = 1;
2033 else if ( Dc_arg_type & ARG_FALSE ) Use_palette_flash = 0;
2034 else if ( Dc_arg_type & ARG_NONE ) Use_palette_flash ^= 1;
2036 if ( Dc_help ) dc_printf( "Usage: palette_flash [bool]\nSets palette_flash to true or false. If nothing passed, then toggles it.\n" );
2037 if ( Dc_status ) dc_printf( "palette_flash is %s\n", (Use_palette_flash?"TRUE":"FALSE") );
2040 int Use_low_mem = 0;
2042 DCF(low_mem,"Uses low memory settings regardless of RAM")
2045 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2046 if ( Dc_arg_type & ARG_TRUE ) Use_low_mem = 1;
2047 else if ( Dc_arg_type & ARG_FALSE ) Use_low_mem = 0;
2048 else if ( Dc_arg_type & ARG_NONE ) Use_low_mem ^= 1;
2050 if ( Dc_help ) dc_printf( "Usage: low_mem [bool]\nSets low_mem to true or false. If nothing passed, then toggles it.\n" );
2051 if ( Dc_status ) dc_printf( "low_mem is %s\n", (Use_low_mem?"TRUE":"FALSE") );
2053 os_config_write_uint( NULL, NOX("LowMem"), Use_low_mem );
2059 DCF(force_fullscreen, "Forces game to startup in fullscreen mode")
2062 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2063 if ( Dc_arg_type & ARG_TRUE ) Use_fullscreen_at_startup = 1;
2064 else if ( Dc_arg_type & ARG_FALSE ) Use_fullscreen_at_startup = 0;
2065 else if ( Dc_arg_type & ARG_NONE ) Use_fullscreen_at_startup ^= 1;
2067 if ( Dc_help ) dc_printf( "Usage: force_fullscreen [bool]\nSets force_fullscreen to true or false. If nothing passed, then toggles it.\n" );
2068 if ( Dc_status ) dc_printf( "force_fullscreen is %s\n", (Use_fullscreen_at_startup?"TRUE":"FALSE") );
2069 os_config_write_uint( NULL, NOX("ForceFullscreen"), Use_fullscreen_at_startup );
2073 int Framerate_delay = 0;
2075 float Freespace_gamma = 1.0f;
2077 DCF(gamma,"Sets Gamma factor")
2080 dc_get_arg(ARG_FLOAT|ARG_NONE);
2081 if ( Dc_arg_type & ARG_FLOAT ) {
2082 Freespace_gamma = Dc_arg_float;
2084 dc_printf( "Gamma reset to 1.0f\n" );
2085 Freespace_gamma = 1.0f;
2087 if ( Freespace_gamma < 0.1f ) {
2088 Freespace_gamma = 0.1f;
2089 } else if ( Freespace_gamma > 5.0f ) {
2090 Freespace_gamma = 5.0f;
2092 gr_set_gamma(Freespace_gamma);
2094 char tmp_gamma_string[32];
2095 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2096 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2100 dc_printf( "Usage: gamma <float>\n" );
2101 dc_printf( "Sets gamma in range 1-3, no argument resets to default 1.2\n" );
2102 Dc_status = 0; // don't print status if help is printed. Too messy.
2106 dc_printf( "Gamma = %.2f\n", Freespace_gamma );
2115 Game_current_mission_filename[0] = 0;
2117 // seed the random number generator
2118 Game_init_seed = time(NULL);
2119 srand( Game_init_seed );
2121 Framerate_delay = 0;
2127 extern void bm_init();
2133 // Initialize the timer before the os
2141 GetCurrentDirectory(1024, whee);
2144 getcwd (whee, 1024);
2147 strcat(whee, EXE_FNAME);
2149 //Initialize the libraries
2150 s1 = timer_get_milliseconds();
2151 if(cfile_init(whee, Game_CDROM_dir)){ // initialize before calling any cfopen stuff!!!
2154 e1 = timer_get_milliseconds();
2156 // time a bunch of cfopens
2158 s2 = timer_get_milliseconds();
2160 for(int idx=0; idx<10000; idx++){
2161 whee = cfopen("capital01.pof", "rb", CFILE_NORMAL, CF_TYPE_MODELS);
2166 //cf_exist("capital01.pof", CF_TYPE_MODELS);
2168 e2 = timer_get_milliseconds();
2171 if (Is_standalone) {
2172 std_init_standalone();
2174 os_init( Osreg_class_name, Osreg_app_name );
2175 os_set_title(Osreg_title);
2178 // initialize localization module. Make sure this is down AFTER initialzing OS.
2179 // int t1 = timer_get_milliseconds();
2180 lcl_init( detect_lang() );
2182 // mprintf(("LCL_INIT() TOOK %d MS\n", timer_get_milliseconds()-t1));
2184 // verify that he has a valid ships.tbl (will Game_ships_tbl_valid if so)
2187 // verify that he has a valid weapons.tbl
2188 verify_weapons_tbl();
2191 // setup the default osreg values if they don't exist
2195 // Output version numbers to registry for auto patching purposes
2196 os_config_write_uint(NOX("Version"), NOX("Major"), FS_VERSION_MAJOR);
2197 os_config_write_uint(NOX("Version"), NOX("Minor"), FS_VERSION_MINOR);
2198 os_config_write_uint(NOX("Version"), NOX("Build"), FS_VERSION_BUILD);
2200 Use_joy_mouse = 0; //os_config_read_uint( NULL, NOX("JoystickMovesCursor"), 1 );
2201 //Use_palette_flash = os_config_read_uint( NULL, NOX("PaletteFlash"), 0 );
2202 Use_low_mem = os_config_read_uint( NULL, NOX("LowMem"), 0 );
2205 Use_fullscreen_at_startup = os_config_read_uint( NULL, NOX("ForceFullscreen"), 1 );
2208 #if defined (PLAT_UNIX) && defined(RELEASE_REAL)
2209 // show the FPS counter if the config file says so
2210 Show_framerate = os_config_read_uint( NULL, NOX("ShowFPS"), 0 );
2214 Asteroids_enabled = 1;
2217 /////////////////////////////
2219 /////////////////////////////
2224 ptr = os_config_read_string(NULL, NOX("Soundcard"), NULL);
2225 mprintf(("soundcard = %s\n", ptr ? ptr : "<nothing>"));
2227 if (!stricmp(ptr, NOX("no sound"))) {
2228 Cmdline_freespace_no_sound = 1;
2230 } else if (!stricmp(ptr, NOX("Aureal A3D"))) {
2232 } else if (!stricmp(ptr, NOX("EAX"))) {
2237 if (!Is_standalone) {
2238 snd_init(use_a3d, use_eax);
2240 /////////////////////////////
2242 /////////////////////////////
2244 ptr = os_config_read_string(NULL, NOX("Videocard"), NULL);
2247 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);
2249 // fire up the UpdateLauncher executable
2251 PROCESS_INFORMATION pi;
2253 memset( &si, 0, sizeof(STARTUPINFO) );
2256 BOOL ret = CreateProcess( LAUNCHER_FNAME, // pointer to name of executable module
2257 NULL, // pointer to command line string
2258 NULL, // pointer to process security attributes
2259 NULL, // pointer to thread security attributes
2260 FALSE, // handle inheritance flag
2261 CREATE_DEFAULT_ERROR_MODE, // creation flags
2262 NULL, // pointer to new environment block
2263 NULL, // pointer to current directory name
2264 &si, // pointer to STARTUPINFO
2265 &pi // pointer to PROCESS_INFORMATION
2268 // If the Launcher could not be started up, let the user know
2270 MessageBox((HWND)os_get_window(), XSTR("The Launcher could not be restarted.", 1450), XSTR("Error", 1451), MB_OK);
2279 if(!stricmp(ptr, "Aucune accélération 3D") || !stricmp(ptr, "Keine 3D-Beschleunigerkarte") || !stricmp(ptr, "No 3D acceleration")){
2281 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);
2289 // check for hi res pack file
2290 int has_sparky_hi = 0;
2292 // check if sparky_hi exists -- access mode 0 means does file exist
2295 if ( _access("sparky_hi_fs2.vp", 0) == 0) {
2298 mprintf(("No sparky_hi_fs2.vp in directory %s\n", dir));
2301 // see if we've got 32 bit in the string
2302 if(strstr(ptr, "32 bit")){
2309 if (!Is_standalone && ptr && (strstr(ptr, NOX("3DFX Glide")))) {
2311 // always 640 for E3
2312 gr_init(GR_640, GR_GLIDE);
2314 // regular or hi-res ?
2316 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2318 if(strstr(ptr, NOX("(1024x768)"))){
2320 gr_init(GR_1024, GR_GLIDE);
2322 gr_init(GR_640, GR_GLIDE);
2325 } else if (!Is_standalone && ptr && (strstr(ptr, NOX("Direct 3D -") ))) {
2327 // always 640 for E3
2329 gr_init(GR_640, GR_DIRECT3D, depth);
2331 // regular or hi-res ?
2333 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2335 if(strstr(ptr, NOX("(1024x768)"))){
2339 gr_init(GR_1024, GR_DIRECT3D, depth);
2343 gr_init(GR_640, GR_DIRECT3D, depth);
2349 if ( Use_fullscreen_at_startup && !Is_standalone) {
2350 gr_init(GR_640, GR_DIRECTDRAW);
2352 gr_init(GR_640, GR_SOFTWARE);
2355 if ( !Is_standalone ) {
2356 gr_init(GR_640, GR_DIRECTDRAW);
2358 gr_init(GR_640, GR_SOFTWARE);
2363 if (!Is_standalone /* && ptr && (strstr(ptr, NOX("OpenGL"))) */) {
2364 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2365 gr_init(GR_1024, GR_OPENGL);
2367 gr_init(GR_640, GR_OPENGL);
2371 gr_init(GR_640, GR_SOFTWARE);
2376 extern int Gr_inited;
2377 if(trying_d3d && !Gr_inited){
2379 extern char Device_init_error[512];
2380 MessageBox( NULL, Device_init_error, "Error intializing Direct3D", MB_OK|MB_TASKMODAL|MB_SETFOREGROUND );
2389 ptr = os_config_read_string(NULL,NOX("Gamma"),NOX("1.80"));
2390 Freespace_gamma = (float)atof(ptr);
2391 if ( Freespace_gamma == 0.0f ) {
2392 Freespace_gamma = 1.80f;
2393 } else if ( Freespace_gamma < 0.1f ) {
2394 Freespace_gamma = 0.1f;
2395 } else if ( Freespace_gamma > 5.0f ) {
2396 Freespace_gamma = 5.0f;
2398 char tmp_gamma_string[32];
2399 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2400 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2402 gr_set_gamma(Freespace_gamma);
2404 #if defined(FS2_DEMO) || defined(OEM_BUILD)
2407 display_title_screen();
2411 // attempt to load up master tracker registry info (login and password)
2412 Multi_tracker_id = -1;
2414 // pxo login and password
2415 ptr = os_config_read_string(NOX("PXO"),NOX("Login"),NULL);
2417 nprintf(("Network","Error reading in PXO login data\n"));
2418 strcpy(Multi_tracker_login,"");
2420 strcpy(Multi_tracker_login,ptr);
2422 ptr = os_config_read_string(NOX("PXO"),NOX("Password"),NULL);
2424 nprintf(("Network","Error reading PXO password\n"));
2425 strcpy(Multi_tracker_passwd,"");
2427 strcpy(Multi_tracker_passwd,ptr);
2430 // pxo squad name and password
2431 ptr = os_config_read_string(NOX("PXO"),NOX("SquadName"),NULL);
2433 nprintf(("Network","Error reading in PXO squad name\n"));
2434 strcpy(Multi_tracker_squad_name, "");
2436 strcpy(Multi_tracker_squad_name, ptr);
2439 // If less than 48MB of RAM, use low memory model.
2442 (Freespace_total_ram < 48*1024*1024) ||
2445 mprintf(( "Using normal memory settings...\n" ));
2446 bm_set_low_mem(1); // Use every other frame of bitmaps
2448 mprintf(( "Using high memory settings...\n" ));
2449 bm_set_low_mem(0); // Use all frames of bitmaps
2452 // load non-darkening pixel defs
2453 palman_load_pixels();
2455 // hud shield icon stuff
2456 hud_shield_game_init();
2458 control_config_common_init(); // sets up localization stuff in the control config
2464 gamesnd_parse_soundstbl();
2469 // standalone's don't use hte joystick and it seems to sometimes cause them to not get shutdown properly
2474 player_controls_init();
2477 //if(!Is_standalone){
2485 ship_init(); // read in ships.tbl
2487 mission_campaign_init(); // load in the default campaign
2489 // navmap_init(); // init the navigation map system
2490 context_help_init();
2491 techroom_intel_init(); // parse species.tbl, load intel info
2493 psnet_init( Multi_options_g.protocol, Multi_options_g.port ); // initialize the networking code
2494 init_animating_pointer();
2496 mission_brief_common_init(); // Mark all the briefing structures as empty.
2497 gr_font_init(); // loads up all fonts
2499 neb2_init(); // fullneb stuff
2503 player_tips_init(); // helpful tips
2506 // load the list of pilot pic filenames (for barracks and pilot select popup quick reference)
2507 pilot_load_pic_list();
2508 pilot_load_squad_pic_list();
2510 load_animating_pointer(NOX("cursor"), 0, 0);
2512 // initialize alpha colors
2513 alpha_colors_init();
2516 // Game_music_paused = 0;
2523 nprintf(("General", "Ships.tbl is : %s\n", Game_ships_tbl_valid ? "VALID" : "INVALID!!!!"));
2524 nprintf(("General", "Weapons.tbl is : %s\n", Game_weapons_tbl_valid ? "VALID" : "INVALID!!!!"));
2526 mprintf(("cfile_init() took %d\n", e1 - s1));
2527 // mprintf(("1000 cfopens() took %d\n", e2 - s2));
2530 char transfer_text[128];
2532 float Start_time = 0.0f;
2534 float Framerate = 0.0f;
2536 float Timing_total = 0.0f;
2537 float Timing_render2 = 0.0f;
2538 float Timing_render3 = 0.0f;
2539 float Timing_flip = 0.0f;
2540 float Timing_clear = 0.0f;
2542 MONITOR(NumPolysDrawn);
2548 void game_get_framerate()
2550 char text[128] = "";
2552 if ( frame_int == -1 ) {
2554 for (i=0; i<FRAME_FILTER; i++ ) {
2555 frametimes[i] = 0.0f;
2560 frametotal -= frametimes[frame_int];
2561 frametotal += flFrametime;
2562 frametimes[frame_int] = flFrametime;
2563 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2565 if ( frametotal != 0.0 ) {
2566 if ( Framecount >= FRAME_FILTER )
2567 Framerate = FRAME_FILTER / frametotal;
2569 Framerate = Framecount / frametotal;
2570 sprintf( text, NOX("FPS: %.1f"), Framerate );
2572 sprintf( text, NOX("FPS: ?") );
2576 if (Show_framerate) {
2577 gr_set_color_fast(&HUD_color_debug);
2578 gr_string( 570, 2, text );
2582 void game_show_framerate()
2586 cur_time = f2fl(timer_get_approx_seconds());
2587 if (cur_time - Start_time > 30.0f) {
2588 mprintf(("%i frames executed in %7.3f seconds, %7.3f frames per second.\n", Framecount, cur_time - Start_time, Framecount/(cur_time - Start_time)));
2589 Start_time += 1000.0f;
2592 //mprintf(( "%s\n", text ));
2595 if ( Debug_dump_frames )
2599 // possibly show control checking info
2600 control_check_indicate();
2602 // int bitmaps_used_this_frame, bitmaps_new_this_frame;
2603 // bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
2604 // MONITOR_INC(BmpUsed, bitmaps_used_this_frame);
2605 // MONITOR_INC(BmpNew, bitmaps_new_this_frame);
2608 if ( Show_cpu == 1 ) {
2613 dy = gr_get_font_height() + 1;
2615 gr_set_color_fast(&HUD_color_debug);
2619 extern int D3D_textures_in;
2620 extern int D3D_textures_in_frame;
2621 extern int Glide_textures_in;
2622 extern int Glide_textures_in_frame;
2623 extern int Glide_explosion_vram;
2624 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2626 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame+D3D_textures_in_frame)/1024 );
2628 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2632 // gr_printf( sx, sy, "BPP: %d", gr_screen.bits_per_pixel );
2634 gr_printf( sx, sy, NOX("DMA: %s"), transfer_text );
2636 gr_printf( sx, sy, NOX("POLYP: %d"), modelstats_num_polys );
2638 gr_printf( sx, sy, NOX("POLYD: %d"), modelstats_num_polys_drawn );
2640 gr_printf( sx, sy, NOX("VERTS: %d"), modelstats_num_verts );
2645 extern int Num_pairs; // Number of object pairs that were checked.
2646 gr_printf( sx, sy, NOX("PAIRS: %d"), Num_pairs );
2649 extern int Num_pairs_checked; // What percent of object pairs were checked.
2650 gr_printf( sx, sy, NOX("FVI: %d"), Num_pairs_checked );
2652 Num_pairs_checked = 0;
2656 gr_printf( sx, sy, NOX("Snds: %d"), snd_num_playing() );
2659 if ( Timing_total > 0.01f ) {
2660 gr_printf( sx, sy, NOX("CLEAR: %.0f%%"), Timing_clear*100.0f/Timing_total );
2662 gr_printf( sx, sy, NOX("REND2D: %.0f%%"), Timing_render2*100.0f/Timing_total );
2664 gr_printf( sx, sy, NOX("REND3D: %.0f%%"), Timing_render3*100.0f/Timing_total );
2666 gr_printf( sx, sy, NOX("FLIP: %.0f%%"), Timing_flip*100.0f/Timing_total );
2668 gr_printf( sx, sy, NOX("GAME: %.0f%%"), (Timing_total-(Timing_render2+Timing_render3+Timing_flip+Timing_clear))*100.0f/Timing_total );
2678 dy = gr_get_font_height() + 1;
2680 gr_set_color_fast(&HUD_color_debug);
2683 extern int TotalRam;
2684 gr_printf( sx, sy, NOX("DYN: %d KB\n"), TotalRam/1024 );
2689 extern int Model_ram;
2690 gr_printf( sx, sy, NOX("POF: %d KB\n"), Model_ram/1024 );
2694 gr_printf( sx, sy, NOX("BMP: %d KB\n"), bm_texture_ram/1024 );
2696 gr_printf( sx, sy, NOX("S-SRAM: %d KB\n"), Snd_sram/1024 ); // mem used to store game sound
2698 gr_printf( sx, sy, NOX("S-HRAM: %d KB\n"), Snd_hram/1024 ); // mem used to store game sound
2702 extern int D3D_textures_in;
2703 extern int Glide_textures_in;
2704 extern int Glide_textures_in_frame;
2705 extern int Glide_explosion_vram;
2706 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2708 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame)/1024 );
2710 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2717 if ( Show_player_pos ) {
2721 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));
2724 MONITOR_INC(NumPolys, modelstats_num_polys);
2725 MONITOR_INC(NumPolysDrawn, modelstats_num_polys_drawn );
2726 MONITOR_INC(NumVerts, modelstats_num_verts );
2728 modelstats_num_polys = 0;
2729 modelstats_num_polys_drawn = 0;
2730 modelstats_num_verts = 0;
2731 modelstats_num_sortnorms = 0;
2735 void game_show_standalone_framerate()
2737 float frame_rate=30.0f;
2738 if ( frame_int == -1 ) {
2740 for (i=0; i<FRAME_FILTER; i++ ) {
2741 frametimes[i] = 0.0f;
2746 frametotal -= frametimes[frame_int];
2747 frametotal += flFrametime;
2748 frametimes[frame_int] = flFrametime;
2749 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2751 if ( frametotal != 0.0 ) {
2752 if ( Framecount >= FRAME_FILTER ){
2753 frame_rate = FRAME_FILTER / frametotal;
2755 frame_rate = Framecount / frametotal;
2758 std_set_standalone_fps(frame_rate);
2762 // function to show the time remaining in a mission. Used only when the end-mission sexpression is used
2763 void game_show_time_left()
2767 // mission_end_time is a global from missionparse.cpp that contains the mission time at which the
2768 // mission should end (in fixed seconds). There is code in missionparse.cpp which actually handles
2769 // checking how much time is left
2771 if ( Mission_end_time == -1 ){
2775 diff = f2i(Mission_end_time - Missiontime);
2776 // be sure to bash to 0. diff could be negative on frame that we quit mission
2781 hud_set_default_color();
2782 gr_printf( 5, 40, XSTR( "Mission time remaining: %d seconds", 179), diff );
2785 //========================================================================================
2786 //=================== NEW DEBUG CONSOLE COMMANDS TO REPLACE OLD DEBUG PAUSE MENU =========
2787 //========================================================================================
2791 DCF(ai_pause,"Pauses ai")
2794 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2795 if ( Dc_arg_type & ARG_TRUE ) ai_paused = 1;
2796 else if ( Dc_arg_type & ARG_FALSE ) ai_paused = 0;
2797 else if ( Dc_arg_type & ARG_NONE ) ai_paused = !ai_paused;
2800 obj_init_all_ships_physics();
2803 if ( Dc_help ) dc_printf( "Usage: ai_paused [bool]\nSets ai_paused to true or false. If nothing passed, then toggles it.\n" );
2804 if ( Dc_status ) dc_printf( "ai_paused is %s\n", (ai_paused?"TRUE":"FALSE") );
2807 DCF(single_step,"Single steps the game")
2810 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2811 if ( Dc_arg_type & ARG_TRUE ) game_single_step = 1;
2812 else if ( Dc_arg_type & ARG_FALSE ) game_single_step = 0;
2813 else if ( Dc_arg_type & ARG_NONE ) game_single_step = !game_single_step;
2815 last_single_step = 0; // Make so single step waits a frame before stepping
2818 if ( Dc_help ) dc_printf( "Usage: single_step [bool]\nSets single_step to true or false. If nothing passed, then toggles it.\n" );
2819 if ( Dc_status ) dc_printf( "single_step is %s\n", (game_single_step?"TRUE":"FALSE") );
2822 DCF_BOOL(physics_pause, physics_paused)
2823 DCF_BOOL(ai_rendering, Ai_render_debug_flag)
2824 DCF_BOOL(ai_firing, Ai_firing_enabled )
2826 // Create some simple aliases to these commands...
2827 debug_command dc_s("s","shortcut for single_step",dcf_single_step);
2828 debug_command dc_p("p","shortcut for physics_pause", dcf_physics_pause );
2829 debug_command dc_r("r","shortcut for ai_rendering", dcf_ai_rendering );
2830 debug_command dc_f("f","shortcut for ai_firing", dcf_ai_firing);
2831 debug_command dc_a("a","shortcut for ai_pause", dcf_ai_pause);
2834 //========================================================================================
2835 //========================================================================================
2838 void game_training_pause_do()
2842 key = game_check_key();
2844 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
2851 void game_increase_skill_level()
2854 if (Game_skill_level >= NUM_SKILL_LEVELS){
2855 Game_skill_level = 0;
2859 int Player_died_time;
2861 int View_percent = 100;
2864 DCF(view, "Sets the percent of the 3d view to render.")
2867 dc_get_arg(ARG_INT);
2868 if ( (Dc_arg_int >= 5 ) || (Dc_arg_int <= 100) ) {
2869 View_percent = Dc_arg_int;
2871 dc_printf( "Illegal value for view. (Must be from 5-100) \n\n");
2877 dc_printf("Usage: view [n]\nwhere n is percent of view to show (5-100).\n");
2881 dc_printf("View is set to %d%%\n", View_percent );
2886 // Set the clip region for the 3d rendering window
2887 void game_set_view_clip()
2889 if ((Game_mode & GM_DEAD) || (supernova_active() >= 2)) {
2890 // Set the clip region for the letterbox "dead view"
2891 int yborder = gr_screen.max_h/4;
2893 // Numeric constants encouraged by J "pig farmer" S, who shall remain semi-anonymous.
2894 // J.S. I've changed my ways!! See the new "no constants" code!!!
2895 gr_set_clip(0, yborder, gr_screen.max_w, gr_screen.max_h - yborder*2 );
2897 // Set the clip region for normal view
2898 if ( View_percent >= 100 ) {
2901 int xborder, yborder;
2903 if ( View_percent < 5 ) {
2907 float fp = i2fl(View_percent)/100.0f;
2908 int fi = fl2i(fl_sqrt(fp)*100.0f);
2909 if ( fi > 100 ) fi=100;
2911 xborder = ( gr_screen.max_w*(100-fi) )/200;
2912 yborder = ( gr_screen.max_h*(100-fi) )/200;
2914 gr_set_clip(xborder, yborder, gr_screen.max_w-xborder*2,gr_screen.max_h-yborder*2 );
2920 void show_debug_stuff()
2923 int laser_count = 0, missile_count = 0;
2925 for (i=0; i<MAX_OBJECTS; i++) {
2926 if (Objects[i].type == OBJ_WEAPON){
2927 if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_LASER){
2929 } else if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_MISSILE){
2935 nprintf(("Mike", "Frame: %i Lasers: %4i, Missiles: %4i\n", Framecount, laser_count, missile_count));
2938 extern int Tool_enabled;
2943 int tst_bitmap = -1;
2945 float tst_offset, tst_offset_total;
2948 void game_tst_frame_pre()
2956 g3_rotate_vertex(&v, &tst_pos);
2957 g3_project_vertex(&v);
2960 if(!((v.sx >= 0) && (v.sx <= gr_screen.max_w) && (v.sy >= 0) && (v.sy <= gr_screen.max_h))){
2964 // big ship? always tst
2966 // within 3000 meters
2967 if( vm_vec_dist_quick(&tst_pos, &Eye_position) <= 3000.0f){
2971 // within 300 meters
2972 if( (vm_vec_dist_quick(&tst_pos, &Eye_position) <= 300.0f) && ((tst_time == 0) || ((time(NULL) - tst_time) >= 10)) ){
2979 void game_tst_frame()
2989 tst_time = time(NULL);
2991 // load the tst bitmap
2992 switch((int)frand_range(0.0f, 3.0)){
2994 tst_bitmap = bm_load("ig_jim");
2996 mprintf(("TST 0\n"));
3000 tst_bitmap = bm_load("ig_kan");
3002 mprintf(("TST 1\n"));
3006 tst_bitmap = bm_load("ig_jim");
3008 mprintf(("TST 2\n"));
3012 tst_bitmap = bm_load("ig_kan");
3014 mprintf(("TST 3\n"));
3023 // get the tst bitmap dimensions
3025 bm_get_info(tst_bitmap, &w, &h);
3028 tst_y = frand_range(0.0f, (float)gr_screen.max_h - h);
3030 snd_play(&Snds[SND_VASUDAN_BUP]);
3032 // tst x and direction
3036 tst_offset_total = (float)w;
3037 tst_offset = (float)w;
3039 tst_x = (float)gr_screen.max_w;
3040 tst_offset_total = (float)-w;
3041 tst_offset = (float)w;
3049 float diff = (tst_offset_total / 0.5f) * flFrametime;
3055 tst_offset -= fl_abs(diff);
3056 } else if(tst_mode == 2){
3059 tst_offset -= fl_abs(diff);
3063 gr_set_bitmap(tst_bitmap);
3064 gr_bitmap((int)tst_x, (int)tst_y);
3067 if(timestamp_elapsed_safe(tst_stamp, 1100)){
3071 // if we passed the switch point
3072 if(tst_offset <= 0.0f){
3077 tst_stamp = timestamp(1000);
3078 tst_offset = fl_abs(tst_offset_total);
3089 void game_tst_mark(object *objp, ship *shipp)
3098 if((objp == NULL) || (shipp == NULL) || (shipp->ship_info_index < 0) || (shipp->ship_info_index >= Num_ship_types)){
3101 sip = &Ship_info[shipp->ship_info_index];
3108 tst_pos = objp->pos;
3109 if(sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)){
3115 extern void render_shields();
3117 void player_repair_frame(float frametime)
3119 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
3121 for(idx=0;idx<MAX_PLAYERS;idx++){
3124 np = &Net_players[idx];
3126 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)){
3128 // don't rearm/repair if the player is dead or dying/departing
3129 if ( !NETPLAYER_IS_DEAD(np) && !(Ships[Objects[np->player->objnum].instance].flags & (SF_DYING|SF_DEPARTING)) ) {
3130 ai_do_repair_frame(&Objects[Net_players[idx].player->objnum],&Ai_info[Ships[Objects[Net_players[idx].player->objnum].instance].ai_index],frametime);
3135 if ( (Player_obj != NULL) && (Player_obj->type == OBJ_SHIP) && !(Game_mode & GM_STANDALONE_SERVER) && (Player_ship != NULL) && !(Player_ship->flags & SF_DYING) ) {
3136 ai_do_repair_frame(Player_obj, &Ai_info[Ships[Player_obj->instance].ai_index], frametime);
3142 #define NUM_FRAMES_TEST 300
3143 #define NUM_MIXED_SOUNDS 16
3144 void do_timing_test(float flFrametime)
3146 static int framecount = 0;
3147 static int test_running = 0;
3148 static float test_time = 0.0f;
3150 static int snds[NUM_MIXED_SOUNDS];
3153 if ( test_running ) {
3155 test_time += flFrametime;
3156 if ( framecount >= NUM_FRAMES_TEST ) {
3158 nprintf(("General", "%d frames took %.3f seconds\n", NUM_FRAMES_TEST, test_time));
3159 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3164 if ( Test_begin == 1 ) {
3170 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3173 // start looping digital sounds
3174 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3175 snds[i] = snd_play_looping( &Snds[i], 0.0f, -1, -1);
3182 DCF(dcf_fov, "Change the field of view")
3185 dc_get_arg(ARG_FLOAT|ARG_NONE);
3186 if ( Dc_arg_type & ARG_NONE ) {
3187 Viewer_zoom = VIEWER_ZOOM_DEFAULT;
3188 dc_printf( "Zoom factor reset\n" );
3190 if ( Dc_arg_type & ARG_FLOAT ) {
3191 if (Dc_arg_float < 0.25f) {
3192 Viewer_zoom = 0.25f;
3193 dc_printf("Zoom factor pinned at 0.25.\n");
3194 } else if (Dc_arg_float > 1.25f) {
3195 Viewer_zoom = 1.25f;
3196 dc_printf("Zoom factor pinned at 1.25.\n");
3198 Viewer_zoom = Dc_arg_float;
3204 dc_printf( "Usage: fov [factor]\nFactor is the zoom factor btwn .25 and 1.25\nNo parameter resets it to default.\n" );
3207 dc_printf("Zoom factor set to %6.3f (original = 0.5, John = 0.75)", Viewer_zoom);
3211 DCF(framerate_cap, "Sets the framerate cap")
3214 dc_get_arg(ARG_INT);
3215 if ( (Dc_arg_int >= 1 ) || (Dc_arg_int <= 120) ) {
3216 Framerate_cap = Dc_arg_int;
3218 dc_printf( "Illegal value for framerate cap. (Must be from 1-120) \n\n");
3224 dc_printf("Usage: framerate_cap [n]\nwhere n is the frames per second to cap framerate at.\n");
3225 dc_printf("If n is 0 or omitted, then the framerate cap is removed\n");
3226 dc_printf("[n] must be from 1 to 120.\n");
3230 if ( Framerate_cap )
3231 dc_printf("Framerate cap is set to %d fps\n", Framerate_cap );
3233 dc_printf("There is no framerate cap currently active.\n");
3237 #define MIN_DIST_TO_DEAD_CAMERA 50.0f
3238 int Show_viewing_from_self = 0;
3240 void say_view_target()
3242 object *view_target;
3244 if ((Viewer_mode & VM_OTHER_SHIP) && (Player_ai->target_objnum != -1))
3245 view_target = &Objects[Player_ai->target_objnum];
3247 view_target = Player_obj;
3249 if (Game_mode & GM_DEAD) {
3250 if (Player_ai->target_objnum != -1)
3251 view_target = &Objects[Player_ai->target_objnum];
3254 if (!(Game_mode & GM_DEAD_DIED) && ((Game_mode & (GM_DEAD_BLEW_UP)) || ((Last_view_target != NULL) && (Last_view_target != view_target)))) {
3255 if (view_target != Player_obj){
3257 char *view_target_name = NULL;
3258 switch(Objects[Player_ai->target_objnum].type) {
3260 view_target_name = Ships[Objects[Player_ai->target_objnum].instance].ship_name;
3263 view_target_name = Weapon_info[Weapons[Objects[Player_ai->target_objnum].instance].weapon_info_index].name;
3264 Viewer_mode &= ~VM_OTHER_SHIP;
3266 case OBJ_JUMP_NODE: {
3267 char jump_node_name[128];
3268 strcpy(jump_node_name, XSTR( "jump node", 184));
3269 view_target_name = jump_node_name;
3270 Viewer_mode &= ~VM_OTHER_SHIP;
3279 if ( view_target_name ) {
3280 HUD_fixed_printf(0.0f, XSTR( "Viewing %s%s\n", 185), (Viewer_mode & VM_OTHER_SHIP) ? XSTR( "from ", 186) : "", view_target_name);
3281 Show_viewing_from_self = 1;
3284 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER) && (Player_obj->type == OBJ_OBSERVER)){
3285 HUD_fixed_printf(2.0f,XSTR( "Viewing from observer\n", 187));
3286 Show_viewing_from_self = 1;
3288 if (Show_viewing_from_self)
3289 HUD_fixed_printf(2.0f, XSTR( "Viewing from self\n", 188));
3294 Last_view_target = view_target;
3298 float Game_hit_x = 0.0f;
3299 float Game_hit_y = 0.0f;
3301 // Reset at the beginning of each frame
3302 void game_whack_reset()
3308 // Apply a 2d whack to the player
3309 void game_whack_apply( float x, float y )
3311 // Do some force feedback
3312 joy_ff_play_dir_effect(x * 80.0f, y * 80.0f);
3318 // mprintf(( "WHACK = %.1f, %.1f\n", Game_hit_x, Game_hit_y ));
3321 // call to apply a "shudder"
3322 void game_shudder_apply(int time, float intensity)
3324 Game_shudder_time = timestamp(time);
3325 Game_shudder_total = time;
3326 Game_shudder_intensity = intensity;
3329 #define FF_SCALE 10000
3330 void apply_hud_shake(matrix *eye_orient)
3332 if (Viewer_obj == Player_obj) {
3333 physics_info *pi = &Player_obj->phys_info;
3341 // Make eye shake due to afterburner
3342 if ( !timestamp_elapsed(pi->afterburner_decay) ) {
3345 dtime = timestamp_until(pi->afterburner_decay);
3349 tangles.p += 0.07f * (float) (r1-RAND_MAX/2)/RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3350 tangles.h += 0.07f * (float) (r2-RAND_MAX/2)/RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3353 // Make eye shake due to engine wash
3355 if (Player_obj->type == OBJ_SHIP && (Ships[Player_obj->instance].wash_intensity > 0) && Wash_on ) {
3358 tangles.p += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r1-RAND_MAX/2)/RAND_MAX;
3359 tangles.h += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r2-RAND_MAX/2)/RAND_MAX;
3361 // get the intensity
3362 float intensity = FF_SCALE * Ships[Player_obj->instance].wash_intensity;
3366 vm_vec_rand_vec_quick(&rand_vec);
3369 joy_ff_play_dir_effect(intensity*rand_vec.xyz.x, intensity*rand_vec.xyz.y);
3373 // make hud shake due to shuddering
3374 if(Game_shudder_time != -1){
3375 // if the timestamp has elapsed
3376 if(timestamp_elapsed(Game_shudder_time)){
3377 Game_shudder_time = -1;
3379 // otherwise apply some shudder
3383 dtime = timestamp_until(Game_shudder_time);
3387 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));
3388 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));
3393 vm_angles_2_matrix(&tm, &tangles);
3394 Assert(vm_vec_mag(&tm.v.fvec) > 0.0f);
3395 Assert(vm_vec_mag(&tm.v.rvec) > 0.0f);
3396 Assert(vm_vec_mag(&tm.v.uvec) > 0.0f);
3397 vm_matrix_x_matrix(&tm2, eye_orient, &tm);
3402 extern void compute_slew_matrix(matrix *orient, angles *a); // TODO: move code to proper place and extern in header file
3404 // Player's velocity just before he blew up. Used to keep camera target moving.
3405 vector Dead_player_last_vel = {1.0f, 1.0f, 1.0f};
3407 // Set eye_pos and eye_orient based on view mode.
3408 void game_render_frame_setup(vector *eye_pos, matrix *eye_orient)
3412 static int last_Viewer_mode = 0;
3413 static int last_Game_mode = 0;
3414 static int last_Viewer_objnum = -1;
3416 // This code is supposed to detect camera "cuts"... like going between
3419 // determine if we need to regenerate the nebula
3420 if( (!(last_Viewer_mode & VM_EXTERNAL) && (Viewer_mode & VM_EXTERNAL)) || // internal to external
3421 ((last_Viewer_mode & VM_EXTERNAL) && !(Viewer_mode & VM_EXTERNAL)) || // external to internal
3422 (!(last_Viewer_mode & VM_DEAD_VIEW) && (Viewer_mode & VM_DEAD_VIEW)) || // non dead-view to dead-view
3423 ((last_Viewer_mode & VM_DEAD_VIEW) && !(Viewer_mode & VM_DEAD_VIEW)) || // dead-view to non dead-view
3424 (!(last_Viewer_mode & VM_WARP_CHASE) && (Viewer_mode & VM_WARP_CHASE)) || // non warp-chase to warp-chase
3425 ((last_Viewer_mode & VM_WARP_CHASE) && !(Viewer_mode & VM_WARP_CHASE)) || // warp-chase to non warp-chase
3426 (!(last_Viewer_mode & VM_OTHER_SHIP) && (Viewer_mode & VM_OTHER_SHIP)) || // non other-ship to other-ship
3427 ((last_Viewer_mode & VM_OTHER_SHIP) && !(Viewer_mode & VM_OTHER_SHIP)) || // other-ship to non-other ship
3428 ((Viewer_mode & VM_OTHER_SHIP) && (last_Viewer_objnum != Player_ai->target_objnum)) // other ship mode, but targets changes
3431 // regenerate the nebula
3435 if ( (last_Viewer_mode != Viewer_mode) || (last_Game_mode != Game_mode) ) {
3436 //mprintf(( "************** Camera cut! ************\n" ));
3437 last_Viewer_mode = Viewer_mode;
3438 last_Game_mode = Game_mode;
3440 // Camera moved. Tell stars & debris to not do blurring.
3446 if ( Viewer_mode & VM_PADLOCK_ANY ) {
3447 player_display_packlock_view();
3450 game_set_view_clip();
3452 if (Game_mode & GM_DEAD) {
3453 vector vec_to_deader, view_pos;
3456 Viewer_mode |= VM_DEAD_VIEW;
3458 if (Player_ai->target_objnum != -1) {
3459 int view_from_player = 1;
3461 if (Viewer_mode & VM_OTHER_SHIP) {
3462 // View from target.
3463 Viewer_obj = &Objects[Player_ai->target_objnum];
3465 last_Viewer_objnum = Player_ai->target_objnum;
3467 if ( Viewer_obj->type == OBJ_SHIP ) {
3468 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3469 view_from_player = 0;
3472 last_Viewer_objnum = -1;
3475 if ( view_from_player ) {
3476 // View target from player ship.
3478 *eye_pos = Player_obj->pos;
3479 vm_vec_normalized_dir(&eye_dir, &Objects[Player_ai->target_objnum].pos, eye_pos);
3480 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3483 dist = vm_vec_normalized_dir(&vec_to_deader, &Player_obj->pos, &Dead_camera_pos);
3485 if (dist < MIN_DIST_TO_DEAD_CAMERA)
3486 dist += flFrametime * 16.0f;
3488 vm_vec_scale(&vec_to_deader, -dist);
3489 vm_vec_add(&Dead_camera_pos, &Player_obj->pos, &vec_to_deader);
3491 view_pos = Player_obj->pos;
3493 if (!(Game_mode & GM_DEAD_BLEW_UP)) {
3494 Viewer_mode &= ~(VM_EXTERNAL | VM_CHASE);
3495 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, 25.0f * flFrametime);
3496 Dead_player_last_vel = Player_obj->phys_info.vel;
3497 //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));
3498 } else if (Player_ai->target_objnum != -1) {
3499 view_pos = Objects[Player_ai->target_objnum].pos;
3501 // Make camera follow explosion, but gradually slow down.
3502 vm_vec_scale_add2(&Player_obj->pos, &Dead_player_last_vel, flFrametime);
3503 view_pos = Player_obj->pos;
3504 vm_vec_scale(&Dead_player_last_vel, 0.99f);
3505 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, min(25.0f, vm_vec_mag_quick(&Dead_player_last_vel)) * flFrametime);
3508 *eye_pos = Dead_camera_pos;
3510 vm_vec_normalized_dir(&eye_dir, &Player_obj->pos, eye_pos);
3512 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3517 // if supernova shockwave
3518 if(supernova_camera_cut()){
3522 // call it dead view
3523 Viewer_mode |= VM_DEAD_VIEW;
3525 // set eye pos and orient
3526 supernova_set_view(eye_pos, eye_orient);
3528 // If already blown up, these other modes can override.
3529 if (!(Game_mode & (GM_DEAD | GM_DEAD_BLEW_UP))) {
3530 Viewer_mode &= ~VM_DEAD_VIEW;
3532 Viewer_obj = Player_obj;
3534 if (Viewer_mode & VM_OTHER_SHIP) {
3535 if (Player_ai->target_objnum != -1){
3536 Viewer_obj = &Objects[Player_ai->target_objnum];
3537 last_Viewer_objnum = Player_ai->target_objnum;
3539 Viewer_mode &= ~VM_OTHER_SHIP;
3540 last_Viewer_objnum = -1;
3543 last_Viewer_objnum = -1;
3546 if (Viewer_mode & VM_EXTERNAL) {
3549 vm_angles_2_matrix(&tm2, &Viewer_external_info.angles);
3550 vm_matrix_x_matrix(&tm, &Viewer_obj->orient, &tm2);
3552 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &tm.v.fvec, 2.0f * Viewer_obj->radius + Viewer_external_info.distance);
3554 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3555 vm_vec_normalize(&eye_dir);
3556 vm_vector_2_matrix(eye_orient, &eye_dir, &Viewer_obj->orient.v.uvec, NULL);
3559 // Modify the orientation based on head orientation.
3560 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3562 } else if ( Viewer_mode & VM_CHASE ) {
3565 if ( Viewer_obj->phys_info.speed < 0.1 )
3566 move_dir = Viewer_obj->orient.v.fvec;
3568 move_dir = Viewer_obj->phys_info.vel;
3569 vm_vec_normalize(&move_dir);
3572 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &move_dir, -3.0f * Viewer_obj->radius - Viewer_chase_info.distance);
3573 vm_vec_scale_add2(eye_pos, &Viewer_obj->orient.v.uvec, 0.75f * Viewer_obj->radius);
3574 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3575 vm_vec_normalize(&eye_dir);
3577 // JAS: I added the following code because if you slew up using
3578 // Descent-style physics, eye_dir and Viewer_obj->orient.v.uvec are
3579 // equal, which causes a zero-length vector in the vm_vector_2_matrix
3580 // call because the up and the forward vector are the same. I fixed
3581 // it by adding in a fraction of the right vector all the time to the
3583 vector tmp_up = Viewer_obj->orient.v.uvec;
3584 vm_vec_scale_add2( &tmp_up, &Viewer_obj->orient.v.rvec, 0.00001f );
3586 vm_vector_2_matrix(eye_orient, &eye_dir, &tmp_up, NULL);
3589 // Modify the orientation based on head orientation.
3590 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3591 } else if ( Viewer_mode & VM_WARP_CHASE ) {
3592 *eye_pos = Camera_pos;
3594 ship * shipp = &Ships[Player_obj->instance];
3596 vm_vec_sub(&eye_dir, &shipp->warp_effect_pos, eye_pos);
3597 vm_vec_normalize(&eye_dir);
3598 vm_vector_2_matrix(eye_orient, &eye_dir, &Player_obj->orient.v.uvec, NULL);
3601 // get an eye position based upon the correct type of object
3602 switch(Viewer_obj->type){
3604 // make a call to get the eye point for the player object
3605 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3608 // make a call to get the eye point for the player object
3609 observer_get_eye( eye_pos, eye_orient, Viewer_obj );
3615 #ifdef JOHNS_DEBUG_CODE
3616 john_debug_stuff(&eye_pos, &eye_orient);
3622 apply_hud_shake(eye_orient);
3624 // setup neb2 rendering
3625 neb2_render_setup(eye_pos, eye_orient);
3629 extern void ai_debug_render_stuff();
3632 int Game_subspace_effect = 0;
3633 DCF_BOOL( subspace, Game_subspace_effect );
3635 // Does everything needed to render a frame
3636 void game_render_frame( vector * eye_pos, matrix * eye_orient )
3640 g3_start_frame(game_zbuffer);
3641 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
3643 // maybe offset the HUD (jitter stuff)
3644 dont_offset = ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER));
3645 HUD_set_offsets(Viewer_obj, !dont_offset);
3647 // for multiplayer clients, call code in Shield.cpp to set up the Shield_hit array. Have to
3648 // do this becaues of the disjointed nature of this system (in terms of setup and execution).
3649 // must be done before ships are rendered
3650 if ( MULTIPLAYER_CLIENT ) {
3651 shield_point_multi_setup();
3654 if ( Game_subspace_effect ) {
3655 stars_draw(0,0,0,1);
3657 stars_draw(1,1,1,0);
3660 obj_render_all(obj_render);
3661 beam_render_all(); // render all beam weapons
3662 particle_render_all(); // render particles after everything else.
3663 trail_render_all(); // render missilie trails after everything else.
3664 mflash_render_all(); // render all muzzle flashes
3666 // Why do we not show the shield effect in these modes? Seems ok.
3667 //if (!(Viewer_mode & (VM_EXTERNAL | VM_SLEWED | VM_CHASE | VM_DEAD_VIEW))) {
3671 // render nebula lightning
3674 // render local player nebula
3675 neb2_render_player();
3678 ai_debug_render_stuff();
3681 #ifndef RELEASE_REAL
3682 // game_framerate_check();
3686 extern void snd_spew_debug_info();
3687 snd_spew_debug_info();
3690 //================ END OF 3D RENDERING STUFF ====================
3694 if( (Game_detail_flags & DETAIL_FLAG_HUD) && !(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) ) ) {
3695 hud_maybe_clear_head_area();
3696 anim_render_all(0, flFrametime);
3699 extern int Multi_display_netinfo;
3700 if(Multi_display_netinfo){
3701 extern void multi_display_netinfo();
3702 multi_display_netinfo();
3705 game_tst_frame_pre();
3708 do_timing_test(flFrametime);
3712 extern int OO_update_index;
3713 multi_rate_display(OO_update_index, 375, 0);
3718 extern void oo_display();
3725 //#define JOHNS_DEBUG_CODE 1
3727 #ifdef JOHNS_DEBUG_CODE
3728 void john_debug_stuff(vector *eye_pos, matrix *eye_orient)
3730 //if ( keyd_pressed[KEY_LSHIFT] )
3732 ship_subsys *tsys = Players[Player_num].targeted_subobject;
3734 model_subsystem *turret = tsys->system_info;
3736 if (turret->type == SUBSYSTEM_TURRET ) {
3737 vector v.fvec, v.uvec;
3738 object * tobj = &Objects[Players[Player_num].targeted_subobject_parent];
3740 ship_model_start(tobj);
3742 model_find_world_point(eye_pos, &turret->turret_firing_point[0], turret->model_num, turret->turret_gun_sobj, &tobj->orient, &tobj->pos );
3743 model_find_world_dir(&v.fvec, &turret->turret_matrix.v.fvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3744 model_find_world_dir(&v.uvec, &turret->turret_matrix.v.uvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3746 vm_vector_2_matrix( eye_orient, &v.fvec, &v.uvec, NULL );
3748 ship_model_stop(tobj);
3758 // following function for dumping frames for purposes of building trailers.
3761 // function to toggle state of dumping every frame into PCX when playing the game
3762 DCF(dump_frames, "Starts/stop frame dumping at 15 hz")
3766 if ( Debug_dump_frames == 0 ) {
3768 Debug_dump_frames = 15;
3769 Debug_dump_trigger = 0;
3770 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3771 dc_printf( "Frame dumping at 15 hz is now ON\n" );
3774 Debug_dump_frames = 0;
3775 Debug_dump_trigger = 0;
3776 gr_dump_frame_stop();
3777 dc_printf( "Frame dumping is now OFF\n" );
3783 DCF(dump_frames_trigger, "Starts/stop frame dumping at 15 hz")
3787 if ( Debug_dump_frames == 0 ) {
3789 Debug_dump_frames = 15;
3790 Debug_dump_trigger = 1;
3791 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3792 dc_printf( "Frame dumping at 15 hz is now ON\n" );
3795 Debug_dump_frames = 0;
3796 Debug_dump_trigger = 0;
3797 gr_dump_frame_stop();
3798 dc_printf( "Frame dumping is now OFF\n" );
3804 DCF(dump_frames30, "Starts/stop frame dumping at 30 hz")
3808 if ( Debug_dump_frames == 0 ) {
3810 Debug_dump_frames = 30;
3811 Debug_dump_trigger = 0;
3812 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3813 dc_printf( "Frame dumping at 30 hz is now ON\n" );
3816 Debug_dump_frames = 0;
3817 Debug_dump_trigger = 0;
3818 gr_dump_frame_stop();
3819 dc_printf( "Frame dumping is now OFF\n" );
3825 DCF(dump_frames30_trigger, "Starts/stop frame dumping at 30 hz")
3829 if ( Debug_dump_frames == 0 ) {
3831 Debug_dump_frames = 30;
3832 Debug_dump_trigger = 1;
3833 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3834 dc_printf( "Triggered frame dumping at 30 hz is now ON\n" );
3837 Debug_dump_frames = 0;
3838 Debug_dump_trigger = 0;
3839 gr_dump_frame_stop();
3840 dc_printf( "Triggered frame dumping is now OFF\n" );
3846 void game_maybe_dump_frame()
3848 if ( !Debug_dump_frames ){
3852 if( Debug_dump_trigger && !keyd_pressed[KEY_Q] ){
3859 Debug_dump_frame_num++;
3865 extern int Player_dead_state;
3867 // Flip the page and time how long it took.
3868 void game_flip_page_and_time_it()
3873 t1 = timer_get_fixed_seconds();
3875 t2 = timer_get_fixed_seconds();
3878 t = (gr_screen.max_w*gr_screen.max_h*gr_screen.bytes_per_pixel)/1024;
3879 sprintf( transfer_text, NOX("%ld MB/s"), fixmuldiv(t,65,d) );
3886 void game_simulation_frame()
3888 // blow ships up in multiplayer dogfight
3889 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){
3890 // blow up all non-player ships
3891 ship_obj *moveup = GET_FIRST(&Ship_obj_list);
3894 while((moveup != END_OF_LIST(&Ship_obj_list)) && (moveup != NULL)){
3896 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)){
3897 moveup = GET_NEXT(moveup);
3900 shipp = &Ships[Objects[moveup->objnum].instance];
3901 sip = &Ship_info[shipp->ship_info_index];
3903 // only blow up small ships
3904 if((sip->flags & SIF_SMALL_SHIP) && (multi_find_player_by_object(&Objects[moveup->objnum]) < 0) ){
3905 // function to simply explode a ship where it is currently at
3906 ship_self_destruct( &Objects[moveup->objnum] );
3909 moveup = GET_NEXT(moveup);
3915 // process AWACS stuff - do this first thing
3918 // single player, set Player hits_this_frame to 0
3919 if ( !(Game_mode & GM_MULTIPLAYER) && Player ) {
3920 Player->damage_this_burst -= (flFrametime * MAX_BURST_DAMAGE / (0.001f * BURST_DURATION));
3921 Player->damage_this_burst = max(Player->damage_this_burst, 0.0f);
3925 supernova_process();
3926 if(supernova_active() >= 5){
3930 // fire targeting lasers now so that
3931 // 1 - created this frame
3932 // 2 - collide this frame
3933 // 3 - render this frame
3934 // 4 - ignored and deleted next frame
3935 // the basic idea being that because it con be confusing to deal with them on a multi-frame basis, they are only valid for
3937 ship_process_targeting_lasers();
3939 // do this here so that it works for multiplayer
3941 // get viewer direction
3942 int viewer_direction = PHYSICS_VIEWER_REAR;
3944 if(Viewer_mode == 0){
3945 viewer_direction = PHYSICS_VIEWER_FRONT;
3947 if(Viewer_mode & VM_PADLOCK_UP){
3948 viewer_direction = PHYSICS_VIEWER_UP;
3950 else if(Viewer_mode & VM_PADLOCK_REAR){
3951 viewer_direction = PHYSICS_VIEWER_REAR;
3953 else if(Viewer_mode & VM_PADLOCK_LEFT){
3954 viewer_direction = PHYSICS_VIEWER_LEFT;
3956 else if(Viewer_mode & VM_PADLOCK_RIGHT){
3957 viewer_direction = PHYSICS_VIEWER_RIGHT;
3960 physics_set_viewer( &Viewer_obj->phys_info, viewer_direction );
3962 physics_set_viewer( NULL, PHYSICS_VIEWER_FRONT );
3965 #define VM_PADLOCK_UP (1 << 7)
3966 #define VM_PADLOCK_REAR (1 << 8)
3967 #define VM_PADLOCK_LEFT (1 << 9)
3968 #define VM_PADLOCK_RIGHT (1 << 10)
3970 // evaluate mission departures and arrivals before we process all objects.
3971 if ( !(Game_mode & GM_MULTIPLAYER) || ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending()) ) {
3973 // we don't want to evaluate mission stuff when any ingame joiner in multiplayer is receiving
3974 // ships/wing packets.
3975 if ( !((Game_mode & GM_MULTIPLAYER) && (Netgame.flags & NG_FLAG_INGAME_JOINING_CRITICAL)) && !(Game_mode & GM_DEMO_PLAYBACK)){
3976 mission_parse_eval_stuff();
3979 // if we're an observer, move ourselves seperately from the standard physics
3980 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
3981 obj_observer_move(flFrametime);
3984 // move all the objects now
3985 obj_move_all(flFrametime);
3987 // check for cargo reveal (this has an internal timestamp, so only runs every N ms)
3988 // AL: 3-15-98: It was decided to not let AI ships inspect cargo
3989 // ship_check_cargo_all();
3990 if(!(Game_mode & GM_DEMO_PLAYBACK)){
3991 mission_eval_goals();
3995 // always check training objectives, even in multiplayer missions. we need to do this so that the directives gauge works properly on clients
3996 if(!(Game_mode & GM_DEMO_PLAYBACK)){
3997 training_check_objectives();
4000 // do all interpolation now
4001 if ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending() && !(Netgame.flags & NG_FLAG_SERVER_LOST)) {
4002 // client side processing of warping in effect stages
4003 multi_do_client_warp(flFrametime);
4005 // client side movement of an observer
4006 if((Net_player->flags & NETINFO_FLAG_OBSERVER) || (Player_obj->type == OBJ_OBSERVER)){
4007 obj_observer_move(flFrametime);
4010 // move all objects - does interpolation now as well
4011 obj_move_all(flFrametime);
4014 // only process the message queue when the player is "in" the game
4015 if ( !Pre_player_entry ){
4016 message_queue_process(); // process any messages send to the player
4019 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4020 message_maybe_distort(); // maybe distort incoming message if comms damaged
4021 player_repair_frame(flFrametime); // AI objects get repaired in ai_process, called from move code...deal with player.
4022 player_process_pending_praise(); // maybe send off a delayed praise message to the player
4023 player_maybe_play_all_alone_msg(); // mabye tell the player he is all alone
4026 if(!(Game_mode & GM_STANDALONE_SERVER)){
4027 // process some stuff every frame (before frame is rendered)
4028 emp_process_local();
4030 hud_update_frame(); // update hud systems
4032 if (!physics_paused) {
4033 // Move particle system
4034 particle_move_all(flFrametime);
4036 // Move missile trails
4037 trail_move_all(flFrametime);
4039 // process muzzle flashes
4040 mflash_process_all();
4042 // Flash the gun flashes
4043 shipfx_flash_do_frame(flFrametime);
4045 shockwave_move_all(flFrametime); // update all the shockwaves
4048 // subspace missile strikes
4051 obj_snd_do_frame(); // update the object-linked persistant sounds
4052 game_maybe_update_sound_environment();
4053 snd_update_listener(&View_position, &Player_obj->phys_info.vel, &Player_obj->orient);
4055 // AL: debug code used for testing ambient subspace sound (ie when enabling subspace through debug console)
4057 if ( Game_subspace_effect ) {
4058 game_start_subspace_ambient_sound();
4064 // Maybe render and process the dead-popup
4065 void game_maybe_do_dead_popup(float frametime)
4067 if ( popupdead_is_active() ) {
4069 int choice = popupdead_do_frame(frametime);
4071 if ( Game_mode & GM_NORMAL ) {
4075 if(game_do_cd_mission_check(Game_current_mission_filename)){
4076 gameseq_post_event(GS_EVENT_ENTER_GAME);
4078 gameseq_post_event(GS_EVENT_MAIN_MENU);
4083 gameseq_post_event(GS_EVENT_END_GAME);
4088 if(game_do_cd_mission_check(Game_current_mission_filename)){
4089 gameseq_post_event(GS_EVENT_START_GAME);
4091 gameseq_post_event(GS_EVENT_MAIN_MENU);
4095 // this should only happen during a red alert mission
4098 Assert(The_mission.red_alert);
4099 if(!The_mission.red_alert){
4101 if(game_do_cd_mission_check(Game_current_mission_filename)){
4102 gameseq_post_event(GS_EVENT_START_GAME);
4104 gameseq_post_event(GS_EVENT_MAIN_MENU);
4109 // choose the previous mission
4110 mission_campaign_previous_mission();
4112 if(game_do_cd_mission_check(Game_current_mission_filename)){
4113 gameseq_post_event(GS_EVENT_START_GAME);
4115 gameseq_post_event(GS_EVENT_MAIN_MENU);
4126 case POPUPDEAD_DO_MAIN_HALL:
4127 multi_quit_game(PROMPT_NONE,-1);
4130 case POPUPDEAD_DO_RESPAWN:
4131 multi_respawn_normal();
4132 event_music_player_respawn();
4135 case POPUPDEAD_DO_OBSERVER:
4136 multi_respawn_observer();
4137 event_music_player_respawn_as_observer();
4146 if ( leave_popup ) {
4152 // returns true if player is actually in a game_play stats
4153 int game_actually_playing()
4157 state = gameseq_get_state();
4158 if ( (state != GS_STATE_GAME_PLAY) && (state != GS_STATE_DEATH_DIED) && (state != GS_STATE_DEATH_BLEW_UP) )
4164 // Draw the 2D HUD gauges
4165 void game_render_hud_2d()
4167 if ( !(Game_detail_flags & DETAIL_FLAG_HUD) ) {
4171 HUD_render_2d(flFrametime);
4175 // Draw the 3D-dependant HUD gauges
4176 void game_render_hud_3d(vector *eye_pos, matrix *eye_orient)
4178 g3_start_frame(0); // 0 = turn zbuffering off
4179 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
4181 if ( (Game_detail_flags & DETAIL_FLAG_HUD) && (supernova_active() < 3)/* && !(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) )*/ ) {
4182 HUD_render_3d(flFrametime);
4186 game_sunspot_process(flFrametime);
4188 // Diminish the palette effect
4189 game_flash_diminish(flFrametime);
4197 int actually_playing;
4198 fix total_time1, total_time2;
4199 fix render2_time1=0, render2_time2=0;
4200 fix render3_time1=0, render3_time2=0;
4201 fix flip_time1=0, flip_time2=0;
4202 fix clear_time1=0, clear_time2=0;
4208 if (Framerate_delay) {
4209 int start_time = timer_get_milliseconds();
4210 while (timer_get_milliseconds() < start_time + Framerate_delay)
4216 demo_do_frame_start();
4218 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4223 // start timing frame
4224 timing_frame_start();
4226 total_time1 = timer_get_fixed_seconds();
4228 // var to hold which state we are in
4229 actually_playing = game_actually_playing();
4231 if ((!(Game_mode & GM_MULTIPLAYER)) || ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER))) {
4232 if (!(Game_mode & GM_STANDALONE_SERVER)){
4233 Assert( OBJ_INDEX(Player_obj) >= 0 );
4237 if (Missiontime > Entry_delay_time){
4238 Pre_player_entry = 0;
4240 ; //nprintf(("AI", "Framecount = %i, time = %7.3f\n", Framecount, f2fl(Missiontime)));
4243 // Note: These are done even before the player enters, else buffers can overflow.
4244 if (! (Game_mode & GM_STANDALONE_SERVER)){
4248 shield_frame_init();
4250 if ( Player->control_mode != PCM_NORMAL )
4253 if ( !Pre_player_entry && actually_playing ) {
4254 if (! (Game_mode & GM_STANDALONE_SERVER) ) {
4256 if( (!popup_running_state()) && (!popupdead_is_active()) ){
4257 game_process_keys();
4259 // don't read flying controls if we're playing a demo back
4260 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4261 read_player_controls( Player_obj, flFrametime);
4265 // if we're not the master, we may have to send the server-critical ship status button_info bits
4266 if ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER)){
4267 multi_maybe_send_ship_status();
4272 // Reset the whack stuff
4275 // These two lines must be outside of Pre_player_entry code,
4276 // otherwise too many lights are added.
4279 if ((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4283 game_simulation_frame();
4285 // if not actually in a game play state, then return. This condition could only be true in
4286 // a multiplayer game.
4287 if ( !actually_playing ) {
4288 Assert( Game_mode & GM_MULTIPLAYER );
4292 if (!Pre_player_entry) {
4293 if (! (Game_mode & GM_STANDALONE_SERVER)) {
4294 clear_time1 = timer_get_fixed_seconds();
4295 // clear the screen to black
4297 if ( (Game_detail_flags & DETAIL_FLAG_CLEAR) ) {
4301 clear_time2 = timer_get_fixed_seconds();
4302 render3_time1 = timer_get_fixed_seconds();
4303 game_render_frame_setup(&eye_pos, &eye_orient);
4304 game_render_frame( &eye_pos, &eye_orient );
4306 // save the eye position and orientation
4307 if ( Game_mode & GM_MULTIPLAYER ) {
4308 Net_player->s_info.eye_pos = eye_pos;
4309 Net_player->s_info.eye_orient = eye_orient;
4312 hud_show_target_model();
4314 // check to see if we should display the death died popup
4315 if(Game_mode & GM_DEAD_BLEW_UP){
4316 if(Game_mode & GM_MULTIPLAYER){
4317 // catch the situation where we're supposed to be warping out on this transition
4318 if(Net_player->flags & NETINFO_FLAG_WARPING_OUT){
4319 gameseq_post_event(GS_EVENT_DEBRIEF);
4320 } else if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4321 Player_died_popup_wait = -1;
4325 if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4326 Player_died_popup_wait = -1;
4332 // hack - sometimes this seems to slip by in multiplayer. this should guarantee that we catch it
4333 if((Game_mode & GM_MULTIPLAYER) && (Player_multi_died_check != -1) && (Game_mode & GM_DEAD_BLEW_UP) ){
4334 if(fl_abs(time(NULL) - Player_multi_died_check) > 4){
4335 if(!popupdead_is_active()){
4339 Player_multi_died_check = -1;
4343 render3_time2 = timer_get_fixed_seconds();
4344 render2_time1 = timer_get_fixed_seconds();
4347 game_get_framerate();
4348 game_show_framerate();
4350 game_show_time_left();
4352 // Draw the 2D HUD gauges
4353 if(supernova_active() < 3){
4354 game_render_hud_2d();
4357 game_set_view_clip();
4359 // Draw 3D HUD gauges
4360 game_render_hud_3d(&eye_pos, &eye_orient);
4364 render2_time2 = timer_get_fixed_seconds();
4366 // maybe render and process the dead popup
4367 game_maybe_do_dead_popup(flFrametime);
4369 // start timing frame
4370 timing_frame_stop();
4371 // timing_display(30, 10);
4373 // If a regular popup is active, don't flip (popup code flips)
4374 if( !popup_running_state() ){
4375 flip_time1 = timer_get_fixed_seconds();
4376 game_flip_page_and_time_it();
4377 flip_time2 = timer_get_fixed_seconds();
4381 game_maybe_dump_frame(); // used to dump pcx files for building trailers
4384 game_show_standalone_framerate();
4388 game_do_training_checks();
4391 // process lightning (nebula only)
4394 total_time2 = timer_get_fixed_seconds();
4396 // Got some timing numbers
4397 Timing_total = f2fl( total_time2 - total_time1 ) * 1000.0f;
4398 Timing_clear = f2fl( clear_time2 - clear_time1 ) * 1000.0f;
4399 Timing_render2 = f2fl( render2_time2- render2_time1 ) * 1000.0f;
4400 Timing_render3 = f2fl( render3_time2- render3_time1 ) * 1000.0f;
4401 Timing_flip = f2fl( flip_time2 - flip_time1 ) * 1000.0f;
4404 demo_do_frame_end();
4406 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4412 #define MAX_FRAMETIME (F1_0/4) // Frametime gets saturated at this. Changed by MK on 11/1/97.
4413 // Some bug was causing Frametime to always get saturated at 2.0 seconds after the player
4414 // died. This resulted in screwed up death sequences.
4416 fix Last_time = 0; // The absolute time of game at end of last frame (beginning of this frame)
4417 fix Last_delta_time = 0; // While game is paused, this keeps track of how much elapsed in the frame before paused.
4418 static int timer_paused=0;
4419 #if defined(TIMER_TEST) && !defined(NDEBUG)
4420 static int stop_count,start_count;
4421 static int time_stopped,time_started;
4423 int saved_timestamp_ticker = -1;
4425 void game_reset_time()
4427 if((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4431 // Last_time = timer_get_fixed_seconds();
4437 void game_stop_time()
4439 if (timer_paused==0) {
4441 time = timer_get_fixed_seconds();
4442 // Save how much time progressed so far in the frame so we can
4443 // use it when we unpause.
4444 Last_delta_time = time - Last_time;
4446 //mprintf(("Last_time in game_stop_time = %7.3f\n", f2fl(Last_delta_time)));
4447 if (Last_delta_time < 0) {
4448 #if defined(TIMER_TEST) && !defined(NDEBUG)
4449 Int3(); //get Matt!!!!
4451 Last_delta_time = 0;
4453 #if defined(TIMER_TEST) && !defined(NDEBUG)
4454 time_stopped = time;
4457 // Stop the timer_tick stuff...
4458 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4459 saved_timestamp_ticker = timestamp_ticker;
4463 #if defined(TIMER_TEST) && !defined(NDEBUG)
4468 void game_start_time()
4471 Assert(timer_paused >= 0);
4472 if (timer_paused==0) {
4474 time = timer_get_fixed_seconds();
4475 #if defined(TIMER_TEST) && !defined(NDEBUG)
4477 Int3(); //get Matt!!!!
4480 // Take current time, and set it backwards to account for time
4481 // that the frame already executed, so that timer_get_fixed_seconds() - Last_time
4482 // will be correct when it goes to calculate the frametime next
4484 Last_time = time - Last_delta_time;
4485 #if defined(TIMER_TEST) && !defined(NDEBUG)
4486 time_started = time;
4489 // Restore the timer_tick stuff...
4490 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4491 Assert( saved_timestamp_ticker > -1 ); // Called out of order, get JAS
4492 timestamp_ticker = saved_timestamp_ticker;
4493 saved_timestamp_ticker = -1;
4496 #if defined(TIMER_TEST) && !defined(NDEBUG)
4502 void game_set_frametime(int state)
4505 float frame_cap_diff;
4507 thistime = timer_get_fixed_seconds();
4509 if ( Last_time == 0 )
4510 Frametime = F1_0 / 30;
4512 Frametime = thistime - Last_time;
4514 // Frametime = F1_0 / 30;
4516 fix debug_frametime = Frametime; // Just used to display frametime.
4518 // If player hasn't entered mission yet, make frame take 1/4 second.
4519 if ((Pre_player_entry) && (state == GS_STATE_GAME_PLAY))
4522 else if ((Debug_dump_frames) && (state == GS_STATE_GAME_PLAY)) { // note link to above if!!!!!
4524 fix frame_speed = F1_0 / Debug_dump_frames;
4526 if (Frametime > frame_speed ){
4527 nprintf(("warning","slow frame: %x\n",Frametime));
4530 thistime = timer_get_fixed_seconds();
4531 Frametime = thistime - Last_time;
4532 } while (Frametime < frame_speed );
4534 Frametime = frame_speed;
4538 Assert( Framerate_cap > 0 );
4540 // Cap the framerate so it doesn't get too high.
4544 cap = F1_0/Framerate_cap;
4545 if (Frametime < cap) {
4546 thistime = cap - Frametime;
4547 //mprintf(("Sleeping for %6.3f seconds.\n", f2fl(thistime)));
4548 Sleep( DWORD(f2fl(thistime) * 1000.0f) );
4550 thistime = timer_get_fixed_seconds();
4554 if((Game_mode & GM_STANDALONE_SERVER) &&
4555 (f2fl(Frametime) < ((float)1.0/(float)Multi_options_g.std_framecap))){
4557 frame_cap_diff = ((float)1.0/(float)Multi_options_g.std_framecap) - f2fl(Frametime);
4558 Sleep((DWORD)(frame_cap_diff*1000));
4560 thistime += fl2f((frame_cap_diff));
4562 Frametime = thistime - Last_time;
4565 // If framerate is too low, cap it.
4566 if (Frametime > MAX_FRAMETIME) {
4568 mprintf(("Frame %2i too long!!: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4570 // to remove warnings in release build
4571 debug_frametime = fl2f(flFrametime);
4573 Frametime = MAX_FRAMETIME;
4576 Frametime = fixmul(Frametime, Game_time_compression);
4578 Last_time = thistime;
4579 //mprintf(("Frame %i, Last_time = %7.3f\n", Framecount, f2fl(Last_time)));
4581 flFrametime = f2fl(Frametime);
4582 //if(!(Game_mode & GM_PLAYING_DEMO)){
4583 timestamp_inc(flFrametime);
4585 /* if ((Framecount > 0) && (Framecount < 10)) {
4586 mprintf(("Frame %2i: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4591 // This is called from game_do_frame(), and from navmap_do_frame()
4592 void game_update_missiontime()
4594 // TODO JAS: Put in if and move this into game_set_frametime,
4595 // fix navmap to call game_stop/start_time
4596 //if ( !timer_paused )
4597 Missiontime += Frametime;
4600 void game_do_frame()
4602 game_set_frametime(GS_STATE_GAME_PLAY);
4603 game_update_missiontime();
4605 if (Game_mode & GM_STANDALONE_SERVER) {
4606 std_multi_set_standalone_missiontime(f2fl(Missiontime));
4609 if ( game_single_step && (last_single_step == game_single_step) ) {
4610 os_set_title( NOX("SINGLE STEP MODE (Pause exits, any other key steps)") );
4611 while( key_checkch() == 0 )
4613 os_set_title( XSTR( "FreeSpace", 171) );
4614 Last_time = timer_get_fixed_seconds();
4617 last_single_step = game_single_step;
4619 if ((gameseq_get_state() == GS_STATE_GAME_PLAY) && Use_mouse_to_fly){
4620 Keep_mouse_centered = 1; // force mouse to center of our window (so we don't hit movement limits)
4624 Keep_mouse_centered = 0;
4625 monitor_update(); // Update monitor variables
4628 void multi_maybe_do_frame()
4630 if ( (Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_IN_MISSION) && !Multi_pause_status){
4635 int Joymouse_button_status = 0;
4637 // Flush all input devices
4645 Joymouse_button_status = 0;
4647 //mprintf(("Game flush!\n" ));
4650 // function for multiplayer only which calls game_do_state_common() when running the
4652 void game_do_dc_networking()
4654 Assert( Game_mode & GM_MULTIPLAYER );
4656 game_do_state_common( gameseq_get_state() );
4659 // Call this whenever in a loop, or when you need to check for a keystroke.
4660 int game_check_key()
4666 // convert keypad enter to normal enter
4667 if ((k & KEY_MASK) == KEY_PADENTER)
4668 k = (k & ~KEY_MASK) | KEY_ENTER;
4675 #define DEMO_TRAILER_TIMEOUT_MS 45000 // 45 seconds of no input, play trailer
4676 static int Demo_show_trailer_timestamp = 0;
4678 void demo_reset_trailer_timer()
4680 Demo_show_trailer_timestamp = timer_get_milliseconds();
4683 void demo_maybe_show_trailer(int k)
4686 // if key pressed, reset demo trailer timer
4688 demo_reset_trailer_timer();
4692 // if mouse moved, reset demo trailer timer
4695 mouse_get_delta(&dx, &dy);
4696 if ( (dx > 0) || (dy > 0) ) {
4697 demo_reset_trailer_timer();
4701 // if joystick has moved, reset demo trailer timer
4704 joy_get_delta(&dx, &dy);
4705 if ( (dx > 0) || (dy > 0) ) {
4706 demo_reset_trailer_timer();
4710 // NOTE: reseting the trailer timer on mouse/joystick presses is handled in
4711 // the low-level code. Ugly, I know... but was the simplest and most
4714 // if 30 seconds since last demo trailer time reset, launch movie
4715 if ( os_foreground() ) {
4716 int now = timer_get_milliseconds();
4717 if ( (now - Demo_show_trailer_timestamp) > DEMO_TRAILER_TIMEOUT_MS ) {
4718 // if ( (now - Demo_show_trailer_timestamp) > 10000 ) {
4720 movie_play( NOX("fstrailer2.mve") );
4721 demo_reset_trailer_timer();
4729 // same as game_check_key(), except this is used while actually in the game. Since there
4730 // generally are differences between game control keys and general UI keys, makes sense to
4731 // have seperate functions for each case. If you are not checking a game control while in a
4732 // mission, you should probably be using game_check_key() instead.
4737 if (!os_foreground()) {
4742 // If we're in a single player game, pause it.
4743 if (!(Game_mode & GM_MULTIPLAYER)){
4744 if ( (gameseq_get_state() == GS_STATE_GAME_PLAY) && (!popup_active()) && (!popupdead_is_active()) ) {
4745 game_process_pause_key();
4753 demo_maybe_show_trailer(k);
4756 // Move the mouse cursor with the joystick.
4757 if (os_foreground() && (!Mouse_hidden) && (Use_joy_mouse) ) {
4758 // Move the mouse cursor with the joystick
4762 joy_get_pos( &jx, &jy, &jz, &jr );
4764 dx = fl2i(f2fl(jx)*flFrametime*500.0f);
4765 dy = fl2i(f2fl(jy)*flFrametime*500.0f);
4768 mouse_get_real_pos( &mx, &my );
4769 mouse_set_pos( mx+dx, my+dy );
4774 m = mouse_down(MOUSE_LEFT_BUTTON);
4776 if ( j != Joymouse_button_status ) {
4777 //mprintf(( "Joy went from %d to %d, mouse is %d\n", Joymouse_button_status, j, m ));
4778 Joymouse_button_status = j;
4780 mouse_mark_button( MOUSE_LEFT_BUTTON, 1 );
4781 } else if ( (!j) && (m) ) {
4782 mouse_mark_button( MOUSE_LEFT_BUTTON, 0 );
4787 // if we should be ignoring keys because of some multiplayer situations
4788 if((Game_mode & GM_MULTIPLAYER) && multi_ignore_controls(k)){
4792 // If a popup is running, don't process all the Fn keys
4793 if( popup_active() ) {
4797 state = gameseq_get_state();
4799 // if ( k ) nprintf(( "General", "Key = %x\n", k ));
4802 case KEY_DEBUGGED + KEY_BACKSP:
4807 launch_context_help();
4812 // if (state != GS_STATE_INITIAL_PLAYER_SELECT) {
4814 // don't allow f2 while warping out in multiplayer
4815 if((Game_mode & GM_MULTIPLAYER) && (Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_WARPING_OUT)){
4820 case GS_STATE_INITIAL_PLAYER_SELECT:
4821 case GS_STATE_OPTIONS_MENU:
4822 case GS_STATE_HUD_CONFIG:
4823 case GS_STATE_CONTROL_CONFIG:
4824 case GS_STATE_DEATH_DIED:
4825 case GS_STATE_DEATH_BLEW_UP:
4826 case GS_STATE_VIEW_MEDALS:
4830 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
4837 // hotkey selection screen -- only valid from briefing and beyond.
4840 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) ) {
4841 gameseq_post_event( GS_EVENT_HOTKEY_SCREEN );
4847 case KEY_DEBUGGED + KEY_F3:
4848 gameseq_post_event( GS_EVENT_TOGGLE_FULLSCREEN );
4851 case KEY_DEBUGGED + KEY_F4:
4852 gameseq_post_event( GS_EVENT_TOGGLE_GLIDE );
4856 if(Game_mode & GM_MULTIPLAYER){
4857 if((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_MULTI_PAUSED)){
4858 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
4862 if ((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_DEATH_DIED) || (state == GS_STATE_DEATH_BLEW_UP) || (state == GS_STATE_GAME_PAUSED) ) {
4863 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
4869 case KEY_ESC | KEY_SHIFTED:
4870 // make sure to quit properly out of multiplayer
4871 if(Game_mode & GM_MULTIPLAYER){
4872 multi_quit_game(PROMPT_NONE);
4875 gameseq_post_event( GS_EVENT_QUIT_GAME );
4880 case KEY_DEBUGGED + KEY_P:
4883 case KEY_PRINT_SCRN:
4885 static int counter = 0;
4890 sprintf( tmp_name, NOX("screen%02d"), counter );
4892 mprintf(( "Dumping screen to '%s'\n", tmp_name ));
4893 gr_print_screen(tmp_name);
4901 case KEY_SHIFTED | KEY_ENTER: {
4903 #if !defined(NDEBUG)
4905 if ( Game_mode & GM_NORMAL ){
4909 // if we're in multiplayer mode, do some special networking
4910 if(Game_mode & GM_MULTIPLAYER){
4911 debug_console(game_do_dc_networking);
4918 if ( Game_mode & GM_NORMAL )
4932 gameseq_post_event(GS_EVENT_QUIT_GAME);
4935 void apply_physics( float damping, float desired_vel, float initial_vel, float t, float * new_vel, float * delta_pos );
4938 void camera_set_position( vector *pos )
4943 void camera_set_orient( matrix *orient )
4945 Camera_orient = *orient;
4948 void camera_set_velocity( vector *vel, int instantaneous )
4950 Camera_desired_velocity.xyz.x = 0.0f;
4951 Camera_desired_velocity.xyz.y = 0.0f;
4952 Camera_desired_velocity.xyz.z = 0.0f;
4954 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.rvec, vel->xyz.x );
4955 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.uvec, vel->xyz.y );
4956 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.fvec, vel->xyz.z );
4958 if ( instantaneous ) {
4959 Camera_velocity = Camera_desired_velocity;
4967 vector new_vel, delta_pos;
4969 apply_physics( Camera_damping, Camera_desired_velocity.xyz.x, Camera_velocity.xyz.x, flFrametime, &new_vel.xyz.x, &delta_pos.xyz.x );
4970 apply_physics( Camera_damping, Camera_desired_velocity.xyz.y, Camera_velocity.xyz.y, flFrametime, &new_vel.xyz.y, &delta_pos.xyz.y );
4971 apply_physics( Camera_damping, Camera_desired_velocity.xyz.z, Camera_velocity.xyz.z, flFrametime, &new_vel.xyz.z, &delta_pos.xyz.z );
4973 Camera_velocity = new_vel;
4975 // mprintf(( "Camera velocity = %.1f,%.1f, %.1f\n", Camera_velocity.xyz.x, Camera_velocity.xyz.y, Camera_velocity.xyz.z ));
4977 vm_vec_add2( &Camera_pos, &delta_pos );
4979 float ot = Camera_time+0.0f;
4981 Camera_time += flFrametime;
4983 if ( (ot < 0.667f) && ( Camera_time >= 0.667f ) ) {
4986 tmp.xyz.z = 4.739f; // always go this fast forward.
4988 // pick x and y velocities so they are always on a
4989 // circle with a 25 m radius.
4991 float tmp_angle = frand()*PI2;
4993 tmp.xyz.x = 22.0f * (float)sin(tmp_angle);
4994 tmp.xyz.y = -22.0f * (float)cos(tmp_angle);
4996 //mprintf(( "Angle = %.1f, vx=%.1f, vy=%.1f\n", tmp_angle, tmp.xyz.x, tmp.xyz.y ));
4998 //mprintf(( "Changing velocity!\n" ));
4999 camera_set_velocity( &tmp, 0 );
5002 if ( (ot < 3.0f ) && ( Camera_time >= 3.0f ) ) {
5003 vector tmp = { 0.0f, 0.0f, 0.0f };
5004 camera_set_velocity( &tmp, 0 );
5009 void end_demo_campaign_do()
5011 #if defined(FS2_DEMO)
5012 // show upsell screens
5013 demo_upsell_show_screens();
5014 #elif defined(OEM_BUILD)
5015 // show oem upsell screens
5016 oem_upsell_show_screens();
5019 // drop into main hall
5020 gameseq_post_event( GS_EVENT_MAIN_MENU );
5023 // All code to process events. This is the only place
5024 // that you should change the state of the game.
5025 void game_process_event( int current_state, int event )
5027 mprintf(("Got event %s in state %s\n", GS_event_text[event], GS_state_text[current_state]));
5030 case GS_EVENT_SIMULATOR_ROOM:
5031 gameseq_set_state(GS_STATE_SIMULATOR_ROOM);
5034 case GS_EVENT_MAIN_MENU:
5035 gameseq_set_state(GS_STATE_MAIN_MENU);
5038 case GS_EVENT_OPTIONS_MENU:
5039 gameseq_push_state( GS_STATE_OPTIONS_MENU );
5042 case GS_EVENT_BARRACKS_MENU:
5043 gameseq_set_state(GS_STATE_BARRACKS_MENU);
5046 case GS_EVENT_TECH_MENU:
5047 gameseq_set_state(GS_STATE_TECH_MENU);
5050 case GS_EVENT_TRAINING_MENU:
5051 gameseq_set_state(GS_STATE_TRAINING_MENU);
5054 case GS_EVENT_START_GAME:
5055 Select_default_ship = 0;
5056 Player_multi_died_check = -1;
5057 gameseq_set_state(GS_STATE_CMD_BRIEF);
5060 case GS_EVENT_START_BRIEFING:
5061 gameseq_set_state(GS_STATE_BRIEFING);
5064 case GS_EVENT_DEBRIEF:
5065 // did we end the campaign in the main freespace 2 single player campaign?
5066 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !stricmp(Campaign.filename, "freespace2")) {
5067 gameseq_post_event(GS_EVENT_END_CAMPAIGN);
5069 gameseq_set_state(GS_STATE_DEBRIEF);
5072 Player_multi_died_check = -1;
5075 case GS_EVENT_SHIP_SELECTION:
5076 gameseq_set_state( GS_STATE_SHIP_SELECT );
5079 case GS_EVENT_WEAPON_SELECTION:
5080 gameseq_set_state( GS_STATE_WEAPON_SELECT );
5083 case GS_EVENT_ENTER_GAME:
5085 // maybe start recording a demo
5087 demo_start_record("test.fsd");
5091 if (Game_mode & GM_MULTIPLAYER) {
5092 // if we're respawning, make sure we change the view mode so that the hud shows up
5093 if (current_state == GS_STATE_DEATH_BLEW_UP) {
5097 gameseq_set_state(GS_STATE_GAME_PLAY);
5099 gameseq_set_state(GS_STATE_GAME_PLAY, 1);
5102 Player_multi_died_check = -1;
5104 // clear multiplayer button info
5105 extern button_info Multi_ship_status_bi;
5106 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
5108 Start_time = f2fl(timer_get_approx_seconds());
5110 mprintf(("Entering game at time = %7.3f\n", Start_time));
5114 case GS_EVENT_START_GAME_QUICK:
5115 Select_default_ship = 1;
5116 gameseq_post_event(GS_EVENT_ENTER_GAME);
5120 case GS_EVENT_END_GAME:
5121 if ( (current_state == GS_STATE_GAME_PLAY) || (current_state == GS_STATE_DEATH_DIED) ||
5122 (current_state == GS_STATE_DEATH_BLEW_UP) || (current_state == GS_STATE_DEBRIEF) || (current_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) {
5123 gameseq_set_state(GS_STATE_MAIN_MENU);
5128 Player_multi_died_check = -1;
5131 case GS_EVENT_QUIT_GAME:
5132 main_hall_stop_music();
5133 main_hall_stop_ambient();
5134 gameseq_set_state(GS_STATE_QUIT_GAME);
5136 Player_multi_died_check = -1;
5139 case GS_EVENT_GAMEPLAY_HELP:
5140 gameseq_push_state( GS_STATE_GAMEPLAY_HELP );
5143 case GS_EVENT_PAUSE_GAME:
5144 gameseq_push_state(GS_STATE_GAME_PAUSED);
5147 case GS_EVENT_DEBUG_PAUSE_GAME:
5148 gameseq_push_state(GS_STATE_DEBUG_PAUSED);
5151 case GS_EVENT_TRAINING_PAUSE:
5152 gameseq_push_state(GS_STATE_TRAINING_PAUSED);
5155 case GS_EVENT_PREVIOUS_STATE:
5156 gameseq_pop_state();
5159 case GS_EVENT_TOGGLE_FULLSCREEN:
5160 #ifndef HARDWARE_ONLY
5162 if ( gr_screen.mode == GR_SOFTWARE ) {
5163 gr_init( GR_640, GR_DIRECTDRAW );
5164 } else if ( gr_screen.mode == GR_DIRECTDRAW ) {
5165 gr_init( GR_640, GR_SOFTWARE );
5171 case GS_EVENT_TOGGLE_GLIDE:
5173 if ( gr_screen.mode != GR_GLIDE ) {
5174 gr_init( GR_640, GR_GLIDE );
5176 gr_init( GR_640, GR_SOFTWARE );
5181 case GS_EVENT_LOAD_MISSION_MENU:
5182 gameseq_set_state(GS_STATE_LOAD_MISSION_MENU);
5185 case GS_EVENT_MISSION_LOG_SCROLLBACK:
5186 gameseq_push_state( GS_STATE_MISSION_LOG_SCROLLBACK );
5189 case GS_EVENT_HUD_CONFIG:
5190 gameseq_push_state( GS_STATE_HUD_CONFIG );
5193 case GS_EVENT_CONTROL_CONFIG:
5194 gameseq_push_state( GS_STATE_CONTROL_CONFIG );
5197 case GS_EVENT_DEATH_DIED:
5198 gameseq_set_state( GS_STATE_DEATH_DIED );
5201 case GS_EVENT_DEATH_BLEW_UP:
5202 if ( current_state == GS_STATE_DEATH_DIED ) {
5203 gameseq_set_state( GS_STATE_DEATH_BLEW_UP );
5204 event_music_player_death();
5206 // multiplayer clients set their extra check here
5207 if(Game_mode & GM_MULTIPLAYER){
5208 // set the multi died absolute last chance check
5209 Player_multi_died_check = time(NULL);
5212 mprintf(( "Ignoring GS_EVENT_DEATH_BLEW_UP because we're in state %d\n", current_state ));
5216 case GS_EVENT_NEW_CAMPAIGN:
5217 if (!mission_load_up_campaign()){
5218 readyroom_continue_campaign();
5221 Player_multi_died_check = -1;
5224 case GS_EVENT_CAMPAIGN_CHEAT:
5225 if (!mission_load_up_campaign()){
5227 // bash campaign value
5228 extern char Main_hall_campaign_cheat[512];
5231 // look for the mission
5232 for(idx=0; idx<Campaign.num_missions; idx++){
5233 if(!stricmp(Campaign.missions[idx].name, Main_hall_campaign_cheat)){
5234 Campaign.next_mission = idx;
5235 Campaign.prev_mission = idx - 1;
5242 readyroom_continue_campaign();
5245 Player_multi_died_check = -1;
5248 case GS_EVENT_CAMPAIGN_ROOM:
5249 gameseq_set_state(GS_STATE_CAMPAIGN_ROOM);
5252 case GS_EVENT_CMD_BRIEF:
5253 gameseq_set_state(GS_STATE_CMD_BRIEF);
5256 case GS_EVENT_RED_ALERT:
5257 gameseq_set_state(GS_STATE_RED_ALERT);
5260 case GS_EVENT_CREDITS:
5261 gameseq_set_state( GS_STATE_CREDITS );
5264 case GS_EVENT_VIEW_MEDALS:
5265 gameseq_push_state( GS_STATE_VIEW_MEDALS );
5268 case GS_EVENT_SHOW_GOALS:
5269 gameseq_push_state( GS_STATE_SHOW_GOALS ); // use push_state() since we might get to this screen through a variety of states
5272 case GS_EVENT_HOTKEY_SCREEN:
5273 gameseq_push_state( GS_STATE_HOTKEY_SCREEN ); // use push_state() since we might get to this screen through a variety of states
5276 // multiplayer stuff follow these comments
5278 case GS_EVENT_MULTI_JOIN_GAME:
5279 gameseq_set_state( GS_STATE_MULTI_JOIN_GAME );
5282 case GS_EVENT_MULTI_HOST_SETUP:
5283 gameseq_set_state( GS_STATE_MULTI_HOST_SETUP );
5286 case GS_EVENT_MULTI_CLIENT_SETUP:
5287 gameseq_set_state( GS_STATE_MULTI_CLIENT_SETUP );
5290 case GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN:
5291 gameseq_set_state(GS_STATE_VIEW_CUTSCENES);
5294 case GS_EVENT_MULTI_STD_WAIT:
5295 gameseq_set_state( GS_STATE_MULTI_STD_WAIT );
5298 case GS_EVENT_STANDALONE_MAIN:
5299 gameseq_set_state( GS_STATE_STANDALONE_MAIN );
5302 case GS_EVENT_MULTI_PAUSE:
5303 gameseq_push_state( GS_STATE_MULTI_PAUSED );
5306 case GS_EVENT_INGAME_PRE_JOIN:
5307 gameseq_set_state( GS_STATE_INGAME_PRE_JOIN );
5310 case GS_EVENT_EVENT_DEBUG:
5311 gameseq_push_state(GS_STATE_EVENT_DEBUG);
5314 // Start a warpout where player automatically goes 70 no matter what
5315 // and can't cancel out of it.
5316 case GS_EVENT_PLAYER_WARPOUT_START_FORCED:
5317 Warpout_forced = 1; // If non-zero, bash the player to speed and go through effect
5319 // Same code as in GS_EVENT_PLAYER_WARPOUT_START only ignores current mode
5320 Player->saved_viewer_mode = Viewer_mode;
5321 Player->control_mode = PCM_WARPOUT_STAGE1;
5322 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5323 Warpout_time = 0.0f; // Start timer!
5326 case GS_EVENT_PLAYER_WARPOUT_START:
5327 if ( Player->control_mode != PCM_NORMAL ) {
5328 mprintf(( "Player isn't in normal mode; cannot warp out.\n" ));
5330 Player->saved_viewer_mode = Viewer_mode;
5331 Player->control_mode = PCM_WARPOUT_STAGE1;
5332 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5333 Warpout_time = 0.0f; // Start timer!
5334 Warpout_forced = 0; // If non-zero, bash the player to speed and go through effect
5338 case GS_EVENT_PLAYER_WARPOUT_STOP:
5339 if ( Player->control_mode != PCM_NORMAL ) {
5340 if ( !Warpout_forced ) { // cannot cancel forced warpout
5341 Player->control_mode = PCM_NORMAL;
5342 Viewer_mode = Player->saved_viewer_mode;
5343 hud_subspace_notify_abort();
5344 mprintf(( "Player put back to normal mode.\n" ));
5345 if ( Warpout_sound > -1 ) {
5346 snd_stop( Warpout_sound );
5353 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE1: // player ship got up to speed
5354 if ( Player->control_mode != PCM_WARPOUT_STAGE1 ) {
5355 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5356 mprintf(( "Player put back to normal mode, because of invalid sequence in stage1.\n" ));
5358 mprintf(( "Hit target speed. Starting warp effect and moving to stage 2!\n" ));
5359 shipfx_warpout_start( Player_obj );
5360 Player->control_mode = PCM_WARPOUT_STAGE2;
5361 Player->saved_viewer_mode = Viewer_mode;
5362 Viewer_mode |= VM_WARP_CHASE;
5364 vector tmp = Player_obj->pos;
5366 ship_get_eye( &tmp, &tmp_m, Player_obj );
5367 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.rvec, 0.0f );
5368 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.uvec, 0.952f );
5369 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.fvec, -1.782f );
5371 camera_set_position( &tmp );
5372 camera_set_orient( &Player_obj->orient );
5373 vector tmp_vel = { 0.0f, 5.1919f, 14.7f };
5375 //mprintf(( "Rad = %.1f\n", Player_obj->radius ));
5376 camera_set_velocity( &tmp_vel, 1);
5380 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE2: // player ship got into the warp effect
5381 if ( Player->control_mode != PCM_WARPOUT_STAGE2 ) {
5382 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5383 mprintf(( "Player put back to normal mode, because of invalid sequence in stage2.\n" ));
5385 mprintf(( "Hit warp effect. Moving to stage 3!\n" ));
5386 Player->control_mode = PCM_WARPOUT_STAGE3;
5390 case GS_EVENT_PLAYER_WARPOUT_DONE: // player ship got through the warp effect
5391 mprintf(( "Player warped out. Going to debriefing!\n" ));
5392 Player->control_mode = PCM_NORMAL;
5393 Viewer_mode = Player->saved_viewer_mode;
5396 // we have a special debriefing screen for multiplayer furballs
5397 if((Game_mode & GM_MULTIPLAYER) && (The_mission.game_type & MISSION_TYPE_MULTI_DOGFIGHT)){
5398 gameseq_post_event(GS_EVENT_MULTI_DOGFIGHT_DEBRIEF);
5400 // do the normal debriefing for all other situations
5402 gameseq_post_event(GS_EVENT_DEBRIEF);
5406 case GS_EVENT_STANDALONE_POSTGAME:
5407 gameseq_set_state(GS_STATE_STANDALONE_POSTGAME);
5410 case GS_EVENT_INITIAL_PLAYER_SELECT:
5411 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5414 case GS_EVENT_GAME_INIT:
5415 #if defined(FS2_DEMO) || defined(OEM_BUILD)
5416 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5418 // see if the command line option has been set to use the last pilot, and act acoordingly
5419 if( player_select_get_last_pilot() ) {
5420 // always enter the main menu -- do the automatic network startup stuff elsewhere
5421 // so that we still have valid checks for networking modes, etc.
5422 gameseq_set_state(GS_STATE_MAIN_MENU);
5424 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5429 case GS_EVENT_MULTI_MISSION_SYNC:
5430 gameseq_set_state(GS_STATE_MULTI_MISSION_SYNC);
5433 case GS_EVENT_MULTI_START_GAME:
5434 gameseq_set_state(GS_STATE_MULTI_START_GAME);
5437 case GS_EVENT_MULTI_HOST_OPTIONS:
5438 gameseq_set_state(GS_STATE_MULTI_HOST_OPTIONS);
5441 case GS_EVENT_MULTI_DOGFIGHT_DEBRIEF:
5442 gameseq_set_state(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
5445 case GS_EVENT_TEAM_SELECT:
5446 gameseq_set_state(GS_STATE_TEAM_SELECT);
5449 case GS_EVENT_END_CAMPAIGN:
5450 gameseq_set_state(GS_STATE_END_OF_CAMPAIGN);
5453 case GS_EVENT_END_DEMO:
5454 gameseq_set_state(GS_STATE_END_DEMO);
5457 case GS_EVENT_LOOP_BRIEF:
5458 gameseq_set_state(GS_STATE_LOOP_BRIEF);
5467 // Called when a state is being left.
5468 // The current state is still at old_state, but as soon as
5469 // this function leaves, then the current state will become
5470 // new state. You should never try to change the state
5471 // in here... if you think you need to, you probably really
5472 // need to post an event, not change the state.
5473 void game_leave_state( int old_state, int new_state )
5475 int end_mission = 1;
5477 switch (new_state) {
5478 case GS_STATE_GAME_PAUSED:
5479 case GS_STATE_DEBUG_PAUSED:
5480 case GS_STATE_OPTIONS_MENU:
5481 case GS_STATE_CONTROL_CONFIG:
5482 case GS_STATE_MISSION_LOG_SCROLLBACK:
5483 case GS_STATE_DEATH_DIED:
5484 case GS_STATE_SHOW_GOALS:
5485 case GS_STATE_HOTKEY_SCREEN:
5486 case GS_STATE_MULTI_PAUSED:
5487 case GS_STATE_TRAINING_PAUSED:
5488 case GS_STATE_EVENT_DEBUG:
5489 case GS_STATE_GAMEPLAY_HELP:
5490 end_mission = 0; // these events shouldn't end a mission
5494 switch (old_state) {
5495 case GS_STATE_BRIEFING:
5496 brief_stop_voices();
5497 if ( (new_state != GS_STATE_OPTIONS_MENU) && (new_state != GS_STATE_WEAPON_SELECT)
5498 && (new_state != GS_STATE_SHIP_SELECT) && (new_state != GS_STATE_HOTKEY_SCREEN)
5499 && (new_state != GS_STATE_TEAM_SELECT) ){
5500 common_select_close();
5501 if ( new_state == GS_STATE_MAIN_MENU ) {
5502 freespace_stop_mission();
5506 // COMMAND LINE OPTION
5507 if (Cmdline_multi_stream_chat_to_file){
5508 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5509 cfclose(Multi_chat_stream);
5513 case GS_STATE_DEBRIEF:
5514 if ( (new_state != GS_STATE_VIEW_MEDALS) && (new_state != GS_STATE_OPTIONS_MENU) ) {
5519 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
5520 multi_df_debrief_close();
5523 case GS_STATE_LOAD_MISSION_MENU:
5524 mission_load_menu_close();
5527 case GS_STATE_SIMULATOR_ROOM:
5531 case GS_STATE_CAMPAIGN_ROOM:
5532 campaign_room_close();
5535 case GS_STATE_CMD_BRIEF:
5536 if (new_state == GS_STATE_OPTIONS_MENU) {
5541 if (new_state == GS_STATE_MAIN_MENU)
5542 freespace_stop_mission();
5547 case GS_STATE_RED_ALERT:
5551 case GS_STATE_SHIP_SELECT:
5552 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_WEAPON_SELECT &&
5553 new_state != GS_STATE_HOTKEY_SCREEN &&
5554 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5555 common_select_close();
5556 if ( new_state == GS_STATE_MAIN_MENU ) {
5557 freespace_stop_mission();
5562 case GS_STATE_WEAPON_SELECT:
5563 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5564 new_state != GS_STATE_HOTKEY_SCREEN &&
5565 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5566 common_select_close();
5567 if ( new_state == GS_STATE_MAIN_MENU ) {
5568 freespace_stop_mission();
5573 case GS_STATE_TEAM_SELECT:
5574 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5575 new_state != GS_STATE_HOTKEY_SCREEN &&
5576 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_WEAPON_SELECT) {
5577 common_select_close();
5578 if ( new_state == GS_STATE_MAIN_MENU ) {
5579 freespace_stop_mission();
5584 case GS_STATE_MAIN_MENU:
5585 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
5592 case GS_STATE_OPTIONS_MENU:
5593 //game_start_time();
5594 if(new_state == GS_STATE_MULTI_JOIN_GAME){
5595 multi_join_clear_game_list();
5597 options_menu_close();
5600 case GS_STATE_BARRACKS_MENU:
5601 if(new_state != GS_STATE_VIEW_MEDALS){
5606 case GS_STATE_MISSION_LOG_SCROLLBACK:
5607 hud_scrollback_close();
5610 case GS_STATE_TRAINING_MENU:
5611 training_menu_close();
5614 case GS_STATE_GAME_PLAY:
5615 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
5616 player_save_target_and_weapon_link_prefs();
5617 game_stop_looped_sounds();
5620 sound_env_disable();
5621 joy_ff_stop_effects();
5623 // stop game time under certain conditions
5624 if ( end_mission || (Game_mode & GM_NORMAL) || ((Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MULTI_PAUSED)) ){
5629 // shut down any recording or playing demos
5634 // when in multiplayer and going back to the main menu, send a leave game packet
5635 // right away (before calling stop mission). stop_mission was taking to long to
5636 // close mission down and I want people to get notified ASAP.
5637 if ( (Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MAIN_MENU) ){
5638 multi_quit_game(PROMPT_NONE);
5641 freespace_stop_mission();
5642 Game_time_compression = F1_0;
5646 case GS_STATE_TECH_MENU:
5650 case GS_STATE_TRAINING_PAUSED:
5651 Training_num_lines = 0;
5652 // fall through to GS_STATE_GAME_PAUSED
5654 case GS_STATE_GAME_PAUSED:
5656 if ( end_mission ) {
5661 case GS_STATE_DEBUG_PAUSED:
5664 pause_debug_close();
5668 case GS_STATE_HUD_CONFIG:
5672 // join/start a game
5673 case GS_STATE_MULTI_JOIN_GAME:
5674 if(new_state != GS_STATE_OPTIONS_MENU){
5675 multi_join_game_close();
5679 case GS_STATE_MULTI_HOST_SETUP:
5680 case GS_STATE_MULTI_CLIENT_SETUP:
5681 // if this is just the host going into the options screen, don't do anything
5682 if((new_state == GS_STATE_MULTI_HOST_OPTIONS) || (new_state == GS_STATE_OPTIONS_MENU)){
5686 // close down the proper state
5687 if(old_state == GS_STATE_MULTI_HOST_SETUP){
5688 multi_create_game_close();
5690 multi_game_client_setup_close();
5693 // COMMAND LINE OPTION
5694 if (Cmdline_multi_stream_chat_to_file){
5695 if( (new_state != GS_STATE_TEAM_SELECT) && (Multi_chat_stream!=NULL) ) {
5696 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5697 cfclose(Multi_chat_stream);
5702 case GS_STATE_CONTROL_CONFIG:
5703 control_config_close();
5706 case GS_STATE_DEATH_DIED:
5707 Game_mode &= ~GM_DEAD_DIED;
5709 // early end while respawning or blowing up in a multiplayer game
5710 if((Game_mode & GM_MULTIPLAYER) && ((new_state == GS_STATE_DEBRIEF) || (new_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) ){
5712 freespace_stop_mission();
5716 case GS_STATE_DEATH_BLEW_UP:
5717 Game_mode &= ~GM_DEAD_BLEW_UP;
5719 // for single player, we might reload mission, etc. For multiplayer, look at my new state
5720 // to determine if I should do anything.
5721 if ( !(Game_mode & GM_MULTIPLAYER) ) {
5723 freespace_stop_mission();
5726 // if we are not respawing as an observer or as a player, our new state will not
5727 // be gameplay state.
5728 if ( (new_state != GS_STATE_GAME_PLAY) && (new_state != GS_STATE_MULTI_PAUSED) ) {
5729 game_stop_time(); // hasn't been called yet!!
5730 freespace_stop_mission();
5736 case GS_STATE_CREDITS:
5740 case GS_STATE_VIEW_MEDALS:
5744 case GS_STATE_SHOW_GOALS:
5745 mission_show_goals_close();
5748 case GS_STATE_HOTKEY_SCREEN:
5749 if ( new_state != GS_STATE_OPTIONS_MENU ) {
5750 mission_hotkey_close();
5754 case GS_STATE_MULTI_MISSION_SYNC:
5755 // if we're moving into the options menu, don't do anything
5756 if(new_state == GS_STATE_OPTIONS_MENU){
5760 Assert( Game_mode & GM_MULTIPLAYER );
5762 if ( new_state == GS_STATE_GAME_PLAY ){
5763 // palette_restore_palette();
5765 // change a couple of flags to indicate our state!!!
5766 Net_player->state = NETPLAYER_STATE_IN_MISSION;
5767 send_netplayer_update_packet();
5769 // set the game mode
5770 Game_mode |= GM_IN_MISSION;
5774 case GS_STATE_VIEW_CUTSCENES:
5775 cutscenes_screen_close();
5778 case GS_STATE_MULTI_STD_WAIT:
5779 multi_standalone_wait_close();
5782 case GS_STATE_STANDALONE_MAIN:
5783 standalone_main_close();
5784 if(new_state == GS_STATE_MULTI_STD_WAIT){
5785 init_multiplayer_stats();
5789 case GS_STATE_MULTI_PAUSED:
5790 // if ( end_mission ){
5795 case GS_STATE_INGAME_PRE_JOIN:
5796 multi_ingame_select_close();
5799 case GS_STATE_STANDALONE_POSTGAME:
5800 multi_standalone_postgame_close();
5803 case GS_STATE_INITIAL_PLAYER_SELECT:
5804 player_select_close();
5807 case GS_STATE_MULTI_START_GAME:
5808 multi_start_game_close();
5811 case GS_STATE_MULTI_HOST_OPTIONS:
5812 multi_host_options_close();
5815 case GS_STATE_END_OF_CAMPAIGN:
5816 mission_campaign_end_close();
5819 case GS_STATE_LOOP_BRIEF:
5825 // Called when a state is being entered.
5826 // The current state is set to the state we're entering at
5827 // this point, and old_state is set to the state we're coming
5828 // from. You should never try to change the state
5829 // in here... if you think you need to, you probably really
5830 // need to post an event, not change the state.
5832 void game_enter_state( int old_state, int new_state )
5834 switch (new_state) {
5835 case GS_STATE_MAIN_MENU:
5836 // in multiplayer mode, be sure that we are not doing networking anymore.
5837 if ( Game_mode & GM_MULTIPLAYER ) {
5838 Assert( Net_player != NULL );
5839 Net_player->flags &= ~NETINFO_FLAG_DO_NETWORKING;
5842 Game_time_compression = F1_0;
5844 // determine which ship this guy is currently based on
5845 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
5848 if (Player->on_bastion) {
5856 case GS_STATE_BRIEFING:
5857 main_hall_stop_music();
5858 main_hall_stop_ambient();
5860 if (Game_mode & GM_NORMAL) {
5861 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
5862 // MWA: or from options or hotkey screens
5863 // JH: or if the command brief state already did this
5864 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
5865 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT)
5866 && (old_state != GS_STATE_CMD_BRIEF) ) {
5867 if ( !game_start_mission() ) // this should put us into a new state on failure!
5871 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
5872 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
5873 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
5875 Game_time_compression = F1_0;
5877 if ( red_alert_mission() ) {
5878 gameseq_post_event(GS_EVENT_RED_ALERT);
5885 case GS_STATE_DEBRIEF:
5886 game_stop_looped_sounds();
5887 mission_goal_fail_incomplete(); // fail all incomplete goals before entering debriefing
5888 if ( (old_state != GS_STATE_VIEW_MEDALS) && (old_state != GS_STATE_OPTIONS_MENU) ){
5893 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
5894 multi_df_debrief_init();
5897 case GS_STATE_LOAD_MISSION_MENU:
5898 mission_load_menu_init();
5901 case GS_STATE_SIMULATOR_ROOM:
5905 case GS_STATE_CAMPAIGN_ROOM:
5906 campaign_room_init();
5909 case GS_STATE_RED_ALERT:
5910 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
5914 case GS_STATE_CMD_BRIEF: {
5915 int team_num = 0; // team number used as index for which cmd brief to use.
5917 if (old_state == GS_STATE_OPTIONS_MENU) {
5921 main_hall_stop_music();
5922 main_hall_stop_ambient();
5924 if (Game_mode & GM_NORMAL) {
5925 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
5926 // MWA: or from options or hotkey screens
5927 // JH: or if the command brief state already did this
5928 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
5929 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT) ) {
5930 if ( !game_start_mission() ) // this should put us into a new state on failure!
5935 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
5936 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
5937 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
5939 cmd_brief_init(team_num);
5945 case GS_STATE_SHIP_SELECT:
5949 case GS_STATE_WEAPON_SELECT:
5950 weapon_select_init();
5953 case GS_STATE_TEAM_SELECT:
5957 case GS_STATE_GAME_PAUSED:
5962 case GS_STATE_DEBUG_PAUSED:
5963 // game_stop_time();
5964 // os_set_title("FreeSpace - PAUSED");
5967 case GS_STATE_TRAINING_PAUSED:
5974 case GS_STATE_OPTIONS_MENU:
5976 options_menu_init();
5979 case GS_STATE_GAME_PLAY:
5980 // coming from the gameplay state or the main menu, we might need to load the mission
5981 if ( (Game_mode & GM_NORMAL) && ((old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_GAME_PLAY) || (old_state == GS_STATE_DEATH_BLEW_UP)) ) {
5982 if ( !game_start_mission() ) // this should put us into a new state.
5987 // if we are coming from the briefing, ship select, weapons loadout, or main menu (in the
5988 // case of quick start), then do bitmap loads, etc Don't do any of the loading stuff
5989 // if we are in multiplayer -- this stuff is all handled in the multi-wait section
5990 if ( !(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_BRIEFING) || (old_state == GS_STATE_SHIP_SELECT) ||
5991 (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) ) {
5992 // JAS: Used to do all paging here.
5996 HUD_printf("Skill level is set to ** %s **", Skill_level_names(Game_skill_level));
6000 main_hall_stop_music();
6001 main_hall_stop_ambient();
6002 event_music_first_pattern(); // start the first pattern
6005 // special code that restores player ship selection and weapons loadout when doing a quick start
6006 if ( !(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_DEATH_BLEW_UP) || (old_state == GS_STATE_GAME_PLAY) ) {
6007 if ( !stricmp(Player_loadout.filename, Game_current_mission_filename) ) {
6008 wss_direct_restore_loadout();
6012 // single-player, quick-start after just died... we need to set weapon linking and kick off the event music
6013 if (!(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_DEATH_BLEW_UP) ) {
6014 event_music_first_pattern(); // start the first pattern
6017 if ( !(Game_mode & GM_STANDALONE_SERVER) && (old_state != GS_STATE_GAME_PAUSED) && (old_state != GS_STATE_MULTI_PAUSED) ) {
6018 event_music_first_pattern(); // start the first pattern
6020 player_restore_target_and_weapon_link_prefs();
6022 Game_mode |= GM_IN_MISSION;
6025 // required to truely make mouse deltas zeroed in debug mouse code
6026 void mouse_force_pos(int x, int y);
6027 if (!Is_standalone) {
6028 mouse_force_pos(gr_screen.max_w / 2, gr_screen.max_h / 2);
6034 // only start time if in single player, or coming from multi wait state
6037 (Game_mode & GM_NORMAL) &&
6038 (old_state != GS_STATE_VIEW_CUTSCENES)
6040 (Game_mode & GM_MULTIPLAYER) && (
6041 (old_state == GS_STATE_MULTI_PAUSED) ||
6042 (old_state == GS_STATE_MULTI_MISSION_SYNC)
6048 // when coming from the multi paused state, reset the timestamps
6049 if ( (Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_MULTI_PAUSED) ){
6050 multi_reset_timestamps();
6053 if ((Game_mode & GM_MULTIPLAYER) && (old_state != GS_STATE_DEATH_BLEW_UP) ) {
6054 // initialize all object update details
6055 multi_oo_gameplay_init();
6058 // under certain circumstances, the server should reset the object update rate limiting stuff
6059 if( ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)) &&
6060 (old_state == GS_STATE_MULTI_PAUSED) || (old_state == GS_STATE_MULTI_MISSION_SYNC) ){
6062 // reinitialize the rate limiting system for all clients
6063 multi_oo_rate_init_all();
6066 // multiplayer clients should always re-initialize their control info rate limiting system
6067 if((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)){
6068 multi_oo_rate_init_all();
6072 if(Game_mode & GM_MULTIPLAYER){
6073 multi_ping_reset_players();
6076 Game_subspace_effect = 0;
6077 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
6078 Game_subspace_effect = 1;
6079 if( !(Game_mode & GM_STANDALONE_SERVER) ){
6080 game_start_subspace_ambient_sound();
6084 sound_env_set(&Game_sound_env);
6085 joy_ff_mission_init(Ship_info[Player_ship->ship_info_index].rotation_time);
6087 // clear multiplayer button info i
6088 extern button_info Multi_ship_status_bi;
6089 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
6092 case GS_STATE_HUD_CONFIG:
6096 case GS_STATE_MULTI_JOIN_GAME:
6097 multi_join_clear_game_list();
6099 if (old_state != GS_STATE_OPTIONS_MENU) {
6100 multi_join_game_init();
6105 case GS_STATE_MULTI_HOST_SETUP:
6106 // don't reinitialize if we're coming back from the host options screen
6107 if ((old_state != GS_STATE_MULTI_HOST_OPTIONS) && (old_state != GS_STATE_OPTIONS_MENU)) {
6108 multi_create_game_init();
6113 case GS_STATE_MULTI_CLIENT_SETUP:
6114 if (old_state != GS_STATE_OPTIONS_MENU) {
6115 multi_game_client_setup_init();
6120 case GS_STATE_CONTROL_CONFIG:
6121 control_config_init();
6124 case GS_STATE_TECH_MENU:
6128 case GS_STATE_BARRACKS_MENU:
6129 if(old_state != GS_STATE_VIEW_MEDALS){
6134 case GS_STATE_MISSION_LOG_SCROLLBACK:
6135 hud_scrollback_init();
6138 case GS_STATE_DEATH_DIED:
6139 Player_died_time = timestamp(10);
6141 if(!(Game_mode & GM_MULTIPLAYER)){
6142 player_show_death_message();
6144 Game_mode |= GM_DEAD_DIED;
6147 case GS_STATE_DEATH_BLEW_UP:
6148 if ( !popupdead_is_active() ) {
6149 Player_ai->target_objnum = -1;
6152 // stop any local EMP effect
6155 Players[Player_num].flags &= ~PLAYER_FLAGS_AUTO_TARGETING; // Prevent immediate switch to a hostile ship.
6156 Game_mode |= GM_DEAD_BLEW_UP;
6157 Show_viewing_from_self = 0;
6159 // timestamp how long we should wait before displaying the died popup
6160 if ( !popupdead_is_active() ) {
6161 Player_died_popup_wait = timestamp(PLAYER_DIED_POPUP_WAIT);
6165 case GS_STATE_GAMEPLAY_HELP:
6166 gameplay_help_init();
6169 case GS_STATE_CREDITS:
6170 main_hall_stop_music();
6171 main_hall_stop_ambient();
6175 case GS_STATE_VIEW_MEDALS:
6176 medal_main_init(Player);
6179 case GS_STATE_SHOW_GOALS:
6180 mission_show_goals_init();
6183 case GS_STATE_HOTKEY_SCREEN:
6184 mission_hotkey_init();
6187 case GS_STATE_MULTI_MISSION_SYNC:
6188 // if we're coming from the options screen, don't do any
6189 if(old_state == GS_STATE_OPTIONS_MENU){
6193 switch(Multi_sync_mode){
6194 case MULTI_SYNC_PRE_BRIEFING:
6195 // if moving from game forming to the team select state
6198 case MULTI_SYNC_POST_BRIEFING:
6199 // if moving from briefing into the mission itself
6202 // tell everyone that we're now loading data
6203 Net_player->state = NETPLAYER_STATE_DATA_LOAD;
6204 send_netplayer_update_packet();
6206 // JAS: Used to do all paging here!!!!
6208 Net_player->state = NETPLAYER_STATE_WAITING;
6209 send_netplayer_update_packet();
6211 Game_time_compression = F1_0;
6213 case MULTI_SYNC_INGAME:
6219 case GS_STATE_VIEW_CUTSCENES:
6220 cutscenes_screen_init();
6223 case GS_STATE_MULTI_STD_WAIT:
6224 multi_standalone_wait_init();
6227 case GS_STATE_STANDALONE_MAIN:
6228 // don't initialize if we're coming from one of these 2 states unless there are no
6229 // players left (reset situation)
6230 if((old_state != GS_STATE_STANDALONE_POSTGAME) || multi_endgame_ending()){
6231 standalone_main_init();
6235 case GS_STATE_MULTI_PAUSED:
6239 case GS_STATE_INGAME_PRE_JOIN:
6240 multi_ingame_select_init();
6243 case GS_STATE_STANDALONE_POSTGAME:
6244 multi_standalone_postgame_init();
6247 case GS_STATE_INITIAL_PLAYER_SELECT:
6248 player_select_init();
6251 case GS_STATE_MULTI_START_GAME:
6252 multi_start_game_init();
6255 case GS_STATE_MULTI_HOST_OPTIONS:
6256 multi_host_options_init();
6259 case GS_STATE_END_OF_CAMPAIGN:
6260 mission_campaign_end_init();
6263 case GS_STATE_LOOP_BRIEF:
6270 // do stuff that may need to be done regardless of state
6271 void game_do_state_common(int state,int no_networking)
6273 game_maybe_draw_mouse(flFrametime); // determine if to draw the mouse this frame
6274 snd_do_frame(); // update sound system
6275 event_music_do_frame(); // music needs to play across many states
6277 multi_log_process();
6279 if (no_networking) {
6283 // maybe do a multiplayer frame based on game mode and state type
6284 if (Game_mode & GM_MULTIPLAYER) {
6286 case GS_STATE_OPTIONS_MENU:
6287 case GS_STATE_GAMEPLAY_HELP:
6288 case GS_STATE_HOTKEY_SCREEN:
6289 case GS_STATE_HUD_CONFIG:
6290 case GS_STATE_CONTROL_CONFIG:
6291 case GS_STATE_MISSION_LOG_SCROLLBACK:
6292 case GS_STATE_SHOW_GOALS:
6293 case GS_STATE_VIEW_CUTSCENES:
6294 case GS_STATE_EVENT_DEBUG:
6295 multi_maybe_do_frame();
6299 game_do_networking();
6303 // Called once a frame.
6304 // You should never try to change the state
6305 // in here... if you think you need to, you probably really
6306 // need to post an event, not change the state.
6307 int Game_do_state_should_skip = 0;
6308 void game_do_state(int state)
6310 // always lets the do_state_common() function determine if the state should be skipped
6311 Game_do_state_should_skip = 0;
6313 // legal to set the should skip state anywhere in this function
6314 game_do_state_common(state); // do stuff that may need to be done regardless of state
6316 if(Game_do_state_should_skip){
6321 case GS_STATE_MAIN_MENU:
6322 game_set_frametime(GS_STATE_MAIN_MENU);
6323 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
6326 main_hall_do(flFrametime);
6330 case GS_STATE_OPTIONS_MENU:
6331 game_set_frametime(GS_STATE_OPTIONS_MENU);
6332 options_menu_do_frame(flFrametime);
6335 case GS_STATE_BARRACKS_MENU:
6336 game_set_frametime(GS_STATE_BARRACKS_MENU);
6337 barracks_do_frame(flFrametime);
6340 case GS_STATE_TRAINING_MENU:
6341 game_set_frametime(GS_STATE_TRAINING_MENU);
6342 training_menu_do_frame(flFrametime);
6345 case GS_STATE_TECH_MENU:
6346 game_set_frametime(GS_STATE_TECH_MENU);
6347 techroom_do_frame(flFrametime);
6350 case GS_STATE_GAMEPLAY_HELP:
6351 game_set_frametime(GS_STATE_GAMEPLAY_HELP);
6352 gameplay_help_do_frame(flFrametime);
6355 case GS_STATE_GAME_PLAY: // do stuff that should be done during gameplay
6359 case GS_STATE_GAME_PAUSED:
6363 case GS_STATE_DEBUG_PAUSED:
6365 game_set_frametime(GS_STATE_DEBUG_PAUSED);
6370 case GS_STATE_TRAINING_PAUSED:
6371 game_training_pause_do();
6374 case GS_STATE_LOAD_MISSION_MENU:
6375 game_set_frametime(GS_STATE_LOAD_MISSION_MENU);
6376 mission_load_menu_do();
6379 case GS_STATE_BRIEFING:
6380 game_set_frametime(GS_STATE_BRIEFING);
6381 brief_do_frame(flFrametime);
6384 case GS_STATE_DEBRIEF:
6385 game_set_frametime(GS_STATE_DEBRIEF);
6386 debrief_do_frame(flFrametime);
6389 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6390 game_set_frametime(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
6391 multi_df_debrief_do();
6394 case GS_STATE_SHIP_SELECT:
6395 game_set_frametime(GS_STATE_SHIP_SELECT);
6396 ship_select_do(flFrametime);
6399 case GS_STATE_WEAPON_SELECT:
6400 game_set_frametime(GS_STATE_WEAPON_SELECT);
6401 weapon_select_do(flFrametime);
6404 case GS_STATE_MISSION_LOG_SCROLLBACK:
6405 game_set_frametime(GS_STATE_MISSION_LOG_SCROLLBACK);
6406 hud_scrollback_do_frame(flFrametime);
6409 case GS_STATE_HUD_CONFIG:
6410 game_set_frametime(GS_STATE_HUD_CONFIG);
6411 hud_config_do_frame(flFrametime);
6414 case GS_STATE_MULTI_JOIN_GAME:
6415 game_set_frametime(GS_STATE_MULTI_JOIN_GAME);
6416 multi_join_game_do_frame();
6419 case GS_STATE_MULTI_HOST_SETUP:
6420 game_set_frametime(GS_STATE_MULTI_HOST_SETUP);
6421 multi_create_game_do();
6424 case GS_STATE_MULTI_CLIENT_SETUP:
6425 game_set_frametime(GS_STATE_MULTI_CLIENT_SETUP);
6426 multi_game_client_setup_do_frame();
6429 case GS_STATE_CONTROL_CONFIG:
6430 game_set_frametime(GS_STATE_CONTROL_CONFIG);
6431 control_config_do_frame(flFrametime);
6434 case GS_STATE_DEATH_DIED:
6438 case GS_STATE_DEATH_BLEW_UP:
6442 case GS_STATE_SIMULATOR_ROOM:
6443 game_set_frametime(GS_STATE_SIMULATOR_ROOM);
6444 sim_room_do_frame(flFrametime);
6447 case GS_STATE_CAMPAIGN_ROOM:
6448 game_set_frametime(GS_STATE_CAMPAIGN_ROOM);
6449 campaign_room_do_frame(flFrametime);
6452 case GS_STATE_RED_ALERT:
6453 game_set_frametime(GS_STATE_RED_ALERT);
6454 red_alert_do_frame(flFrametime);
6457 case GS_STATE_CMD_BRIEF:
6458 game_set_frametime(GS_STATE_CMD_BRIEF);
6459 cmd_brief_do_frame(flFrametime);
6462 case GS_STATE_CREDITS:
6463 game_set_frametime(GS_STATE_CREDITS);
6464 credits_do_frame(flFrametime);
6467 case GS_STATE_VIEW_MEDALS:
6468 game_set_frametime(GS_STATE_VIEW_MEDALS);
6472 case GS_STATE_SHOW_GOALS:
6473 game_set_frametime(GS_STATE_SHOW_GOALS);
6474 mission_show_goals_do_frame(flFrametime);
6477 case GS_STATE_HOTKEY_SCREEN:
6478 game_set_frametime(GS_STATE_HOTKEY_SCREEN);
6479 mission_hotkey_do_frame(flFrametime);
6482 case GS_STATE_VIEW_CUTSCENES:
6483 game_set_frametime(GS_STATE_VIEW_CUTSCENES);
6484 cutscenes_screen_do_frame();
6487 case GS_STATE_MULTI_STD_WAIT:
6488 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6489 multi_standalone_wait_do();
6492 case GS_STATE_STANDALONE_MAIN:
6493 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6494 standalone_main_do();
6497 case GS_STATE_MULTI_PAUSED:
6498 game_set_frametime(GS_STATE_MULTI_PAUSED);
6502 case GS_STATE_TEAM_SELECT:
6503 game_set_frametime(GS_STATE_TEAM_SELECT);
6507 case GS_STATE_INGAME_PRE_JOIN:
6508 game_set_frametime(GS_STATE_INGAME_PRE_JOIN);
6509 multi_ingame_select_do();
6512 case GS_STATE_EVENT_DEBUG:
6514 game_set_frametime(GS_STATE_EVENT_DEBUG);
6515 game_show_event_debug(flFrametime);
6519 case GS_STATE_STANDALONE_POSTGAME:
6520 game_set_frametime(GS_STATE_STANDALONE_POSTGAME);
6521 multi_standalone_postgame_do();
6524 case GS_STATE_INITIAL_PLAYER_SELECT:
6525 game_set_frametime(GS_STATE_INITIAL_PLAYER_SELECT);
6529 case GS_STATE_MULTI_MISSION_SYNC:
6530 game_set_frametime(GS_STATE_MULTI_MISSION_SYNC);
6534 case GS_STATE_MULTI_START_GAME:
6535 game_set_frametime(GS_STATE_MULTI_START_GAME);
6536 multi_start_game_do();
6539 case GS_STATE_MULTI_HOST_OPTIONS:
6540 game_set_frametime(GS_STATE_MULTI_HOST_OPTIONS);
6541 multi_host_options_do();
6544 case GS_STATE_END_OF_CAMPAIGN:
6545 mission_campaign_end_do();
6548 case GS_STATE_END_DEMO:
6549 game_set_frametime(GS_STATE_END_DEMO);
6550 end_demo_campaign_do();
6553 case GS_STATE_LOOP_BRIEF:
6554 game_set_frametime(GS_STATE_LOOP_BRIEF);
6558 } // end switch(gs_current_state)
6562 // return 0 if there is enough RAM to run FreeSpace, otherwise return -1
6563 int game_do_ram_check(int ram_in_bytes)
6565 if ( ram_in_bytes < 30*1024*1024 ) {
6566 int allowed_to_run = 1;
6567 if ( ram_in_bytes < 25*1024*1024 ) {
6572 int Freespace_total_ram_MB;
6573 Freespace_total_ram_MB = fl2i(ram_in_bytes/(1024*1024));
6575 if ( allowed_to_run ) {
6577 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);
6582 msgbox_rval = MessageBox( NULL, tmp, XSTR( "Not Enough RAM", 194), MB_OKCANCEL );
6583 if ( msgbox_rval == IDCANCEL ) {
6590 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);
6592 MessageBox( NULL, tmp, XSTR( "Not Enough RAM", 194), MB_OK );
6603 // Check if there is a freespace.exe in the /update directory (relative to where fs.exe is installed).
6604 // If so, copy it over and remove the update directory.
6605 void game_maybe_update_launcher(char *exe_dir)
6608 char src_filename[MAX_PATH];
6609 char dest_filename[MAX_PATH];
6611 strcpy(src_filename, exe_dir);
6612 strcat(src_filename, NOX("\\update\\freespace.exe"));
6614 strcpy(dest_filename, exe_dir);
6615 strcat(dest_filename, NOX("\\freespace.exe"));
6617 // see if src_filename exists
6619 fp = fopen(src_filename, "rb");
6625 SetFileAttributes(dest_filename, FILE_ATTRIBUTE_NORMAL);
6627 // copy updated freespace.exe to freespace exe dir
6628 if ( CopyFile(src_filename, dest_filename, 0) == 0 ) {
6629 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 );
6633 // delete the file in the update directory
6634 DeleteFile(src_filename);
6636 // safe to assume directory is empty, since freespace.exe should only be the file ever in the update dir
6637 char update_dir[MAX_PATH];
6638 strcpy(update_dir, exe_dir);
6639 strcat(update_dir, NOX("\\update"));
6640 RemoveDirectory(update_dir);
6646 void game_spew_pof_info_sub(int model_num, polymodel *pm, int sm, CFILE *out, int *out_total, int *out_destroyed_total)
6650 int sub_total_destroyed = 0;
6654 // get the total for all his children
6655 for (i=pm->submodel[sm].first_child; i>-1; i = pm->submodel[i].next_sibling ) {
6656 game_spew_pof_info_sub(model_num, pm, i, out, &sub_total, &sub_total_destroyed);
6659 // find the # of faces for this _individual_ object
6660 total = submodel_get_num_polys(model_num, sm);
6661 if(strstr(pm->submodel[sm].name, "-destroyed")){
6662 sub_total_destroyed = total;
6666 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[sm].name, total);
6669 *out_total += total + sub_total;
6670 *out_destroyed_total += sub_total_destroyed;
6673 #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);
6674 void game_spew_pof_info()
6676 char *pof_list[1000];
6679 int idx, model_num, i, j;
6681 int total, root_total, model_total, destroyed_total, counted;
6685 num_files = cf_get_file_list(1000, pof_list, CF_TYPE_MODELS, "*.pof");
6687 // spew info on all the pofs
6693 out = cfopen("pofspew.txt", "wt", CFILE_NORMAL, CF_TYPE_DATA);
6698 for(idx=0; idx<num_files; idx++, counted++){
6699 sprintf(str, "%s.pof", pof_list[idx]);
6700 model_num = model_load(str, 0, NULL);
6702 pm = model_get(model_num);
6704 // if we have a real model
6709 // go through and print all raw submodels
6710 cfputs("RAW\n", out);
6713 for (i=0; i<pm->n_models; i++) {
6714 total = submodel_get_num_polys(model_num, i);
6716 model_total += total;
6717 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[i].name, total);
6720 sprintf(str, "Model total %d\n", model_total);
6723 // now go through and do it by LOD
6724 cfputs("BY LOD\n\n", out);
6725 for(i=0; i<pm->n_detail_levels; i++){
6726 sprintf(str, "LOD %d\n", i);
6730 root_total = submodel_get_num_polys(model_num, pm->detail[i] );
6732 destroyed_total = 0;
6733 for (j=pm->submodel[pm->detail[i]].first_child; j>-1; j = pm->submodel[j].next_sibling ) {
6734 game_spew_pof_info_sub(model_num, pm, j, out, &total, &destroyed_total);
6737 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[pm->detail[i]].name, root_total);
6740 sprintf(str, "TOTAL: %d\n", total + root_total);
6742 sprintf(str, "TOTAL not counting destroyed faces %d\n", (total + root_total) - destroyed_total);
6744 sprintf(str, "TOTAL destroyed faces %d\n\n", destroyed_total);
6747 cfputs("------------------------------------------------------------------------\n\n", out);
6751 if(counted >= MAX_POLYGON_MODELS - 5){
6764 game_spew_pof_info();
6767 int PASCAL WinMainSub(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
6772 // Don't let more than one instance of Freespace run.
6773 HWND hwnd = FindWindow( NOX( "FreeSpaceClass" ), NULL );
6775 SetForegroundWindow(hwnd);
6780 // Find out how much RAM is on this machine
6783 ms.dwLength = sizeof(MEMORYSTATUS);
6784 GlobalMemoryStatus(&ms);
6785 Freespace_total_ram = ms.dwTotalPhys;
6787 if ( game_do_ram_check(Freespace_total_ram) == -1 ) {
6791 if ( ms.dwTotalVirtual < 1024 ) {
6792 MessageBox( NULL, XSTR( "FreeSpace requires virtual memory to run.\r\n", 196), XSTR( "No Virtual Memory", 197), MB_OK );
6796 if (!vm_init(24*1024*1024)) {
6797 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 );
6801 char *tmp_mem = (char *) malloc(16 * 1024 * 1024);
6803 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);
6811 /* this code doesn't work, and we will hit an error about being unable to load the direct draw
6812 dll before we get here anyway if it's not installed (unless we load it manually, which doesn't
6813 seem worth bothering with.
6817 lResult = RegOpenKeyEx(
6818 HKEY_LOCAL_MACHINE, // Where it is
6819 "Software\\Microsoft\\DirectX", // name of key
6820 NULL, // DWORD reserved
6821 KEY_QUERY_VALUE, // Allows all changes
6822 &hKey // Location to store key
6825 if (lResult == ERROR_SUCCESS) {
6827 DWORD dwType, dwLen;
6830 lResult = RegQueryValueEx(
6831 hKey, // Handle to key
6832 "Version", // The values name
6833 NULL, // DWORD reserved
6834 &dwType, // What kind it is
6835 (ubyte *) version, // value to set
6836 &dwLen // How many bytes to set
6839 if (lResult == ERROR_SUCCESS) {
6840 dx_version = atoi(strstr(version, ".") + 1);
6844 DWORD dwType, dwLen;
6847 lResult = RegQueryValueEx(
6848 hKey, // Handle to key
6849 "InstalledVersion", // The values name
6850 NULL, // DWORD reserved
6851 &dwType, // What kind it is
6852 (ubyte *) &val, // value to set
6853 &dwLen // How many bytes to set
6856 if (lResult == ERROR_SUCCESS) {
6864 if (dx_version < 3) {
6865 MessageBox(NULL, "DirectX 3.0 or higher is required and wasn't detected. You can get the\n"
6866 "latest version of DirectX at:\n\n"
6867 "http://www.microsoft.com/msdownload/directx/dxf/enduser5.0/default.htm", "DirectX required", MB_OK);
6869 MessageBox(NULL, "DirectX 3.0 or higher is required and wasn't detected. You can install\n"
6870 "DirectX 5.2 by pressing the 'Install DirectX' button on the FreeSpace Launcher", "DirectX required", MB_OK);
6875 //=====================================================
6876 // Make sure we're running in the right directory.
6880 if ( GetModuleFileName( hInst, exe_dir, 1023 ) > 0 ) {
6881 char *p = exe_dir + strlen(exe_dir);
6883 // chop off the filename
6884 while( (p>exe_dir) && (*p!='\\') && (*p!='/') && (*p!=':') ) {
6890 if ( strlen(exe_dir) > 0 ) {
6891 SetCurrentDirectory(exe_dir);
6894 // check for updated freespace.exe
6895 game_maybe_update_launcher(exe_dir);
6903 extern void windebug_memwatch_init();
6904 windebug_memwatch_init();
6908 parse_cmdline(szCmdLine);
6910 #ifdef STANDALONE_ONLY_BUILD
6912 nprintf(("Network", "Standalone running"));
6915 nprintf(("Network", "Standalone running"));
6923 // maybe spew pof stuff
6924 if(Cmdline_spew_pof_info){
6925 game_spew_pof_info();
6930 // non-demo, non-standalone, play the intro movie
6935 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) ){
6937 #if defined(OEM_BUILD)
6938 game_do_cd_check_specific(FS_CDROM_VOLUME_1, 1);
6940 game_do_cd_check_specific(FS_CDROM_VOLUME_2, 2);
6941 #endif // defined(OEM_BUILD)
6946 if ( !Is_standalone ) {
6948 // release -- movies always play
6951 // 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
6952 movie_play( NOX("intro.mve"), 0 );
6954 // debug version, movie will only play with -showmovies
6955 #elif !defined(NDEBUG)
6957 movie_play( NOX("intro.mve"), 0);
6960 if ( Cmdline_show_movies )
6961 movie_play( NOX("intro.mve"), 0 );
6970 gameseq_post_event(GS_EVENT_STANDALONE_MAIN);
6972 gameseq_post_event(GS_EVENT_GAME_INIT); // start the game rolling -- check for default pilot, or go to the pilot select screen
6976 // only important for non THREADED mode
6979 state = gameseq_process_events();
6980 if ( state == GS_STATE_QUIT_GAME ){
6987 demo_upsell_show_screens();
6989 #elif defined(OEM_BUILD)
6990 // show upsell screens on exit
6991 oem_upsell_show_screens();
6998 int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
7004 result = WinMainSub(hInst, hPrev, szCmdLine, nCmdShow);
7006 __except(RecordExceptionInfo(GetExceptionInformation(), "Freespace 2 Main Thread"))
7008 // Do nothing here - RecordExceptionInfo() has already done
7009 // everything that is needed. Actually this code won't even
7010 // get called unless you return EXCEPTION_EXECUTE_HANDLER from
7011 // the __except clause.
7015 nprintf(("WinMain", "exceptions shall fall through"));
7017 result = WinMainSub(hInst, hPrev, szCmdLine, nCmdShow);
7023 // launcher the fslauncher program on exit
7024 void game_launch_launcher_on_exit()
7028 PROCESS_INFORMATION pi;
7029 char cmd_line[2048];
7030 char original_path[1024] = "";
7032 memset( &si, 0, sizeof(STARTUPINFO) );
7036 _getcwd(original_path, 1023);
7038 // set up command line
7039 strcpy(cmd_line, original_path);
7040 strcat(cmd_line, "\\");
7041 strcat(cmd_line, LAUNCHER_FNAME);
7042 strcat(cmd_line, " -straight_to_update");
7044 BOOL ret = CreateProcess( NULL, // pointer to name of executable module
7045 cmd_line, // pointer to command line string
7046 NULL, // pointer to process security attributes
7047 NULL, // pointer to thread security attributes
7048 FALSE, // handle inheritance flag
7049 CREATE_DEFAULT_ERROR_MODE, // creation flags
7050 NULL, // pointer to new environment block
7051 NULL, // pointer to current directory name
7052 &si, // pointer to STARTUPINFO
7053 &pi // pointer to PROCESS_INFORMATION
7055 // to eliminate build warnings
7065 // This function is called when FreeSpace terminates normally.
7067 void game_shutdown(void)
7073 // don't ever flip a page on the standalone!
7074 if(!(Game_mode & GM_STANDALONE_SERVER)){
7080 // if the player has left the "player select" screen and quit the game without actually choosing
7081 // a player, Player will be NULL, in which case we shouldn't write the player file out!
7082 if (!(Game_mode & GM_STANDALONE_SERVER) && (Player!=NULL) && !Is_standalone){
7086 // load up common multiplayer icons
7087 multi_unload_common_icons();
7089 shockwave_close(); // release any memory used by shockwave system
7090 fireball_close(); // free fireball system
7091 ship_close(); // free any memory that was allocated for the ships
7092 hud_free_scrollback_list();// free space allocated to store hud messages in hud scrollback
7093 unload_animating_pointer();// frees the frames used for the animating mouse pointer
7094 bm_unload_all(); // free bitmaps
7095 mission_campaign_close(); // close out the campaign stuff
7096 multi_voice_close(); // close down multiplayer voice (including freeing buffers, etc)
7098 #ifdef MULTI_USE_LAG
7102 // the menu close functions will unload the bitmaps if they were displayed during the game
7103 #if !defined(PRESS_TOUR_BUILD) && !defined(PD_BUILD)
7106 training_menu_close();
7109 extern void joy_close();
7112 audiostream_close();
7114 event_music_close();
7118 // HACKITY HACK HACK
7119 // if this flag is set, we should be firing up the launcher when exiting freespace
7120 extern int Multi_update_fireup_launcher_on_exit;
7121 if(Multi_update_fireup_launcher_on_exit){
7122 game_launch_launcher_on_exit();
7126 // game_stop_looped_sounds()
7128 // This function will call the appropriate stop looped sound functions for those
7129 // modules which use looping sounds. It is not enough just to stop a looping sound
7130 // at the DirectSound level, the game is keeping track of looping sounds, and this
7131 // function is used to inform the game that looping sounds are being halted.
7133 void game_stop_looped_sounds()
7135 hud_stop_looped_locking_sounds();
7136 hud_stop_looped_engine_sounds();
7137 afterburner_stop_sounds();
7138 player_stop_looped_sounds();
7139 obj_snd_stop_all(); // stop all object-linked persistant sounds
7140 game_stop_subspace_ambient_sound();
7141 snd_stop(Radar_static_looping);
7142 Radar_static_looping = -1;
7143 snd_stop(Target_static_looping);
7144 shipfx_stop_engine_wash_sound();
7145 Target_static_looping = -1;
7148 //////////////////////////////////////////////////////////////////////////
7150 // Code for supporting an animating mouse pointer
7153 //////////////////////////////////////////////////////////////////////////
7155 typedef struct animating_obj
7164 static animating_obj Animating_mouse;
7166 // ----------------------------------------------------------------------------
7167 // init_animating_pointer()
7169 // Called by load_animating_pointer() to ensure the Animating_mouse struct
7170 // gets properly initialized
7172 void init_animating_pointer()
7174 Animating_mouse.first_frame = -1;
7175 Animating_mouse.num_frames = 0;
7176 Animating_mouse.current_frame = -1;
7177 Animating_mouse.time = 0.0f;
7178 Animating_mouse.elapsed_time = 0.0f;
7181 // ----------------------------------------------------------------------------
7182 // load_animating_pointer()
7184 // Called at game init to load in the frames for the animating mouse pointer
7186 // input: filename => filename of animation file that holds the animation
7188 void load_animating_pointer(char *filename, int dx, int dy)
7193 init_animating_pointer();
7195 am = &Animating_mouse;
7196 am->first_frame = bm_load_animation(filename, &am->num_frames, &fps);
7197 if ( am->first_frame == -1 )
7198 Error(LOCATION, "Could not load animation %s for the mouse pointer\n", filename);
7199 am->current_frame = 0;
7200 am->time = am->num_frames / i2fl(fps);
7203 // ----------------------------------------------------------------------------
7204 // unload_animating_pointer()
7206 // Called at game shutdown to free the memory used to store the animation frames
7208 void unload_animating_pointer()
7213 am = &Animating_mouse;
7214 for ( i = 0; i < am->num_frames; i++ ) {
7215 Assert( (am->first_frame+i) >= 0 );
7216 bm_release(am->first_frame + i);
7219 am->first_frame = -1;
7221 am->current_frame = -1;
7224 // draw the correct frame of the game mouse... called from game_maybe_draw_mouse()
7225 void game_render_mouse(float frametime)
7230 // if animating cursor exists, play the next frame
7231 am = &Animating_mouse;
7232 if ( am->first_frame != -1 ) {
7233 mouse_get_pos(&mx, &my);
7234 am->elapsed_time += frametime;
7235 am->current_frame = fl2i( ( am->elapsed_time / am->time ) * (am->num_frames-1) );
7236 if ( am->current_frame >= am->num_frames ) {
7237 am->current_frame = 0;
7238 am->elapsed_time = 0.0f;
7240 gr_set_cursor_bitmap(am->first_frame + am->current_frame);
7244 // ----------------------------------------------------------------------------
7245 // game_maybe_draw_mouse()
7247 // determines whether to draw the mouse pointer at all, and what frame of
7248 // animation to use if the mouse is animating
7250 // Sets mouse.cpp globals Mouse_hidden and Mouse_moved based on the state of the game.
7252 // input: frametime => elapsed frame time in seconds since last call
7254 void game_maybe_draw_mouse(float frametime)
7258 game_state = gameseq_get_state();
7260 switch ( game_state ) {
7261 case GS_STATE_GAME_PAUSED:
7262 // case GS_STATE_MULTI_PAUSED:
7263 case GS_STATE_GAME_PLAY:
7264 case GS_STATE_DEATH_DIED:
7265 case GS_STATE_DEATH_BLEW_UP:
7266 if ( popup_active() || popupdead_is_active() ) {
7278 if ( !Mouse_hidden )
7279 game_render_mouse(frametime);
7283 void game_do_training_checks()
7287 waypoint_list *wplp;
7289 if (Training_context & TRAINING_CONTEXT_SPEED) {
7290 s = (int) Player_obj->phys_info.fspeed;
7291 if ((s >= Training_context_speed_min) && (s <= Training_context_speed_max)) {
7292 if (!Training_context_speed_set) {
7293 Training_context_speed_set = 1;
7294 Training_context_speed_timestamp = timestamp();
7298 Training_context_speed_set = 0;
7301 if (Training_context & TRAINING_CONTEXT_FLY_PATH) {
7302 wplp = &Waypoint_lists[Training_context_path];
7303 if (wplp->count > Training_context_goal_waypoint) {
7304 i = Training_context_goal_waypoint;
7306 d = vm_vec_dist(&wplp->waypoints[i], &Player_obj->pos);
7307 if (d <= Training_context_distance) {
7308 Training_context_at_waypoint = i;
7309 if (Training_context_goal_waypoint == i) {
7310 Training_context_goal_waypoint++;
7311 snd_play(&Snds[SND_CARGO_REVEAL], 0.0f);
7318 if (i == wplp->count)
7321 } while (i != Training_context_goal_waypoint);
7325 if ((Players_target == UNINITIALIZED) || (Player_ai->target_objnum != Players_target) || (Player_ai->targeted_subsys != Players_targeted_subsys)) {
7326 Players_target = Player_ai->target_objnum;
7327 Players_targeted_subsys = Player_ai->targeted_subsys;
7328 Players_target_timestamp = timestamp();
7332 /////////// Following is for event debug view screen
7336 #define EVENT_DEBUG_MAX 5000
7337 #define EVENT_DEBUG_EVENT 0x8000
7339 int Event_debug_index[EVENT_DEBUG_MAX];
7342 void game_add_event_debug_index(int n, int indent)
7344 if (ED_count < EVENT_DEBUG_MAX)
7345 Event_debug_index[ED_count++] = n | (indent << 16);
7348 void game_add_event_debug_sexp(int n, int indent)
7353 if (Sexp_nodes[n].first >= 0) {
7354 game_add_event_debug_sexp(Sexp_nodes[n].first, indent);
7355 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7359 game_add_event_debug_index(n, indent);
7360 if (Sexp_nodes[n].subtype == SEXP_ATOM_OPERATOR)
7361 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent + 1);
7363 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7366 void game_event_debug_init()
7371 for (e=0; e<Num_mission_events; e++) {
7372 game_add_event_debug_index(e | EVENT_DEBUG_EVENT, 0);
7373 game_add_event_debug_sexp(Mission_events[e].formula, 1);
7377 void game_show_event_debug(float frametime)
7381 int font_height, font_width;
7383 static int scroll_offset = 0;
7385 k = game_check_key();
7391 if (scroll_offset < 0)
7401 scroll_offset -= 20;
7402 if (scroll_offset < 0)
7407 scroll_offset += 20; // not font-independent, hard-coded since I counted the lines!
7411 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
7417 gr_set_color_fast(&Color_bright);
7419 gr_printf(0x8000, 5, NOX("EVENT DEBUG VIEW"));
7421 gr_set_color_fast(&Color_normal);
7423 gr_get_string_size(&font_width, &font_height, NOX("test"));
7424 y_max = gr_screen.max_h - font_height - 5;
7428 while (k < ED_count) {
7429 if (y_index > y_max)
7432 z = Event_debug_index[k];
7433 if (z & EVENT_DEBUG_EVENT) {
7435 sprintf(buf, NOX("%s%s (%s) %s%d %d"), (Mission_events[z].flags & MEF_CURRENT) ? NOX("* ") : "",
7436 Mission_events[z].name, Mission_events[z].result ? NOX("True") : NOX("False"),
7437 (Mission_events[z].chain_delay < 0) ? "" : NOX("x "),
7438 Mission_events[z].repeat_count, Mission_events[z].interval);
7446 strcat(buf, Sexp_nodes[z & 0x7fff].text);
7447 switch (Sexp_nodes[z & 0x7fff].value) {
7449 strcat(buf, NOX(" (True)"));
7453 strcat(buf, NOX(" (False)"));
7456 case SEXP_KNOWN_TRUE:
7457 strcat(buf, NOX(" (Always true)"));
7460 case SEXP_KNOWN_FALSE:
7461 strcat(buf, NOX(" (Always false)"));
7464 case SEXP_CANT_EVAL:
7465 strcat(buf, NOX(" (Can't eval)"));
7469 case SEXP_NAN_FOREVER:
7470 strcat(buf, NOX(" (Not a number)"));
7475 gr_printf(10, y_index, buf);
7476 y_index += font_height;
7489 extern int Tmap_npixels;
7491 int Tmap_num_too_big = 0;
7492 int Num_models_needing_splitting = 0;
7494 void Time_model( int modelnum )
7496 // mprintf(( "Timing ship '%s'\n", si->name ));
7498 vector eye_pos, model_pos;
7499 matrix eye_orient, model_orient;
7501 polymodel *pm = model_get( modelnum );
7503 int l = strlen(pm->filename);
7505 if ( (l == '/') || (l=='\\') || (l==':')) {
7511 char *pof_file = &pm->filename[l];
7513 int model_needs_splitting = 0;
7515 //fprintf( Texture_fp, "Model: %s\n", pof_file );
7517 for (i=0; i<pm->n_textures; i++ ) {
7518 char filename[1024];
7521 int bmp_num = pm->original_textures[i];
7522 if ( bmp_num > -1 ) {
7523 bm_get_palette(pm->original_textures[i], pal, filename );
7525 bm_get_info( pm->original_textures[i],&w, &h );
7528 if ( (w > 512) || (h > 512) ) {
7529 fprintf( Texture_fp, "%s\t%s\t%d\t%d\n", pof_file, filename, w, h );
7531 model_needs_splitting++;
7534 //fprintf( Texture_fp, "\tTexture %d is bogus\n", i );
7538 if ( model_needs_splitting ) {
7539 Num_models_needing_splitting++;
7541 eye_orient = model_orient = vmd_identity_matrix;
7542 eye_pos = model_pos = vmd_zero_vector;
7544 eye_pos.xyz.z = -pm->rad*2.0f;
7546 vector eye_to_model;
7548 vm_vec_sub( &eye_to_model, &model_pos, &eye_pos );
7549 vm_vector_2_matrix( &eye_orient, &eye_to_model, NULL, NULL );
7551 fix t1 = timer_get_fixed_seconds();
7554 ta.p = ta.b = ta.h = 0.0f;
7559 int bitmaps_used_this_frame, bitmaps_new_this_frame;
7561 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7563 modelstats_num_polys = modelstats_num_verts = 0;
7565 while( ta.h < PI2 ) {
7568 vm_angles_2_matrix(&m1, &ta );
7569 vm_matrix_x_matrix( &model_orient, &vmd_identity_matrix, &m1 );
7576 g3_set_view_matrix( &eye_pos, &eye_orient, Viewer_zoom );
7578 model_clear_instance( modelnum );
7579 model_set_detail_level(0); // use highest detail level
7580 model_render( modelnum, &model_orient, &model_pos, MR_LOCK_DETAIL); //|MR_NO_POLYS );
7588 int k = key_inkey();
7589 if ( k == KEY_ESC ) {
7594 fix t2 = timer_get_fixed_seconds();
7596 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7597 //bitmaps_used_this_frame /= framecount;
7599 modelstats_num_polys /= framecount;
7600 modelstats_num_verts /= framecount;
7602 Tmap_npixels /=framecount;
7605 mprintf(( "'%s' is %.2f FPS\n", pof_file, i2fl(framecount)/f2fl(t2-t1) ));
7606 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 );
7607 // 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 );
7613 int Time_models = 0;
7614 DCF_BOOL( time_models, Time_models );
7616 void Do_model_timings_test()
7620 if ( !Time_models ) return;
7622 mprintf(( "Timing models!\n" ));
7626 ubyte model_used[MAX_POLYGON_MODELS];
7627 int model_id[MAX_POLYGON_MODELS];
7628 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7633 for (i=0; i<Num_ship_types; i++ ) {
7634 Ship_info[i].modelnum = model_load( Ship_info[i].pof_file, 0, NULL );
7636 model_used[Ship_info[i].modelnum%MAX_POLYGON_MODELS]++;
7637 model_id[Ship_info[i].modelnum%MAX_POLYGON_MODELS] = Ship_info[i].modelnum;
7640 Texture_fp = fopen( NOX("ShipTextures.txt"), "wt" );
7641 if ( !Texture_fp ) return;
7643 Time_fp = fopen( NOX("ShipTimings.txt"), "wt" );
7644 if ( !Time_fp ) return;
7646 fprintf( Time_fp, "Name\tFPS\tTRAM\tPolys\tVerts\tPixels\n" );
7647 // fprintf( Time_fp, "FPS\tTRAM\tPolys\tVerts\tPixels\n" );
7649 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7650 if ( model_used[i] ) {
7651 Time_model( model_id[i] );
7655 fprintf( Texture_fp, "Number too big: %d\n", Tmap_num_too_big );
7656 fprintf( Texture_fp, "Number of models needing splitting: %d\n", Num_models_needing_splitting );
7665 // Call this function when you want to inform the player that a feature is not
7666 // enabled in the DEMO version of FreSpace
7667 void game_feature_not_in_demo_popup()
7669 popup(PF_USE_AFFIRMATIVE_ICON|PF_BODY_BIG, 1, POPUP_OK, XSTR( "Sorry, this feature is available only in the retail version", 200));
7672 // format the specified time (fixed point) into a nice string
7673 void game_format_time(fix m_time,char *time_str)
7676 int hours,minutes,seconds;
7679 mtime = f2fl(m_time);
7681 // get the hours, minutes and seconds
7682 hours = (int)(mtime / 3600.0f);
7684 mtime -= (3600.0f * (float)hours);
7686 seconds = (int)mtime%60;
7687 minutes = (int)mtime/60;
7689 // print the hour if necessary
7691 sprintf(time_str,XSTR( "%d:", 201),hours);
7692 // if there are less than 10 minutes, print a leading 0
7694 strcpy(tmp,NOX("0"));
7695 strcat(time_str,tmp);
7699 // print the minutes
7701 sprintf(tmp,XSTR( "%d:", 201),minutes);
7702 strcat(time_str,tmp);
7704 sprintf(time_str,XSTR( "%d:", 201),minutes);
7707 // print the seconds
7709 strcpy(tmp,NOX("0"));
7710 strcat(time_str,tmp);
7712 sprintf(tmp,"%d",seconds);
7713 strcat(time_str,tmp);
7716 // Stuff version string in *str.
7717 void get_version_string(char *str)
7720 if ( FS_VERSION_BUILD == 0 ) {
7721 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
7723 sprintf(str,"v%d.%02d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD );
7726 #if defined (FS2_DEMO)
7728 #elif defined (OEM_BUILD)
7729 strcat(str, " (OEM)");
7735 char myname[_MAX_PATH];
7736 int namelen, major, minor, build, waste;
7737 unsigned int buf_size;
7743 // Find my EXE file name
7744 hMod = GetModuleHandle(NULL);
7745 namelen = GetModuleFileName( hMod, myname, _MAX_PATH );
7747 version_size = GetFileVersionInfoSize(myname, &bogus_handle );
7748 infop = (char *)malloc(version_size);
7749 result = GetFileVersionInfo( myname, 0, version_size, (LPVOID)infop );
7751 // get the product version
7752 result = VerQueryValue((LPVOID)infop, TEXT("\\StringFileInfo\\040904b0\\ProductVersion"), &bufp, &buf_size );
7753 sscanf( (char *)bufp, "%d, %d, %d, %d", &major, &minor, &build, &waste );
7755 sprintf(str,"Dv%d.%02d",major, minor);
7757 sprintf(str,"v%d.%02d",major, minor);
7762 void get_version_string_short(char *str)
7764 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
7767 // ----------------------------------------------------------------
7769 // OEM UPSELL SCREENS BEGIN
7771 // ----------------------------------------------------------------
7772 #if defined(OEM_BUILD)
7774 #define NUM_OEM_UPSELL_SCREENS 3
7775 #define OEM_UPSELL_SCREEN_DELAY 10000
7777 static int Oem_upsell_bitmaps_loaded = 0;
7778 static int Oem_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS];
7779 static int Oem_upsell_screen_number = 0;
7780 static int Oem_upsell_show_next_bitmap_time;
7783 static char *Oem_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS] =
7796 static int Oem_normal_cursor = -1;
7797 static int Oem_web_cursor = -1;
7798 //#define OEM_UPSELL_URL "http://www.interplay-store.com/"
7799 #define OEM_UPSELL_URL "http://www.interplay.com/cgi-bin/oemlinks.pl/pid=483421&cid=18384"
7801 void oem_upsell_next_screen()
7803 Oem_upsell_screen_number++;
7804 if ( Oem_upsell_screen_number == (NUM_OEM_UPSELL_SCREENS-1) ) {
7805 // extra long delay, mouse shown on last upsell
7806 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY*2;
7810 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
7814 void oem_upsell_load_bitmaps()
7818 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
7819 Oem_upsell_bitmaps[gr_screen.res][i] = bm_load(Oem_upsell_bitmap_filenames[gr_screen.res][i]);
7823 void oem_upsell_unload_bitmaps()
7827 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
7828 if(Oem_upsell_bitmaps[gr_screen.res][i] >= 0){
7829 bm_unload(Oem_upsell_bitmaps[gr_screen.res][i]);
7834 Oem_upsell_bitmaps_loaded = 0;
7837 // clickable hotspot on 3rd OEM upsell screen
7838 static int Oem_upsell3_button_coords[GR_NUM_RESOLUTIONS][4] = {
7840 28, 350, 287, 96 // x, y, w, h
7843 45, 561, 460, 152 // x, y, w, h
7847 void oem_upsell_show_screens()
7849 int current_time, k;
7852 if ( !Oem_upsell_bitmaps_loaded ) {
7853 oem_upsell_load_bitmaps();
7854 Oem_upsell_bitmaps_loaded = 1;
7857 // may use upsell screens more than once
7858 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
7859 Oem_upsell_screen_number = 0;
7865 int nframes; // used to pass, not really needed (should be 1)
7866 Oem_normal_cursor = gr_get_cursor_bitmap();
7867 Oem_web_cursor = bm_load_animation("cursorweb", &nframes);
7868 Assert(Oem_web_cursor >= 0);
7869 if (Oem_web_cursor < 0) {
7870 Oem_web_cursor = Oem_normal_cursor;
7875 //oem_reset_trailer_timer();
7877 current_time = timer_get_milliseconds();
7882 // advance screen on keypress or timeout
7883 if (( k > 0 ) || (mouse_up_count(MOUSE_LEFT_BUTTON) > 0) || (current_time > Oem_upsell_show_next_bitmap_time)) {
7884 oem_upsell_next_screen();
7887 // check if we are done
7888 if ( Oem_upsell_screen_number >= NUM_OEM_UPSELL_SCREENS ) {
7889 Oem_upsell_screen_number--;
7892 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] < 0 ) {
7897 // show me the upsell
7898 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] >= 0 ) {
7899 gr_set_bitmap(Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number]);
7903 // if this is the 3rd upsell, make it clickable, d00d
7904 if ( Oem_upsell_screen_number == NUM_OEM_UPSELL_SCREENS-1 ) {
7906 int button_state = mouse_get_pos(&mx, &my);
7907 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])
7908 && (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]) )
7911 gr_set_cursor_bitmap(Oem_web_cursor); //, GR_CURSOR_LOCK);
7914 if (button_state & MOUSE_LEFT_BUTTON) {
7916 multi_pxo_url(OEM_UPSELL_URL);
7920 // switch cursor back to normal one
7921 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
7926 if (gameseq_get_state() != GS_STATE_END_DEMO) {
7936 oem_upsell_unload_bitmaps();
7938 // switch cursor back to normal one
7939 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
7943 #endif // defined(OEM_BUILD)
7944 // ----------------------------------------------------------------
7946 // OEM UPSELL SCREENS END
7948 // ----------------------------------------------------------------
7952 // ----------------------------------------------------------------
7954 // DEMO UPSELL SCREENS BEGIN
7956 // ----------------------------------------------------------------
7960 //#define NUM_DEMO_UPSELL_SCREENS 4
7962 #define NUM_DEMO_UPSELL_SCREENS 2
7963 #define DEMO_UPSELL_SCREEN_DELAY 3000
7965 static int Demo_upsell_bitmaps_loaded = 0;
7966 static int Demo_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS];
7967 static int Demo_upsell_screen_number = 0;
7968 static int Demo_upsell_show_next_bitmap_time;
7971 static char *Demo_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS] =
7984 void demo_upsell_next_screen()
7986 Demo_upsell_screen_number++;
7987 if ( Demo_upsell_screen_number == (NUM_DEMO_UPSELL_SCREENS-1) ) {
7988 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY*4;
7990 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
7994 if ( Demo_upsell_screen_number < NUM_DEMO_UPSELL_SCREENS ) {
7995 if ( Demo_upsell_bitmap_filenames[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
7996 #ifndef HARDWARE_ONLY
7997 palette_use_bm_palette(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8004 void demo_upsell_load_bitmaps()
8008 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8009 Demo_upsell_bitmaps[gr_screen.res][i] = bm_load(Demo_upsell_bitmap_filenames[gr_screen.res][i]);
8013 void demo_upsell_unload_bitmaps()
8017 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8018 if(Demo_upsell_bitmaps[gr_screen.res][i] >= 0){
8019 bm_unload(Demo_upsell_bitmaps[gr_screen.res][i]);
8024 Demo_upsell_bitmaps_loaded = 0;
8027 void demo_upsell_show_screens()
8029 int current_time, k;
8032 if ( !Demo_upsell_bitmaps_loaded ) {
8033 demo_upsell_load_bitmaps();
8034 Demo_upsell_bitmaps_loaded = 1;
8037 // may use upsell screens more than once
8038 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
8039 Demo_upsell_screen_number = 0;
8046 demo_reset_trailer_timer();
8048 current_time = timer_get_milliseconds();
8055 // don't time out, wait for keypress
8057 if ( current_time > Demo_upsell_show_next_bitmap_time ) {
8058 demo_upsell_next_screen();
8063 demo_upsell_next_screen();
8066 if ( Demo_upsell_screen_number >= NUM_DEMO_UPSELL_SCREENS ) {
8067 Demo_upsell_screen_number--;
8070 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] < 0 ) {
8075 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
8076 gr_set_bitmap(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8081 if (gameseq_get_state() != GS_STATE_END_DEMO) {
8091 demo_upsell_unload_bitmaps();
8096 // ----------------------------------------------------------------
8098 // DEMO UPSELL SCREENS END
8100 // ----------------------------------------------------------------
8103 // ----------------------------------------------------------------
8105 // Subspace Ambient Sound START
8107 // ----------------------------------------------------------------
8109 static int Subspace_ambient_left_channel = -1;
8110 static int Subspace_ambient_right_channel = -1;
8113 void game_start_subspace_ambient_sound()
8115 if ( Subspace_ambient_left_channel < 0 ) {
8116 Subspace_ambient_left_channel = snd_play_looping(&Snds[SND_SUBSPACE_LEFT_CHANNEL], -1.0f);
8119 if ( Subspace_ambient_right_channel < 0 ) {
8120 Subspace_ambient_right_channel = snd_play_looping(&Snds[SND_SUBSPACE_RIGHT_CHANNEL], 1.0f);
8124 void game_stop_subspace_ambient_sound()
8126 if ( Subspace_ambient_left_channel >= 0 ) {
8127 snd_stop(Subspace_ambient_left_channel);
8128 Subspace_ambient_left_channel = -1;
8131 if ( Subspace_ambient_right_channel >= 0 ) {
8132 snd_stop(Subspace_ambient_right_channel);
8133 Subspace_ambient_right_channel = -1;
8137 // ----------------------------------------------------------------
8139 // Subspace Ambient Sound END
8141 // ----------------------------------------------------------------
8143 // ----------------------------------------------------------------
8145 // CDROM detection code START
8147 // ----------------------------------------------------------------
8149 #define CD_SIZE_72_MINUTE_MAX (697000000)
8151 uint game_get_cd_used_space(char *path)
8155 char use_path[512] = "";
8156 char sub_path[512] = "";
8157 WIN32_FIND_DATA find;
8160 // recurse through all files and directories
8161 strcpy(use_path, path);
8162 strcat(use_path, "*.*");
8163 find_handle = FindFirstFile(use_path, &find);
8166 if(find_handle == INVALID_HANDLE_VALUE){
8172 // subdirectory. make sure to ignore . and ..
8173 if((find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && stricmp(find.cFileName, ".") && stricmp(find.cFileName, "..")){
8175 strcpy(sub_path, path);
8176 strcat(sub_path, find.cFileName);
8177 strcat(sub_path, "\\");
8178 total += game_get_cd_used_space(sub_path);
8180 total += (uint)find.nFileSizeLow;
8182 } while(FindNextFile(find_handle, &find));
8185 FindClose(find_handle);
8197 // if volume_name is non-null, the CD name must match that
8198 int find_freespace_cd(char *volume_name)
8201 char oldpath[MAX_PATH];
8205 int volume_match = 0;
8209 GetCurrentDirectory(MAX_PATH, oldpath);
8211 for (i = 0; i < 26; i++)
8217 path[0] = (char)('A'+i);
8218 if (GetDriveType(path) == DRIVE_CDROM) {
8220 if ( GetVolumeInformation(path, volume, 256, NULL, NULL, NULL, NULL, 0) == TRUE ) {
8221 nprintf(("CD", "CD volume: %s\n", volume));
8223 // check for any CD volume
8224 int volume1_present = 0;
8225 int volume2_present = 0;
8226 int volume3_present = 0;
8228 char full_check[512] = "";
8230 // look for setup.exe
8231 strcpy(full_check, path);
8232 strcat(full_check, "setup.exe");
8233 find_handle = _findfirst(full_check, &find);
8234 if(find_handle != -1){
8235 volume1_present = 1;
8236 _findclose(find_handle);
8239 // look for intro.mve
8240 strcpy(full_check, path);
8241 strcat(full_check, "intro.mve");
8242 find_handle = _findfirst(full_check, &find);
8243 if(find_handle != -1){
8244 volume2_present = 1;
8245 _findclose(find_handle);
8248 // look for endpart1.mve
8249 strcpy(full_check, path);
8250 strcat(full_check, "endpart1.mve");
8251 find_handle = _findfirst(full_check, &find);
8252 if(find_handle != -1){
8253 volume3_present = 1;
8254 _findclose(find_handle);
8257 // see if we have the specific CD we're looking for
8258 if ( volume_name ) {
8260 if ( !stricmp(volume_name, FS_CDROM_VOLUME_1) && volume1_present) {
8264 if ( !stricmp(volume_name, FS_CDROM_VOLUME_2) && volume2_present) {
8268 if ( !stricmp(volume_name, FS_CDROM_VOLUME_3) && volume3_present) {
8272 if ( volume1_present || volume2_present || volume3_present ) {
8277 // 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
8278 if ( volume_match ){
8280 // 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
8281 if(volume2_present || volume3_present) {
8282 // first step - check to make sure its a cdrom
8283 if(GetDriveType(path) != DRIVE_CDROM){
8287 #if !defined(OEM_BUILD)
8288 // oem not on 80 min cds, so dont check tha size
8290 uint used_space = game_get_cd_used_space(path);
8291 if(used_space < CD_SIZE_72_MINUTE_MAX){
8294 #endif // !defined(OEM_BUILD)
8302 #endif // RELEASE_REAL
8308 SetCurrentDirectory(oldpath);
8317 int set_cdrom_path(int drive_num)
8321 if (drive_num < 0) { //no CD
8323 // strcpy(CDROM_dir,"j:\\FreeSpaceCD\\"); //set directory
8326 strcpy(Game_CDROM_dir,""); //set directory
8330 sprintf(Game_CDROM_dir,NOX("%c:\\"), 'a' + drive_num ); //set directory
8346 i = find_freespace_cd();
8348 rval = set_cdrom_path(i);
8352 nprintf(("CD", "Using %s for FreeSpace CD\n", CDROM_dir));
8354 nprintf(("CD", "FreeSpace CD not found\n"));
8362 int Last_cd_label_found = 0;
8363 char Last_cd_label[256];
8365 int game_cd_changed()
8372 if ( strlen(Game_CDROM_dir) == 0 ) {
8376 found = GetVolumeInformation(Game_CDROM_dir, label, 256, NULL, NULL, NULL, NULL, 0);
8378 if ( found != Last_cd_label_found ) {
8379 Last_cd_label_found = found;
8381 mprintf(( "CD '%s' was inserted\n", label ));
8384 mprintf(( "CD '%s' was removed\n", Last_cd_label ));
8388 if ( Last_cd_label_found ) {
8389 if ( !stricmp( Last_cd_label, label )) {
8390 //mprintf(( "CD didn't change\n" ));
8392 mprintf(( "CD was changed from '%s' to '%s'\n", Last_cd_label, label ));
8396 // none found before, none found now.
8397 //mprintf(( "still no CD...\n" ));
8401 Last_cd_label_found = found;
8403 strcpy( Last_cd_label, label );
8405 strcpy( Last_cd_label, "" );
8416 // check if _any_ FreeSpace2 CDs are in the drive
8417 // return: 1 => CD now in drive
8418 // 0 => Could not find CD, they refuse to put it in the drive
8419 int game_do_cd_check(char *volume_name)
8421 #if !defined(GAME_CD_CHECK)
8427 int num_attempts = 0;
8428 int refresh_files = 0;
8430 int path_set_ok, popup_rval;
8432 cd_drive_num = find_freespace_cd(volume_name);
8433 path_set_ok = set_cdrom_path(cd_drive_num);
8434 if ( path_set_ok ) {
8436 if ( refresh_files ) {
8448 // no CD found, so prompt user
8449 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR( "FreeSpace 2 CD not found\n\nInsert a FreeSpace 2 CD to continue", 202));
8451 if ( popup_rval != 1 ) {
8456 if ( num_attempts++ > 5 ) {
8467 // check if _any_ FreeSpace2 CDs are in the drive
8468 // return: 1 => CD now in drive
8469 // 0 => Could not find CD, they refuse to put it in the drive
8470 int game_do_cd_check_specific(char *volume_name, int cdnum)
8475 int num_attempts = 0;
8476 int refresh_files = 0;
8478 int path_set_ok, popup_rval;
8480 cd_drive_num = find_freespace_cd(volume_name);
8481 path_set_ok = set_cdrom_path(cd_drive_num);
8482 if ( path_set_ok ) {
8484 if ( refresh_files ) {
8495 // no CD found, so prompt user
8496 #if defined(DVD_MESSAGE_HACK)
8497 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert DVD", 1468));
8499 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert CD %d", 1468), cdnum);
8502 if ( popup_rval != 1 ) {
8507 if ( num_attempts++ > 5 ) {
8517 // only need to do this in RELEASE_REAL
8518 int game_do_cd_mission_check(char *filename)
8524 fs_builtin_mission *m = game_find_builtin_mission(filename);
8526 // check for changed CD
8527 if(game_cd_changed()){
8532 if((Game_mode & GM_MULTIPLAYER) || Is_standalone){
8536 // not builtin, so do a general check (any FS2 CD will do)
8538 return game_do_cd_check();
8541 // does not have any CD requirement, do a general check
8542 if(strlen(m->cd_volume) <= 0){
8543 return game_do_cd_check();
8547 if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_1)){
8549 } else if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_2)){
8551 } else if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_3)){
8554 return game_do_cd_check();
8557 // did we find the cd?
8558 if(find_freespace_cd(m->cd_volume) >= 0){
8562 // make sure the volume exists
8563 int num_attempts = 0;
8564 int refresh_files = 0;
8566 int path_set_ok, popup_rval;
8568 cd_drive_num = find_freespace_cd(m->cd_volume);
8569 path_set_ok = set_cdrom_path(cd_drive_num);
8570 if ( path_set_ok ) {
8572 if ( refresh_files ) {
8579 // no CD found, so prompt user
8580 #if defined(DVD_MESSAGE_HACK)
8581 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert DVD", 1468));
8583 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert CD %d", 1468), cd_num);
8587 if ( popup_rval != 1 ) {
8592 if ( num_attempts++ > 5 ) {
8604 // ----------------------------------------------------------------
8606 // CDROM detection code END
8608 // ----------------------------------------------------------------
8610 // ----------------------------------------------------------------
8612 // Language Autodetection stuff
8615 // this layout order must match Lcl_languages in localize.cpp in order for the
8616 // correct language to be detected
8617 int Lang_auto_detect_checksums[LCL_NUM_LANGUAGES] = {
8618 589986744, // English
8619 -1132430286, // German
8623 // default setting is "-1" to use config file with English as fall back
8624 // DO NOT change the default setting here or something uncouth might happen
8625 // in the localization code
8631 // try and open the file to verify
8632 CFILE *detect = cfopen("font01.vf", "rb");
8634 // will use default setting if something went wrong
8639 // get the long checksum of the file
8641 cfseek(detect, 0, SEEK_SET);
8642 cf_chksum_long(detect, &file_checksum);
8646 // now compare the checksum/filesize against known #'s
8647 for (idx=0; idx<LCL_NUM_LANGUAGES; idx++) {
8648 if (Lang_auto_detect_checksums[idx] == (int)file_checksum) {
8653 // notify if a match was not found, include detected checksum
8654 printf("ERROR: Unknown Language Checksum: %i\n", (int)file_checksum);
8655 printf("Using default language...\n\n");
8661 // End Auto Lang stuff
8663 // ----------------------------------------------------------------
8665 // ----------------------------------------------------------------
8666 // SHIPS TBL VERIFICATION STUFF
8669 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
8670 #define NUM_SHIPS_TBL_CHECKSUMS 1
8673 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8674 1696074201, // FS2 demo
8678 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8679 -463907578, // US - beta 1
8680 1696074201, // FS2 demo
8683 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8684 // -1022810006, // 1.0 FULL
8685 -1254285366 // 1.2 FULL (German)
8689 void verify_ships_tbl()
8693 Game_ships_tbl_valid = 1;
8699 // detect if the packfile exists
8700 CFILE *detect = cfopen("ships.tbl", "rb");
8701 Game_ships_tbl_valid = 0;
8705 Game_ships_tbl_valid = 0;
8709 // get the long checksum of the file
8711 cfseek(detect, 0, SEEK_SET);
8712 cf_chksum_long(detect, &file_checksum);
8716 // now compare the checksum/filesize against known #'s
8717 for(idx=0; idx<NUM_SHIPS_TBL_CHECKSUMS; idx++){
8718 if(Game_ships_tbl_checksums[idx] == (int)file_checksum){
8719 Game_ships_tbl_valid = 1;
8726 DCF(shipspew, "display the checksum for the current ships.tbl")
8729 CFILE *detect = cfopen("ships.tbl", "rb");
8730 // get the long checksum of the file
8732 cfseek(detect, 0, SEEK_SET);
8733 cf_chksum_long(detect, &file_checksum);
8736 dc_printf("%d", file_checksum);
8739 // ----------------------------------------------------------------
8740 // WEAPONS TBL VERIFICATION STUFF
8743 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
8744 #define NUM_WEAPONS_TBL_CHECKSUMS 1
8747 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8748 -266420030, // demo 1
8752 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8753 141718090, // US - beta 1
8754 -266420030, // demo 1
8757 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8758 // 399297860, // 1.0 FULL
8759 -553984927 // 1.2 FULL (german)
8763 void verify_weapons_tbl()
8767 Game_weapons_tbl_valid = 1;
8773 // detect if the packfile exists
8774 CFILE *detect = cfopen("weapons.tbl", "rb");
8775 Game_weapons_tbl_valid = 0;
8779 Game_weapons_tbl_valid = 0;
8783 // get the long checksum of the file
8785 cfseek(detect, 0, SEEK_SET);
8786 cf_chksum_long(detect, &file_checksum);
8790 // now compare the checksum/filesize against known #'s
8791 for(idx=0; idx<NUM_WEAPONS_TBL_CHECKSUMS; idx++){
8792 if(Game_weapons_tbl_checksums[idx] == (int)file_checksum){
8793 Game_weapons_tbl_valid = 1;
8800 DCF(wepspew, "display the checksum for the current weapons.tbl")
8803 CFILE *detect = cfopen("weapons.tbl", "rb");
8804 // get the long checksum of the file
8806 cfseek(detect, 0, SEEK_SET);
8807 cf_chksum_long(detect, &file_checksum);
8810 dc_printf("%d", file_checksum);
8813 // if the game is running using hacked data
8814 int game_hacked_data()
8817 if(!Game_weapons_tbl_valid || !Game_ships_tbl_valid){
8825 void display_title_screen()
8827 #if defined(FS2_DEMO) || defined(OEM_BUILD)
8828 ///int title_bitmap;
8831 int title_bitmap = bm_load(Game_demo_title_screen_fname[gr_screen.res]);
8832 if (title_bitmap == -1) {
8838 if((gr_screen.mode == GR_DIRECT3D) && (Gr_bitmap_poly)){
8839 extern void d3d_start_frame();
8845 gr_set_bitmap(title_bitmap);
8852 if((gr_screen.mode == GR_DIRECT3D) && (Gr_bitmap_poly)){
8853 extern void d3d_stop_frame();
8861 bm_unload(title_bitmap);
8862 #endif // FS2_DEMO || OEM_BUILD
8865 // return true if the game is running with "low memory", which is less than 48MB
8866 bool game_using_low_mem()
8868 if (Use_low_mem == 0) {