std::string FightersDestroyedEvent::CombatLogDescription(int viewing_empire_id) const { if (events.empty()) return ""; const auto& events_to_show = events; auto num_events_remaining = events.size(); std::stringstream ss; // Use show_events_for_empire to show events in this order: viewing empire, // ALL_EMPIRES and then the remainder. auto show_events_for_empire = [&ss, &num_events_remaining, &events_to_show, &viewing_empire_id] (boost::optional<int> show_empire_id) { int count; int target_empire_id; for (const auto& index_and_event : events_to_show) { std::tie(target_empire_id, count) = index_and_event; // Skip if this is not the particular attacker requested if (show_empire_id && *show_empire_id != target_empire_id) continue; // Skip if no particular empire was requested and this empire is the viewing // empire or ALL_EMPIRES if (!show_empire_id && (target_empire_id == viewing_empire_id || target_empire_id == ALL_EMPIRES)) continue; auto count_str = std::to_string(index_and_event.second); auto target_empire_link = EmpireLink(target_empire_id); const auto&& target_link = FighterOrPublicNameLink( viewing_empire_id, INVALID_OBJECT_ID, target_empire_id); if (count == 1) { const std::string& template_str = UserString("ENC_COMBAT_FIGHTER_INCAPACITATED_STR"); ss << str(FlexibleFormat(template_str) % target_empire_link % target_link); }else { const std::string& template_str = UserString("ENC_COMBAT_FIGHTER_INCAPACITATED_REPEATED_STR"); ss << str(FlexibleFormat(template_str) % count_str % target_empire_link % target_link); } if (--num_events_remaining > 0) ss << "\n"; } }; // Sort the events by viewing empire, then ALL_EMPIRES and then other empires. show_events_for_empire(viewing_empire_id); show_events_for_empire(ALL_EMPIRES); show_events_for_empire(boost::none); return ss.str(); }
boost::statechart::result PlayingGame::react(const EndGame& msg) { if (TRACE_EXECUTION) Logger().debugStream() << "(HumanClientFSM) PlayingGame.EndGame"; Message::EndGameReason reason; std::string reason_player_name; ExtractMessageData(msg.m_message, reason, reason_player_name); std::string reason_message; bool error = false; switch (reason) { case Message::LOCAL_CLIENT_DISCONNECT: Client().EndGame(true); reason_message = UserString("SERVER_LOST"); break; case Message::PLAYER_DISCONNECT: Client().EndGame(true); reason_message = boost::io::str(FlexibleFormat(UserString("PLAYER_DISCONNECTED")) % reason_player_name); error = true; break; case Message::YOU_ARE_ELIMINATED: Client().EndGame(true); reason_message = UserString("PLAYER_DEFEATED"); break; } ClientUI::MessageBox(reason_message, error); return transit<IntroMenu>(); }
bool SpecialsPanel::EventFilter(GG::Wnd* w, const GG::WndEvent& event) { if (event.Type() != GG::WndEvent::RClick) return false; const GG::Pt& pt = event.Point(); for (std::map<std::string, StatisticIcon*>::const_iterator it = m_icons.begin(); it != m_icons.end(); ++it) { if (it->second != w) continue; std::string popup_label = boost::io::str(FlexibleFormat(UserString("ENC_LOOKUP")) % UserString(it->first)); GG::MenuItem menu_contents; menu_contents.next_level.push_back(GG::MenuItem(popup_label, 1, false, false)); GG::PopupMenu popup(pt.x, pt.y, ClientUI::GetFont(), menu_contents, ClientUI::TextColor(), ClientUI::WndOuterBorderColor(), ClientUI::WndColor(), ClientUI::EditHiliteColor()); if (!popup.Run() || popup.MenuID() != 1) { return false; break; } ClientUI::GetClientUI()->ZoomToSpecial(it->first); return true; } return false; }
std::string IncapacitationEvent::CombatLogDescription(int viewing_empire_id) const { std::shared_ptr<const UniverseObject> object = GetUniverseObject(object_id); std::string template_str, object_str; int owner_id = object_owner_id; if (!object && object_id < 0) { template_str = UserString("ENC_COMBAT_FIGHTER_INCAPACITATED_STR"); object_str = UserString("OBJ_FIGHTER"); } else if (!object) { template_str = UserString("ENC_COMBAT_UNKNOWN_DESTROYED_STR"); object_str = UserString("ENC_COMBAT_UNKNOWN_OBJECT"); } else if (object->ObjectType() == OBJ_PLANET) { template_str = UserString("ENC_COMBAT_PLANET_INCAPACITATED_STR"); object_str = PublicNameLink(viewing_empire_id, object_id); } else { // ships or other to-be-determined objects... template_str = UserString("ENC_COMBAT_DESTROYED_STR"); object_str = PublicNameLink(viewing_empire_id, object_id); } std::string owner_string = " "; if (const Empire* owner = GetEmpire(owner_id)) owner_string += owner->Name() + " "; std::string object_link = FighterOrPublicNameLink(viewing_empire_id, object_id, object_owner_id); return str(FlexibleFormat(template_str) % owner_string % object_link); }
std::string WeaponFireEvent::CombatLogDetails(int viewing_empire_id) const { const std::string& template_str = UserString("ENC_COMBAT_ATTACK_DETAILS"); if (shield >= 0) return str(FlexibleFormat(template_str) % ShipPartLink(weapon_name) % power % shield % damage); else return str(FlexibleFormat(template_str) % ShipPartLink(weapon_name) % power % UserString("ENC_COMBAT_SHIELD_PIERCED") % damage); }
bool SpecialsPanel::EventFilter(GG::Wnd* w, const GG::WndEvent& event) { if (event.Type() != GG::WndEvent::RClick) return false; const GG::Pt& pt = event.Point(); for (const std::map<std::string, StatisticIcon*>::value_type& entry : m_icons) { if (entry.second != w) continue; bool retval = false; auto zoom_action = [&entry, &retval]() { retval = true; ClientUI::GetClientUI()->ZoomToSpecial(entry.first); }; CUIPopupMenu popup(pt.x, pt.y); std::string popup_label = boost::io::str(FlexibleFormat(UserString("ENC_LOOKUP")) % UserString(entry.first)); popup.AddMenuItem(GG::MenuItem(popup_label, false, false, zoom_action)); popup.Run(); return retval; } return false; }
bool PopulationPanel::EventFilter(GG::Wnd* w, const GG::WndEvent& event) { if (event.Type() != GG::WndEvent::RClick) return false; const GG::Pt& pt = event.Point(); TemporaryPtr<const PopCenter> pc = GetPopCenter(); if (!pc) return false; const std::string& species_name = pc->SpeciesName(); if (species_name.empty()) return false; if (m_meter_stats[0].second != w) return false; GG::MenuItem menu_contents; std::string popup_label = boost::io::str(FlexibleFormat(UserString("ENC_LOOKUP")) % UserString(species_name)); menu_contents.next_level.push_back(GG::MenuItem(popup_label, 1, false, false)); CUIPopupMenu popup(pt.x, pt.y, menu_contents); if (!popup.Run() || popup.MenuID() != 1) return false; ClientUI::GetClientUI()->ZoomToSpecies(species_name); return true; }
boost::statechart::result PlayingGame::react(const EndGame& msg) { if (TRACE_EXECUTION) DebugLogger() << "(HumanClientFSM) PlayingGame.EndGame"; Message::EndGameReason reason; std::string reason_player_name; ExtractMessageData(msg.m_message, reason, reason_player_name); std::string reason_message; bool error = false; switch (reason) { case Message::LOCAL_CLIENT_DISCONNECT: Client().EndGame(true); reason_message = UserString("SERVER_LOST"); break; case Message::PLAYER_DISCONNECT: Client().EndGame(true); reason_message = boost::io::str(FlexibleFormat(UserString("PLAYER_DISCONNECTED")) % reason_player_name); error = true; break; case Message::YOU_ARE_ELIMINATED: Client().EndGame(true); reason_message = UserString("PLAYER_DEFEATED"); break; } ClientUI::MessageBox(reason_message, error); Client().Remove(Client().GetClientUI()->GetMapWnd()); Client().GetClientUI()->GetMapWnd()->RemoveWindows(); Client().Networking().SetHostPlayerID(Networking::INVALID_PLAYER_ID); Client().Networking().SetPlayerID(Networking::INVALID_PLAYER_ID); return transit<IntroMenu>(); }
bool ResourcePanel::EventFilter(GG::Wnd* w, const GG::WndEvent& event) { if (event.Type() != GG::WndEvent::RClick) return false; const GG::Pt& pt = event.Point(); MeterType meter_type = INVALID_METER_TYPE; for (const auto& meter_stat : m_meter_stats) { if (meter_stat.second.get() == w) { meter_type = meter_stat.first; break; } } if (meter_type == INVALID_METER_TYPE) return false; std::string meter_string = boost::lexical_cast<std::string>(meter_type); std::string meter_title; if (UserStringExists(meter_string)) meter_title = UserString(meter_string); if (meter_title.empty()) return false; bool retval = false; auto pedia_zoom_to_article_action = [&meter_string, &retval]() { retval = ClientUI::GetClientUI()->ZoomToMeterTypeArticle(meter_string); }; auto popup = GG::Wnd::Create<CUIPopupMenu>(pt.x, pt.y); std::string popup_label = boost::io::str(FlexibleFormat(UserString("ENC_LOOKUP")) % meter_title); popup->AddMenuItem(GG::MenuItem(popup_label, false, false, pedia_zoom_to_article_action)); popup->Run(); return retval; }
//////////////////////////////////////////////////////////// // PlayingTurn //////////////////////////////////////////////////////////// PlayingTurn::PlayingTurn(my_context ctx) : Base(ctx) { if (TRACE_EXECUTION) Logger().debugStream() << "(HumanClientFSM) PlayingTurn"; Client().Register(Client().m_ui->GetMapWnd()); Client().m_ui->GetMapWnd()->InitTurn(); // TODO: reselect last fleet if stored in save game ui data? Client().m_ui->GetMessageWnd()->HandleGameStatusUpdate( boost::io::str(FlexibleFormat(UserString("TURN_BEGIN")) % CurrentTurn()) + "\n"); Client().m_ui->GetMessageWnd()->HandlePlayerStatusUpdate(Message::PLAYING_TURN, Client().PlayerID()); Client().m_ui->GetPlayerListWnd()->Refresh(); Client().m_ui->GetPlayerListWnd()->HandlePlayerStatusUpdate(Message::PLAYING_TURN, Client().PlayerID()); Client().m_ui->GetMapWnd()->EnableOrderIssuing(Client().EmpireID() != ALL_EMPIRES); // if not controlling an empire, the player (observer) can't do anything // other than waiting for more turn updates. Turn updates received when not // in WaitingForTurnData state will be ignored, and the Turn button is // disabled. So, posting TurnEnded here has the effect of automatically // keeping observers in the WaitingForTurnData state so they can receive // updates from the server. if (Client().EmpireID() == ALL_EMPIRES) post_event(TurnEnded()); else if (GetOptionsDB().Get<bool>("auto-advance-first-turn")) { static bool once = true; if (once) { post_event(AutoAdvanceFirstTurn()); once = false; } } }
boost::statechart::result PlayingGame::react(const EndGame& msg) { if (TRACE_EXECUTION) DebugLogger() << "(HumanClientFSM) PlayingGame.EndGame"; Message::EndGameReason reason; std::string reason_player_name; ExtractMessageData(msg.m_message, reason, reason_player_name); std::string reason_message; bool error = false; switch (reason) { case Message::LOCAL_CLIENT_DISCONNECT: Client().EndGame(true); reason_message = UserString("SERVER_LOST"); break; case Message::PLAYER_DISCONNECT: Client().EndGame(true); reason_message = boost::io::str(FlexibleFormat(UserString("PLAYER_DISCONNECTED")) % reason_player_name); error = true; break; } //Note: Any transit<> transition must occur before the MessageBox(). // MessageBox blocks and can allow other events to transit<> to a new state // which makes this transit fatal. boost::statechart::result retval = transit<IntroMenu>(); ClientUI::MessageBox(reason_message, error); return retval; }
std::string Fleet::GenerateFleetName(const std::vector<int>& ship_ids, int new_fleet_id) { // TODO: Change returned name based on passed ship designs. eg. return "colony fleet" if // ships are colony ships, or "battle fleet" if ships are armed. if (new_fleet_id == INVALID_OBJECT_ID) return UserString("NEW_FLEET_NAME_NO_NUMBER"); return boost::io::str(FlexibleFormat(UserString("NEW_FLEET_NAME")) % boost::lexical_cast<std::string>(new_fleet_id)); }
std::string HullType::StatDescription() const { std::string retval = str(FlexibleFormat(UserString("HULL_DESC")) % m_starlane_speed % m_fuel % m_battle_speed % m_structure); return retval; }
std::string FighterAttackedEvent::CombatLogDescription(int viewing_empire_id) const { std::string attacked_by = FighterOrPublicNameLink(viewing_empire_id, attacked_by_object_id, attacker_owner_empire_id); std::string empire_coloured_attacked_fighter = EmpireColorWrappedText(attacked_owner_id, UserString("OBJ_FIGHTER")); const std::string& template_str = UserString("ENC_COMBAT_ATTACK_SIMPLE_STR"); return str(FlexibleFormat(template_str) % attacked_by % empire_coloured_attacked_fighter); }
bool PopulationPanel::EventFilter(GG::Wnd* w, const GG::WndEvent& event) { if (event.Type() != GG::WndEvent::RClick) return false; const GG::Pt& pt = event.Point(); MeterType meter_type = INVALID_METER_TYPE; for (const std::pair<MeterType, StatisticIcon*>& meter_stat : m_meter_stats) { if (meter_stat.second == w) { meter_type = meter_stat.first; break; } } if (meter_type == INVALID_METER_TYPE) return false; std::string meter_string = boost::lexical_cast<std::string>(meter_type); std::string meter_title; if (UserStringExists(meter_string)) meter_title = UserString(meter_string); std::string species_name; bool retval = false; CUIPopupMenu popup(pt.x, pt.y); std::shared_ptr<const PopCenter> pc = GetPopCenter(); if (meter_type == METER_POPULATION && pc) { species_name = pc->SpeciesName(); if (!species_name.empty()) { auto zoom_species_action = [&retval, &species_name]() { retval = ClientUI::GetClientUI()->ZoomToSpecies(species_name); }; std::string species_label = boost::io::str(FlexibleFormat(UserString("ENC_LOOKUP")) % UserString(species_name)); popup.AddMenuItem(GG::MenuItem(species_label, false, false, zoom_species_action)); } } if (!meter_title.empty()) { auto pedia_meter_type_action = [&retval, &meter_string]() { retval = ClientUI::GetClientUI()->ZoomToMeterTypeArticle(meter_string); }; std::string popup_label = boost::io::str(FlexibleFormat(UserString("ENC_LOOKUP")) % meter_title); popup.AddMenuItem(GG::MenuItem(popup_label, false, false, pedia_meter_type_action)); } popup.Run(); return retval; }
void AIClientApp::HandlePythonAICrash() { // Note: If python crashed during initialization then the AI has not // been associated with a PlayerConnection so the server will not // know the AI's PlayerName. std::stringstream err_msg; err_msg << "AIClientApp failed due to error in python AI code for " << PlayerName() << ". Exiting Soon."; ErrorLogger() << err_msg.str() << " id = " << PlayerID(); Networking().SendMessage( ErrorMessage(str(FlexibleFormat(UserString("ERROR_PYTHON_AI_CRASHED")) % PlayerName()) , true)); }
void CombatLogWnd::CombatLogWndImpl::SetLog(int log_id) { if (!CombatLogAvailable(log_id)) { ErrorLogger() << "Couldn't find combat log with id: " << log_id; return; } m_wnd.DeleteChildren(); GG::Layout* layout = new GG::Layout(m_wnd.UpperLeft().x, m_wnd.UpperLeft().y , m_wnd.Width(), m_wnd.Height() , 1, 1 ///< numrows, numcols , 0, 0 ///< wnd margin, cell margin ); m_wnd.SetLayout(layout); const CombatLog& log = GetCombatLog(log_id); int client_empire_id = HumanClientApp::GetApp()->EmpireID(); // Write Header text DebugLogger() << "Setting log with " << log.combat_events.size() << " events"; TemporaryPtr<const System> system = GetSystem(log.system_id); const std::string& sys_name = (system ? system->PublicName(client_empire_id) : UserString("ERROR")); AddRow(DecorateLinkText(str(FlexibleFormat(UserString("ENC_COMBAT_LOG_DESCRIPTION_STR")) % LinkTaggedIDText(VarText::SYSTEM_ID_TAG, log.system_id, sys_name) % log.turn) + "\n" )); AddRow(DecorateLinkText(UserString("COMBAT_INITIAL_FORCES"))); AddRow(DecorateLinkText(CountsToText(CountByOwner(log.empire_ids, log.object_ids)))); std::stringstream summary_text; summary_text << std::endl << UserString("COMBAT_SUMMARY_DESTROYED") << std::endl << CountsToText(CountByOwner(log.empire_ids, log.destroyed_object_ids)); AddRow(DecorateLinkText(summary_text.str())); // Write Logs for (std::vector<CombatEventPtr>::const_iterator it = log.combat_events.begin(); it != log.combat_events.end(); ++it) { DebugLogger() << "event debug info: " << it->get()->DebugString(); std::vector<GG::Wnd *> flat_logs = MakeCombatLogPanel(m_font->SpaceWidth()*10, client_empire_id, *it); for (std::vector<GG::Wnd *>::iterator log_it = flat_logs.begin(); log_it != flat_logs.end(); ++log_it) { AddRow(*log_it); } } // Add a dummy row that the layout manager can use to add space. AddRow(DecorateLinkText("")); layout->SetRowStretch(layout->Rows() - 1, 1); HandleWndChanged(); }
std::string StealthChangeEvent::StealthChangeEventDetail::CombatLogDescription(int viewing_empire_id) const { std::string attacker_link = FighterOrPublicNameLink(viewing_empire_id, attacker_id, attacker_empire_id); std::string target_link = FighterOrPublicNameLink(viewing_empire_id, target_id, target_empire_id); std::string empire_link = EmpireLink(target_empire_id); const std::string& template_str = UserString("ENC_COMBAT_STEALTH_DECLOAK_ATTACK"); return str(FlexibleFormat(template_str) % attacker_link % target_link % empire_link); }
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(); return discard_event(); }
std::string WeaponFireEvent::CombatLogDescription(int viewing_empire_id) const { std::string attacker_link = FighterOrPublicNameLink(viewing_empire_id, attacker_id, attacker_owner_id); std::string target_link = FighterOrPublicNameLink(viewing_empire_id, target_id, target_owner_id); const std::string& template_str = UserString("ENC_COMBAT_ATTACK_STR"); return str(FlexibleFormat(template_str) % attacker_link % target_link % damage % bout % round); }
std::string WeaponsPlatformEvent::CombatLogDescription(int viewing_empire_id) const { if (events.empty()) return ""; std::vector<std::string> damaged_target_links; std::vector<std::string> undamaged_target_links; for (const auto& target : events) { if (target.second.empty()) continue; const auto& fire_event(*target.second.begin()); std::string target_public_name( FighterOrPublicNameLink(viewing_empire_id, target.first, fire_event->target_owner_id)); double damage = 0.0f; for (auto attack_it : target.second) { damage += attack_it->damage; } if (damage <= 0.0f) { undamaged_target_links.push_back(target_public_name); } else { damaged_target_links.push_back( str(FlexibleFormat(UserString("ENC_COMBAT_PLATFORM_TARGET_AND_DAMAGE")) % target_public_name % damage)); } } std::string desc = ""; const std::vector<std::string> attacker_link( 1, FighterOrPublicNameLink(viewing_empire_id, attacker_id, attacker_owner_id)); if (!damaged_target_links.empty() ) { desc += FlexibleFormatList(attacker_link, damaged_target_links, UserString("ENC_COMBAT_PLATFORM_DAMAGE_MANY_EVENTS"), UserString("ENC_COMBAT_PLATFORM_DAMAGE_1_EVENTS")).str(); if (!undamaged_target_links.empty()) desc += "\n"; } if (!undamaged_target_links.empty()) { desc += FlexibleFormatList(attacker_link, undamaged_target_links, UserString("ENC_COMBAT_PLATFORM_NO_DAMAGE_MANY_EVENTS"), UserString("ENC_COMBAT_PLATFORM_NO_DAMAGE_1_EVENTS")).str(); } return desc; }
std::string FighterLaunchEvent::CombatLogDescription(int viewing_empire_id) const { std::string launched_from_link = PublicNameLink(viewing_empire_id, launched_from_id); std::string empire_coloured_fighter = EmpireColorWrappedText(fighter_owner_empire_id, UserString("OBJ_FIGHTER")); // launching negative fighters indicates recovery of them by the ship const std::string& template_str = (number_launched >= 0 ? UserString("ENC_COMBAT_LAUNCH_STR") : UserString("ENC_COMBAT_RECOVER_STR")); return str(FlexibleFormat(template_str) % launched_from_link % empire_coloured_fighter % std::abs(number_launched)); }
boost::statechart::result WaitingForTurnData::react(const SaveGameComplete& msg) { if (TRACE_EXECUTION) DebugLogger() << "(HumanClientFSM) WaitingForTurnData.SaveGameComplete"; std::string save_filename; int bytes_written; ExtractMessageData(msg.m_message, save_filename, bytes_written); Client().GetClientUI()->GetMessageWnd()->HandleGameStatusUpdate( boost::io::str(FlexibleFormat(UserString("SERVER_SAVE_COMPLETE")) % save_filename % bytes_written) + "\n"); DebugLogger() << "Save Complete on Server"; return discard_event(); }
void BuildingIndicator::Refresh() { if (!s_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); s_scanline_shader = boost::shared_ptr<ShaderProgram>( ShaderProgram::shaderProgramFactory("", shader_text)); } SetBrowseModeTime(GetOptionsDB().Get<int>("UI.tooltip-delay")); TemporaryPtr<const Building> building = GetBuilding(m_building_id); if (!building) return; ClearBrowseInfoWnd(); if (m_graphic) { delete m_graphic; m_graphic = 0; } if (m_scrap_indicator) { delete m_scrap_indicator; m_scrap_indicator = 0; } if (const BuildingType* type = GetBuildingType(building->BuildingTypeName())) { boost::shared_ptr<GG::Texture> texture = ClientUI::BuildingIcon(type->Name()); m_graphic = new GG::StaticGraphic(texture, GG::GRAPHIC_FITGRAPHIC | GG::GRAPHIC_PROPSCALE); AttachChild(m_graphic); std::string desc = UserString(type->Description()); if (building->GetMeter(METER_STEALTH)) desc = UserString("METER_STEALTH") + boost::io::str(boost::format(": %3.1f\n\n") % building->GetMeter(METER_STEALTH)->Current()) + desc; if (GetOptionsDB().Get<bool>("UI.autogenerated-effects-descriptions") && !type->Effects().empty()) desc += boost::io::str(FlexibleFormat(UserString("ENC_EFFECTS_STR")) % AutoGeneratedDescription(type->Effects())); SetBrowseInfoWnd(boost::shared_ptr<GG::BrowseInfoWnd>( new IconTextBrowseWnd(texture, UserString(type->Name()), desc))); } if (building && building->OrderedScrapped()) { boost::shared_ptr<GG::Texture> scrap_texture = ClientUI::GetTexture(ClientUI::ArtDir() / "misc" / "scrapped.png", true); m_scrap_indicator = new GG::StaticGraphic(scrap_texture, GG::GRAPHIC_FITGRAPHIC | GG::GRAPHIC_PROPSCALE); AttachChild(m_scrap_indicator); } DoLayout(); }
//////////////////////////////////////////////////////////// // PlayingTurn //////////////////////////////////////////////////////////// PlayingTurn::PlayingTurn(my_context ctx) : Base(ctx) { if (TRACE_EXECUTION) DebugLogger() << "(HumanClientFSM) PlayingTurn"; Client().Register(Client().GetClientUI()->GetMapWnd()); Client().GetClientUI()->GetMapWnd()->InitTurn(); Client().GetClientUI()->GetMapWnd()->RegisterWindows(); // only useful at game start but InitTurn() takes a long time, don't want to display windows before content is ready. could go in WaitingForGameStart dtor but what if it is given e.g. an error reaction? // TODO: reselect last fleet if stored in save game ui data? Client().GetClientUI()->GetMessageWnd()->HandleGameStatusUpdate( boost::io::str(FlexibleFormat(UserString("TURN_BEGIN")) % CurrentTurn()) + "\n"); Client().GetClientUI()->GetMessageWnd()->HandlePlayerStatusUpdate(Message::PLAYING_TURN, Client().PlayerID()); Client().GetClientUI()->GetPlayerListWnd()->Refresh(); Client().GetClientUI()->GetPlayerListWnd()->HandlePlayerStatusUpdate(Message::PLAYING_TURN, Client().PlayerID()); if (Client().GetApp()->GetClientType() != Networking::CLIENT_TYPE_HUMAN_OBSERVER) Client().GetClientUI()->GetMapWnd()->EnableOrderIssuing(true); if (Client().GetApp()->GetClientType() == Networking::CLIENT_TYPE_HUMAN_OBSERVER) { // observers can't do anything but wait for the next update, and need to // be back in WaitingForTurnData, so posting TurnEnded here has the effect // of keeping observers in the WaitingForTurnData state so they can receive // updates from the server. post_event(TurnEnded()); } else if (Client().GetApp()->GetClientType() == Networking::CLIENT_TYPE_HUMAN_PLAYER) { if (Client().GetClientUI()->GetMapWnd()->AutoEndTurnEnabled()) { // if in-game-GUI auto turn advance enabled, set auto turn counter to 1 Client().InitAutoTurns(1); } if (Client().AutoTurnsLeft() <= 0 && GetOptionsDB().Get<bool>("auto-quit")) { // if no auto turns left, and supposed to quit after that, quit DebugLogger() << "auto-quit ending game."; std::cout << "auto-quit ending game." << std::endl; Client().EndGame(true); throw HumanClientApp::CleanQuit(); } // if there are still auto turns left, advance the turn automatically, // and decrease the auto turn counter if (Client().AutoTurnsLeft() > 0) { post_event(AdvanceTurn()); Client().DecAutoTurns(); } } }
std::string FightersAttackFightersEvent::CombatLogDescription(int viewing_empire_id) const { if (events.empty()) return ""; const auto& events_to_show = events; auto num_events_remaining = events.size(); std::stringstream ss; // Use show_events_for_empire to show events in this order: viewing empire, ALL_EMPIRES and // then the remainder. auto show_events_for_empire = [&ss, &num_events_remaining, &events_to_show, &viewing_empire_id] (boost::optional<int> show_attacker) { int attacker_empire; int target_empire; for (const auto& index_and_event : events_to_show) { std::tie(attacker_empire, target_empire) = index_and_event.first; // Skip if this is not the particular attacker requested if (show_attacker && *show_attacker != attacker_empire) continue; // Skip if no particular attacker was requested and this empire is the viewing // empire or ALL_EMPIRES if (!show_attacker && (attacker_empire == viewing_empire_id || attacker_empire == ALL_EMPIRES)) continue; auto count = std::to_string(index_and_event.second); const auto&& attacker_link = FighterOrPublicNameLink( viewing_empire_id, INVALID_OBJECT_ID, attacker_empire); const auto&& target_link = FighterOrPublicNameLink( viewing_empire_id, INVALID_OBJECT_ID, target_empire); const std::string& template_str = UserString("ENC_COMBAT_ATTACK_REPEATED_STR"); ss << str(FlexibleFormat(template_str) % count % attacker_link % target_link); if (--num_events_remaining > 0) ss << "\n"; } }; // Sort the events by viewing empire, then ALL_EMPIRES and then other empires. show_events_for_empire(viewing_empire_id); show_events_for_empire(ALL_EMPIRES); show_events_for_empire(boost::none); return ss.str(); }
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(); }
boost::statechart::result PlayingGame::react(const EndGame& msg) { TraceLogger(FSM) << "(HumanClientFSM) PlayingGame.EndGame"; Message::EndGameReason reason; std::string reason_player_name; ExtractEndGameMessageData(msg.m_message, reason, reason_player_name); std::string reason_message; bool error = false; switch (reason) { case Message::LOCAL_CLIENT_DISCONNECT: reason_message = UserString("SERVER_LOST"); break; case Message::PLAYER_DISCONNECT: reason_message = boost::io::str(FlexibleFormat(UserString("PLAYER_DISCONNECTED")) % reason_player_name); error = true; break; } // See reaction_transition_note. auto retval = discard_event(); Client().ResetToIntro(true); ClientUI::MessageBox(reason_message, error); return retval; }
void FieldIcon::RClick(const GG::Pt& pt, GG::Flags<GG::ModKey> mod_keys) { if (!Disabled()) RightClickedSignal(m_field_id); GG::MenuItem menu_contents; TemporaryPtr<const Field> field = GetField(m_field_id); if (!field) return; const std::string& field_type_name = field->FieldTypeName(); if (field_type_name.empty()) return; std::string popup_label = boost::io::str(FlexibleFormat(UserString("ENC_LOOKUP")) % UserString(field_type_name)); menu_contents.next_level.push_back(GG::MenuItem(popup_label, 1, false, false)); GG::PopupMenu popup(pt.x, pt.y, ClientUI::GetFont(), menu_contents, ClientUI::TextColor(), ClientUI::WndOuterBorderColor(), ClientUI::WndColor(), ClientUI::EditHiliteColor()); if (!popup.Run() || popup.MenuID() != 1) return; ClientUI::GetClientUI()->ZoomToFieldType(field_type_name); }
void SystemResourceSummaryBrowseWnd::UpdateAllocation(GG::Y& top) { // adds pairs of labels for allocation of resources in system, starting at vertical position \a top and // updates \a top to be the vertical position after the last entry for (unsigned int i = 0; i < m_allocation_labels_and_amounts.size(); ++i) { DeleteChild(m_allocation_labels_and_amounts[i].first); DeleteChild(m_allocation_labels_and_amounts[i].second); } m_allocation_labels_and_amounts.clear(); TemporaryPtr<const System> system = GetSystem(m_system_id); if (!system || m_resource_type == INVALID_RESOURCE_TYPE) return; m_allocation = 0.0; // add label-value pair for each resource-consuming object in system to indicate amount of resource consumed std::vector<TemporaryPtr<const UniverseObject> > objects = Objects().FindObjects<const UniverseObject>(system->ContainedObjectIDs()); for (std::vector<TemporaryPtr<const UniverseObject> >::const_iterator it = objects.begin(); it != objects.end(); ++it) { TemporaryPtr<const UniverseObject> obj = *it; // display information only for the requested player if (m_empire_id != ALL_EMPIRES && !obj->OwnedBy(m_empire_id)) continue; // if m_empire_id == ALL_EMPIRES, display resource production for all empires. otherwise, skip this resource production if it's not owned by the requested player std::string name = obj->Name(); double allocation = ObjectResourceConsumption(obj, m_resource_type, m_empire_id); // don't add summary entries for objects that consume no resource. (otherwise there would be a loooong pointless list of 0's if (allocation <= 0.0) { if (allocation < 0.0) ErrorLogger() << "object " << obj->Name() << " is reported having negative " << boost::lexical_cast<std::string>(m_resource_type) << " consumption"; continue; } m_allocation += allocation; std::string amount_text = DoubleToString(allocation, 3, false); GG::Label* label = new CUILabel(name, GG::FORMAT_RIGHT); label->MoveTo(GG::Pt(GG::X0, top)); label->Resize(GG::Pt(LabelWidth(), row_height)); AttachChild(label); GG::Label* value = new CUILabel(amount_text); value->MoveTo(GG::Pt(LabelWidth(), top)); value->Resize(GG::Pt(ValueWidth(), row_height)); AttachChild(value); m_allocation_labels_and_amounts.push_back(std::pair<GG::Label*, GG::Label*>(label, value)); top += row_height; } if (m_allocation_labels_and_amounts.empty()) { // add "blank" line to indicate no allocation GG::Label* label = new CUILabel(UserString("NOT_APPLICABLE"), GG::FORMAT_RIGHT); label->MoveTo(GG::Pt(GG::X0, top)); label->Resize(GG::Pt(LabelWidth(), row_height)); AttachChild(label); GG::Label* value = new CUILabel(""); value->MoveTo(GG::Pt(LabelWidth(), top)); value->Resize(GG::Pt(ValueWidth(), row_height)); AttachChild(value); m_allocation_labels_and_amounts.push_back(std::pair<GG::Label*, GG::Label*>(label, value)); top += row_height; } // set consumption / allocation label std::string resource_text = ""; switch (m_resource_type) { case RE_INDUSTRY: resource_text = UserString("INDUSTRY_CONSUMPTION"); break; case RE_RESEARCH: resource_text = UserString("RESEARCH_CONSUMPTION"); break; case RE_TRADE: resource_text = UserString("TRADE_CONSUMPTION"); break; default: resource_text = UserString("UNKNOWN_VALUE_SYMBOL"); break; } std::string system_allocation_text = DoubleToString(m_allocation, 3, false); // for research only, local allocation makes no sense if (m_resource_type == RE_RESEARCH && m_allocation == 0.0) system_allocation_text = UserString("NOT_APPLICABLE"); m_allocation_label->SetText(boost::io::str(FlexibleFormat(UserString("RESOURCE_ALLOCATION_TOOLTIP")) % resource_text % system_allocation_text)); // height of label already added to top outside this function }