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