Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Starshatter.cpp
Go to the documentation of this file.
1 /* Project Starshatter 5.0
2  Destroyer Studios LLC
3  Copyright © 1997-2007. All Rights Reserved.
4 
5  SUBSYSTEM: Stars.exe
6  FILE: Starshatter.cpp
7  AUTHOR: John DiCamillo
8 
9 */
10 
11 
12 #include "MemDebug.h"
13 #include "Starshatter.h"
14 
15 #include "MenuScreen.h"
16 #include "LoadScreen.h"
17 #include "PlanScreen.h"
18 #include "CmpnScreen.h"
19 
20 #include "AudioConfig.h"
21 #include "MusicDirector.h"
22 #include "HUDSounds.h"
23 #include "Player.h"
24 
25 #include "Shot.h"
26 #include "Drive.h"
27 #include "LandingGear.h"
28 #include "Explosion.h"
29 #include "FlightDeck.h"
30 #include "NavLight.h"
31 #include "Debris.h"
32 #include "Contact.h"
33 #include "QuantumDrive.h"
34 #include "Sensor.h"
35 #include "Power.h"
36 #include "SystemDesign.h"
37 #include "WeaponDesign.h"
38 
39 #include "Campaign.h"
40 #include "CampaignSaveGame.h"
41 #include "CombatRoster.h"
42 #include "CombatZone.h"
43 #include "CampaignPlan.h"
44 
45 #include "Galaxy.h"
46 #include "StarSystem.h"
47 #include "Mission.h"
48 #include "Sim.h"
49 #include "SimEvent.h"
50 #include "Element.h"
51 #include "Ship.h"
52 #include "ShipCtrl.h"
53 #include "ShipDesign.h"
54 #include "HUDView.h"
55 #include "MFD.h"
56 #include "RadioMessage.h"
57 #include "RadioTraffic.h"
58 #include "RadioVox.h"
59 #include "CameraDirector.h"
60 #include "ModConfig.h"
61 #include "KeyMap.h"
62 
63 #include "GameScreen.h"
64 #include "QuantumView.h"
65 #include "QuitView.h"
66 #include "RadioView.h"
67 #include "TacticalView.h"
68 #include "DisplayView.h"
69 
70 #include "LoadDlg.h"
71 #include "TacRefDlg.h"
72 #include "CmpLoadDlg.h"
73 #include "Terrain.h"
74 
75 #include "NetClientConfig.h"
76 #include "NetServerConfig.h"
77 #include "NetLayer.h"
78 #include "NetLobbyClient.h"
79 #include "NetLobbyServer.h"
80 #include "NetGame.h"
81 #include "NetUtil.h"
82 
83 #include "ParseUtil.h"
84 #include "Token.h"
85 
86 #include "MachineInfo.h"
87 #include "Game.h"
88 #include "VideoFactory.h"
89 #include "Screen.h"
90 #include "Window.h"
91 #include "ActiveWindow.h"
92 #include "Button.h"
93 #include "CameraView.h"
94 #include "ImgView.h"
95 #include "FadeView.h"
96 #include "Color.h"
97 #include "Bitmap.h"
98 #include "Font.h"
99 #include "FontMgr.h"
100 #include "Keyboard.h"
101 #include "Joystick.h"
102 #include "MouseController.h"
103 #include "Mouse.h"
104 #include "TrackIR.h"
105 #include "EventDispatch.h"
106 #include "MultiController.h"
107 #include "Archive.h"
108 #include "DataLoader.h"
109 #include "Random.h"
110 #include "Resource.h"
111 #include "Universe.h"
112 #include "Video.h"
113 #include "VideoSettings.h"
114 #include "WebBrowser.h"
115 
116 // +--------------------------------------------------------------------+
117 
118 int quick_mode = 0;
121 
122 int Starshatter::keymap[256];
123 int Starshatter::keyalt[256];
125 
126 static Mission* current_mission = 0;
127 static Mission* cutscene_mission = 0;
128 static double cutscene_basetime = 0;
129 static int cut_efx_volume = 100;
130 static int cut_wrn_volume = 100;
131 static double time_til_change = 0;
132 static bool exit_latch = true;
133 static bool show_missions = false;
134 static bool use_file_system = false;
135 static bool no_splash = false;
136 
142 };
143 
144 // +--------------------------------------------------------------------+
145 
147 : gamewin(0), menuscreen(0), loadscreen(0), planscreen(0),
148 cmpnscreen(0), gamescreen(0), splash(0), splash_index(0),
149 input(0), loader(0), cam_dir(0), music_dir(0),
150 field_of_view(2), time_mark(0), minutes(0),
151 player_ship(0), net_lobby(0),
152 spinning(false), tactical(false), mouse_x(0), mouse_y(0),
153 game_mode(MENU_MODE), mouse_input(0), head_tracker(0),
154 terminal(0), verdana(0), limerick18(0), limerick12(0),
155 HUDfont(0), GUIfont(0), GUI_small_font(0), title_font(0),
156 ocrb(0), req_change_video(0), video_changed(0),
157 lens_flare(true), corona(true), nebula(true), dust(0),
158 load_step(0), load_progress(0),
159 chat_mode(0), exit_time(1.2), cutscene(0)
160 {
161  if (!instance)
162  instance = this;
163 
164  app_name = "Starshatter: The Gathering Storm";
165  title_text = "STARSHATTER";
166  palette_name = "alpha";
167 
168  gamma = 128; // default - flat gamma ramp
169 
170  if (!DataLoader::GetLoader())
172 
174  int loadstat = loader->EnableDatafile("shatter.dat");
175 
176  if (loadstat != DataLoader::DATAFILE_OK) {
177  const char* err_msg = loadstat == DataLoader::DATAFILE_INVALID ?
178  "The file 'shatter.dat' appears to have been damaged. Please re-install Starshatter." :
179  "Starshatter cannot open the file 'shatter.dat'. Please re-install Starshatter.";
180 
181  ::MessageBox(hwnd, err_msg, "Starshatter - Error", MB_OK);
182  ::Print(err_msg);
183  ::Print("\n\nFATAL ERROR: EXIT.");
184  exit(-1);
185  }
186 
187  if (loader->FindFile("vox.dat"))
188  loader->EnableDatafile("vox.dat");
189 
190  if (loader->FindFile("start.dat"))
191  loader->EnableDatafile("start.dat");
192 
193  loadstat = loader->EnableDatafile("content.dat");
194 
195  if (loadstat != DataLoader::DATAFILE_OK) {
196  const char* err_msg = loadstat == DataLoader::DATAFILE_INVALID ?
197  "The file 'content.dat' appears to have been damaged. Please re-install the latest Starshatter update." :
198  "Starshatter cannot open the file 'content.dat'. Please re-install the latest Starshatter update.";
199 
200  ::MessageBox(hwnd, err_msg, "Starshatter - Error", MB_OK);
201  ::Print(err_msg);
202  ::Print("\n\nFATAL ERROR: EXIT.");
203  exit(-1);
204  }
205 
206  LoadVideoConfig("video.cfg");
207 
208  // create the fonts
209  loader->SetDataPath("Fonts/");
210 
211  HUDfont = new(__FILE__,__LINE__) Font("HUDfont");
212  FontMgr::Register("HUD", HUDfont);
213 
214  GUIfont = new(__FILE__,__LINE__) Font("GUIfont");
215  FontMgr::Register("GUI", GUIfont);
216 
217  GUI_small_font = new(__FILE__,__LINE__) Font("GUIsmall");
218  FontMgr::Register("GUIsmall", GUI_small_font);
219 
220  limerick12 = new(__FILE__,__LINE__) Font("Limerick12");
221  limerick18 = new(__FILE__,__LINE__) Font("Limerick18");
222  terminal = new(__FILE__,__LINE__) Font("Terminal");
223  verdana = new(__FILE__,__LINE__) Font("Verdana");
224  ocrb = new(__FILE__,__LINE__) Font("OCRB");
225 
226  FontMgr::Register("Limerick12", limerick12);
227  FontMgr::Register("Limerick18", limerick18);
228  FontMgr::Register("Terminal", terminal);
229  FontMgr::Register("Verdana", verdana);
230  FontMgr::Register("OCRB", ocrb);
231 
232  loader->SetDataPath(0);
233 
234  ZeroMemory(keymap, sizeof(keymap));
235  ZeroMemory(keyalt, sizeof(keyalt));
236 }
237 
239 {
240  if (video_changed) {
241  SaveVideoConfig("video.cfg");
242  }
243 
244  DeleteFile("video2.cfg");
245  StopLobby();
246 
247  if (Status() <= EXIT)
248  Player::Save();
249 
250  delete menuscreen;
251  delete loadscreen;
252  delete planscreen;
253  delete gamescreen;
254  delete cmpnscreen;
255 
256  menuscreen = 0;
257  loadscreen = 0;
258  planscreen = 0;
259  gamescreen = 0;
260  cmpnscreen = 0;
261 
262  music_dir = 0;
263 
264  // delete all the ships and stuff
265  // BEFORE getting rid of the system
266  // and weapons catalogs!
267  delete world;
268  world = 0; // don't let base class double delete the world
269 
270  delete quick_mission;
271 
275 
276  Player::Close();
277  Drive::Close();
279  MFD::Close();
282  Campaign::Close();
284  Galaxy::Close();
286  RadioVox::Close();
287  Ship::Close();
294  QuitView::Close();
297 
298  Mouse::Close();
300  FontMgr::Close();
301  Button::Close();
303 
304  delete ocrb;
305  delete limerick12;
306  delete limerick18;
307  delete verdana;
308  delete terminal;
309  delete HUDfont;
310  delete GUIfont;
311  delete GUI_small_font;
312  delete input;
313  delete head_tracker;
314 
315  instance = 0;
316 }
317 
318 void
320 {
323 }
324 
325 // +--------------------------------------------------------------------+
326 
327 bool
329 {
330  WebBrowser browser;
331  browser.OpenURL("http://matrixgames.com/support");
332  return true;
333 }
334 
335 // +--------------------------------------------------------------------+
336 
337 void
339 {
340  int nkeys = keycfg.GetNumKeys();
341 
342  if (nkeys > 0) {
343  Starshatter::MapKeys(&keycfg, nkeys);
344  input->MapKeys(keycfg.GetMapping(), nkeys);
345  }
346 }
347 
348 void
349 Starshatter::MapKeys(KeyMap* mapping, int nkeys)
350 {
351  for (int i = 0; i < nkeys; i++) {
352  KeyMapEntry* k = mapping->GetKeyMap(i);
353 
354  if (k->act >= KEY_MAP_FIRST && k->act <= KEY_MAP_LAST)
355  MapKey(k->act, k->key, k->alt);
356  }
357 }
358 
359 void
360 Starshatter::MapKey(int act, int key, int alt)
361 {
362  keymap[act] = key;
363  keyalt[act] = alt;
364 
365  GetAsyncKeyState(key);
366  GetAsyncKeyState(alt);
367 }
368 
369 // +--------------------------------------------------------------------+
370 
371 bool
372 Starshatter::Init(HINSTANCE hi, HINSTANCE hpi, LPSTR cmdline, int nCmdShow)
373 {
374  if (strstr(cmdline, "-win") || strstr(cmdline, "-dbg")) {
375  if (video_settings) {
376  video_settings->is_windowed = true;
377 
378  Print(" STARSHATTER RUNNING IN WINDOW MODE\n");
379  }
380  }
381 
382  if (strstr(cmdline, "-filesys")) {
383  use_file_system = true;
384  Print(" FILE SYSTEM ENABLED\n");
385  }
386 
387  if (strstr(cmdline, "-nosplash")) {
388  no_splash = true;
389  }
390 
391  if (loader)
392  loader->UseFileSystem(use_file_system);
393 
394  return Game::Init(hi, hpi, cmdline, nCmdShow);
395 }
396 
397 // +--------------------------------------------------------------------+
398 
399 bool
401 {
402  if (!Game::InitGame())
403  return false;
404 
405  RandomInit();
406 
409 
410  InitMouse();
411 
417 
418  int nkeys = keycfg.LoadKeyMap("key.cfg", 256);
419 
420  if (nkeys)
421  Print(" Loaded key.cfg\n\n");
422 
423  // create the appropriate motion controller and player_ship
424  input = new(__FILE__,__LINE__) MultiController;
425  Keyboard* k = new(__FILE__,__LINE__) Keyboard;
426  input->AddController(k);
427 
428  mouse_input = new(__FILE__,__LINE__) MouseController;
430 
431  ::Print("\nStarshatter::InitGame() create joystick\n");
432  Joystick* j = new(__FILE__,__LINE__) Joystick;
433  j->SetSensitivity(15, 5000);
434  input->AddController(j);
435 
437  ::Print("\n");
438 
439  head_tracker = new(__FILE__,__LINE__) TrackIR();
440  MapKeys();
441 
442  SystemDesign::Initialize("sys.def");
443  WeaponDesign::Initialize("wep.def");
445 
446  // if no splashes, we need to initialize the campaign engine now
447  if (no_splash) {
452  }
453 
454  // otherwise, the campaign engine will get initialized during the splashes
455  else {
456  SetupSplash();
457  }
458 
460  minutes = 0;
461 
462  return true;
463 }
464 
465 void
467 {
468  if (loader) {
469  loader->SetDataPath(0);
470 
472  Mouse::Show(false);
477  }
478 }
479 
480 // +--------------------------------------------------------------------+
481 
482 void
484 {
485  req_change_video = true;
486 }
487 
488 int
490 {
491  if (video_settings)
492  return video_settings->GetWidth();
493 
494  return 0;
495 }
496 
497 // +--------------------------------------------------------------------+
498 
499 int
501 {
502  if (video_settings)
503  return video_settings->GetHeight();
504 
505  return 0;
506 }
507 
508 // +--------------------------------------------------------------------+
509 
510 void
512 {
513  if (game_mode != MENU_MODE && game_mode != CMPN_MODE)
514  return;
515 
517  if (!p)
518  return;
519 
521  Campaign* c = 0;
523 
524 
525  // resume saved game?
526  if (saved.length()) {
527  CampaignSaveGame savegame;
528  savegame.Load(saved);
529  c = savegame.GetCampaign();
530  }
531 
532  // start training campaign?
533  else if (p->Trained() < 255) {
534  c = list[0];
535  c->Load();
536  }
537 
538  // start new dynamic campaign sequence?
539  else {
540  c = list[1];
541  c->Load();
542  }
543 
544  if (c)
546 
547  Mouse::Show(false);
549 }
550 
551 // +--------------------------------------------------------------------+
552 
553 bool
555 {
556  return use_file_system;
557 }
558 
559 // +--------------------------------------------------------------------+
560 
561 void
563 {
564  if (menuscreen && game_mode == MENU_MODE) {
566 
567  LoadDlg* load_dlg = menuscreen->GetLoadDlg();
568 
569  if (load_dlg && load_dlg->IsShown()) {
570  load_activity = Game::GetText("Starshatter.load.tac-ref");
571  load_progress = 1;
572  catalog_index = 0;
573  }
574  else {
576  }
577  }
578 }
579 
580 // +--------------------------------------------------------------------+
581 
582 void
584 {
585  if (game_mode == m)
586  return;
587 
588  const char* mode_name[] = {
589  "MENU_MODE", // main menu
590  "CLOD_MODE", // loading campaign
591  "CMPN_MODE", // operational command for dynamic campaign
592  "PREP_MODE", // loading mission info for planning
593  "PLAN_MODE", // mission briefing
594  "LOAD_MODE", // loading mission into simulator
595  "PLAY_MODE", // active simulation
596  "EXIT_MODE" // shutting down
597  };
598 
599  if (m >= MENU_MODE && m <= EXIT_MODE)
600  Print(">>> Starshatter::SetGameMode(%d) (%s)\n", m, mode_name[m]);
601  else
602  Print(">>> Starshatter::SetGameMode(%d) (UNKNOWN MODE)\n", m);
603 
605  if (mouse_con)
606  mouse_con->SetActive(false);
607 
608  if (m == CLOD_MODE || m == PREP_MODE || m == LOAD_MODE) {
609  load_step = 0;
610  load_progress = 0;
611  load_activity = Game::GetText("Starshatter.load.general");
612  paused = true;
613  }
614 
615  else if (m == CMPN_MODE) {
616  load_step = 0;
617  load_progress = 100;
618  load_activity = Game::GetText("Starshatter.load.complete");
619  paused = false;
620  }
621 
622  else if (m == PLAY_MODE) {
623  Print(" Starting Game...\n");
624 
625  player_ship = 0;
626  load_progress = 100;
627  load_activity = Game::GetText("Starshatter.load.complete");
628 
629  if (!world) {
630  CreateWorld();
632  }
633 
634  if (gamescreen)
636 
639 
641  Pause(false);
642 
643  Print(" Stardate: %.1f\n", StarSystem::GetBaseTime());
644  }
645 
646  else if (m == PLAN_MODE) {
647  if (game_mode == PLAY_MODE) {
648  Print(" Returning to Plan Mode...\n");
649  if (soundcard)
651 
652  StopNetGame();
653  Pause(true);
654  Print(" Stardate: %.1f\n", StarSystem::GetBaseTime());
655  }
656  }
657 
658  else if (m == MENU_MODE) {
659  Print(" Returning to Main Menu...\n");
660 
661  if (game_mode == PLAN_MODE || game_mode == PLAY_MODE) {
662  if (soundcard)
664 
665  StopNetGame();
666  }
667 
668  paused = true;
669  }
670 
671  if (m == EXIT_MODE) {
672  Print(" Shutting Down (Returning to Windows)...\n");
673 
674  if (game_mode == PLAN_MODE || game_mode == PLAY_MODE) {
675  if (soundcard)
677 
678  StopNetGame();
679  }
680 
681  Print(" Stardate: %.1f\n", StarSystem::GetBaseTime());
682  Print(" Bitmap Cache Footprint: %d KB\n", Bitmap::CacheMemoryFootprint() / 1024);
683 
684  paused = true;
685  }
686 
687  FlushKeys();
688  game_mode = m;
689 }
690 
691 // +--------------------------------------------------------------------+
692 
693 bool
695 {
696  bool result = false;
697 
698  if (menuscreen) {
699  delete menuscreen;
700  menuscreen = 0;
701  }
702 
703  if (loadscreen) {
704  delete loadscreen;
705  loadscreen = 0;
706  }
707 
708  if (planscreen) {
709  delete planscreen;
710  planscreen = 0;
711  }
712 
713  if (gamescreen) {
714  delete gamescreen;
715  gamescreen = 0;
716  }
717 
718  if (cmpnscreen) {
719  delete cmpnscreen;
720  cmpnscreen = 0;
721  }
722 
723  loader->SetDataPath(0);
724 
725  LoadVideoConfig("video2.cfg");
726 
727  result = ResetVideo();
728 
729  InitMouse();
730 
731  req_change_video = false;
732  video_changed = true;
733 
734  return result;
735 }
736 
737 bool
739 {
740  if (Game::ResizeVideo()) {
741  InitMouse();
742  Mouse::Show(true);
743 
744  return true;
745  }
746 
747  return false;
748 }
749 
750 // +--------------------------------------------------------------------+
751 
752 void
754 {
761 
762  // create world
763  if (!world) {
764  Sim* sim = new(__FILE__,__LINE__) Sim(input);
765  world = sim;
766  Print(" World Created.\n");
767  }
768 
770 }
771 
772 void
774 {
775  Memory::Check();
776 
777  current_mission = 0;
778 
779  if (Campaign::GetCampaign()) {
780  current_mission = Campaign::GetCampaign()->GetMission();
781  }
782 
783  Sim* sim = (Sim*) world;
784 
785  if (sim) {
786  bool dynamic = false;
787  Campaign* campaign = Campaign::GetCampaign();
788 
789  if (campaign && campaign->IsDynamic())
790  dynamic = true;
791 
792  sim->UnloadMission();
793  sim->LoadMission(current_mission);
794  sim->ExecMission();
795  sim->SetTestMode(test_mode && !dynamic ? true : false);
796 
797  Print(" Mission Instantiated.\n");
798  }
799 
800  Memory::Check();
801 }
802 
803 // +--------------------------------------------------------------------+
804 
805 int
806 Starshatter::KeyDown(int action) const
807 {
808  int k = Joystick::KeyDownMap(action) ||
809  Keyboard::KeyDownMap(action);
810 
811  return k;
812 }
813 
814 // +--------------------------------------------------------------------+
815 
816 bool
818 {
820 
821  if (active && paused) {
822  // Route Events to EventTargets
824  if (ed)
825  ed->Dispatch();
826 
827  UpdateWorld();
828  GameState();
829  UpdateScreen();
830  CollectStats();
831 
832  /***
833  static DWORD vmf_time = 0;
834 
835  if (real_time() - vmf_time > 5000) {
836  vmf_time = real_time();
837  DWORD vmf = video->VidMemFree() / (1024 * 1024);
838  ::Print("\n###### %02d:%02d - Video Memory Free: %d MB\n\n",
839  vmf_time / 60000,
840  vmf_time / 1000,
841  vmf);
842  }
843  ***/
844  }
845 
846  Game::GameLoop();
847  return false; // must return false to keep processing
848  // true tells the outer loop to sleep until a
849  // windows event is available
850 }
851 
852 // +--------------------------------------------------------------------+
853 
854 void
856 {
857  long new_time = real_time;
858  double delta = new_time - frame_time; // in milliseconds
859  seconds = max_frame_length; // in seconds
860  gui_seconds = delta * 0.001;
861 
862  if (frame_time == 0)
863  gui_seconds = 0;
864 
865  if (delta < time_comp * max_frame_length * 1000) {
866  seconds = time_comp * delta * 0.001;
867  }
868  else {
870  }
871 
872  frame_time = new_time;
873 
874  Galaxy* galaxy = Galaxy::GetInstance();
875  if (galaxy) galaxy->ExecFrame();
876 
877  // Cutscene missions have a tendency to mess with the stardate
878  // to manage time-of-day and camera effects. It's a bad idea to
879  // evaluate campaign actions and events while the cutscene is
880  // changing the time base.
881  if (!cutscene_mission) {
882  Campaign* campaign = Campaign::GetCampaign();
883  if (campaign) campaign->ExecFrame();
884  }
885 
886  if (paused) {
887  if (world)
888  world->ExecFrame(0);
889  }
890 
891  else {
892  game_time += (DWORD) (seconds * 1000);
893 
895 
896  if (world)
898  }
899 
900  if (game_mode == PLAY_MODE || InCutscene()) {
901  if (cam_dir) {
902  if (head_tracker && head_tracker->IsRunning() && !InCutscene()) {
906  }
907 
909  }
910 
911  Sim* sim = Sim::GetSim();
912  SimRegion* rgn = sim ? sim->GetActiveRegion() : 0;
913 
914  if (rgn) {
915  ListIter<Ship> iter = rgn->Ships();
916  while (++iter) {
917  Ship* s = iter.value();
918  s->SelectDetail(seconds);
919  }
920  }
921  }
922 }
923 
924 // +--------------------------------------------------------------------+
925 
926 void
928 {
929  if (splash) {
930  static bool quick_splash = false;
931 
932  if (GetKey() != 0)
933  quick_splash = true;
934 
935  if (quick_splash) {
936  splash->FadeIn(0);
937  splash->StopHold();
938  splash->FadeOut(0);
939  }
940 
941  if (splash->Done()) {
942  splash = 0; // this will get deleted along with gamewin
943  splash_index++;
944 
945  if (gamewin) {
947  delete gamewin;
948  gamewin = 0;
949  }
950 
951  if (splash_index < 2) {
954  SetupSplash();
955  }
956  else {
959  SetupMenuScreen();
960  }
961 
962  FlushKeys();
963  }
964  }
965 
966  else if (game_mode == MENU_MODE) {
967  bool campaign_select = false;
968 
969  if (cmpnscreen) {
970  campaign_select = cmpnscreen->IsShown();
971  cmpnscreen->Hide();
972  }
973 
974  if (gamescreen)
975  gamescreen->Hide();
976 
977  if (planscreen)
978  planscreen->Hide();
979 
980  if (loadscreen)
981  loadscreen->Hide();
982 
983  if (!menuscreen) {
984  SetupMenuScreen();
985  }
986  else {
987  menuscreen->Show();
988 
989  if (campaign_select)
991  }
992 
996 
998  }
999 
1000  else if (game_mode == CLOD_MODE ||
1001  game_mode == PREP_MODE ||
1002  game_mode == LOAD_MODE) {
1003  if (menuscreen)
1004  menuscreen->Hide();
1005 
1006  if (planscreen)
1007  planscreen->Hide();
1008 
1009  if (cmpnscreen)
1010  cmpnscreen->Hide();
1011 
1012  if (!loadscreen)
1013  SetupLoadScreen();
1014  else
1015  loadscreen->Show();
1016 
1017  if (game_mode == CLOD_MODE)
1019  else
1021 
1023  }
1024 
1025  else if (game_mode == PLAN_MODE) {
1026  if (menuscreen)
1027  menuscreen->Hide();
1028 
1029  if (cmpnscreen)
1030  menuscreen->Hide();
1031 
1032  if (loadscreen)
1033  loadscreen->Hide();
1034 
1035  if (gamescreen)
1036  gamescreen->Hide();
1037 
1038  if (!planscreen)
1039  SetupPlanScreen();
1040  else
1041  planscreen->Show();
1042 
1044  if (p && p->ShowAward()) {
1045  if (!planscreen->IsAwardShown())
1047  }
1048 
1049  else if (ShipStats::NumStats()) {
1050  if (!planscreen->IsDebriefShown()) {
1052  show_missions = true;
1053  }
1054  }
1055 
1056  else {
1057  if (!planscreen->IsMsnShown() && !planscreen->IsNavShown())
1059  }
1060 
1062 
1064  }
1065 
1066 
1067  else if (game_mode == CMPN_MODE) {
1068  if (menuscreen)
1069  menuscreen->Hide();
1070 
1071  if (planscreen)
1072  planscreen->Hide();
1073 
1074  if (loadscreen)
1075  loadscreen->Hide();
1076 
1077  if (gamescreen)
1078  gamescreen->Hide();
1079 
1080  if (!cmpnscreen)
1081  SetupCmpnScreen();
1082  else
1083  cmpnscreen->Show();
1084 
1086  }
1087 
1088  else if (game_mode == PLAY_MODE) {
1089  if (menuscreen)
1090  menuscreen->Hide();
1091 
1092  if (cmpnscreen)
1093  cmpnscreen->Hide();
1094 
1095  if (planscreen)
1096  planscreen->Hide();
1097 
1098  if (loadscreen)
1099  loadscreen->Hide();
1100 
1101  if (!gamescreen)
1102  SetupGameScreen();
1103  else
1104  gamescreen->Show();
1105 
1107  }
1108 
1109  if (game_mode == EXIT_MODE) {
1110  exit_time -= Game::GUITime();
1111 
1112  if (exit_time <= 0)
1113  Game::Exit();
1114  }
1115 
1116  if (net_lobby)
1117  net_lobby->ExecFrame();
1118 
1119  if (music_dir)
1120  music_dir->ExecFrame();
1121 
1122  Memory::Check();
1123 }
1124 
1125 // +--------------------------------------------------------------------+
1126 
1127 void
1129 {
1130  if (!Mouse::RButton()) {
1132  Mouse::Show(true);
1133  }
1134 
1135  if (time_til_change > 0)
1136  time_til_change -= Game::GUITime();
1137 
1138  if (!menuscreen)
1139  return;
1140 
1141  if (KeyDown(KEY_EXIT)) {
1142  if (time_til_change <= 0) {
1143  time_til_change = 0.5;
1144 
1145  if (!exit_latch && !menuscreen->CloseTopmost()) {
1147  }
1148  }
1149 
1150  exit_latch = true;
1151  }
1152  else {
1153  exit_latch = false;
1154  }
1155 
1156  LoadDlg* load_dlg = menuscreen->GetLoadDlg();
1157 
1158  if (load_dlg && load_dlg->IsShown()) {
1159  // load all ship designs in the standard catalog
1162  load_activity = Game::GetText("Starshatter.load.tac-ref");
1163 
1164  if (load_progress < 95)
1165  load_progress++;
1166  }
1167 
1168  else {
1170  }
1171  }
1172 
1173  if (show_missions) {
1174  if (net_lobby)
1176  else
1178 
1179  show_missions = false;
1180  }
1181 
1182  menuscreen->ExecFrame();
1183 
1184  if (req_change_video) {
1185  ChangeVideo();
1186  SetupMenuScreen();
1187  }
1188 }
1189 
1190 // +--------------------------------------------------------------------+
1191 
1192 void
1194 {
1196 
1197  if (time_til_change > 0)
1198  time_til_change -= Game::GUITime();
1199 
1200  if (KeyDown(KEY_EXIT)) {
1201  if (time_til_change <= 0) {
1202  time_til_change = 1;
1203 
1204  if (!exit_latch && !planscreen->CloseTopmost()) {
1205  Campaign* campaign = Campaign::GetCampaign();
1206  if (campaign && (campaign->IsDynamic() || campaign->IsTraining()))
1208  else
1210  }
1211  }
1212 
1213  exit_latch = true;
1214  }
1215  else {
1216  exit_latch = false;
1217  }
1218 
1219  planscreen->ExecFrame();
1220  show_missions = true;
1221 }
1222 
1223 // +--------------------------------------------------------------------+
1224 
1225 void
1227 {
1229 
1230  if (time_til_change > 0)
1231  time_til_change -= Game::GUITime();
1232 
1233  exit_latch = KeyDown(KEY_EXIT) ? true : false;
1234 
1235  if (InCutscene() && player_ship) {
1236  // warp effect:
1237  if (player_ship->WarpFactor() > 1) {
1240  else
1242  }
1243 
1244  else {
1247  }
1248  }
1249 
1250  if (InCutscene() && exit_latch) {
1251  time_til_change = 1;
1252  EndCutscene();
1253  EndMission();
1255  }
1256 
1257  else if (time_til_change <= 0 && exit_latch) {
1258  time_til_change = 1;
1259 
1260  if (!cmpnscreen || !cmpnscreen->CloseTopmost()) {
1262  }
1263  }
1264 
1265  // time control for campaign mode:
1266  else if (game_mode == CMPN_MODE) {
1267  if (time_til_change <= 0) {
1268  if (KeyDown(KEY_PAUSE)) {
1269  time_til_change = 1;
1270  Pause(!paused);
1271  }
1272 
1273  else if (KeyDown(KEY_TIME_COMPRESS)) {
1274  time_til_change = 1;
1275 
1276  switch (TimeCompression()) {
1277  case 1: SetTimeCompression(2); break;
1278  case 2: SetTimeCompression(4); break;
1279  case 4: SetTimeCompression(8); break;
1280  }
1281  }
1282 
1283  else if (KeyDown(KEY_TIME_EXPAND)) {
1284  time_til_change = 1;
1285 
1286  switch (TimeCompression()) {
1287  case 8: SetTimeCompression( 4); break;
1288  case 4: SetTimeCompression( 2); break;
1289  default: SetTimeCompression( 1); break;
1290  }
1291  }
1292  }
1293  }
1294 
1295  if (show_missions && !InCutscene()) {
1297  show_missions = false;
1298  }
1299 
1300  cmpnscreen->ExecFrame();
1301 }
1302 
1303 // +--------------------------------------------------------------------+
1304 
1305 void
1307 {
1308  Mouse::Show(false);
1310 
1311  if (game_mode == CLOD_MODE) {
1313 
1314  switch (load_step) {
1315  case 0:
1316  load_activity = Game::GetText("Starshatter.load.campaign");
1317  load_progress = 1;
1318  catalog_index = 0;
1319  break;
1320 
1321  case 1:
1322  // load all ship designs in the standard catalog
1325  load_activity = Game::GetText("Starshatter.load.campaign");
1326 
1327  if (load_progress < 80)
1328  load_progress++;
1329 
1330  load_step = 0; // force return to current step on next frame
1331  }
1332  else {
1333  load_activity = Game::GetText("Starshatter.load.start");
1334  load_progress = 80;
1335  }
1336  break;
1337 
1338  case 2:
1339  if (Campaign::GetCampaign())
1341  break;
1342 
1343  default:
1344  if (dlg && load_progress < 100) {
1345  load_progress++;
1346  }
1347  else {
1348  load_activity = Game::GetText("Starshatter.load.ready");
1349  load_progress = 100;
1351  }
1352  break;
1353  }
1354  }
1355  else {
1356  switch (load_step) {
1357  case 0:
1358  load_activity = Game::GetText("Starshatter.load.drives");
1359  load_progress = 0;
1360  break;
1361 
1362  case 1:
1365  load_activity = Game::GetText("Starshatter.load.explosions");
1366  load_progress = 5;
1367  break;
1368 
1369  case 2:
1371  load_activity = Game::GetText("Starshatter.load.systems");
1372  load_progress = 10;
1373  break;
1374 
1375  case 3:
1378  load_activity = Game::GetText("Starshatter.load.ships");
1379  load_progress = 15;
1380  break;
1381 
1382  case 4:
1383  Ship::Initialize();
1384  Shot::Initialize();
1385  load_activity = Game::GetText("Starshatter.load.hud");
1386  load_progress = 20;
1387  break;
1388 
1389  case 5:
1390  MFD::Initialize();
1391  load_activity = Game::GetText("Starshatter.load.menus");
1392  load_progress = 25;
1393  break;
1394 
1395  case 6:
1399 
1400  if (!gamescreen && game_mode != PREP_MODE)
1401  SetupGameScreen();
1402 
1403  load_activity = Game::GetText("Starshatter.load.mission");
1404  load_progress = 65;
1405  break;
1406 
1407  case 7:
1408  if (game_mode == PREP_MODE) {
1409  if (Campaign::GetCampaign())
1412  load_activity = Game::GetText("Starshatter.load.loaded");
1413  load_progress = 100;
1414  Button::PlaySound(4);
1415  }
1416  else {
1417  CreateWorld();
1418  load_activity = Game::GetText("Starshatter.load.simulation");
1419  load_progress = 75;
1420  }
1421  break;
1422 
1423  case 8:
1425  load_activity = Game::GetText("Starshatter.load.viewscreen");
1426  load_progress = 90;
1427  break;
1428 
1429  default:
1431  load_activity = Game::GetText("Starshatter.load.ready");
1432  load_progress = 100;
1433  break;
1434  }
1435  }
1436 
1437  load_step++;
1438  loadscreen->ExecFrame();
1439 }
1440 
1441 // +--------------------------------------------------------------------+
1442 
1443 void
1445 {
1448  if (mode == CameraDirector::MODE_DROP) {
1449  player_ship->DropCam(15, 0);
1452  }
1453 
1454  else {
1455  cam_dir->SetMode(mode);
1456 
1457  if (mode == CameraDirector::MODE_ORBIT) {
1459  if (mouse_con)
1460  mouse_con->SetActive(false);
1461  }
1462  }
1463  }
1464 }
1465 
1466 void
1468 {
1469  Sim* sim = (Sim*) world;
1470  List<Ship>& seln = sim->GetSelection().container();
1471 
1472  if (cam_dir) {
1473  if (seln.isEmpty())
1475 
1476  else if (seln.size() == 1)
1477  cam_dir->SetViewObject(seln[0]);
1478 
1479  else
1480  cam_dir->SetViewObjectGroup(seln);
1481  }
1482 }
1483 
1484 // +--------------------------------------------------------------------+
1485 
1486 void
1488 {
1489  Sim* sim = (Sim*) world;
1490 
1491  if (!gamescreen || !sim)
1492  return;
1493 
1494  if (InCutscene()) {
1495  if (player_ship) {
1496  // warp effect:
1497  if (player_ship->WarpFactor() > 1) {
1500  else
1502  }
1503 
1504  else {
1507  }
1508  }
1509 
1511  gamescreen->ExecFrame();
1512 
1513  if (KeyDown(KEY_EXIT)) {
1515  exit_latch = true;
1516  time_til_change = 1;
1517 
1518  sim->SkipCutscene();
1519  }
1520 
1521  return;
1522  }
1523 
1524  if (time_til_change > 0)
1525  time_til_change -= Game::GUITime();
1526 
1527  if (exit_latch && !KeyDown(KEY_EXIT))
1528  exit_latch = false;
1529 
1530  DoMouseFrame();
1531 
1532  HUDView* hud_view = HUDView::GetInstance();
1533 
1534  // changing to a new ship?
1535  if (player_ship != sim->GetPlayerShip()) {
1539 
1540  Ship* new_player = sim->GetPlayerShip();
1541 
1542  if (new_player) {
1543  if (new_player->IsDropship() && Ship::GetFlightModel() < 2 && Ship::GetControlModel() < 1)
1544  input->SwapYawRoll(true);
1545  else
1546  input->SwapYawRoll(false);
1547 
1548  if (hud_view) {
1549  hud_view->SetHUDMode(HUDView::HUD_MODE_TAC);
1550  hud_view->HideHUDWarn();
1551  }
1552  }
1553  }
1554 
1555  player_ship = sim->GetPlayerShip();
1556 
1557  if (player_ship) {
1558  // warp effect:
1559  if (player_ship->WarpFactor() > 1) {
1562  else
1564  }
1565 
1566  else {
1569  }
1570 
1572 
1574  tactical = true;
1575  else
1576  tactical = false;
1577 
1578  if (player_ship->InTransition())
1580  }
1581 
1582  if (chat_mode) {
1583  DoChatMode();
1584  }
1585 
1586  else {
1587  DoGameKeys();
1588  }
1589 
1591  gamescreen->ExecFrame();
1592 
1593  if (Game::GameTime() - time_mark > 60000) {
1595  minutes++;
1596  if (minutes > 60)
1597  Print(" TIME %2d:%02d:00\n", minutes/60, minutes%60);
1598  else
1599  Print(" TIME %2d:00\n", minutes);
1600  }
1601 }
1602 
1603 void
1605 {
1606  Sim* sim = (Sim*) world;
1607  HUDView* hud_view = HUDView::GetInstance();
1608 
1609  if (time_til_change <= 0) {
1610  if (KeyDown(KEY_CAM_BRIDGE)) {
1612  time_til_change = 0.5;
1613  }
1614 
1615  else if (KeyDown(KEY_CAM_VIRT)) {
1617  time_til_change = 0.5;
1618  }
1619 
1620  else if (KeyDown(KEY_CAM_CHASE)) {
1622  time_til_change = 0.5;
1623  }
1624 
1625  else if (KeyDown(KEY_CAM_DROP)) {
1627  time_til_change = 0.5;
1628  }
1629 
1630  else if (KeyDown(KEY_CAM_EXTERN)) {
1632  time_til_change = 0.5;
1633  }
1634 
1635  else if (KeyDown(KEY_TARGET_PADLOCK)) {
1637  time_til_change = 0.5;
1638  }
1639 
1640  else if (KeyDown(KEY_SWAP_ROLL_YAW)) {
1642  time_til_change = 0.5;
1643  }
1644 
1645  else if (KeyDown(KEY_ZOOM_WIDE)) {
1646  time_til_change = 0.5;
1647  if (gamescreen->GetFieldOfView() <= 2)
1648  field_of_view = 3; // wide
1649  else
1650  field_of_view = 2; // normal
1651 
1652  // don't mess with fov during warp:
1653  if (player_ship && player_ship->WarpFactor() <= 1)
1655  }
1656 
1657  else if (!exit_latch && KeyDown(KEY_EXIT)) {
1658  exit_latch = true;
1659  time_til_change = 0.5;
1660 
1661  if (!gamescreen->CloseTopmost()) {
1662  QuitView* quit = QuitView::GetInstance();
1663  if (quit)
1664  quit->ShowMenu();
1665  else
1667  }
1668  }
1669 
1670  else if (KeyDown(KEY_PAUSE)) {
1671  Pause(!paused);
1672  time_til_change = 0.5;
1673  }
1674 
1675 
1676  else if (KeyDown(KEY_TIME_COMPRESS)) {
1677  time_til_change = 0.5;
1678  if (NetGame::IsNetGame())
1679  SetTimeCompression(1);
1680  else
1681  switch (TimeCompression()) {
1682  case 1: SetTimeCompression(2); break;
1683  default: SetTimeCompression(4); break;
1684  }
1685  }
1686 
1687  else if (KeyDown(KEY_TIME_EXPAND)) {
1688  time_til_change = 0.5;
1689 
1690  if (NetGame::IsNetGame())
1691  SetTimeCompression(1);
1692  else
1693  switch (TimeCompression()) {
1694  case 4: SetTimeCompression( 2); break;
1695  default: SetTimeCompression( 1); break;
1696  }
1697  }
1698 
1699  else if (KeyDown(KEY_TIME_SKIP)) {
1700  time_til_change = 0.5;
1701 
1702  if (player_ship && !NetGame::IsNetGame()) {
1703  player_ship->TimeSkip();
1704  }
1705  }
1706 
1707  else if (KeyDown(KEY_COMMAND_MODE)) {
1708  if (player_ship) {
1709  time_til_change = 0.5;
1711  }
1712  }
1713 
1714  /*** For Debug Convenience Only: ***/
1715  else if (KeyDown(KEY_INC_STARDATE)) {
1717  }
1718 
1719  else if (KeyDown(KEY_DEC_STARDATE)) {
1721  }
1722  /***/
1723  }
1724 
1725  if (gamescreen && time_til_change <= 0) {
1726  if (KeyDown(KEY_MFD1)) {
1728  time_til_change = 0.5;
1729  }
1730 
1731  else if (KeyDown(KEY_MFD2)) {
1733  time_til_change = 0.5;
1734  }
1735 
1736  else if (KeyDown(KEY_MFD3)) {
1738  time_til_change = 0.5;
1739  }
1740 
1741  else if (KeyDown(KEY_MFD4)) {
1743  time_til_change = 0.5;
1744  }
1745 
1746  else if (KeyDown(KEY_RADIO_MENU)) {
1747  RadioView* radio_view = RadioView::GetInstance();
1748  if (radio_view) {
1749  if (radio_view->IsMenuShown())
1750  radio_view->CloseMenu();
1751  else
1752  radio_view->ShowMenu();
1753  }
1754  time_til_change = 0.5;
1755  }
1756 
1757  else if (KeyDown(KEY_QUANTUM_MENU)) {
1758  QuantumView* quantum_view = QuantumView::GetInstance();
1759  if (quantum_view) {
1760  if (quantum_view->IsMenuShown())
1761  quantum_view->CloseMenu();
1762  else
1763  quantum_view->ShowMenu();
1764  }
1765  time_til_change = 0.5;
1766  }
1767 
1768  else if (KeyDown(KEY_CAM_VIEW_SELECTION)) {
1769  time_til_change = 0.5;
1770  ViewSelection();
1771  }
1772 
1773  else if (KeyDown(KEY_HUD_MODE)) {
1774  time_til_change = 0.5;
1775  if (hud_view)
1776  hud_view->CycleHUDMode();
1777  }
1778 
1779  else if (KeyDown(KEY_HUD_COLOR)) {
1780  time_til_change = 0.5;
1781  if (hud_view)
1782  hud_view->CycleHUDColor();
1783  }
1784 
1785  else if (KeyDown(KEY_HUD_WARN)) {
1786  time_til_change = 0.5;
1787  if (hud_view)
1788  hud_view->CycleHUDWarn();
1789  }
1790 
1791  else if (KeyDown(KEY_HUD_INST)) {
1792  time_til_change = 0.5;
1793  if (hud_view)
1794  hud_view->CycleHUDInst();
1795  }
1796 
1797  else if (KeyDown(KEY_SELF_DESTRUCT)) {
1798  time_til_change = 0.5;
1799 
1800  if (player_ship && !player_ship->InTransition()) {
1801  double damage = player_ship->Design()->scuttle;
1802 
1803  if (NetGame::IsNetGameClient()) {
1805  }
1806  else {
1807  Point scuttle_loc = player_ship->Location() + RandomDirection() * player_ship->Radius();
1808  player_ship->InflictDamage(damage, 0, 1, scuttle_loc);
1809  }
1810 
1811  if (player_ship->Integrity() < 1) {
1812  ::Print(" %s 0-0-0-Destruct-0\n\n", player_ship->Name());
1813 
1815  if (s)
1817 
1819  }
1820  }
1821  }
1822  }
1823 
1824  if (gamescreen && player_ship && time_til_change <= 0 && !::GetAsyncKeyState(VK_SHIFT) && !::GetAsyncKeyState(VK_MENU)) {
1825  if (KeyDown(KEY_NAV_DLG)) {
1827  time_til_change = 0.5;
1828  }
1829 
1830  else if (KeyDown(KEY_WEP_DLG)) {
1833  time_til_change = 0.5;
1834  }
1835 
1836  else if (KeyDown(KEY_FLT_DLG)) {
1837  if (player_ship && player_ship->NumFlightDecks() > 0)
1839  time_til_change = 0.5;
1840  }
1841 
1842  else if (KeyDown(KEY_ENG_DLG)) {
1845  time_til_change = 0.5;
1846  }
1847  }
1848 
1849  if (cam_dir) {
1850  double spin = (PI/2) * Game::FrameTime(); // Game::GUITime();
1851 
1852  if (avi_file)
1853  spin /= 6;
1854 
1856  cam_dir->ExternalAzimuth(spin);
1857 
1858  else if (KeyDown(KEY_CAM_EXT_MINUS_AZ))
1859  cam_dir->ExternalAzimuth(-spin);
1860 
1862  cam_dir->ExternalElevation(spin);
1863 
1864  else if (KeyDown(KEY_CAM_EXT_MINUS_EL))
1865  cam_dir->ExternalElevation(-spin);
1866 
1868  cam_dir->VirtualAzimuth(-spin);
1869 
1870  else if (KeyDown(KEY_CAM_VIRT_MINUS_AZ))
1871  cam_dir->VirtualAzimuth(spin);
1872 
1874  cam_dir->VirtualElevation(spin);
1875 
1876  else if (KeyDown(KEY_CAM_VIRT_MINUS_EL))
1877  cam_dir->VirtualElevation(-spin);
1878 
1880  if (!gamescreen->IsNavShown()) {
1881  cam_dir->ExternalRange((float) (1 + 1.5 * Game::FrameTime())); // 1.1f);
1882  }
1883  }
1884 
1885  else if (KeyDown(KEY_CAM_EXT_MINUS_RANGE)) {
1886  if (!gamescreen->IsNavShown()) {
1887  cam_dir->ExternalRange((float) (1 - 1.5 * Game::FrameTime())); // 0.9f);
1888  }
1889  }
1890 
1891  if (tactical && !gamescreen->IsFormShown()) {
1892  if (Mouse::Wheel()) {
1893  int w = Mouse::Wheel();
1894 
1895  if (w < 0) {
1896  while (w < 0) {
1897  cam_dir->ExternalRange(1.25f);
1898  w += 120;
1899  }
1900  }
1901  else {
1902  while (w > 0) {
1903  cam_dir->ExternalRange(0.75f);
1904  w -= 120;
1905  }
1906  }
1907  }
1908 
1909  else if (Mouse::LButton() && Mouse::RButton()) {
1910  if (mouse_dy < 0)
1911  cam_dir->ExternalRange(0.85f);
1912  else if (mouse_dy > 0)
1913  cam_dir->ExternalRange(1.15f);
1914  }
1915 
1916  else if (Mouse::MButton() && time_til_change <= 0) {
1917  time_til_change = 0.5;
1918  ViewSelection();
1919  }
1920 
1921  else {
1922  if (mouse_dx || mouse_dy) {
1925  cam_dir->VirtualElevation(mouse_dy * 0.2 * DEGREES);
1926  }
1927  else {
1929  cam_dir->ExternalElevation(mouse_dy * 0.2 * DEGREES);
1930  }
1931  }
1932  }
1933  }
1934  }
1935 
1936  // radio message hot keys:
1937  static bool comm_key = false;
1938 
1940  if (!comm_key)
1942  comm_key = true;
1943  }
1944 
1945  else if (KeyDown(KEY_COMM_ESCORT_TGT)) {
1946  if (!comm_key)
1948  comm_key = true;
1949  }
1950 
1951  else if (KeyDown(KEY_COMM_WEP_FREE)) {
1952  if (!comm_key)
1954  comm_key = true;
1955  }
1956 
1957  else if (KeyDown(KEY_COMM_WEP_HOLD)) {
1958  if (!comm_key)
1960  comm_key = true;
1961  }
1962 
1963  else if (KeyDown(KEY_COMM_COVER_ME)) {
1964  if (!comm_key)
1966  comm_key = true;
1967  }
1968 
1969  else if (KeyDown(KEY_COMM_SKIP_NAV)) {
1970  if (!comm_key)
1972  comm_key = true;
1973  }
1974 
1975  else if (KeyDown(KEY_COMM_RETURN_TO_BASE)) {
1976  if (!comm_key)
1978  comm_key = true;
1979  }
1980 
1981  else if (KeyDown(KEY_COMM_CALL_INBOUND)) {
1982  if (!comm_key)
1984  comm_key = true;
1985  }
1986 
1987  else if (KeyDown(KEY_COMM_REQUEST_PICTURE)) {
1988  if (!comm_key)
1990  comm_key = true;
1991  }
1992 
1993  else if (KeyDown(KEY_COMM_REQUEST_SUPPORT)) {
1994  if (!comm_key)
1996  comm_key = true;
1997  }
1998 
1999  else if (KeyDown(KEY_CHAT_BROADCAST)) {
2000  if (!comm_key)
2002  comm_key = true;
2003  }
2004 
2005  else if (KeyDown(KEY_CHAT_TEAM)) {
2006  if (!comm_key)
2008  comm_key = true;
2009  }
2010 
2011  else if (KeyDown(KEY_CHAT_WING)) {
2012  if (!comm_key)
2014  comm_key = true;
2015  }
2016 
2017  else if (KeyDown(KEY_CHAT_UNIT) && sim->GetSelection().container().size()) {
2018  if (!comm_key)
2020  comm_key = true;
2021  }
2022 
2023  else {
2024  comm_key = false;
2025  }
2026 }
2027 
2028 void
2030 {
2032  bool send_chat = false;
2033  Text name = "Player";
2034 
2035  if (player_ship)
2036  name = player_ship->Name();
2037 
2038  if (p)
2039  name = p->Name();
2040 
2041  if (chat_text.length()) {
2042  if (chat_text[0] >= '0' && chat_text[0] <= '9') {
2043  if (p) {
2044  chat_text = p->ChatMacro(chat_text[0] - '0');
2045  send_chat = true;
2046  }
2047  }
2048  }
2049 
2050  if (KeyDown(KEY_EXIT)) {
2051  SetChatMode(0);
2052  time_til_change = 0.5;
2053  }
2054 
2055  else if (send_chat || Keyboard::KeyDown(VK_RETURN)) {
2056  switch (chat_mode) {
2057  default:
2058  case CHAT_BROADCAST:
2059  {
2060  NetUtil::SendChat(0, name, chat_text);
2061  }
2062  break;
2063 
2064  case CHAT_TEAM:
2065  if (player_ship) {
2067  }
2068  break;
2069 
2070  case CHAT_WING:
2071  if (player_ship) {
2072  Element* elem = player_ship->GetElement();
2073  if (elem) {
2074  for (int i = 1; i <= elem->NumShips(); i++) {
2075  Ship* s = elem->GetShip(i);
2076  if (s && s != player_ship)
2077  NetUtil::SendChat(s->GetObjID(), name, chat_text);
2078  }
2079  }
2080  }
2081  break;
2082 
2083  case CHAT_UNIT:
2084  {
2085  Sim* sim = Sim::GetSim();
2086  ListIter<Ship> seln = sim->GetSelection();
2087 
2088  while (++seln) {
2089  Ship* s = seln.value();
2090  if (s != player_ship)
2091  NetUtil::SendChat(s->GetObjID(), name, chat_text);
2092  }
2093  }
2094  break;
2095  }
2096 
2097  HUDView::Message("%s> %s", name.data(), chat_text.data());
2098 
2099  SetChatMode(0);
2100  time_til_change = 0.5;
2101  }
2102 
2103  else {
2104  int key = 0;
2105  int shift = 0;
2106 
2107  while (GetKeyPlus(key, shift)) {
2108  if (key >= 'A' && key <= 'Z') {
2109  if (shift & 1)
2110  chat_text += (char) key;
2111  else
2112  chat_text += (char) tolower(key);
2113  }
2114  else {
2115  switch (key) {
2116  case VK_BACK:
2118  break;
2119 
2120  case VK_SPACE: chat_text += ' '; break;
2121  case '0': if (shift & 1) chat_text += ')'; else chat_text += '0'; break;
2122  case '1': if (shift & 1) chat_text += '!'; else chat_text += '1'; break;
2123  case '2': if (shift & 1) chat_text += '@'; else chat_text += '2'; break;
2124  case '3': if (shift & 1) chat_text += '#'; else chat_text += '3'; break;
2125  case '4': if (shift & 1) chat_text += '$'; else chat_text += '4'; break;
2126  case '5': if (shift & 1) chat_text += '%'; else chat_text += '5'; break;
2127  case '6': if (shift & 1) chat_text += '^'; else chat_text += '6'; break;
2128  case '7': if (shift & 1) chat_text += '&'; else chat_text += '7'; break;
2129  case '8': if (shift & 1) chat_text += '*'; else chat_text += '8'; break;
2130  case '9': if (shift & 1) chat_text += '('; else chat_text += '9'; break;
2131  case 186: if (shift & 1) chat_text += ':'; else chat_text += ';'; break;
2132  case 187: if (shift & 1) chat_text += '+'; else chat_text += '='; break;
2133  case 188: if (shift & 1) chat_text += '<'; else chat_text += ','; break;
2134  case 189: if (shift & 1) chat_text += '_'; else chat_text += '-'; break;
2135  case 190: if (shift & 1) chat_text += '>'; else chat_text += '.'; break;
2136  case 191: if (shift & 1) chat_text += '?'; else chat_text += '/'; break;
2137  case 192: if (shift & 1) chat_text += '~'; else chat_text += '`'; break;
2138  case 219: if (shift & 1) chat_text += '{'; else chat_text += '['; break;
2139  case 221: if (shift & 1) chat_text += '}'; else chat_text += ']'; break;
2140  case 220: if (shift & 1) chat_text += '|'; else chat_text += '\\'; break;
2141  case 222: if (shift & 1) chat_text += '"'; else chat_text += '\''; break;
2142  }
2143  }
2144  }
2145  }
2146 }
2147 
2148 void
2150 {
2151  if (mode >= 0 && mode <= 4 && mode != chat_mode) {
2152  chat_text = "";
2153 
2154  if (!NetGame::IsNetGame()) {
2155  chat_mode = 0;
2156  }
2157  else {
2158  chat_mode = mode;
2159 
2160  // flush input before reading chat message:
2161  if (chat_mode) {
2162  FlushKeys();
2163  }
2164 
2165  // flush input before sampling flight controls:
2166  else {
2167  for (int i = 1; i < 255; i++) {
2168  Keyboard::KeyDown(i);
2169  }
2170  }
2171  }
2172  }
2173 }
2174 
2175 // +--------------------------------------------------------------------+
2176 
2177 void
2179 {
2180  EventDispatch* event_dispatch = EventDispatch::GetInstance();
2181  if (event_dispatch && event_dispatch->GetCapture())
2182  return;
2183 
2184  mouse_dx = 0;
2185  mouse_dy = 0;
2186 
2187  static int old_mouse_x = 0;
2188  static int old_mouse_y = 0;
2189 
2190  if (!spinning && Mouse::RButton()) {
2191  spinning = true;
2192  old_mouse_x = Mouse::X();
2193  old_mouse_y = Mouse::Y();
2194  mouse_x = Mouse::X();
2195  mouse_y = Mouse::Y();
2196  Mouse::Show(false);
2197  }
2198 
2199  else if (spinning) {
2200  if (!Mouse::RButton()) {
2201  spinning = false;
2202 
2203  if (tactical) {
2204  Mouse::Show(true);
2206  }
2207 
2208  Mouse::SetCursorPos(old_mouse_x, old_mouse_y);
2209  }
2210 
2211  else {
2212  mouse_dx = Mouse::X() - mouse_x;
2213  mouse_dy = Mouse::Y() - mouse_y;
2214 
2216  }
2217  }
2218 
2219  else if (cutscene || !player_ship) {
2220  Mouse::Show(false);
2221  return;
2222  }
2223 
2224  // hide mouse cursor when mouse controller is actively steering:
2225  else if (mouse_input && mouse_input->Active()) {
2226  if (mouse_input->Selector() == 1) {
2227  Mouse::Show(false);
2228  }
2229 
2230  else if (mouse_input->Selector() == 2) {
2231  Mouse::Show(true);
2233  }
2234  }
2235 
2236  else {
2237  HUDView* hud_view = HUDView::GetInstance();
2238 
2239  if (hud_view && hud_view->GetHUDMode() != HUDView::HUD_MODE_OFF) {
2240  Mouse::Show(true);
2242  }
2243  }
2244 
2245  if (gamescreen && gamescreen->IsFormShown())
2246  return;
2247 
2249 
2250  if (tac_view)
2251  tac_view->DoMouseFrame();
2252 }
2253 
2254 // +--------------------------------------------------------------------+
2255 
2256 void
2258 {
2259  Color::SetFade(0);
2260 
2261  if (gamewin) {
2263  delete gamewin;
2264  gamewin = 0;
2265  }
2266 
2267  switch (splash_index) {
2268  case 0:
2270  loader->SetDataPath(0);
2271  loader->LoadBitmap("matrix.pcx", splash_image);
2272  break;
2273 
2274  case 1:
2275  default:
2277  loader->SetDataPath(0);
2278  loader->LoadBitmap("studio.pcx", splash_image);
2279  break;
2280  }
2281 
2282  int screen_width = GetScreenWidth();
2283  int screen_height = GetScreenHeight();
2284 
2285  gamewin = new(__FILE__,__LINE__) Window(screen, 0, 0, screen_width, screen_height);
2286  splash = new(__FILE__,__LINE__) FadeView(gamewin, 2, 2, 2);
2287 
2289  gamewin->AddView(new(__FILE__,__LINE__) ImgView(gamewin, &splash_image));
2291 }
2292 
2293 // +--------------------------------------------------------------------+
2294 
2295 void
2297 {
2298  if (menuscreen) {
2299  delete menuscreen;
2300  menuscreen = 0;
2301  }
2302 
2303  menuscreen = new(__FILE__,__LINE__) MenuScreen();
2305 }
2306 
2307 // +--------------------------------------------------------------------+
2308 
2309 void
2311 {
2312  if (cmpnscreen) {
2313  delete cmpnscreen;
2314  cmpnscreen = 0;
2315  }
2316 
2317  cmpnscreen = new(__FILE__,__LINE__) CmpnScreen();
2319 }
2320 
2321 // +--------------------------------------------------------------------+
2322 
2323 void
2325 {
2326  if (planscreen) {
2327  delete planscreen;
2328  planscreen = 0;
2329  }
2330 
2331  planscreen = new(__FILE__,__LINE__) PlanScreen();
2333 }
2334 
2335 // +--------------------------------------------------------------------+
2336 
2337 void
2339 {
2340  if (loadscreen) {
2341  delete loadscreen;
2342  loadscreen = 0;
2343  }
2344 
2345  loadscreen = new(__FILE__,__LINE__) LoadScreen();
2347 }
2348 
2349 // +--------------------------------------------------------------------+
2350 
2351 void
2353 {
2354  if (gamescreen) {
2355  delete gamescreen;
2356  gamescreen = 0;
2357  }
2358 
2359  gamescreen = new(__FILE__,__LINE__) GameScreen();
2362 
2363  // initialize player_ship's MFD choices:
2365 }
2366 
2367 // +--------------------------------------------------------------------+
2368 
2369 void
2370 Starshatter::LoadVideoConfig(const char* filename)
2371 {
2372  // set up defaults:
2373  int screen_width = 1024;
2374  int screen_height = 768;
2375  int screen_depth = 32;
2376  int terrain_detail_level = 3;
2377  bool shadows_enabled = true;
2378  bool spec_maps_enabled = true;
2379  bool bump_maps_enabled = true;
2380  bool vertex_shader = true;
2381  bool pixel_shader = true;
2382  float depth_bias = video_settings->depth_bias;
2383 
2384  max_tex_size = 2048;
2385 
2386  if (MachineInfo::GetCpuSpeed() >= 1000 && MachineInfo::GetTotalRam() > 128)
2387  terrain_detail_level = 4;
2388 
2389  Terrain::SetDetailLevel(terrain_detail_level);
2390 
2391  // read the config file:
2392  BYTE* block = 0;
2393  int blocklen = 0;
2394 
2395  FILE* f = ::fopen(filename, "rb");
2396 
2397  if (f) {
2398  ::fseek(f, 0, SEEK_END);
2399  blocklen = ftell(f);
2400  ::fseek(f, 0, SEEK_SET);
2401 
2402  block = new(__FILE__,__LINE__) BYTE[blocklen+1];
2403  block[blocklen] = 0;
2404 
2405  ::fread(block, blocklen, 1, f);
2406  ::fclose(f);
2407  }
2408 
2409  if (blocklen == 0)
2410  return;
2411 
2412  Parser parser(new(__FILE__,__LINE__) BlockReader((const char*) block, blocklen));
2413  Term* term = parser.ParseTerm();
2414 
2415  if (!term) {
2416  Print("ERROR: could not parse '%s'.\n", filename);
2417  exit(-3);
2418  }
2419  else {
2420  TermText* file_type = term->isText();
2421  if (!file_type || file_type->value() != "VIDEO") {
2422  Print("WARNING: invalid %s file. Using defaults\n", filename);
2423  return;
2424  }
2425  }
2426 
2427  do {
2428  delete term;
2429 
2430  term = parser.ParseTerm();
2431 
2432  if (term) {
2433  TermDef* def = term->isDef();
2434  if (def) {
2435  if (def->name()->value() == "width") {
2436  int w;
2437  GetDefNumber(w, def, filename);
2438 
2439  switch (w) {
2440  case 800:
2441  screen_width = 800;
2442  screen_height = 600;
2443  break;
2444 
2445  case 1024:
2446  screen_width = 1024;
2447  screen_height = 768;
2448  break;
2449 
2450  case 1152:
2451  screen_width = 1152;
2452  screen_height = 864;
2453  break;
2454 
2455  case 1280:
2456  screen_width = 1280;
2457  screen_height = 960;
2458  break;
2459 
2460  case 1440:
2461  screen_width = 1440;
2462  screen_height = 900;
2463  break;
2464 
2465  default:
2466  screen_width = w;
2467  screen_height = (w*3)/4;
2468  break;
2469  }
2470  }
2471 
2472  else if (def->name()->value() == "height") {
2473  int h;
2474  GetDefNumber(h, def, filename);
2475 
2476  if (screen_width == 1280 && (h == 800 || h == 1024))
2477  screen_height = h;
2478  else if (screen_width == 1600 && (h == 900 || h == 1200))
2479  screen_height = h;
2480  }
2481 
2482  else if (def->name()->value() == "depth" ||
2483  def->name()->value() == "bpp") {
2484 
2485  int bpp;
2486  GetDefNumber(bpp, def, filename);
2487 
2488  switch (bpp) {
2489  case 8:
2490  case 16:
2491  case 24:
2492  case 32:
2493  screen_depth = bpp;
2494  break;
2495 
2496  default:
2497  Print("WARNING: Invalid screen bpp (%d) in '%s'\n", bpp, filename);
2498  screen_depth = 8;
2499  break;
2500  }
2501  }
2502 
2503  else if (def->name()->value() == "max_tex") {
2504  int n;
2505  GetDefNumber(n, def, filename);
2506  if (n >= 64 && n <= 4096)
2507  max_tex_size = n;
2508  }
2509 
2510  else if (def->name()->value() == "gamma") {
2511  int level;
2512  GetDefNumber(level, def, filename);
2513  if (level >= 0 && level <= 255)
2514  gamma = level;
2515  }
2516 
2517  else if (def->name()->value() == "terrain_detail_level") {
2518  GetDefNumber(terrain_detail_level, def, filename);
2519  Terrain::SetDetailLevel(terrain_detail_level);
2520  }
2521 
2522  else if (def->name()->value() == "terrain_texture_enable") {
2523  bool enable;
2524  GetDefBool(enable, def, filename);
2525 
2526  // no longer supported!
2527  }
2528 
2529  else if (def->name()->value() == "shadows") {
2530  GetDefBool(shadows_enabled, def, filename);
2531  }
2532 
2533  else if (def->name()->value() == "spec_maps") {
2534  GetDefBool(spec_maps_enabled, def, filename);
2535  }
2536 
2537  else if (def->name()->value() == "bump_maps") {
2538  GetDefBool(bump_maps_enabled, def, filename);
2539  }
2540 
2541  else if (def->name()->value() == "vertex_shader") {
2542  GetDefBool(vertex_shader, def, filename);
2543  }
2544 
2545  else if (def->name()->value() == "pixel_shader") {
2546  GetDefBool(pixel_shader, def, filename);
2547  }
2548 
2549  else if (def->name()->value().contains("bias")) {
2550  GetDefNumber(depth_bias, def, filename);
2551  }
2552 
2553  else if (def->name()->value() == "flare") {
2554  bool b;
2555  GetDefBool(b, def, filename);
2556  lens_flare = b;
2557  }
2558 
2559  else if (def->name()->value() == "corona") {
2560  bool b;
2561  GetDefBool(b, def, filename);
2562  corona = b;
2563  }
2564 
2565  else if (def->name()->value() == "nebula") {
2566  bool b;
2567  GetDefBool(b, def, filename);
2568  nebula = b;
2569  }
2570 
2571  else if (def->name()->value() == "dust") {
2572  GetDefNumber(dust, def, filename);
2573  }
2574 
2575  else if (def->name()->value().indexOf("cam_range") == 0) {
2576  double range_max = 0;
2577  GetDefNumber(range_max, def, filename);
2578  CameraDirector::SetRangeLimit(range_max);
2579  }
2580  }
2581  else {
2582  Print("WARNING: term ignored in '%s'\n", filename);
2583  term->print();
2584  }
2585  }
2586  }
2587  while (term);
2588 
2589  loader->ReleaseBuffer(block);
2590 
2591  if (video_settings) {
2592  video_settings->fullscreen_mode.width = screen_width;
2593  video_settings->fullscreen_mode.height = screen_height;
2594 
2595  if (screen_depth == 16)
2597  else
2599 
2600  video_settings->shadows = shadows_enabled;
2601  video_settings->specmaps = spec_maps_enabled;
2602  video_settings->bumpmaps = bump_maps_enabled;
2603  video_settings->enable_vs = vertex_shader;
2604  video_settings->enable_ps = pixel_shader;
2605  video_settings->depth_bias = depth_bias;
2606  }
2607 
2608  if (video) {
2609  video->SetShadowEnabled(shadows_enabled);
2610  video->SetSpecMapEnabled(spec_maps_enabled);
2611  video->SetBumpMapEnabled(bump_maps_enabled);
2612  }
2613 }
2614 
2615 // +--------------------------------------------------------------------+
2616 
2617 void
2618 Starshatter::SaveVideoConfig(const char* filename)
2619 {
2620  if (!video_settings)
2621  return;
2622 
2623  FILE* f = fopen(filename, "w");
2624  if (f) {
2625  fprintf(f, "VIDEO\n\n");
2626  fprintf(f, "width: %4d\n", video_settings->fullscreen_mode.width);
2627  fprintf(f, "height: %4d\n", video_settings->fullscreen_mode.height);
2628  fprintf(f, "depth: %4d\n", video_settings->fullscreen_mode.format == VideoMode::FMT_R5G6B5 ? 16 : 32);
2629  fprintf(f, "\n");
2630  fprintf(f, "max_tex: %4d\n", max_tex_size);
2631  fprintf(f, "primary3D: %s\n", "true");
2632  fprintf(f, "gamma: %4d\n", gamma);
2633  fprintf(f, "\n");
2634  fprintf(f, "terrain_detail_level: %d\n", Terrain::DetailLevel());
2635  fprintf(f, "terrain_texture_enable: %true\n");
2636  fprintf(f, "\n");
2637 
2638  fprintf(f, "shadows: %s\n", video_settings->shadows ? "true" : "false");
2639  fprintf(f, "spec_maps: %s\n", video_settings->specmaps ? "true" : "false");
2640  fprintf(f, "bump_maps: %s\n", video_settings->bumpmaps ? "true" : "false");
2641  fprintf(f, "bias: %f\n", video_settings->depth_bias);
2642  fprintf(f, "\n");
2643 
2644  fprintf(f, "flare: %s\n", lens_flare ? "true" : "false");
2645  fprintf(f, "corona: %s\n", corona ? "true" : "false");
2646  fprintf(f, "nebula: %s\n", nebula ? "true" : "false");
2647  fprintf(f, "dust: %d\n", dust);
2648 
2649  if (CameraDirector::GetRangeLimit() != 300e3)
2650  fprintf(f, " cam_range_max: %f,\n", CameraDirector::GetRangeLimit());
2651 
2652  fclose(f);
2653  }
2654 
2655  video_changed = false;
2656 }
2657 
2658 // +--------------------------------------------------------------------+
2659 
2660 void
2662 {
2663  if (video)
2665 }
2666 
2667 // +--------------------------------------------------------------------+
2668 
2669 void
2670 Starshatter::ExecCutscene(const char* msn_file, const char* path)
2671 {
2672  if (InCutscene() || !msn_file || !*msn_file) return;
2673 
2674  if (!world)
2675  CreateWorld();
2676 
2677  cutscene_mission = new(__FILE__,__LINE__) Mission(0);
2678  cutscene_basetime = StarSystem::GetBaseTime();
2679 
2680  if (cutscene_mission->Load(msn_file, path)) {
2681  Sim* sim = (Sim*) world;
2682 
2683  if (sim) {
2684  bool dynamic = false;
2685  Campaign* campaign = Campaign::GetCampaign();
2686 
2687  if (campaign && campaign->IsDynamic())
2688  dynamic = true;
2689 
2690  sim->UnloadMission();
2691  sim->LoadMission(cutscene_mission, true); // attempt to preload the tex cache
2692  sim->ExecMission();
2693  sim->ShowGrid(false);
2694  player_ship = sim->GetPlayerShip();
2695 
2696  Print(" Cutscene Instantiated.\n");
2697 
2698  UpdateWorld();
2699  }
2700  }
2701  else {
2702  delete cutscene_mission;
2703  cutscene_mission = 0;
2704  cutscene_basetime = 0;
2705  }
2706 }
2707 
2708 void
2710 {
2711  Sim* sim = Sim::GetSim();
2712 
2713  if (cutscene == 0 && !sim->IsNetGame()) {
2714  HUDView* hud_view = HUDView::GetInstance();
2715  if (hud_view)
2716  hud_view->SetHUDMode(HUDView::HUD_MODE_OFF);
2717 
2718  if (sim->GetPlayerShip())
2719  sim->GetPlayerShip()->SetControls(0);
2720 
2721  AudioConfig* audio_cfg = AudioConfig::GetInstance();
2722 
2723  if (audio_cfg) {
2724  cut_efx_volume = audio_cfg->GetEfxVolume();
2725  cut_wrn_volume = audio_cfg->GetWrnVolume();
2726  }
2727 
2729  }
2730 
2731  cutscene++;
2732 }
2733 
2734 void
2736 {
2737  cutscene--;
2738 
2739  if (cutscene == 0) {
2740  DisplayView* disp_view = DisplayView::GetInstance();
2741  if (disp_view)
2742  disp_view->ClearDisplay();
2743 
2744  HUDView* hud_view = HUDView::GetInstance();
2745  if (hud_view)
2746  hud_view->SetHUDMode(HUDView::HUD_MODE_TAC);
2747 
2748  Sim* sim = Sim::GetSim();
2749  if (sim->GetPlayerShip())
2750  sim->GetPlayerShip()->SetControls(sim->GetControls());
2751 
2752  if (cam_dir) {
2753  cam_dir->SetViewOrbital(0);
2755  cam_dir->SetOrbitPoint(PI/4,PI/4,1);
2756  cam_dir->SetOrbitRates(0,0,0);
2757  }
2758 
2759  AudioConfig* audio_cfg = AudioConfig::GetInstance();
2760 
2761  if (audio_cfg) {
2762  audio_cfg->SetEfxVolume(cut_efx_volume);
2763  audio_cfg->SetWrnVolume(cut_wrn_volume);
2764  }
2765 
2767  if (p)
2769  }
2770 }
2771 
2772 void
2774 {
2775  if (cutscene_mission) {
2776  Sim* sim = Sim::GetSim();
2777 
2778  if (sim && sim->GetMission() == cutscene_mission) {
2780  sim->UnloadMission();
2781 
2782  // restore world clock (true => absolute time reference)
2783  if (cutscene_basetime != 0)
2784  StarSystem::SetBaseTime(cutscene_basetime, true);
2785 
2786  delete cutscene_mission;
2787  cutscene_mission = 0;
2788  cutscene_basetime = 0;
2789 
2790  return;
2791  }
2792  }
2793 
2795 }
2796 
2797 Mission*
2799 {
2800  return cutscene_mission;
2801 }
2802 
2803 const char*
2805 {
2806  if (cutscene_mission)
2807  return cutscene_mission->Subtitles();
2808 
2809  return "";
2810 }
2811 
2812 // +--------------------------------------------------------------------+
2813 
2814 int
2816 {
2817  return lobby_mode;
2818 }
2819 
2820 void
2822 {
2823  lobby_mode = mode;
2824 }
2825 
2826 void
2828 {
2829  if (!net_lobby) {
2830  if (lobby_mode == NET_LOBBY_SERVER) {
2832  NetServerConfig* server_config = NetServerConfig::GetInstance();
2833 
2834  if (server_config)
2835  net_lobby = new(__FILE__,__LINE__) NetLobbyServer;
2836  }
2837 
2838  else {
2839  NetClientConfig* client_config = NetClientConfig::GetInstance();
2840  if (client_config)
2841  client_config->Login();
2842 
2844  }
2845  }
2846 
2848 }
2849 
2850 void
2852 {
2853  if (net_lobby) {
2854  if (net_lobby->IsServer()) {
2855  delete net_lobby;
2857  }
2858 
2859  else {
2860  NetClientConfig* client_config = NetClientConfig::GetInstance();
2861  if (client_config)
2862  client_config->Logout();
2863  }
2864 
2865  net_lobby = 0;
2866  }
2867 
2869 }
2870 
2871 void
2873 {
2874  // local server:
2875  NetLobby* lobby = NetLobby::GetInstance();
2876 
2877  if (lobby && lobby->IsServer()) {
2878  lobby->GameStop();
2879  }
2880 
2881  // client connected to remote server:
2882  else {
2884  if (config && config->GetHostRequest()) {
2885  config->Login();
2886 
2887  NetLobbyClient* conn = config->GetConnection();
2888 
2889  if (conn) {
2890  conn->GameStop();
2891  conn->SelectMission(0);
2892  }
2893  }
2894  }
2895 }