////////////////////////////////////////////////// // ResearchWnd // ////////////////////////////////////////////////// ResearchWnd::ResearchWnd(GG::X w, GG::Y h) : GG::Wnd(GG::X0, GG::Y0, w, h, GG::INTERACTIVE | GG::ONTOP), m_research_info_panel(0), m_queue_lb(0), m_tech_tree_wnd(0), m_enabled(false) { m_research_info_panel = new ProductionInfoPanel(GG::X(GetOptionsDB().Get<int>("UI.queue-width")), GG::Y(200), UserString("RESEARCH_INFO_PANEL_TITLE"), UserString("RESEARCH_INFO_RP"), OUTER_LINE_THICKNESS, ClientUI::KnownTechFillColor(), ClientUI::KnownTechTextAndBorderColor()); m_queue_lb = new QueueListBox(GG::X(2), m_research_info_panel->Height(), m_research_info_panel->Width() - 4, ClientSize().y - 4 - m_research_info_panel->Height(), "RESEARCH_QUEUE_ROW", UserString("RESEARCH_QUEUE_PROMPT")); m_queue_lb->SetStyle(GG::LIST_NOSORT | GG::LIST_NOSEL | GG::LIST_USERDELETE); GG::Connect(m_queue_lb->QueueItemMovedSignal, &ResearchWnd::QueueItemMoved, this); GG::Connect(m_queue_lb->LeftClickedSignal, &ResearchWnd::QueueItemClickedSlot, this); GG::Connect(m_queue_lb->DoubleClickedSignal, &ResearchWnd::QueueItemDoubleClickedSlot, this); GG::Pt tech_tree_wnd_size = ClientSize() - GG::Pt(m_research_info_panel->Width(), GG::Y0); m_tech_tree_wnd = new TechTreeWnd(tech_tree_wnd_size.x, tech_tree_wnd_size.y); GG::Connect(m_tech_tree_wnd->AddTechsToQueueSignal, &ResearchWnd::AddTechsToQueueSlot, this); AttachChild(m_research_info_panel); AttachChild(m_queue_lb); AttachChild(m_tech_tree_wnd); SetChildClippingMode(ClipToClient); DoLayout(); }
boost::statechart::result PlayingTurn::react(const SaveGameComplete& msg) { TraceLogger(FSM) << "(HumanClientFSM) PlayingTurn.SaveGameComplete"; std::string save_filename; int bytes_written; ExtractServerSaveGameCompleteMessageData(msg.m_message, save_filename, bytes_written); Client().GetClientUI().GetMessageWnd()->HandleGameStatusUpdate( boost::io::str(FlexibleFormat(UserString("SERVER_SAVE_COMPLETE")) % save_filename % bytes_written) + "\n"); Client().SaveGameCompleted(); // auto quit save has completed, close the app if (Client().GetApp()->GetClientType() == Networking::CLIENT_TYPE_HUMAN_PLAYER && Client().AutoTurnsLeft() <= 0 && GetOptionsDB().Get<bool>("auto-quit")) { DebugLogger(FSM) << "auto-quit save completed, ending game."; Client().ExitApp(0); } return discard_event(); }
Encyclopedia::Encyclopedia() : articles() { try { parse::encyclopedia_articles(*this); } catch (const std::exception& e) { ErrorLogger() << "Failed parsing encyclopedia articles: error: " << e.what(); throw e; } if (GetOptionsDB().Get<bool>("verbose-logging")) { DebugLogger() << "(Category) Encyclopedia Articles:"; for (std::map<std::string, std::vector<EncyclopediaArticle> >::const_iterator category_it = articles.begin(); category_it != articles.end(); ++category_it) { const std::string& category = category_it->first; const std::vector<EncyclopediaArticle>& article_vec = category_it->second; for (std::vector<EncyclopediaArticle>::const_iterator article_it = article_vec.begin(); article_it != article_vec.end(); ++article_it) { DebugLogger() << "(" << UserString(category) << ") : " << UserString(article_it->name); } } } }
////////////////////////////////////////////////// // ProductionWnd // ////////////////////////////////////////////////// ProductionWnd::ProductionWnd(GG::X w, GG::Y h) : GG::Wnd(GG::X0, GG::Y0, w, h, GG::INTERACTIVE | GG::ONTOP), m_production_info_panel(0), m_queue_wnd(0), m_build_designator_wnd(0), m_order_issuing_enabled(false), m_empire_shown_id(ALL_EMPIRES) { //DebugLogger() << "ProductionWindow: app-width: "<< GetOptionsDB().Get<int>("app-width") // << " ; windowed width: " << GetOptionsDB().Get<int>("app-width-windowed"); GG::X queue_width(GetOptionsDB().Get<int>("UI.queue-width")); GG::Y info_height(ClientUI::Pts()*8); m_production_info_panel = new ProductionInfoPanel(UserString("PRODUCTION_WND_TITLE"), UserString("PRODUCTION_INFO_PP"), GG::X0, GG::Y0, queue_width, info_height, "production.InfoPanel"); m_queue_wnd = new ProductionQueueWnd(GG::X0, info_height, queue_width, ClientSize().y - info_height); m_build_designator_wnd = new BuildDesignatorWnd(ClientSize().x, ClientSize().y); SetChildClippingMode(ClipToClient); GG::Connect(m_build_designator_wnd->AddBuildToQueueSignal, &ProductionWnd::AddBuildToQueueSlot, this); GG::Connect(m_build_designator_wnd->BuildQuantityChangedSignal, &ProductionWnd::ChangeBuildQuantitySlot, this); GG::Connect(m_build_designator_wnd->SystemSelectedSignal, SystemSelectedSignal); GG::Connect(m_queue_wnd->GetQueueListBox()->QueueItemMovedSignal, &ProductionWnd::QueueItemMoved, this); GG::Connect(m_queue_wnd->GetQueueListBox()->QueueItemDeletedSignal, &ProductionWnd::DeleteQueueItem, this); GG::Connect(m_queue_wnd->GetQueueListBox()->LeftClickedSignal, &ProductionWnd::QueueItemClickedSlot, this); GG::Connect(m_queue_wnd->GetQueueListBox()->DoubleClickedSignal, &ProductionWnd::QueueItemDoubleClickedSlot, this); GG::Connect(m_queue_wnd->GetQueueListBox()->QueueItemRalliedToSignal, &ProductionWnd::QueueItemRallied, this); GG::Connect(m_queue_wnd->GetQueueListBox()->ShowPediaSignal, &ProductionWnd::ShowPedia, this); GG::Connect(m_queue_wnd->GetQueueListBox()->QueueItemPausedSignal, &ProductionWnd::QueueItemPaused, this); AttachChild(m_production_info_panel); AttachChild(m_queue_wnd); AttachChild(m_build_designator_wnd); }
InGameMenu::InGameMenu(): CUIWnd(UserString("GAME_MENU_WINDOW_TITLE"), GG::INTERACTIVE | GG::MODAL) { m_save_btn = new CUIButton(UserString("GAME_MENU_SAVE")); m_load_btn = new CUIButton(UserString("GAME_MENU_LOAD")); m_options_btn = new CUIButton(UserString("INTRO_BTN_OPTIONS")); m_exit_btn = new CUIButton(UserString("GAME_MENU_RESIGN")); m_done_btn = new CUIButton(UserString("DONE")); AttachChild(m_save_btn); AttachChild(m_load_btn); AttachChild(m_options_btn); AttachChild(m_exit_btn); AttachChild(m_done_btn); GG::Connect(m_save_btn->LeftClickedSignal, &InGameMenu::Save, this); GG::Connect(m_load_btn->LeftClickedSignal, &InGameMenu::Load, this); GG::Connect(m_options_btn->LeftClickedSignal, &InGameMenu::Options, this); GG::Connect(m_exit_btn->LeftClickedSignal, &InGameMenu::Exit, this); GG::Connect(m_done_btn->LeftClickedSignal, &InGameMenu::Done, this); if (!HumanClientApp::GetApp()->SinglePlayerGame()) { // need lobby to load a multiplayer game; menu load of a file is insufficient m_load_btn->Disable(); } if (!HumanClientApp::GetApp()->CanSaveNow()) { m_save_btn->Disable(); m_save_btn->SetBrowseModeTime(GetOptionsDB().Get<int>("UI.tooltip-delay")); m_save_btn->SetBrowseInfoWnd(boost::shared_ptr<GG::BrowseInfoWnd>( new TextBrowseWnd(UserString("BUTTON_DISABLED"), UserString("SAVE_DISABLED_BROWSE_TEXT"), GG::X(400)))); } ResetDefaultPosition(); DoLayout(); }
SpeciesManager::SpeciesManager() { if (s_instance) throw std::runtime_error("Attempted to create more than one SpeciesManager."); s_instance = this; try { parse::species(m_species); } catch (const std::exception& e) { ErrorLogger() << "Failed parsing species: error: " << e.what(); throw e; } if (GetOptionsDB().Get<bool>("verbose-logging")) { DebugLogger() << "Species:"; for (iterator it = begin(); it != end(); ++it) { const Species* s = it->second; DebugLogger() << " ... " << s->Name() << " \t" << (s->Playable() ? "Playable " : " ") << (s->Native() ? "Native " : " ") << (s->CanProduceShips() ? "CanProduceShips " : " ") << (s->CanColonize() ? "CanColonize " : " "); } } }
void HumanClientApp::StartServer() { std::string SERVER_CLIENT_EXE = ServerClientExe(); DebugLogger() << "HumanClientApp::StartServer: " << SERVER_CLIENT_EXE; #ifdef FREEORION_MACOSX // On OSX set environment variable DYLD_LIBRARY_PATH to python framework folder // bundled with app, so the dynamic linker uses the bundled python library. // Otherwise the dynamic linker will look for a correct python lib in system // paths, and if it can't find it, throw an error and terminate! // Setting environment variable here, spawned child processes will inherit it. setenv("DYLD_LIBRARY_PATH", GetPythonHome().string().c_str(), 1); #endif std::vector<std::string> args; std::string ai_config = GetOptionsDB().Get<std::string>("ai-config"); std::string ai_path = GetOptionsDB().Get<std::string>("ai-path"); args.push_back("\"" + SERVER_CLIENT_EXE + "\""); args.push_back("--resource-dir"); args.push_back("\"" + GetOptionsDB().Get<std::string>("resource-dir") + "\""); args.push_back("--log-level"); args.push_back(GetOptionsDB().Get<std::string>("log-level")); if (GetOptionsDB().Get<bool>("test-3d-combat")) args.push_back("--test-3d-combat"); if (ai_path != GetOptionsDB().GetDefaultValueString("ai-path")) { args.push_back("--ai-path"); args.push_back(ai_path); DebugLogger() << "ai-path set to '" << ai_path << "'"; } if (!ai_config.empty()) { args.push_back("--ai-config"); args.push_back(ai_config); DebugLogger() << "ai-config set to '" << ai_config << "'"; } else { DebugLogger() << "ai-config not set."; } m_server_process = Process(SERVER_CLIENT_EXE, args); }
HumanClientApp::HumanClientApp(int width, int height, bool calculate_fps, const std::string& name, int x, int y, bool fullscreen, bool fake_mode_change) : ClientApp(), SDLGUI(width, height, calculate_fps, name, x, y, fullscreen, fake_mode_change), m_fsm(0), m_single_player_game(true), m_game_started(false), m_connected(false), m_auto_turns(0), m_have_window_focus(true) { #ifdef ENABLE_CRASH_BACKTRACE signal(SIGSEGV, SigHandler); #endif #ifdef FREEORION_MACOSX SDL_SetHint(SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK, "1"); #endif m_fsm = new HumanClientFSM(*this); const std::string HUMAN_CLIENT_LOG_FILENAME((GetUserDir() / "freeorion.log").string()); InitLogger(HUMAN_CLIENT_LOG_FILENAME, "Client"); try { DebugLogger() << "GL Version String: " << GetGLVersionString(); } catch (...) { ErrorLogger() << "Unable to get GL Version String?"; } LogDependencyVersions(); boost::shared_ptr<GG::StyleFactory> style(new CUIStyle()); SetStyleFactory(style); SetMinDragTime(0); m_ui = boost::shared_ptr<ClientUI>(new ClientUI()); if ((GetOptionsDB().Get<bool>("UI.sound.music-enabled"))) Sound::GetSound().PlayMusic(GetOptionsDB().Get<std::string>("UI.sound.bg-music"), -1); Sound::GetSound().SetMusicVolume(GetOptionsDB().Get<int>("UI.sound.music-volume")); Sound::GetSound().SetUISoundsVolume(GetOptionsDB().Get<int>("UI.sound.volume")); EnableFPS(); UpdateFPSLimit(); GG::Connect(GetOptionsDB().OptionChangedSignal("show-fps"), &HumanClientApp::UpdateFPSLimit, this); boost::shared_ptr<GG::BrowseInfoWnd> default_browse_info_wnd( new GG::TextBoxBrowseInfoWnd(GG::X(400), ClientUI::GetFont(), GG::Clr(0, 0, 0, 200), ClientUI::WndOuterBorderColor(), ClientUI::TextColor(), GG::FORMAT_LEFT | GG::FORMAT_WORDBREAK, 1)); GG::Wnd::SetDefaultBrowseInfoWnd(default_browse_info_wnd); boost::shared_ptr<GG::Texture> cursor_texture = m_ui->GetTexture(ClientUI::ArtDir() / "cursors" / "default_cursor.png"); SetCursor(boost::shared_ptr<GG::TextureCursor>(new GG::TextureCursor(cursor_texture, GG::Pt(GG::X(6), GG::Y(3))))); RenderCursor(true); EnableKeyPressRepeat(GetOptionsDB().Get<int>("UI.keypress-repeat-delay"), GetOptionsDB().Get<int>("UI.keypress-repeat-interval")); EnableMouseButtonDownRepeat(GetOptionsDB().Get<int>("UI.mouse-click-repeat-delay"), GetOptionsDB().Get<int>("UI.mouse-click-repeat-interval")); GG::Connect(WindowResizedSignal, &HumanClientApp::HandleWindowResize, this); GG::Connect(FocusChangedSignal, &HumanClientApp::HandleFocusChange, this); GG::Connect(WindowMovedSignal, &HumanClientApp::HandleWindowMove, this); /* TODO: Wire these signals if theyare needed GG::Connect(WindowClosingSignal, &HumanClientApp::HandleWindowClosing, this); GG::Connect(WindowClosedSignal, &HumanClientApp::HandleWindowClose, this); */ SetStringtableDependentOptionDefaults(); SetGLVersionDependentOptionDefaults(); this->SetMouseLRSwapped(GetOptionsDB().Get<bool>("UI.swap-mouse-lr")); std::map<std::string, std::map<int, int> > named_key_maps; parse::keymaps(GetResourceDir() / "keymaps.txt", named_key_maps); if (GetOptionsDB().Get<bool>("verbose-logging")) { DebugLogger() << "Keymaps:"; for (std::map<std::string, std::map<int, int> >::const_iterator km_it = named_key_maps.begin(); km_it != named_key_maps.end(); ++km_it) { DebugLogger() << "Keymap name = \"" << km_it->first << "\""; const std::map<int, int>& key_map = km_it->second; for (std::map<int, int>::const_iterator keys_it = key_map.begin(); keys_it != key_map.end(); ++keys_it) DebugLogger() << " " << char(keys_it->first) << " : " << char(keys_it->second); } } std::map<std::string, std::map<int, int> >::const_iterator km_it = named_key_maps.find("TEST"); if (km_it != named_key_maps.end()) { const std::map<int, int> int_key_map = km_it->second; std::map<GG::Key, GG::Key> key_map; for (std::map<int, int>::const_iterator key_int_it = int_key_map.begin(); key_int_it != int_key_map.end(); ++key_int_it) { key_map[GG::Key(key_int_it->first)] = GG::Key(key_int_it->second); } this->SetKeyMap(key_map); } ConnectKeyboardAcceleratorSignals(); InitAutoTurns(GetOptionsDB().Get<int>("auto-advance-n-turns")); if (fake_mode_change && !FramebuffersAvailable()) { ErrorLogger() << "Requested fake mode changes, but the framebuffer opengl extension is not available. Ignoring."; } m_fsm->initiate(); }
void Set(const std::string& option, bool value) { GetOptionsDB().Set(OPTIONS_ROOT + option, value); GetOptionsDB().Commit(); }
bool Get(const std::string& option) const { return GetOptionsDB().Get<bool>(OPTIONS_ROOT + option); }
void FleetButton::PlayFleetButtonOpenSound() { Sound::GetSound().PlaySound(GetOptionsDB().Get<std::string>("UI.sound.fleet-button-click"), true); }
int mainSetupAndRun() { try { int colour_depth = GetOptionsDB().Get<int>("color-depth"); bool fullscreen = GetOptionsDB().Get<bool>("fullscreen"); bool fake_mode_change = GetOptionsDB().Get<bool>("fake-mode-change"); std::pair<int, int> width_height = HumanClientApp::GetWindowWidthHeight(); int width(width_height.first), height(width_height.second); std::pair<int, int> left_top = HumanClientApp::GetWindowLeftTop(); int left(left_top.first), top(left_top.second); int fullscreen_monitor_id = GetOptionsDB().Get<int>("fullscreen-monitor-id"); #ifdef FREEORION_WIN32 # ifdef IDI_ICON1 // set window icon to embedded application icon HWND hwnd; window->getCustomAttribute("WINDOW", &hwnd); HINSTANCE hInst = (HINSTANCE)GetModuleHandle(NULL); SetClassLong (hwnd, GCL_HICON, (LONG)LoadIcon (hInst, MAKEINTRESOURCE (IDI_ICON1))); # endif #endif parse::init(); HumanClientApp app(width_height.first, width_height.second, true, "FreeOrion " + FreeOrionVersionString(), left, top, fullscreen, fake_mode_change); if (GetOptionsDB().Get<bool>("quickstart")) { // immediately start the server, establish network connections, and // go into a single player game, using default universe options (a // standard quickstart, without requiring the user to click the // quickstart button). app.NewSinglePlayerGame(true); // acceptable to call before app() } std::string load_filename = GetOptionsDB().Get<std::string>("load"); if (!load_filename.empty()) { // immediately start the server, establish network connections, and // go into a single player game, loading the indicated file // (without requiring the user to click the load button). app.LoadSinglePlayerGame(load_filename); // acceptable to call before app() } // run rendering loop app(); // calls GUI::operator() which calls SDLGUI::Run() which starts rendering loop } catch (const HumanClientApp::CleanQuit&) { // do nothing std::cout << "mainSetupAndRun caught CleanQuit" << std::endl; } catch (const std::invalid_argument& e) { ErrorLogger() << "main() caught exception(std::invalid_argument): " << e.what(); std::cerr << "main() caught exception(std::invalid_arg): " << e.what() << std::endl; } catch (const std::runtime_error& e) { ErrorLogger() << "main() caught exception(std::runtime_error): " << e.what(); std::cerr << "main() caught exception(std::runtime_error): " << e.what() << std::endl; } catch (const boost::io::format_error& e) { ErrorLogger() << "main() caught exception(boost::io::format_error): " << e.what(); std::cerr << "main() caught exception(boost::io::format_error): " << e.what() << std::endl; } catch (const GG::ExceptionBase& e) { ErrorLogger() << "main() caught exception(" << e.type() << "): " << e.what(); std::cerr << "main() caught exception(" << e.type() << "): " << e.what() << std::endl; } catch (const std::exception& e) { ErrorLogger() << "main() caught exception(std::exception): " << e.what(); std::cerr << "main() caught exception(std::exception): " << e.what() << std::endl; } catch (...) { ErrorLogger() << "main() caught unknown exception."; std::cerr << "main() caught unknown exception." << std::endl; } return 0; }
void HumanClientApp::Autosave() { // autosave only on appropriate turn numbers, and when enabled for current // game type (single vs. multiplayer) int autosave_turns = GetOptionsDB().Get<int>("autosave.turns"); if (autosave_turns < 1) return; // avoid divide by zero if (CurrentTurn() % autosave_turns != 0 && CurrentTurn() != 1) return; // turns divisible by autosave_turns, and first turn, have autosaves done if (m_single_player_game && !GetOptionsDB().Get<bool>("autosave.single-player")) return; if (!m_single_player_game && !GetOptionsDB().Get<bool>("autosave.multiplayer")) return; const char* legal_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_-"; // get empire name, filtered for filename acceptability int client_empire_id = EmpireID(); const Empire* empire = GetEmpire(client_empire_id); std::string empire_name; if (empire) empire_name = empire->Name(); else empire_name = UserString("OBSERVER"); std::string::size_type first_good_empire_char = empire_name.find_first_of(legal_chars); if (first_good_empire_char == std::string::npos) { empire_name.clear(); } else { std::string::size_type first_bad_empire_char = empire_name.find_first_not_of(legal_chars, first_good_empire_char); empire_name = empire_name.substr(first_good_empire_char, first_bad_empire_char - first_good_empire_char); } // get player name, also filtered std::string player_name; if (empire) player_name = empire->PlayerName(); std::string::size_type first_good_player_char = player_name.find_first_of(legal_chars); if (first_good_player_char == std::string::npos) { player_name.clear(); } else { std::string::size_type first_bad_player_char = player_name.find_first_not_of(legal_chars, first_good_player_char); player_name = player_name.substr(first_good_player_char, first_bad_player_char - first_good_player_char); } // select filename extension std::string extension; if (m_single_player_game) extension = SP_SAVE_FILE_EXTENSION; else extension = MP_SAVE_FILE_EXTENSION; // Add timestamp to autosave generated files std::string datetime_str = FilenameTimestamp(); boost::filesystem::path autosave_dir_path(GetSaveDir() / "auto"); std::string save_filename = boost::io::str(boost::format("FreeOrion_%s_%s_%04d_%s%s") % player_name % empire_name % CurrentTurn() % datetime_str % extension); boost::filesystem::path save_path(autosave_dir_path / save_filename); std::string path_string = PathString(save_path); try { // ensure autosave directory exists if (!exists(autosave_dir_path)) boost::filesystem::create_directories(autosave_dir_path); } catch (const std::exception& e) { ErrorLogger() << "Autosave unable to check / create autosave directory: " << e.what(); std::cerr << "Autosave unable to check / create autosave directory: " << e.what() << std::endl; } // check for and remove excess oldest autosaves int max_autosaves = GetOptionsDB().Get<int>("autosave.limit"); RemoveOldestFiles(max_autosaves, autosave_dir_path); // create new save DebugLogger() << "Autosaving to: " << path_string; try { SaveGame(path_string); } catch (const std::exception& e) { ErrorLogger() << "Autosave failed: " << e.what(); std::cerr << "Autosave failed: " << e.what() << std::endl; } }
std::pair<int, int> HumanClientApp::GetWindowWidthHeight() { int width(800), height(600); bool fullscreen = GetOptionsDB().Get<bool>("fullscreen"); if (!fullscreen) { width = GetOptionsDB().Get<int>("app-width-windowed"); height = GetOptionsDB().Get<int>("app-height-windowed"); return std::make_pair(width, height); } bool reset_fullscreen = GetOptionsDB().Get<bool>("reset-fullscreen-size"); if (!reset_fullscreen) { width = GetOptionsDB().Get<int>("app-width"); height = GetOptionsDB().Get<int>("app-height"); return std::make_pair(width, height); } GetOptionsDB().Set<bool>("reset-fullscreen-size", false); GG::Pt default_resolution = GetDefaultResolutionStatic(GetOptionsDB().Get<int>("fullscreen-monitor-id")); GetOptionsDB().Set("app-width", Value(default_resolution.x)); GetOptionsDB().Set("app-height", Value(default_resolution.y)); GetOptionsDB().Commit(); return std::make_pair(Value(default_resolution.x), Value(default_resolution.y)); }
~ScopedTimerImpl() { if (m_timer.elapsed() * 1000.0 > 1 && ( m_always_output || GetOptionsDB().Get<bool>("verbose-logging"))) Logger().debugStream() << m_name << " time: " << (m_timer.elapsed() * 1000.0); }
///////////////////////////////// // IntroScreen ///////////////////////////////// IntroScreen::IntroScreen() : GG::Wnd(GG::X0, GG::Y0, GG::GUI::GetGUI()->AppWidth(), GG::GUI::GetGUI()->AppHeight(), GG::Flags<GG::WndFlag>()), m_single_player(0), m_quick_start(0), m_multi_player(0), m_load_game(0), m_options(0), m_about(0), m_credits(0), m_exit_game(0), m_credits_wnd(0), m_menu(0), m_splash(0), m_logo(0), m_version(0) { m_menu = new CUIWnd(UserString("INTRO_WINDOW_TITLE"), GG::X1, GG::Y1, MAIN_MENU_WIDTH, MAIN_MENU_HEIGHT, GG::ONTOP | GG::INTERACTIVE); m_splash = new GG::StaticGraphic(GG::X0, GG::Y0, Width(), Height(), ClientUI::GetTexture(ClientUI::ArtDir() / "splash.png"), GG::GRAPHIC_FITGRAPHIC, GG::INTERACTIVE); m_logo = new GG::StaticGraphic(GG::X0, GG::Y0, Width(), Height() / 10, ClientUI::GetTexture(ClientUI::ArtDir() / "logo.png"), GG::GRAPHIC_FITGRAPHIC | GG::GRAPHIC_PROPSCALE); m_version = new GG::TextControl(GG::X0, GG::Y0, FreeOrionVersionString(), ClientUI::GetFont(), ClientUI::TextColor()); m_version->MoveTo(GG::Pt(Width() - m_version->Width(), Height() - m_version->Height())); AttachChild(m_splash); m_splash->AttachChild(m_logo); m_splash->AttachChild(m_menu); m_splash->AttachChild(m_version); //size calculation consts and variables const GG::X MIN_BUTTON_WIDTH(160); const GG::Y MIN_BUTTON_HEIGHT(40); const GG::X H_BUTTON_MARGIN(16); //horizontal empty space const GG::Y V_BUTTON_MARGIN(16); //vertical empty space GG::X button_width(0); //width of the buttons GG::Y button_height(0); //height of the buttons const GG::X H_MAINMENU_MARGIN(40); //horizontal empty space const GG::Y V_MAINMENU_MARGIN(40); //vertical empty space GG::X mainmenu_width(0); //width of the mainmenu GG::Y mainmenu_height(0); //height of the mainmenu //calculate necessary button width boost::shared_ptr<GG::Font> font = ClientUI::GetFont(); button_width = std::max(font->TextExtent(UserString("INTRO_BTN_SINGLE_PLAYER")).x, button_width); button_width = std::max(font->TextExtent(UserString("INTRO_BTN_QUICK_START")).x, button_width); button_width = std::max(font->TextExtent(UserString("INTRO_BTN_MULTI_PLAYER")).x, button_width); button_width = std::max(font->TextExtent(UserString("INTRO_BTN_LOAD_GAME")).x, button_width); button_width = std::max(font->TextExtent(UserString("INTRO_BTN_OPTIONS")).x, button_width); button_width = std::max(font->TextExtent(UserString("INTRO_BTN_ABOUT")).x, button_width); button_width = std::max(font->TextExtent(UserString("INTRO_BTN_CREDITS")).x, button_width); button_width = std::max(font->TextExtent(UserString("INTRO_BTN_EXIT")).x, button_width); button_width += H_BUTTON_MARGIN; button_width = std::max(MIN_BUTTON_WIDTH, button_width); //calculate necessary button height button_height = std::max(MIN_BUTTON_HEIGHT, font->Height() + V_BUTTON_MARGIN); //culate window width and height mainmenu_width = button_width + H_MAINMENU_MARGIN; mainmenu_height = 8.75 * button_height + V_MAINMENU_MARGIN; // 8 rows + 0.75 before exit button // position menu window GG::Pt ul(Width() * GetOptionsDB().Get<double>("UI.main-menu.x") - mainmenu_width/2, Height() * GetOptionsDB().Get<double>("UI.main-menu.y") - mainmenu_height/2); GG::Pt lr(Width() * GetOptionsDB().Get<double>("UI.main-menu.x") + mainmenu_width/2, Height() * GetOptionsDB().Get<double>("UI.main-menu.y") + mainmenu_height/2); m_menu->SizeMove(ul, lr); //create buttons GG::Y button_y(12); //relativ buttonlocation GG::X button_x(15); m_single_player = new CUIButton(button_x, button_y, button_width, UserString("INTRO_BTN_SINGLE_PLAYER")); button_y += button_height; m_quick_start = new CUIButton(button_x, button_y, button_width, UserString("INTRO_BTN_QUICK_START")); button_y += button_height; m_multi_player = new CUIButton(button_x, button_y, button_width, UserString("INTRO_BTN_MULTI_PLAYER")); button_y += button_height; m_load_game = new CUIButton(button_x, button_y, button_width, UserString("INTRO_BTN_LOAD_GAME")); button_y += button_height; m_options = new CUIButton(button_x, button_y, button_width, UserString("INTRO_BTN_OPTIONS")); button_y += button_height; m_about = new CUIButton(button_x, button_y, button_width, UserString("INTRO_BTN_ABOUT")); button_y += button_height; m_credits = new CUIButton(button_x, button_y, button_width, UserString("INTRO_BTN_CREDITS")); button_y += 1.75 * button_height; m_exit_game = new CUIButton(button_x, button_y, button_width, UserString("INTRO_BTN_EXIT")); //attach buttons m_menu->AttachChild(m_single_player); m_menu->AttachChild(m_quick_start); m_menu->AttachChild(m_multi_player); m_menu->AttachChild(m_load_game); m_menu->AttachChild(m_options); m_menu->AttachChild(m_about); m_menu->AttachChild(m_credits); m_menu->AttachChild(m_exit_game); //connect signals and slots GG::Connect(m_single_player->ClickedSignal, &IntroScreen::OnSinglePlayer, this); GG::Connect(m_quick_start->ClickedSignal, &IntroScreen::OnQuickStart, this); GG::Connect(m_multi_player->ClickedSignal, &IntroScreen::OnMultiPlayer, this); GG::Connect(m_load_game->ClickedSignal, &IntroScreen::OnLoadGame, this); GG::Connect(m_options->ClickedSignal, &IntroScreen::OnOptions, this); GG::Connect(m_about->ClickedSignal, &IntroScreen::OnAbout, this); GG::Connect(m_credits->ClickedSignal, &IntroScreen::OnCredits, this); GG::Connect(m_exit_game->ClickedSignal, &IntroScreen::OnExitGame, this); }
void FleetButton::Init(const std::vector<int>& fleet_IDs, SizeType size_type) { //std::cout << "FleetButton::Init" << std::endl; // get fleets std::vector<TemporaryPtr<const Fleet> > fleets; for (std::vector<int>::const_iterator it = fleet_IDs.begin(); it != fleet_IDs.end(); ++it) { TemporaryPtr<const Fleet> fleet = GetFleet(*it); if (!fleet) { ErrorLogger() << "FleetButton::FleetButton couldn't get fleet with id " << *it; continue; } m_fleets.push_back(*it); fleets.push_back(fleet); } // determine owner(s) of fleet(s). Only care whether or not there is more than one owner, as owner // is used to determine colouration int owner_id = ALL_EMPIRES; int multiple_owners = false; if (fleets.empty()) { // leave as ALL_EMPIRES } else if (fleets.size() == 1) { owner_id = (*fleets.begin())->Owner(); } else { owner_id = (*fleets.begin())->Owner(); // use ALL_EMPIRES if there are multiple owners (including no owner and an owner) for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) { TemporaryPtr<const Fleet> fleet = *it; if (fleet->Owner() != owner_id) { owner_id = ALL_EMPIRES; multiple_owners = true; break; } } } // get fleet colour if (multiple_owners) { SetColor(GG::CLR_WHITE); } else if (owner_id == ALL_EMPIRES) { // all ships owned by now empire bool monsters = true; // find if any ship in fleets in button is not a monster for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) { TemporaryPtr<const Fleet> fleet = *it; for (std::set<int>::const_iterator ship_it = fleet->ShipIDs().begin(); ship_it != fleet->ShipIDs().end(); ++ship_it) { if (TemporaryPtr<const Ship> ship = GetShip(*ship_it)) { if (!ship->IsMonster()) { monsters = false; break; } } } } if (monsters) SetColor(GG::CLR_RED); else SetColor(GG::CLR_WHITE); } else { // single empire owner if (const Empire* empire = GetEmpire(owner_id)) SetColor(empire->Color()); else SetColor(GG::CLR_GRAY); // should never be necessary... but just in case } // determine direction button should be rotated to orient along a starlane GLfloat pointing_angle = 0.0f; TemporaryPtr<const Fleet> first_fleet; if (!m_fleets.empty()) first_fleet = *fleets.begin(); if (first_fleet && first_fleet->SystemID() == INVALID_OBJECT_ID && first_fleet->NextSystemID() != INVALID_OBJECT_ID) { int next_sys_id = first_fleet->NextSystemID(); if (TemporaryPtr<const UniverseObject> obj = GetUniverseObject(next_sys_id)) { // fleet is not in a system and has a valid next destination, so can orient it in that direction // fleet icons might not appear on the screen in the exact place corresponding to their // actual universe position, but if they're moving along a starlane, this code will assume // their apparent position will only be different from their true position in a direction // parallel with the starlane, so the direction from their true position to their destination // position can be used to get a direction vector to orient the icon float dest_x = obj->X(), dest_y = obj->Y(); float cur_x = first_fleet->X(), cur_y = first_fleet->Y(); const MapWnd* map_wnd = ClientUI::GetClientUI()->GetMapWnd(); GG::Pt dest = map_wnd->ScreenCoordsFromUniversePosition(dest_x, dest_y); GG::Pt cur = map_wnd->ScreenCoordsFromUniversePosition(cur_x, cur_y); GG::Pt direction_vector = dest - cur; if (direction_vector.x != GG::X0 || direction_vector.y != GG::Y0) pointing_angle = 360.0f / TWO_PI * std::atan2(static_cast<float>(Value(direction_vector.y)), static_cast<float>(Value(direction_vector.x))) + 90; } } // select icon(s) for fleet(s) int num_ships = 0; for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) { TemporaryPtr<const Fleet> fleet = *it; if (fleet) num_ships += fleet->NumShips(); } boost::shared_ptr<GG::Texture> size_texture = FleetSizeIcon(num_ships, size_type); std::vector<boost::shared_ptr<GG::Texture> > head_textures = FleetHeadIcons(fleets, size_type); // add RotatingGraphics for all icons needed if (size_texture) { RotatingGraphic* icon = new RotatingGraphic(size_texture, GG::GRAPHIC_FITGRAPHIC | GG::GRAPHIC_PROPSCALE); icon->SetPhaseOffset(pointing_angle); icon->SetRPM(0.0f); icon->SetColor(this->Color()); m_icons.push_back(icon); Resize(GG::Pt(size_texture->DefaultWidth(), size_texture->DefaultHeight())); AttachChild(icon); } for (std::vector<boost::shared_ptr<GG::Texture> >::const_iterator it = head_textures.begin(); it != head_textures.end(); ++it) { RotatingGraphic* icon = new RotatingGraphic(*it, GG::GRAPHIC_FITGRAPHIC | GG::GRAPHIC_PROPSCALE); icon->SetPhaseOffset(pointing_angle); icon->SetRPM(0.0f); icon->SetColor(this->Color()); m_icons.push_back(icon); if (Width() < (*it)->DefaultWidth()) Resize(GG::Pt((*it)->DefaultWidth(), (*it)->DefaultHeight())); AttachChild(icon); } // set up selection indicator m_selection_indicator = new RotatingGraphic(FleetSelectionIndicatorIcon(), GG::GRAPHIC_FITGRAPHIC | GG::GRAPHIC_PROPSCALE); m_selection_indicator->SetRPM(ClientUI::SystemSelectionIndicatorRPM()); LayoutIcons(); // Scanlines for not currently-visible objects? int empire_id = HumanClientApp::GetApp()->EmpireID(); if (empire_id == ALL_EMPIRES || !GetOptionsDB().Get<bool>("UI.system-fog-of-war")) return; bool at_least_one_fleet_visible = false; for (std::vector<int>::const_iterator it = m_fleets.begin(); it != m_fleets.end(); ++it) { if (GetUniverse().GetObjectVisibilityByEmpire(*it, empire_id) >= VIS_BASIC_VISIBILITY) { at_least_one_fleet_visible = true; break; } } // Create scanline renderer control m_scanline_control = new ScanlineControl(GG::X0, GG::Y0, Width(), Height()); if (!at_least_one_fleet_visible) AttachChild(m_scanline_control); }
bool ShouldOutput(const boost::chrono::nanoseconds & duration) { return (duration >= m_threshold && (m_enable_output || GetOptionsDB().Get<bool>("verbose-logging"))); }
int mainConfigOptionsSetup(const std::vector<std::string>& args) { InitDirs((args.empty() ? "" : *args.begin())); // read and process command-line arguments, if any try { // add entries in options DB that have no other obvious place GetOptionsDB().AddFlag('h', "help", UserStringNop("OPTIONS_DB_HELP"), false); GetOptionsDB().AddFlag('g', "generate-config-xml", UserStringNop("OPTIONS_DB_GENERATE_CONFIG_XML"), false); GetOptionsDB().AddFlag('f', "fullscreen", UserStringNop("OPTIONS_DB_FULLSCREEN"), STORE_FULLSCREEN_FLAG); GetOptionsDB().Add("reset-fullscreen-size", UserStringNop("OPTIONS_DB_RESET_FSSIZE"), true); GetOptionsDB().Add<bool>("fake-mode-change", UserStringNop("OPTIONS_DB_FAKE_MODE_CHANGE"), FAKE_MODE_CHANGE_FLAG); GetOptionsDB().Add<int>("fullscreen-monitor-id", UserStringNop("OPTIONS_DB_FULLSCREEN_MONITOR_ID"), 0, RangedValidator<int>(0, 5)); GetOptionsDB().AddFlag('q', "quickstart", UserStringNop("OPTIONS_DB_QUICKSTART"), false); GetOptionsDB().AddFlag("auto-quit", UserStringNop("OPTIONS_DB_AUTO_QUIT"), false); GetOptionsDB().Add<int>("auto-advance-n-turns", UserStringNop("OPTIONS_DB_AUTO_N_TURNS"), 0, RangedValidator<int>(0, 400), false); GetOptionsDB().Add<std::string>("load", UserStringNop("OPTIONS_DB_LOAD"), "", Validator<std::string>(), false); GetOptionsDB().Add("UI.sound.music-enabled", UserStringNop("OPTIONS_DB_MUSIC_ON"), true); GetOptionsDB().Add("UI.sound.enabled", UserStringNop("OPTIONS_DB_SOUND_ON"), true); GetOptionsDB().Add<std::string>("version-string", UserStringNop("OPTIONS_DB_VERSION_STRING"), FreeOrionVersionString(), Validator<std::string>(), true); GetOptionsDB().AddFlag('r', "render-simple", UserStringNop("OPTIONS_DB_RENDER_SIMPLE"), false); // Add the keyboard shortcuts Hotkey::AddOptions(GetOptionsDB()); // read config.xml and set options entries from it, if present { XMLDoc doc; try { boost::filesystem::ifstream ifs(GetConfigPath()); if (ifs) { doc.ReadDoc(ifs); // reject config files from out-of-date version if (doc.root_node.ContainsChild("version-string") && doc.root_node.Child("version-string").Text() == FreeOrionVersionString()) { GetOptionsDB().SetFromXML(doc); } } } catch (const std::exception&) { std::cerr << UserString("UNABLE_TO_READ_CONFIG_XML") << std::endl; } } // override previously-saved and default options with command line parameters and flags GetOptionsDB().SetFromCommandLine(args); // Handle the case where the resource-dir does not exist anymore // gracefully by resetting it to the standard path into the // application bundle. This may happen if a previous installed // version of FreeOrion was residing in a different directory. if (!boost::filesystem::exists(GetResourceDir()) || !boost::filesystem::exists(GetResourceDir() / "credits.xml") || !boost::filesystem::exists(GetResourceDir() / "data" / "art" / "misc" / "missing.png")) { DebugLogger() << "Resources directory from config.xml missing or does not contain expected files. Resetting to default."; GetOptionsDB().Set<std::string>("resource-dir", ""); // double-check that resetting actually fixed things... if (!boost::filesystem::exists(GetResourceDir()) || !boost::filesystem::exists(GetResourceDir() / "credits.xml") || !boost::filesystem::exists(GetResourceDir() / "data" / "art" / "misc" / "missing.png")) { DebugLogger() << "Default Resources directory missing or does not contain expected files. Cannot start game."; throw std::runtime_error("Unable to load game resources at default location: " + PathString(GetResourceDir()) + " : Install may be broken."); } } // did the player request generation of config.xml, saving the default (or current) options to disk? if (GetOptionsDB().Get<bool>("generate-config-xml")) { try { GetOptionsDB().Commit(); } catch (const std::exception&) { std::cerr << UserString("UNABLE_TO_WRITE_CONFIG_XML") << std::endl; } } if (GetOptionsDB().Get<bool>("render-simple")) { GetOptionsDB().Set<bool>("UI.galaxy-gas-background",false); GetOptionsDB().Set<bool>("UI.galaxy-starfields", false); GetOptionsDB().Set<bool>("show-fps", true); } } catch (const std::invalid_argument& e) { std::cerr << "main() caught exception(std::invalid_argument): " << e.what() << std::endl; boost::this_thread::sleep(boost::posix_time::seconds(3)); return 1; } catch (const std::runtime_error& e) { std::cerr << "main() caught exception(std::runtime_error): " << e.what() << std::endl; boost::this_thread::sleep(boost::posix_time::seconds(3)); return 1; } catch (const std::exception& e) { std::cerr << "main() caught exception(std::exception): " << e.what() << std::endl; boost::this_thread::sleep(boost::posix_time::seconds(3)); return 1; } catch (...) { std::cerr << "main() caught unknown exception." << std::endl; return 1; } return 0; }
void HumanClientApp::NewSinglePlayerGame(bool quickstart) { if (!GetOptionsDB().Get<bool>("force-external-server")) { try { StartServer(); } catch (const std::runtime_error& err) { ErrorLogger() << "HumanClientApp::NewSinglePlayerGame : Couldn't start server. Got error message: " << err.what(); ClientUI::MessageBox(UserString("SERVER_WONT_START"), true); return; } } bool ended_with_ok = false; if (!quickstart) { GalaxySetupWnd galaxy_wnd; galaxy_wnd.Run(); ended_with_ok = galaxy_wnd.EndedWithOk(); } bool failed = false; unsigned int start_time = Ticks(); while (!m_networking.ConnectToLocalHostServer(boost::posix_time::seconds(2))) { if (SERVER_CONNECT_TIMEOUT < Ticks() - start_time) { ClientUI::MessageBox(UserString("ERR_CONNECT_TIMED_OUT"), true); failed = true; break; } } m_connected = !failed; if (!failed && (quickstart || ended_with_ok)) { DebugLogger() << "HumanClientApp::NewSinglePlayerGame : Connected to server"; SinglePlayerSetupData setup_data; setup_data.m_new_game = true; setup_data.m_filename.clear(); // not used for new game // get values stored in options from previous time game was run or // from just having run GalaxySetupWnd // GalaxySetupData setup_data.m_seed = GetOptionsDB().Get<std::string>("GameSetup.seed"); setup_data.m_size = GetOptionsDB().Get<int>("GameSetup.stars"); setup_data.m_shape = GetOptionsDB().Get<Shape>("GameSetup.galaxy-shape"); setup_data.m_age = GetOptionsDB().Get<GalaxySetupOption>("GameSetup.galaxy-age"); setup_data.m_starlane_freq = GetOptionsDB().Get<GalaxySetupOption>("GameSetup.starlane-frequency"); setup_data.m_planet_density = GetOptionsDB().Get<GalaxySetupOption>("GameSetup.planet-density"); setup_data.m_specials_freq = GetOptionsDB().Get<GalaxySetupOption>("GameSetup.specials-frequency"); setup_data.m_monster_freq = GetOptionsDB().Get<GalaxySetupOption>("GameSetup.monster-frequency"); setup_data.m_native_freq = GetOptionsDB().Get<GalaxySetupOption>("GameSetup.native-frequency"); setup_data.m_ai_aggr = GetOptionsDB().Get<Aggression>("GameSetup.ai-aggression"); // SinglePlayerSetupData contains a map of PlayerSetupData, for // the human and AI players. Need to compile this information // from the specified human options and number of requested AIs // Human player setup data first PlayerSetupData human_player_setup_data; human_player_setup_data.m_player_name = GetOptionsDB().Get<std::string>("GameSetup.player-name"); human_player_setup_data.m_empire_name = GetOptionsDB().Get<std::string>("GameSetup.empire-name"); // DB stores index into array of available colours, so need to get that array to look up value of index. // if stored value is invalid, use a default colour const std::vector<GG::Clr>& empire_colours = EmpireColors(); int colour_index = GetOptionsDB().Get<int>("GameSetup.empire-color"); if (colour_index >= 0 && colour_index < static_cast<int>(empire_colours.size())) human_player_setup_data.m_empire_color = empire_colours[colour_index]; else human_player_setup_data.m_empire_color = GG::CLR_GREEN; human_player_setup_data.m_starting_species_name = GetOptionsDB().Get<std::string>("GameSetup.starting-species"); if (human_player_setup_data.m_starting_species_name == "1") human_player_setup_data.m_starting_species_name = "SP_HUMAN"; // kludge / bug workaround for bug with options storage and retreival. Empty-string options are stored, but read in as "true" boolean, and converted to string equal to "1" if (!GetSpecies(human_player_setup_data.m_starting_species_name)) { const SpeciesManager& sm = GetSpeciesManager(); if (sm.NumPlayableSpecies() < 1) human_player_setup_data.m_starting_species_name.clear(); else human_player_setup_data.m_starting_species_name = sm.playable_begin()->first; } human_player_setup_data.m_save_game_empire_id = ALL_EMPIRES; // not used for new games human_player_setup_data.m_client_type = Networking::CLIENT_TYPE_HUMAN_PLAYER; // add to setup data players setup_data.m_players.push_back(human_player_setup_data); // AI player setup data. One entry for each requested AI int num_AIs = GetOptionsDB().Get<int>("GameSetup.ai-players"); for (int ai_i = 1; ai_i <= num_AIs; ++ai_i) { PlayerSetupData ai_setup_data; ai_setup_data.m_player_name = "AI_" + boost::lexical_cast<std::string>(ai_i); ai_setup_data.m_empire_name.clear(); // leave blank, to be set by server in Universe::GenerateEmpires ai_setup_data.m_empire_color = GG::CLR_ZERO; // to be set by server ai_setup_data.m_starting_species_name.clear(); // leave blank, to be set by server ai_setup_data.m_save_game_empire_id = ALL_EMPIRES; // not used for new games ai_setup_data.m_client_type = Networking::CLIENT_TYPE_AI_PLAYER; setup_data.m_players.push_back(ai_setup_data); } m_networking.SendMessage(HostSPGameMessage(setup_data)); m_fsm->process_event(HostSPGameRequested()); } else { DebugLogger() << "HumanClientApp::NewSinglePlayerGame killing server due to canceled game or server connection failure"; if (m_networking.Connected()) { DebugLogger() << "HumanClientApp::NewSinglePlayerGame Sending server shutdown message."; m_networking.SendMessage(ShutdownServerMessage(m_networking.PlayerID())); boost::this_thread::sleep(boost::posix_time::seconds(1)); m_networking.DisconnectFromServer(); if (!m_networking.Connected()) DebugLogger() << "HumanClientApp::NewSinglePlayerGame Disconnected from server."; else ErrorLogger() << "HumanClientApp::NewSinglePlayerGame Unexpectedly still connected to server...?"; } KillServer(); } }
void HumanClientApp::LoadSinglePlayerGame(std::string filename/* = ""*/) { DebugLogger() << "HumanClientApp::LoadSinglePlayerGame"; if (!filename.empty()) { if (!exists(FilenameToPath(filename))) { std::string msg = "HumanClientApp::LoadSinglePlayerGame() given a nonexistent file \"" + filename + "\" to load; aborting."; DebugLogger() << msg; std::cerr << msg << '\n'; abort(); } } else { try { SaveFileDialog sfd(SP_SAVE_FILE_EXTENSION, true); sfd.Run(); if (!sfd.Result().empty()) filename = sfd.Result(); } catch (const std::exception& e) { ClientUI::MessageBox(e.what(), true); } } if (filename.empty()) { DebugLogger() << "HumanClientApp::LoadSinglePlayerGame has empty filename. Aborting load."; return; } // end any currently-playing game before loading new one if (m_game_started) { EndGame(); // delay to make sure old game is fully cleaned up before attempting to start a new one boost::this_thread::sleep(boost::posix_time::seconds(3)); } else { DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() not already in a game, so don't need to end it"; } if (!GetOptionsDB().Get<bool>("force-external-server")) { DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() Starting server"; StartServer(); DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() Server started"; } else { DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() assuming external server will be available"; } DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() Connecting to server"; unsigned int start_time = Ticks(); while (!m_networking.ConnectToLocalHostServer()) { if (SERVER_CONNECT_TIMEOUT < Ticks() - start_time) { ErrorLogger() << "HumanClientApp::LoadSinglePlayerGame() server connecting timed out"; ClientUI::MessageBox(UserString("ERR_CONNECT_TIMED_OUT"), true); KillServer(); return; } } DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() Connected to server"; m_connected = true; m_networking.SetPlayerID(Networking::INVALID_PLAYER_ID); m_networking.SetHostPlayerID(Networking::INVALID_PLAYER_ID); SetEmpireID(ALL_EMPIRES); SinglePlayerSetupData setup_data; // leving GalaxySetupData information default / blank : not used when loading a game setup_data.m_new_game = false; setup_data.m_filename = filename; // leving setup_data.m_players empty : not specified when loading a game, as server will generate from save file m_networking.SendMessage(HostSPGameMessage(setup_data)); m_fsm->process_event(HostSPGameRequested()); }
void SaveGame(const std::string& filename, const ServerSaveGameData& server_save_game_data, const std::vector<PlayerSaveGameData>& player_save_game_data, const Universe& universe, const EmpireManager& empire_manager, const SpeciesManager& species_manager, const CombatLogManager& combat_log_manager, const GalaxySetupData& galaxy_setup_data, bool multiplayer) { ScopedTimer timer("SaveGame: " + filename, true); bool use_binary = GetOptionsDB().Get<bool>("binary-serialization"); DebugLogger() << "SaveGame(" << (use_binary ? "binary" : "zlib-xml") << ") filename: " << filename; GetUniverse().EncodingEmpire() = ALL_EMPIRES; DebugLogger() << "Compiling save empire and preview data"; std::map<int, SaveGameEmpireData> empire_save_game_data = CompileSaveGameEmpireData(empire_manager); SaveGamePreviewData save_preview_data; CompileSaveGamePreviewData(server_save_game_data, player_save_game_data, empire_save_game_data, save_preview_data); // reinterpret save game data as header data for uncompressed header std::vector<PlayerSaveHeaderData> player_save_header_data; for (std::vector<PlayerSaveGameData>::const_iterator it = player_save_game_data.begin(); it != player_save_game_data.end(); ++it) { player_save_header_data.push_back(*it); } try { fs::path path = FilenameToPath(filename); // A relative path should be relative to the save directory. if (path.is_relative()) { path = GetSaveDir()/path; DebugLogger() << "Made save path relative to save dir. Is now: " << path; } if (multiplayer) { // Make sure the path points into our save directory if (!IsInside(path, GetSaveDir())) { path = GetSaveDir() / path.filename(); } } // set up output archive / stream for saving fs::ofstream ofs(path, std::ios_base::binary); if (!ofs) throw std::runtime_error(UNABLE_TO_OPEN_FILE); if (use_binary) { DebugLogger() << "Creating binary oarchive"; freeorion_bin_oarchive boa(ofs); boa << BOOST_SERIALIZATION_NVP(save_preview_data); boa << BOOST_SERIALIZATION_NVP(galaxy_setup_data); boa << BOOST_SERIALIZATION_NVP(server_save_game_data); boa << BOOST_SERIALIZATION_NVP(player_save_header_data); boa << BOOST_SERIALIZATION_NVP(empire_save_game_data); boa << BOOST_SERIALIZATION_NVP(player_save_game_data); boa << BOOST_SERIALIZATION_NVP(empire_manager); boa << BOOST_SERIALIZATION_NVP(species_manager); boa << BOOST_SERIALIZATION_NVP(combat_log_manager); Serialize(boa, universe); DebugLogger() << "Done serializing"; } else { // Two-tier serialization: // main archive is uncompressed serialized header data first // then contains a string for compressed second archive // that contains the main gamestate info // allocate buffers for serialized gamestate DebugLogger() << "Allocating buffers for XML serialization..."; std::string serial_str, compressed_str; try { serial_str.reserve( std::pow(2.0, 29.0)); compressed_str.reserve(std::pow(2.0, 26.0)); } catch (...) { DebugLogger() << "Unable to preallocate full serialization buffers. Attempting serialization with dynamic buffer allocation."; } // wrap buffer string in iostream::stream to receive serialized data typedef boost::iostreams::back_insert_device<std::string> InsertDevice; InsertDevice serial_inserter(serial_str); boost::iostreams::stream<InsertDevice> s_sink(serial_inserter); // create archive with (preallocated) buffer... freeorion_xml_oarchive xoa(s_sink); // serialize main gamestate info xoa << BOOST_SERIALIZATION_NVP(player_save_game_data); xoa << BOOST_SERIALIZATION_NVP(empire_manager); xoa << BOOST_SERIALIZATION_NVP(species_manager); xoa << BOOST_SERIALIZATION_NVP(combat_log_manager); Serialize(xoa, universe); s_sink.flush(); // wrap gamestate string in iostream::stream to extract serialized data typedef boost::iostreams::basic_array_source<char> SourceDevice; SourceDevice source(serial_str.data(), serial_str.size()); boost::iostreams::stream<SourceDevice> s_source(source); // wrap compresed buffer string in iostream::streams to receive compressed string InsertDevice compressed_inserter(compressed_str); boost::iostreams::stream<InsertDevice> c_sink(compressed_inserter); // compression-filter gamestate into compressed string boost::iostreams::filtering_ostreambuf o; o.push(boost::iostreams::zlib_compressor()); o.push(c_sink); boost::iostreams::copy(s_source, o); c_sink.flush(); // write to save file: uncompressed header serialized data, with compressed main archive string at end... freeorion_xml_oarchive xoa2(ofs); // serialize uncompressed save header info xoa2 << BOOST_SERIALIZATION_NVP(save_preview_data); xoa2 << BOOST_SERIALIZATION_NVP(galaxy_setup_data); xoa2 << BOOST_SERIALIZATION_NVP(server_save_game_data); xoa2 << BOOST_SERIALIZATION_NVP(player_save_header_data); xoa2 << BOOST_SERIALIZATION_NVP(empire_save_game_data); // append compressed gamestate info xoa2 << BOOST_SERIALIZATION_NVP(compressed_str); } } catch (const std::exception& e) { ErrorLogger() << UserString("UNABLE_TO_WRITE_SAVE_FILE") << " SaveGame exception: " << ": " << e.what(); throw e; } DebugLogger() << "SaveGame : Successfully wrote save file"; }
bool HumanClientApp::ToggleFullscreen() { bool fs = GetOptionsDB().Get<bool>("fullscreen"); GetOptionsDB().Set<bool>("fullscreen", !fs); Reinitialize(); return true; }
void SpecialsPanel::Update() { //std::cout << "SpecialsPanel::Update" << std::endl; for (std::map<std::string, StatisticIcon*>::iterator it = m_icons.begin(); it != m_icons.end(); ++it) DeleteChild(it->second); m_icons.clear(); // get specials to display TemporaryPtr<const UniverseObject> obj = GetUniverseObject(m_object_id); if (!obj) { ErrorLogger() << "SpecialsPanel::Update couldn't get object with id " << m_object_id; return; } const std::map<std::string, std::pair<int, float> >& specials = obj->Specials(); // get specials and use them to create specials icons // for specials with a nonzero for (std::map<std::string, std::pair<int, float> >::const_iterator it = specials.begin(); it != specials.end(); ++it) { const Special* special = GetSpecial(it->first); StatisticIcon* graphic = 0; if (it->second.second > 0.0f) graphic = new StatisticIcon(ClientUI::SpecialIcon(special->Name()), it->second.second, 2, false); else graphic = new StatisticIcon(ClientUI::SpecialIcon(special->Name())); graphic->SetBrowseModeTime(GetOptionsDB().Get<int>("UI.tooltip-delay")); std::string desc = UserString(special->Description()); if (it->second.second > 0.0f) desc += "\n" + boost::io::str(FlexibleFormat(UserString("SPECIAL_CAPACITY")) % DoubleToString(it->second.second, 2, false)); if (it->second.first > 0) desc += "\n" + boost::io::str(FlexibleFormat(UserString("ADDED_ON_TURN")) % boost::lexical_cast<std::string>(it->second.first)); else desc += "\n" + UserString("ADDED_ON_INITIAL_TURN"); if (GetOptionsDB().Get<bool>("UI.autogenerated-effects-descriptions") && !special->Effects().empty()) { desc += boost::io::str(FlexibleFormat(UserString("ENC_EFFECTS_STR")) % EffectsDescription(special->Effects())); } graphic->SetBrowseInfoWnd(boost::shared_ptr<GG::BrowseInfoWnd>( new IconTextBrowseWnd(ClientUI::SpecialIcon(special->Name()), UserString(special->Name()), desc))); m_icons[it->first] = graphic; graphic->InstallEventFilter(this); } const GG::X AVAILABLE_WIDTH = Width() - EDGE_PAD; GG::X x(EDGE_PAD); GG::Y y(EDGE_PAD); for (std::map<std::string, StatisticIcon*>::iterator it = m_icons.begin(); it != m_icons.end(); ++it) { StatisticIcon* icon = it->second; icon->SizeMove(GG::Pt(x, y), GG::Pt(x,y) + GG::Pt(SPECIAL_ICON_WIDTH, SPECIAL_ICON_HEIGHT)); AttachChild(icon); x += SPECIAL_ICON_WIDTH + EDGE_PAD; if (x + SPECIAL_ICON_WIDTH + EDGE_PAD > AVAILABLE_WIDTH) { x = GG::X(EDGE_PAD); y += SPECIAL_ICON_HEIGHT + EDGE_PAD; } } if (m_icons.empty()) { Resize(GG::Pt(Width(), GG::Y0)); } else { Resize(GG::Pt(Width(), y + SPECIAL_ICON_HEIGHT + EDGE_PAD*2)); } }
ServerConnectWnd::ServerConnectWnd() : CUIWnd(UserString("SCONNECT_WINDOW_TITLE"), (GG::GUI::GetGUI()->AppWidth() - WINDOW_WIDTH) / 2, (GG::GUI::GetGUI()->AppHeight() - WINDOW_HEIGHT) / 2, WINDOW_WIDTH, WINDOW_HEIGHT, GG::INTERACTIVE | GG::MODAL), m_host_or_join_radio_group(0), m_LAN_game_label(0), m_servers_lb(0), m_find_LAN_servers_bn(0), m_internet_game_label(0), m_IP_address_edit(0), m_player_name_edit(0), m_ok_bn(0), m_cancel_bn(0) { Sound::TempUISoundDisabler sound_disabler; boost::shared_ptr<GG::Font> font = ClientUI::GetFont(); GG::TextControl* player_name_label = new GG::TextControl(GG::X0, GG::Y0, GG::X1, GG::Y1, UserString("PLAYER_NAME_LABEL"), font, ClientUI::TextColor(), GG::FORMAT_LEFT); m_player_name_edit = new CUIEdit(GG::X0, GG::Y0, GG::X1, GetOptionsDB().Get<std::string>("multiplayersetup.player-name")); m_host_or_join_radio_group = new GG::RadioButtonGroup(GG::X0, GG::Y0, GG::X1, GG::Y1, GG::VERTICAL); m_host_or_join_radio_group->AddButton(new CUIStateButton(UserString("HOST_GAME_BN"), GG::X0, GG::Y0, GG::X1, GG::Y1, GG::FORMAT_LEFT, GG::SBSTYLE_3D_RADIO)); m_host_or_join_radio_group->AddButton(new CUIStateButton(UserString("JOIN_GAME_BN"), GG::X0, GG::Y0, GG::X1, GG::Y1, GG::FORMAT_LEFT, GG::SBSTYLE_3D_RADIO)); m_LAN_game_label = new GG::TextControl(GG::X0, GG::Y0, UserString("LAN_GAME_LABEL"), font, ClientUI::TextColor(), GG::FORMAT_LEFT); m_servers_lb = new CUIListBox(GG::X0, GG::Y0, GG::X1, GG::Y1); m_servers_lb->SetStyle(GG::LIST_NOSORT | GG::LIST_SINGLESEL); m_find_LAN_servers_bn = new CUIButton(UserString("REFRESH_LIST_BN")); m_internet_game_label = new GG::TextControl(GG::X0, GG::Y0, UserString("INTERNET_GAME_LABEL"), font, ClientUI::TextColor(), GG::FORMAT_LEFT); m_IP_address_edit = new CUIEdit(GG::X0, GG::Y0, GG::X1, GetOptionsDB().Get<std::string>("multiplayersetup.host-address")); m_ok_bn = new CUIButton(UserString("OK")); m_cancel_bn = new CUIButton(UserString("CANCEL")); const GG::X OK_CANCEL_BUTTON_WIDTH(80); const int CONTROL_MARGIN = 5; GG::Layout* layout = new GG::Layout(GG::X0, GG::Y0, GG::X1, GG::Y1, 8, 4, CONTROL_MARGIN); layout->SetMinimumColumnWidth(0, player_name_label->MinUsableSize().x + CONTROL_MARGIN); layout->SetColumnStretch(1, 1.0); layout->SetMinimumColumnWidth(2, OK_CANCEL_BUTTON_WIDTH + CONTROL_MARGIN); layout->SetMinimumColumnWidth(3, OK_CANCEL_BUTTON_WIDTH + CONTROL_MARGIN); layout->SetMinimumRowHeight(0, m_player_name_edit->Height() + CONTROL_MARGIN); layout->SetMinimumRowHeight(1, m_host_or_join_radio_group->MinUsableSize().y); layout->SetMinimumRowHeight(2, m_LAN_game_label->Height() + (2 * CONTROL_MARGIN)); layout->SetRowStretch(3, 1.0); layout->SetMinimumRowHeight(4, m_find_LAN_servers_bn->Height() + CONTROL_MARGIN); layout->SetMinimumRowHeight(5, m_internet_game_label->Height() + CONTROL_MARGIN); layout->SetMinimumRowHeight(6, m_IP_address_edit->Height() + CONTROL_MARGIN); layout->SetMinimumRowHeight(7, m_ok_bn->Height() + CONTROL_MARGIN); layout->Add(player_name_label, 0, 0, 1, 1, GG::ALIGN_VCENTER); layout->Add(m_player_name_edit, 0, 1, 1, 3, GG::ALIGN_VCENTER); layout->Add(m_host_or_join_radio_group, 1, 0, 1, 4); layout->Add(m_LAN_game_label, 2, 0, 1, 4, GG::ALIGN_BOTTOM); layout->Add(m_servers_lb, 3, 0, 1, 4); layout->Add(m_find_LAN_servers_bn, 4, 3); layout->Add(m_internet_game_label, 5, 0, 1, 4); layout->Add(m_IP_address_edit, 6, 0, 1, 4); layout->Add(m_ok_bn, 7, 2); layout->Add(m_cancel_bn, 7, 3); SetLayout(layout); m_LAN_servers = HumanClientApp::GetApp()->Networking().DiscoverLANServers(); Init(); }
int main(int argc, char* argv[]) { InitDirs(argv[0]); std::vector<std::string> args; for (int i = 0; i < argc; ++i) args.push_back(argv[i]); #else int wmain(int argc, wchar_t* argv[], wchar_t* envp[]) { // copy UTF-16 command line arguments to UTF-8 vector std::vector<std::string> args; for (int i = 0; i < argc; ++i) { std::wstring argi16(argv[i]); std::string argi8; utf8::utf16to8(argi16.begin(), argi16.end(), std::back_inserter(argi8)); args.push_back(argi8); } InitDirs((args.empty() ? "" : *args.begin())); #endif try { GetOptionsDB().AddFlag('h', "help", "Print this help message."); // read config.xml and set options entries from it, if present XMLDoc doc; { boost::filesystem::ifstream ifs(GetConfigPath()); if (ifs) { doc.ReadDoc(ifs); GetOptionsDB().SetFromXML(doc); } } GetOptionsDB().SetFromCommandLine(args); if (GetOptionsDB().Get<bool>("help")) { GetOptionsDB().GetUsage(std::cerr); return 0; } parse::init(); ServerApp g_app; g_app(); // Calls ServerApp::Run() to run app (intialization and main process loop) } catch (const std::invalid_argument& e) { Logger().errorStream() << "main() caught exception(std::invalid_arg): " << e.what(); std::cerr << "main() caught exception(std::invalid_arg): " << e.what() << std::endl; return 1; } catch (const std::runtime_error& e) { Logger().errorStream() << "main() caught exception(std::runtime_error): " << e.what(); std::cerr << "main() caught exception(std::runtime_error): " << e.what() << std::endl; return 1; } catch (const std::exception& e) { Logger().errorStream() << "main() caught exception(std::exception): " << e.what(); std::cerr << "main() caught exception(std::exception): " << e.what() << std::endl; return 1; } catch (...) { Logger().errorStream() << "main() caught unknown exception."; std::cerr << "main() caught unknown exception." << std::endl; return 1; } return 0; }
void AutoResolveCombat(CombatInfo& combat_info) { if (combat_info.objects.Empty()) return; const System* system = combat_info.objects.Object<System>(combat_info.system_id); if (!system) Logger().errorStream() << "AutoResolveCombat couldn't get system with id " << combat_info.system_id; else Logger().debugStream() << "AutoResolveCombat at " << system->Name(); if (GetOptionsDB().Get<bool>("verbose-logging")) { Logger().debugStream() << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"; Logger().debugStream() << "AutoResolveCombat objects before resolution: " << combat_info.objects.Dump(); } // reasonably unpredictable but reproducible random seeding const int base_seed = combat_info.objects.begin()->first + CurrentTurn(); // compile list of valid objects to attack or be attacked in this combat std::set<int> valid_target_object_ids; // all objects that can be attacked std::set<int> valid_attacker_object_ids; // all objects that can attack std::map<int, std::set<int> > empire_valid_attacker_object_ids; // objects that can attack that each empire owns float monster_detection = 0.0; for (ObjectMap::iterator it = combat_info.objects.begin(); it != combat_info.objects.end(); ++it) { const UniverseObject* obj = it->second; //Logger().debugStream() << "Considerting object " << obj->Name() << " owned by " << obj->Owner(); if (ObjectCanAttack(obj)) { //Logger().debugStream() << "... can attack"; valid_attacker_object_ids.insert(it->first); empire_valid_attacker_object_ids[obj->Owner()].insert(it->first); } if (ObjectCanBeAttacked(obj)) { //Logger().debugStream() << "... can be attacked"; valid_target_object_ids.insert(it->first); } if (obj->Unowned() && obj->ObjectType() == OBJ_SHIP) monster_detection = std::max(monster_detection, obj->CurrentMeterValue(METER_DETECTION)); } // map from empire to set of IDs of objects that empire's objects // could potentially target. std::map<int, std::set<int> > empire_valid_target_object_ids; // objects that each empire can attack for (std::set<int>::const_iterator target_it = valid_target_object_ids.begin(); target_it != valid_target_object_ids.end(); ++target_it) { int object_id = *target_it; const UniverseObject* obj = combat_info.objects.Object(object_id); //Logger().debugStream() << "Considering attackability of object " << obj->Name() << " owned by " << obj->Owner(); // for all empires, can they attack this object? for (std::set<int>::const_iterator empire_it = combat_info.empire_ids.begin(); empire_it != combat_info.empire_ids.end(); ++empire_it) { int attacking_empire_id = *empire_it; if (attacking_empire_id == ALL_EMPIRES) { if (ObjectAttackableByMonsters(obj, monster_detection)) { //Logger().debugStream() << "object: " << obj->Name() << " attackable by monsters"; empire_valid_target_object_ids[ALL_EMPIRES].insert(object_id); } } else { // call function to find if empires can attack objects... if (ObjectAttackableByEmpire(obj, attacking_empire_id)) { //Logger().debugStream() << "object: " << obj->Name() << " attackable by empire " << attacking_empire_id; empire_valid_target_object_ids[attacking_empire_id].insert(object_id); } } } } // Each combat "round" a randomly-selected object in the battle attacks // something, if it is able to do so. The number of rounds scales with the // number of objects, so the total actions per object is independent of // number of objects in the battle const int NUM_COMBAT_ROUNDS = 3*valid_attacker_object_ids.size(); for (int round = 1; round <= NUM_COMBAT_ROUNDS; ++round) { Seed(base_seed + round); // ensure each combat round produces different results // ensure something can attack and something can be attacked if (valid_attacker_object_ids.empty()) { Logger().debugStream() << "Nothing left can attack; combat over"; break; } if (empire_valid_target_object_ids.empty()) { Logger().debugStream() << "Nothing left can be attacked; combat over"; break; } // empires may have valid targets, but nothing to attack with. If all // empires have no attackers or no valid targers, combat is over bool someone_can_attack_something = false; for (std::map<int, std::set<int> >::const_iterator attacker_it = empire_valid_attacker_object_ids.begin(); attacker_it != empire_valid_attacker_object_ids.end(); ++attacker_it) { if (empire_valid_target_object_ids.find(attacker_it->first) != empire_valid_target_object_ids.end()) { someone_can_attack_something = true; break; } } if (!someone_can_attack_something) { Logger().debugStream() << "No empire has valid targets and something to attack with; combat over."; break; } Logger().debugStream() << "Combat at " << system->Name() << " (" << combat_info.system_id << ") Round " << round; // select attacking object in battle SmallIntDistType attacker_id_num_dist = SmallIntDist(0, valid_attacker_object_ids.size() - 1); std::set<int>::const_iterator attacker_it = valid_attacker_object_ids.begin(); std::advance(attacker_it, attacker_id_num_dist()); assert(attacker_it != valid_attacker_object_ids.end()); int attacker_id = *attacker_it; UniverseObject* attacker = combat_info.objects.Object(attacker_id); if (!attacker) { Logger().errorStream() << "AutoResolveCombat couldn't get object with id " << attacker_id; continue; } Logger().debugStream() << "Attacker: " << attacker->Name(); Ship* attack_ship = universe_object_cast<Ship*>(attacker); Planet* attack_planet = universe_object_cast<Planet*>(attacker); // loop over weapons of attacking object. each gets a shot at a // randomly selected target object std::vector<PartAttackInfo> weapons; if (attack_ship) { weapons = ShipWeaponsStrengths(attack_ship); for (std::vector<PartAttackInfo>::const_iterator part_it = weapons.begin(); part_it != weapons.end(); ++part_it) { Logger().debugStream() << "weapon: " << part_it->part_type_name << " attack: " << part_it->part_attack; } } else if (attack_planet) { // treat planet defenses as short range weapons.push_back(PartAttackInfo(PC_SHORT_RANGE, "", attack_planet->CurrentMeterValue(METER_DEFENSE))); } if (weapons.empty()) { Logger().debugStream() << "no weapons' can't attack"; continue; // no ability to attack! } for (std::vector<PartAttackInfo>::const_iterator weapon_it = weapons.begin(); weapon_it != weapons.end(); ++weapon_it) { // select object from valid targets for this object's owner TODO: with this weapon... Logger().debugStream() << "Attacking with weapon " << weapon_it->part_type_name << " with power " << weapon_it->part_attack; // get valid targets set for attacker owner. need to do this for // each weapon that is attacking, as the previous shot might have // destroyed something int attacker_owner_id = attacker->Owner(); std::map<int, std::set<int> >::iterator target_vec_it = empire_valid_target_object_ids.find(attacker_owner_id); if (target_vec_it == empire_valid_target_object_ids.end()) { Logger().debugStream() << "No targets for attacker with id: " << attacker_owner_id; break; } const std::set<int>& valid_target_ids = target_vec_it->second; if (valid_target_ids.empty()) break; // should be redundant with this entry being erased when emptied // select target object SmallIntDistType target_id_num_dist = SmallIntDist(0, valid_target_ids.size() - 1); std::set<int>::const_iterator target_it = valid_target_ids.begin(); std::advance(target_it, target_id_num_dist()); assert(target_it != valid_target_ids.end()); int target_id = *target_it; UniverseObject* target = combat_info.objects.Object(target_id); if (!target) { Logger().errorStream() << "AutoResolveCombat couldn't get target object with id " << target_id; continue; } Logger().debugStream() << "Target: " << target->Name(); // do actual attacks, and mark attackers as valid targets for attacked object's owners if (attack_ship) { if (Ship* target_ship = universe_object_cast<Ship*>(target)) { AttackShipShip(attack_ship, weapon_it->part_attack, target_ship, combat_info.damaged_object_ids); empire_valid_target_object_ids[target_ship->Owner()].insert(attacker_id); } else if (Planet* target_planet = universe_object_cast<Planet*>(target)) { AttackShipPlanet(attack_ship, weapon_it->part_attack, target_planet, combat_info.damaged_object_ids); empire_valid_target_object_ids[target_planet->Owner()].insert(attacker_id); } } else if (attack_planet) { if (Ship* target_ship = universe_object_cast<Ship*>(target)) { AttackPlanetShip(attack_planet, target_ship, combat_info.damaged_object_ids); empire_valid_target_object_ids[target_ship->Owner()].insert(attacker_id); } else if (Planet* target_planet = universe_object_cast<Planet*>(target)) { AttackPlanetPlanet(attack_planet, target_planet, combat_info.damaged_object_ids); empire_valid_target_object_ids[target_planet->Owner()].insert(attacker_id); } } // check for destruction of target object if (target->ObjectType() == OBJ_SHIP) { if (target->CurrentMeterValue(METER_STRUCTURE) <= 0.0) { Logger().debugStream() << "!! Target Ship is destroyed!"; // object id destroyed combat_info.destroyed_object_ids.insert(target_id); // all empires in battle know object was destroyed for (std::set<int>::const_iterator it = combat_info.empire_ids.begin(); it != combat_info.empire_ids.end(); ++it) { int empire_id = *it; if (empire_id != ALL_EMPIRES) combat_info.destroyed_object_knowers[empire_id].insert(target_id); } // remove destroyed ship's ID from lists of valid attackers and targets valid_attacker_object_ids.erase(target_id); valid_target_object_ids.erase(target_id); // probably not necessary as this set isn't used in this loop for (target_vec_it = empire_valid_target_object_ids.begin(); target_vec_it != empire_valid_target_object_ids.end(); ++target_vec_it) { target_vec_it->second.erase(target_id); } for (target_vec_it = empire_valid_attacker_object_ids.begin(); target_vec_it != empire_valid_attacker_object_ids.end(); ++target_vec_it) { target_vec_it->second.erase(target_id); } // TODO: only erase from owner's entry in this list } } else if (target->ObjectType() == OBJ_PLANET) { if (target->CurrentMeterValue(METER_SHIELD) <= 0.0 && target->CurrentMeterValue(METER_DEFENSE) <= 0.0 && target->CurrentMeterValue(METER_CONSTRUCTION) <= 0.0) { Logger().debugStream() << "!! Target Planet is knocked out of battle"; // remove disabled planet's ID from lists of valid attackers and targets valid_attacker_object_ids.erase(target_id); valid_target_object_ids.erase(target_id); // probably not necessary as this set isn't used in this loop for (target_vec_it = empire_valid_target_object_ids.begin(); target_vec_it != empire_valid_target_object_ids.end(); ++target_vec_it) { target_vec_it->second.erase(target_id); } for (target_vec_it = empire_valid_attacker_object_ids.begin(); target_vec_it != empire_valid_attacker_object_ids.end(); ++target_vec_it) { target_vec_it->second.erase(target_id); } // TODO: only erase from owner's entry in this list } } // check if any empire has no remaining target or attacker objects. // If so, remove that empire's entry std::map<int, std::set<int> > temp = empire_valid_target_object_ids; for (target_vec_it = empire_valid_target_object_ids.begin(); target_vec_it != empire_valid_target_object_ids.end(); ++target_vec_it) { if (target_vec_it->second.empty()) { temp.erase(target_vec_it->first); Logger().debugStream() << "No valid targets left for empire with id: " << target_vec_it->first; } } empire_valid_target_object_ids = temp; temp = empire_valid_attacker_object_ids; for (target_vec_it = empire_valid_attacker_object_ids.begin(); target_vec_it != empire_valid_attacker_object_ids.end(); ++target_vec_it) { if (target_vec_it->second.empty()) { temp.erase(target_vec_it->first); Logger().debugStream() << "No valid attacking objects left for empire with id: " << target_vec_it->first; } } empire_valid_attacker_object_ids = temp; } // end for over weapons } // end for over combat arounds // ensure every participant knows what happened. // TODO: assemble list of objects to copy for each empire. this should // include objects the empire already knows about with standard // visibility system, and also any objects the empire knows are // destroyed or for (std::map<int, ObjectMap>::iterator it = combat_info.empire_known_objects.begin(); it != combat_info.empire_known_objects.end(); ++it) { it->second.Copy(combat_info.objects); } if (GetOptionsDB().Get<bool>("verbose-logging")) Logger().debugStream() << "AutoResolveCombat objects after resolution: " << combat_info.objects.Dump(); }
void FleetButton::Init(const std::vector<int>& fleet_IDs, SizeType size_type) { if (!scanline_shader && GetOptionsDB().Get<bool>("UI.system-fog-of-war")) { boost::filesystem::path shader_path = GetRootDataDir() / "default" / "shaders" / "scanlines.frag"; std::string shader_text; ReadFile(shader_path, shader_text); scanline_shader = boost::shared_ptr<ShaderProgram>( ShaderProgram::shaderProgramFactory("", shader_text)); } // get fleets std::vector<TemporaryPtr<const Fleet> > fleets; for (std::vector<int>::const_iterator it = fleet_IDs.begin(); it != fleet_IDs.end(); ++it) { TemporaryPtr<const Fleet> fleet = GetFleet(*it); if (!fleet) { Logger().errorStream() << "FleetButton::FleetButton couldn't get fleet with id " << *it; continue; } m_fleets.push_back(*it); fleets.push_back(fleet); } // determine owner(s) of fleet(s). Only care whether or not there is more than one owner, as owner // is used to determine colouration int owner_id = ALL_EMPIRES; int multiple_owners = false; if (fleets.empty()) { // leave as ALL_EMPIRES } else if (fleets.size() == 1) { owner_id = (*fleets.begin())->Owner(); } else { owner_id = (*fleets.begin())->Owner(); // use ALL_EMPIRES if there are multiple owners (including no owner and an owner) for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) { TemporaryPtr<const Fleet> fleet = *it; if (fleet->Owner() != owner_id) { owner_id = ALL_EMPIRES; multiple_owners = true; break; } } } // get fleet colour if (multiple_owners) { SetColor(GG::CLR_WHITE); } else if (owner_id == ALL_EMPIRES) { // all ships owned by now empire bool monsters = true; // find if any ship in fleets in button is not a monster for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) { TemporaryPtr<const Fleet> fleet = *it; for (std::set<int>::const_iterator ship_it = fleet->ShipIDs().begin(); ship_it != fleet->ShipIDs().end(); ++ship_it) { if (TemporaryPtr<const Ship> ship = GetShip(*ship_it)) { if (!ship->IsMonster()) { monsters = false; break; } } } } if (monsters) SetColor(GG::CLR_RED); else SetColor(GG::CLR_WHITE); } else { // single empire owner if (const Empire* empire = Empires().Lookup(owner_id)) SetColor(empire->Color()); else SetColor(GG::CLR_GRAY); // should never be necessary... but just in case } // select icon(s) for fleet(s) int num_ships = 0; for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) { TemporaryPtr<const Fleet> fleet = *it; if (fleet) num_ships += fleet->NumShips(); } m_size_icon = FleetSizeIcon(num_ships, size_type); m_head_icons = FleetHeadIcons(fleets, size_type); // resize to fit icon by first determining necessary size, and then resizing GG::X texture_width(0); GG::Y texture_height(0); if (!m_head_icons.empty()) { texture_width = m_head_icons.front()->DefaultWidth(); texture_height = m_head_icons.front()->DefaultHeight(); } if (m_size_icon) { texture_width = std::max(texture_width, m_size_icon->DefaultWidth()); texture_height = std::max(texture_height, m_size_icon->DefaultHeight()); } // determine if fleet icon should be rotated. this should be done if the fleet is moving along // a starlane, which is the case if the fleet is not in a system and has a valid next system GG::Pt direction_vector(GG::X(0), GG::Y(1)); // default, unrotated button orientation TemporaryPtr<const Fleet> first_fleet; if (!m_fleets.empty()) first_fleet = *fleets.begin(); if (first_fleet && first_fleet->SystemID() == INVALID_OBJECT_ID) { int next_sys_id = first_fleet->NextSystemID(); if (TemporaryPtr<const UniverseObject> obj = GetUniverseObject(next_sys_id)) { // fleet is not in a system and has a valid next destination, so can orient it in that direction // fleet icons might not appear on the screen in the exact place corresponding to their // actual universe position, but if they're moving along a starlane, this code will assume // their apparent position will only be different from their true position in a direction // parallel with the starlane, so the direction from their true position to their destination // position can be used to get a direction vector to orient the icon double dest_x = obj->X(), dest_y = obj->Y(); double cur_x = first_fleet->X(), cur_y = first_fleet->Y(); const MapWnd* map_wnd = ClientUI::GetClientUI()->GetMapWnd(); GG::Pt dest = map_wnd->ScreenCoordsFromUniversePosition(dest_x, dest_y); GG::Pt cur = map_wnd->ScreenCoordsFromUniversePosition(cur_x, cur_y); direction_vector = dest - cur; } } // check for unrotated texture if (Value(direction_vector.x) == 0) { // not rotated. can do simple texture blits m_vertex_components.clear(); } else { // texture is rotated, so need some extra math // get rotated corner vetex x and y components (x1, y1, x2, y2, x3, y3, x4, y4) for texture of appropriate size m_vertex_components = VectorAlignedQuadVertices(direction_vector, Value(texture_height), Value(texture_width)); } // size icon according to texture size (average two dimensions) int diameter = static_cast<int>((Value(texture_width) + Value(texture_height)) / 2.0); Resize(GG::Pt(GG::X(diameter), GG::Y(diameter))); // get selection indicator texture m_selection_texture = ClientUI::GetTexture(ClientUI::ArtDir() / "icons" / "fleet" / "fleet_selection.png", true); }
void Sound::Impl::PlaySound(const boost::filesystem::path& path, bool is_ui_sound/* = false*/) { if (!m_initialized || !GetOptionsDB().Get<bool>("UI.sound.enabled") || (is_ui_sound && UISoundsTemporarilyDisabled())) return; std::string filename = PathString(path); ALuint current_buffer; ALenum source_state; ALsizei ogg_freq; FILE *file = nullptr; int m_i; bool found_buffer = false; bool found_source = false; #ifdef FREEORION_WIN32 ov_callbacks callbacks = { (size_t (*)(void *, size_t, size_t, void *)) fread, (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap, (int (*)(void *)) fclose, (long (*)(void *)) ftell }; #endif if (alcGetCurrentContext()) { /* First check if the sound data of the file we want to play is already buffered somewhere */ std::map<std::string, ALuint>::iterator it = m_buffers.find(filename); if (it != m_buffers.end()) { current_buffer = it->second; found_buffer = true; } else { if ((file = fopen(filename.c_str(), "rb")) != nullptr) { // make sure we CAN open it OggVorbis_File ogg_file; vorbis_info *vorbis_info; ALenum ogg_format; #ifdef FREEORION_WIN32 if (!(ov_test_callbacks(file, &ogg_file, nullptr, 0, callbacks))) // check if it's a proper ogg #else if (!(ov_test(file, &ogg_file, nullptr, 0))) // check if it's a proper ogg #endif { ov_test_open(&ogg_file); // it is, now fully open the file /* now we need to take some info we will need later */ vorbis_info = ov_info(&ogg_file, -1); if (vorbis_info->channels == 1) ogg_format = AL_FORMAT_MONO16; else ogg_format = AL_FORMAT_STEREO16; ogg_freq = vorbis_info->rate; ogg_int64_t byte_size = ov_pcm_total(&ogg_file, -1) * vorbis_info->channels * 2; if (byte_size <= 1024 * 1024 * 1024) { /* fill up the buffers and queue them up for the first time */ ALuint sound_handle; alGenBuffers(1, &sound_handle); int loop = 0; RefillBuffer(&ogg_file, ogg_format, ogg_freq, sound_handle, byte_size, loop); current_buffer = sound_handle; found_buffer = true; m_buffers.insert(std::make_pair(filename, sound_handle)); } else { ErrorLogger() << "PlaySound: unable to open file " << filename.c_str() << " too big to buffer. Aborting\n"; } ov_clear(&ogg_file); } else { ErrorLogger() << "PlaySound: unable to open file " << filename.c_str() << " possibly not a .ogg vorbis file. Aborting\n"; } } } if (found_buffer) { /* Now that we have the buffer, we need to find a source to send it to */ for (m_i = 1; m_i < NUM_SOURCES; ++m_i) { // as we're playing sounds we start at 1. 0 is reserved for music alGetSourcei(m_sources[m_i], AL_SOURCE_STATE, &source_state); if ((source_state != AL_PLAYING) && (source_state != AL_PAUSED)) { found_source = true; alSourcei(m_sources[m_i], AL_BUFFER, current_buffer); alSourcePlay(m_sources[m_i]); break; // so that the sound won't block all the sources } } if (!found_source) ErrorLogger() << "PlaySound: Could not find aviable source - playback aborted\n"; } source_state = alGetError(); if (source_state != AL_NONE) ErrorLogger() << "PlaySound: OpenAL ERROR: " << alGetString(source_state); /* it's important to check for errors, as some functions won't work properly if * they're called when there is a unchecked previous error. */ } }
void FleetButton::PlayFleetButtonRolloverSound() { Sound::GetSound().PlaySound(GetOptionsDB().Get<std::string>("UI.sound.fleet-button-rollover"), true); }