int UniverseObject::AgeInTurns() const { if (m_created_on_turn == BEFORE_FIRST_TURN) return SINCE_BEFORE_TIME_AGE; if ((m_created_on_turn == INVALID_GAME_TURN) || (CurrentTurn() == INVALID_GAME_TURN)) return INVALID_OBJECT_AGE; return CurrentTurn() - m_created_on_turn; }
void HearthstoneLogTracker::CardReturned( Player player, const string& cardId ) { DBG( "Card returned %s on turn %d: %s", PLAYER_NAMES[ player ], CurrentTurn(), cardId.c_str() ); // Make sure we remove the "Choose One"-cards from the history // if we decide to withdraw them after a second of thought if( !mCardHistoryList.empty() && mCardHistoryList.back().turn == CurrentTurn() && mCardHistoryList.back().player == player && mCardHistoryList.back().cardId == cardId ) { mCardHistoryList.pop_back(); } }
//////////////////////////////////////////////////////////// // 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; } } }
int SitRepPanel::NumVisibleSitrepsThisTurn() const { int count = 0; int client_empire_id = HumanClientApp::GetApp()->EmpireID(); // which empires to count sitreps for? std::vector<int> empire_ids; if (HumanClientApp::GetApp()->Empires().Lookup(client_empire_id)) { empire_ids.push_back(client_empire_id); } else { for (EmpireManager::const_iterator it = Empires().begin(); it != Empires().end(); ++it) empire_ids.push_back(it->first); } for (std::vector<int>::const_iterator empire_it = empire_ids.begin(); empire_it != empire_ids.end(); ++empire_it) { const Empire* empire = HumanClientApp::GetApp()->Empires().Lookup(*empire_it); if (!empire) continue; for (Empire::SitRepItr sitrep_it = empire->SitRepBegin(); sitrep_it != empire->SitRepEnd(); ++sitrep_it) { if (CurrentTurn() != sitrep_it->GetTurn()) continue; if (m_hidden_sitrep_templates.find(sitrep_it->GetTemplateString()) != m_hidden_sitrep_templates.end()) continue; ++count; } } return count; }
int IssueCreateShipDesignOrder(const std::string& name, const std::string& description, const std::string& hull, const std::vector<std::string> parts, const std::string& icon, const std::string& model, bool nameDescInStringTable) { if (name.empty() || description.empty() || hull.empty()) { Logger().errorStream() << "AIInterface::IssueCreateShipDesignOrderOrder : passed an empty name, description, or hull."; return 0; } if (!ShipDesign::ValidDesign(hull, parts)) { Logger().errorStream() << "AIInterface::IssueCreateShipDesignOrderOrder : pass a hull and parts that do not make a valid ShipDesign"; return 0; } int empire_id = AIClientApp::GetApp()->EmpireID(); int current_turn = CurrentTurn(); // create design from stuff chosen in UI ShipDesign* design = new ShipDesign(name, description, current_turn, ClientApp::GetApp()->EmpireID(), hull, parts, icon, model, nameDescInStringTable); if (!design) { Logger().errorStream() << "AIInterface::IssueCreateShipDesignOrderOrder failed to create a new ShipDesign object"; return 0; } int new_design_id = AIClientApp::GetApp()->GetNewDesignID(); AIClientApp::GetApp()->Orders().IssueOrder(OrderPtr(new ShipDesignOrder(empire_id, new_design_id, *design))); delete design; return 1; }
int ResourceCenter::TurnsSinceFocusChange() const { if (m_last_turn_focus_changed == INVALID_GAME_TURN) return 0; int current_turn = CurrentTurn(); if (current_turn == INVALID_GAME_TURN) return 0; return current_turn - m_last_turn_focus_changed; }
double Planet::NextTurnCurrentMeterValue(MeterType type) const { MeterType max_meter_type = INVALID_METER_TYPE; switch (type) { case METER_TARGET_POPULATION: case METER_TARGET_HEALTH: case METER_POPULATION: case METER_HEALTH: case METER_FOOD_CONSUMPTION: return PopCenterNextTurnMeterValue(type); break; case METER_TARGET_FARMING: case METER_TARGET_INDUSTRY: case METER_TARGET_RESEARCH: case METER_TARGET_TRADE: case METER_TARGET_MINING: case METER_TARGET_CONSTRUCTION: case METER_FARMING: case METER_INDUSTRY: case METER_RESEARCH: case METER_TRADE: case METER_MINING: case METER_CONSTRUCTION: return ResourceCenterNextTurnMeterValue(type); break; case METER_SHIELD: max_meter_type = METER_MAX_SHIELD; break; case METER_TROOPS: max_meter_type = METER_MAX_TROOPS; break; case METER_DEFENSE: max_meter_type = METER_MAX_DEFENSE; break; break; default: return UniverseObject::NextTurnCurrentMeterValue(type); } const Meter* meter = GetMeter(type); if (!meter) { throw std::invalid_argument("Planet::NextTurnCurrentMeterValue passed meter type that the Planet does not have, but should."); } double current_meter_value = meter->Current(); const Meter* max_meter = GetMeter(max_meter_type); if (!max_meter) { throw std::runtime_error("Planet::NextTurnCurrentMeterValue dealing with invalid meter type"); } double max_meter_value = max_meter->Current(); // being attacked prevents meter growth if (LastTurnAttackedByShip() >= CurrentTurn()) { return std::min(current_meter_value, max_meter_value); } // currently meter growth is one per turn. return std::min(current_meter_value + 1.0, max_meter_value); }
UniverseObject::UniverseObject(const std::string name, double x, double y) : StateChangedSignal(blocking_combiner<boost::signals2::optional_last_value<void> >(GetUniverse().UniverseObjectSignalsInhibited())), m_name(name), m_id(INVALID_OBJECT_ID), m_x(x), m_y(y), m_owner_empire_id(ALL_EMPIRES), m_system_id(INVALID_OBJECT_ID), m_meters(), m_created_on_turn(INVALID_GAME_TURN) { m_created_on_turn = CurrentTurn(); }
UniverseObject::UniverseObject() : StateChangedSignal(GetUniverse().UniverseObjectSignalsInhibited()), m_name(""), m_id(INVALID_OBJECT_ID), m_x(INVALID_POSITION), m_y(INVALID_POSITION), m_owner_empire_id(ALL_EMPIRES), m_system_id(INVALID_OBJECT_ID), m_meters(), m_created_on_turn(-1) { //Logger().debugStream() << "UniverseObject::UniverseObject()"; m_created_on_turn = CurrentTurn(); }
float Ship::NextTurnCurrentMeterValue(MeterType type) const { const Meter* meter = UniverseObject::GetMeter(type); if (!meter) throw std::invalid_argument("Ship::NextTurnCurrentMeterValue passed meter type that the Ship does not have: " + boost::lexical_cast<std::string>(type)); float current_meter_value = meter->Current(); //if (type == METER_FUEL) { // // todo: consider fleet movement or being stationary, which may partly replenish fuel // // todo: consider fleet passing through or being in a supplied system, which replenishes fuel //} if (type == METER_SHIELD) { if (m_last_turn_active_in_combat >= CurrentTurn()) return std::max(0.0f, // battle just happened. shields limited to max shield, but don't regen std::min(current_meter_value, UniverseObject::GetMeter(METER_MAX_SHIELD)->Current())); else // shields regneerate to max shield return UniverseObject::GetMeter(METER_MAX_SHIELD)->Current(); } // ResourceCenter-like resource meter growth... MeterType target_meter_type = INVALID_METER_TYPE; switch (type) { case METER_TARGET_INDUSTRY: case METER_TARGET_RESEARCH: case METER_TARGET_TRADE: return current_meter_value; break; case METER_INDUSTRY: target_meter_type = METER_TARGET_INDUSTRY; break; case METER_RESEARCH: target_meter_type = METER_TARGET_RESEARCH; break; case METER_TRADE: target_meter_type = METER_TARGET_TRADE; break; default: return UniverseObject::NextTurnCurrentMeterValue(type); } const Meter* target_meter = UniverseObject::GetMeter(target_meter_type); if (!target_meter) throw std::runtime_error("Ship::NextTurnCurrentMeterValue dealing with invalid meter type: " + boost::lexical_cast<std::string>(type)); float target_meter_value = target_meter->Current(); // meter growth or decay towards target is one per turn. if (target_meter_value > current_meter_value) return std::min(current_meter_value + 1.0f, target_meter_value); else if (target_meter_value < current_meter_value) return std::max(target_meter_value, current_meter_value - 1.0f); else return current_meter_value; }
//////////////////////////////////////////////////////////// // 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(); } } }
float Planet::NextTurnCurrentMeterValue(MeterType type) const { MeterType max_meter_type = INVALID_METER_TYPE; switch (type) { case METER_TARGET_POPULATION: case METER_POPULATION: case METER_TARGET_HAPPINESS: case METER_HAPPINESS: return PopCenterNextTurnMeterValue(type); break; case METER_TARGET_INDUSTRY: case METER_TARGET_RESEARCH: case METER_TARGET_TRADE: case METER_TARGET_CONSTRUCTION: case METER_INDUSTRY: case METER_RESEARCH: case METER_TRADE: case METER_CONSTRUCTION: return ResourceCenterNextTurnMeterValue(type); break; case METER_SHIELD: max_meter_type = METER_MAX_SHIELD; break; case METER_TROOPS: max_meter_type = METER_MAX_TROOPS; break; case METER_DEFENSE: max_meter_type = METER_MAX_DEFENSE; break; case METER_SUPPLY: max_meter_type = METER_MAX_SUPPLY; break; break; default: return UniverseObject::NextTurnCurrentMeterValue(type); } const Meter* meter = GetMeter(type); if (!meter) { throw std::invalid_argument("Planet::NextTurnCurrentMeterValue passed meter type that the Planet does not have, but should: " + boost::lexical_cast<std::string>(type)); } float current_meter_value = meter->Current(); const Meter* max_meter = GetMeter(max_meter_type); if (!max_meter) { throw std::runtime_error("Planet::NextTurnCurrentMeterValue dealing with invalid meter type: " + boost::lexical_cast<std::string>(type)); } float max_meter_value = max_meter->Current(); // being attacked prevents meter growth if (LastTurnAttackedByShip() >= CurrentTurn()) return std::min(current_meter_value, max_meter_value); // currently meter growth is one per turn. return std::min(current_meter_value + 1.0f, max_meter_value); }
UniverseObject::UniverseObject(const std::string name, double x, double y, const std::set<int>& owners/* = std::set<int>()*/) : StateChangedSignal(GetUniverse().UniverseObjectSignalsInhibited()), m_name(name), m_id(INVALID_OBJECT_ID), m_x(x), m_y(y), m_owner_empire_id(ALL_EMPIRES), m_system_id(INVALID_OBJECT_ID), m_meters(), m_created_on_turn(-1) { //Logger().debugStream() << "UniverseObject::UniverseObject(" << name << ", " << x << ", " << y << ")"; //if (m_x < 0.0 || GetUniverse().UniverseWidth() < m_x || m_y < 0.0 || GetUniverse().UniverseWidth() < m_y) // throw std::invalid_argument("UniverseObject::UniverseObject : Attempted to create an object \"" + m_name + "\" off the map area."); m_created_on_turn = CurrentTurn(); }
float Ship::NextTurnCurrentMeterValue(MeterType type) const { //if (type == METER_FUEL) { // // todo: consider fleet movement or being stationary, which may partly replenish fuel // // todo: consider fleet passing through or being in a supplied system, which replenishes fuel //} else if (type == METER_SUPPLY) { // // todo: consider fleet passing through or being in a supplied system, which replenishes supplies //} if (type == METER_SHIELD) { if (m_last_turn_active_in_combat >= CurrentTurn()) return std::max(0.0f, std::min(UniverseObject::GetMeter(METER_SHIELD)->Current(), UniverseObject::GetMeter(METER_MAX_SHIELD)->Current())); else return UniverseObject::GetMeter(METER_MAX_SHIELD)->Current(); } return UniverseObject::NextTurnCurrentMeterValue(type); }
void ResourceCenter::SetFocus(const std::string& focus) { if (focus == m_focus) return; if (focus.empty()) { ClearFocus(); return; } std::vector<std::string> avail_foci = AvailableFoci(); if (std::find(avail_foci.begin(), avail_foci.end(), focus) != avail_foci.end()) { m_focus = focus; if (m_focus == m_focus_turn_initial) m_last_turn_focus_changed = m_last_turn_focus_changed_turn_initial; else m_last_turn_focus_changed = CurrentTurn(); ResourceCenterChangedSignal(); return; } ErrorLogger() << "ResourceCenter::SetFocus Exploiter!-- unavailable focus " << focus << " attempted to be set for object w/ dump string: " << Dump(); }
void HumanClientApp::StartTurn() { DebugLogger() << "HumanClientApp::StartTurn"; const Empire *empire = GetEmpire(EmpireID()); if (empire) { double RP = empire->ResourceOutput(RE_RESEARCH); double PP = empire->ResourceOutput(RE_INDUSTRY); int turn_number = CurrentTurn(); float ratio = (RP/(PP+0.0001)); const GG::Clr color = empire->Color(); DebugLogger() << "Current Output (turn " << turn_number << ") RP/PP: " << ratio << " (" << RP << "/" << PP << ")"; DebugLogger() << "EmpireColors: " << static_cast<int>(color.r) << " " << static_cast<int>(color.g) << " " << static_cast<int>(color.b) << " " << static_cast<int>(color.a); } ClientApp::StartTurn(); m_fsm->process_event(TurnEnded()); }
void UniverseObject::AddSpecial(const std::string& name, float capacity) { m_specials[name] = std::make_pair(CurrentTurn(), capacity); }
void SitRepPanel::NextClicked() { m_showing_turn = std::min(CurrentTurn(), std::max(1, m_showing_turn + 1)); Update(); }
void SitRepPanel::Update() { Logger().debugStream() << "SitRepPanel::Update()"; m_sitreps_lb->Clear(); if (m_showing_turn == INVALID_GAME_TURN) this->SetName(UserString("SITREP_PANEL_TITLE")); else this->SetName(boost::io::str(FlexibleFormat(UserString("SITREP_PANEL_TITLE_TURN")) % m_showing_turn)); // get sitrep entries for this client's player empire, or for all empires // if this client is an observer or moderator. // todo: double check that no-empire players are actually moderator or // observers, instead of just passing the client empire id. std::list<SitRepEntry> currentTurnSitreps; GetTurnSitrepsFromEmpire(currentTurnSitreps, HumanClientApp::GetApp()->EmpireID()); // order sitreps for display std::vector<SitRepEntry> orderedSitreps; std::vector<std::string> ordered_templates = OrderedSitrepTemplateStrings(); for (std::vector<std::string>::const_iterator template_it = ordered_templates.begin(); template_it != ordered_templates.end(); ++template_it) { for (std::list<SitRepEntry>::iterator sitrep_it = currentTurnSitreps.begin(); sitrep_it != currentTurnSitreps.end(); sitrep_it++) { if (sitrep_it->GetTemplateString() == *template_it) { //Logger().debugStream() << "saving into orderedSitreps - sitrep of template "<<*template_it<<" with full string "<< sitrep_it->GetText(); orderedSitreps.push_back(*sitrep_it); //Logger().debugStream()<< "deleting above sitrep from currentTurnSitreps"; sitrep_it = --currentTurnSitreps.erase(sitrep_it); } } } // copy remaining unordered sitreps for (std::list<SitRepEntry>::iterator sitrep_it = currentTurnSitreps.begin(); sitrep_it != currentTurnSitreps.end(); sitrep_it++) { orderedSitreps.push_back(*sitrep_it); } // create UI rows for all sitrps GG::X width = m_sitreps_lb->Width() - 8; for (std::vector<SitRepEntry>::iterator sitrep_it = orderedSitreps.begin(); sitrep_it != orderedSitreps.end(); sitrep_it++) { m_sitreps_lb->Insert(new SitRepRow(width, GG::Y(ClientUI::Pts()*2), *sitrep_it)); } // if at first turn, disable back button if (CurrentTurn() >= 1 && m_showing_turn > 1) { m_prev_turn_button->Disable(false); } else { m_prev_turn_button->Disable(); } // if at current turn, disable forward button if (CurrentTurn() >= 1 && m_showing_turn < CurrentTurn()) { m_next_turn_button->Disable(false); m_last_turn_button->Disable(false); } else { m_next_turn_button->Disable(); m_last_turn_button->Disable(); } }
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; } }
Ship::Ship(int empire_id, int design_id, const std::string& species_name, int produced_by_empire_id/* = ALL_EMPIRES*/) : UniverseObject(), m_design_id(design_id), m_fleet_id(INVALID_OBJECT_ID), m_ordered_scrapped(false), m_ordered_colonize_planet_id(INVALID_OBJECT_ID), m_ordered_invade_planet_id(INVALID_OBJECT_ID), m_ordered_bombard_planet_id(INVALID_OBJECT_ID), m_last_turn_active_in_combat(INVALID_GAME_TURN), m_species_name(species_name), m_produced_by_empire_id(produced_by_empire_id), m_arrived_on_turn(CurrentTurn()) { if (!GetShipDesign(design_id)) throw std::invalid_argument("Attempted to construct a Ship with an invalid design id"); if (!m_species_name.empty() && !GetSpecies(m_species_name)) DebugLogger() << "Ship created with invalid species name: " << m_species_name; SetOwner(empire_id); UniverseObject::Init(); AddMeter(METER_FUEL); AddMeter(METER_MAX_FUEL); AddMeter(METER_SHIELD); AddMeter(METER_MAX_SHIELD); AddMeter(METER_DETECTION); AddMeter(METER_STRUCTURE); AddMeter(METER_MAX_STRUCTURE); AddMeter(METER_SPEED); AddMeter(METER_TARGET_INDUSTRY); AddMeter(METER_INDUSTRY); AddMeter(METER_TARGET_RESEARCH); AddMeter(METER_RESEARCH); AddMeter(METER_TARGET_TRADE); AddMeter(METER_TRADE); const std::vector<std::string>& part_names = Design()->Parts(); for (std::size_t i = 0; i < part_names.size(); ++i) { if (part_names[i] != "") { const PartType* part = GetPartType(part_names[i]); if (!part) { ErrorLogger() << "Ship::Ship couldn't get part with name " << part_names[i]; continue; } switch (part->Class()) { case PC_COLONY: case PC_TROOPS: { m_part_meters[std::make_pair(METER_CAPACITY, part->Name())]; break; } case PC_DIRECT_WEAPON: // capacity is damage, secondary stat is shots per attack case PC_FIGHTER_HANGAR: { // capacity is how many fighters contained, secondary stat is damage per fighter attack m_part_meters[std::make_pair(METER_SECONDARY_STAT, part->Name())]; m_part_meters[std::make_pair(METER_MAX_SECONDARY_STAT, part->Name())]; // intentionally no break here } case PC_FIGHTER_BAY: { // capacity is how many fighters launched per combat round m_part_meters[std::make_pair(METER_CAPACITY, part->Name())]; m_part_meters[std::make_pair(METER_MAX_CAPACITY, part->Name())]; break; } default: break; } } } }
int SitRepPanel::NumVisibleSitrepsThisTurn() const { std::map<int, std::list<SitRepEntry> > turns = GetSitRepsSortedByTurn(HumanClientApp::GetApp()->EmpireID(), m_hidden_sitrep_templates); return turns[CurrentTurn()].size(); }
void HearthstoneLogTracker::CardPlayed( Player player, const string& cardId, int internalId ) { DBG( "%s played card %s on turn %d", PLAYER_NAMES[ player ], cardId.c_str(), CurrentTurn() ); mCardHistoryList.push_back( CardHistoryItem( CurrentTurn(), player, cardId, internalId ) ); }
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(); }
int Variable<int>::Eval(const ScriptingContext& context) const { const adobe::name_t& property_name = m_property_name.back(); IF_CURRENT_VALUE(int) if (m_ref_type == ValueRef::NON_OBJECT_REFERENCE) { if (property_name == CurrentTurn_name) return CurrentTurn(); // add more non-object reference int functions here Logger().errorStream() << "Variable<int>::Eval unrecognized non-object property: " << ReconstructName(m_property_name, m_ref_type); return 0; } const UniverseObject* object = FollowReference(m_property_name.begin(), m_property_name.end(), m_ref_type, context); if (!object) { Logger().errorStream() << "Variable<int>::Eval unable to follow reference: " << ReconstructName(m_property_name, m_ref_type); return 0; } if (property_name == Owner_name) { return object->Owner(); } else if (property_name == ID_name) { return object->ID(); } else if (property_name == CreationTurn_name) { return object->CreationTurn(); } else if (property_name == Age_name) { return object->AgeInTurns(); } else if (property_name == ProducedByEmpireID_name) { if (const Ship* ship = universe_object_cast<const Ship*>(object)) return ship->ProducedByEmpireID(); else if (const Building* building = universe_object_cast<const Building*>(object)) return building->ProducedByEmpireID(); else return ALL_EMPIRES; } else if (property_name == DesignID_name) { if (const Ship* ship = universe_object_cast<const Ship*>(object)) return ship->DesignID(); else return ShipDesign::INVALID_DESIGN_ID; } else if (property_name == Species_name) { if (const Planet* planet = universe_object_cast<const Planet*>(object)) return GetSpeciesManager().GetSpeciesID(planet->SpeciesName()); else if (const Ship* ship = universe_object_cast<const Ship*>(object)) return GetSpeciesManager().GetSpeciesID(ship->SpeciesName()); else return -1; } else if (property_name == FleetID_name) { if (const Ship* ship = universe_object_cast<const Ship*>(object)) return ship->FleetID(); else if (const Fleet* fleet = universe_object_cast<const Fleet*>(object)) return fleet->ID(); else return INVALID_OBJECT_ID; } else if (property_name == PlanetID_name) { if (const Building* building = universe_object_cast<const Building*>(object)) return building->PlanetID(); else if (const Planet* planet = universe_object_cast<const Planet*>(object)) return planet->ID(); else return INVALID_OBJECT_ID; } else if (property_name == SystemID_name) { return object->SystemID(); } else if (property_name == FinalDestinationID_name) { if (const Fleet* fleet = universe_object_cast<const Fleet*>(object)) return fleet->FinalDestinationID(); else return INVALID_OBJECT_ID; } else if (property_name == NextSystemID_name) { if (const Fleet* fleet = universe_object_cast<const Fleet*>(object)) return fleet->NextSystemID(); else return INVALID_OBJECT_ID; } else if (property_name == PreviousSystemID_name) { if (const Fleet* fleet = universe_object_cast<const Fleet*>(object)) return fleet->PreviousSystemID(); else return INVALID_OBJECT_ID; } else if (property_name == NumShips_name) { if (const Fleet* fleet = universe_object_cast<const Fleet*>(object)) return fleet->NumShips(); else return 0; } else if (property_name == LastTurnBattleHere_name) { if (const System* system = universe_object_cast<const System*>(object)) return system->LastTurnBattleHere(); else return INVALID_GAME_TURN; } else if (property_name == Orbit_name) { if (const System* system = GetSystem(object->SystemID())) return system->OrbitOfObjectID(object->ID()); return -1; } Logger().errorStream() << "Variable<int>::Eval unrecognized object property: " << ReconstructName(m_property_name, m_ref_type); return 0; }
void UniverseObject::AddSpecial(const std::string& name) { m_specials[name] = CurrentTurn(); }
void HearthstoneLogTracker::HandleLogLine( const QString& line ) { if( line.trimmed().isEmpty() || line.startsWith( "(Filename:" ) ) { return; } // CardPlayed / CardReturned / PlayerDied static QRegExp regex( "ProcessChanges.*\\[.*id=(\\d+).*cardId=(\\w+|).*\\].*zone from (.*) ->\\s?(.*)" ); if( regex.indexIn(line) != -1 ) { QStringList captures = regex.capturedTexts(); int id = captures[1].toInt(); QString cardId = captures[2]; QString from = captures[3]; QString to = captures[4]; bool draw = from.contains( "DECK" ) && to.contains( "HAND" ); bool mulligan = from.contains( "HAND" ) && to.contains( "DECK" ); // Discarded cards by playing Soulfire, Doomguard etc. bool discard = from.contains( "HAND" ) && to.contains( "GRAVEYARD" ); if( !draw && !mulligan && !discard ) { if( from.contains( "FRIENDLY HAND" ) ) { CardPlayed( PLAYER_SELF, cardId.toStdString(), id ); } else if( from.contains( "OPPOSING HAND" ) ) { CardPlayed( PLAYER_OPPONENT, cardId.toStdString(), id ); } else if( from.contains( "OPPOSING SECRET" ) && to.contains( "OPPOSING GRAVEYARD" ) ) { SecretResolved( PLAYER_OPPONENT, cardId.toStdString(), id ); } } if( from.contains( "FRIENDLY PLAY" ) && to.contains( "FRIENDLY HAND" ) ) { CardReturned( PLAYER_SELF, cardId.toStdString() ); } DBG( "Card %s from %s -> %s. (draw: %d, mulligan %d, discard %d) [%d]", qt2cstr( cardId ), qt2cstr( from ), qt2cstr( to ), draw, mulligan, discard, id ); } // Outcome static QRegExp regexOutcome( "name=(victory|defeat)_screen_start" ); if( regexOutcome.indexIn(line) != -1 ) { QStringList captures = regexOutcome.capturedTexts(); QString outcome = captures[1]; if( outcome == "victory" ) { emit HandleOutcome( OUTCOME_VICTORY ); } else if( outcome == "defeat" ) { emit HandleOutcome( OUTCOME_DEFEAT ); } emit HandleMatchEnd( mCardHistoryList ); Reset(); } // Coin static QRegExp regexCoin( "ProcessChanges.*zonePos=5.*zone from -> (.*)" ); // unique because from is nothing -> " " if( regexCoin.indexIn(line) != -1 ) { QStringList captures = regexCoin.capturedTexts(); QString to = captures[1]; if( to.contains( "FRIENDLY HAND" ) ) { // I go second because I get the coin emit HandleOrder( ORDER_SECOND ); } else if( to.contains( "OPPOSING HAND" ) ) { // Opponent got coin, so I go first emit HandleOrder( ORDER_FIRST ); } } // Turn Info static QRegExp regexTurn( "change=powerTask.*tag=NEXT_STEP value=MAIN_ACTION" ); if( regexTurn.indexIn(line) != -1 ) { mTurnCounter++; emit HandleTurn( mTurnCounter ); // reset hero power usage on turn change mHeroPowerUsed = false; } // Hero Power static QRegExp regexHeroPowerEquip( "player=(\\d+).*-> FRIENDLY PLAY \\(Hero Power\\)" ); if( regexHeroPowerEquip.indexIn(line) != -1 ) { QStringList captures = regexHeroPowerEquip.capturedTexts(); QString playerId = captures[1]; mHeroPlayerId = playerId.toInt(); DBG( "Hero Power Equip -> My Player Id: %d", mHeroPlayerId ); } static QRegExp regexHeroPower( "PowerProcessor\\.DoTaskListForCard.*cardId=(\\w+).*player=(\\d+)" ); if( regexHeroPower.indexIn(line) != -1 ) { QStringList captures = regexHeroPower.capturedTexts(); QString cardId = captures[1]; int playerId = captures[2].toInt(); Player player = ( playerId == mHeroPlayerId ) ? PLAYER_SELF : PLAYER_OPPONENT; bool isHeroPower = false; for( int i = 0; i < NUM_HERO_POWER_CARDS; i++ ) { if( cardId == HERO_POWER_CARD_IDS[ i ] ) { isHeroPower = true; break; } } // Power log line is emitted multiple times // Make sure we only account for first occurrence // Plus line is emitted when match starts, so ignore turn 0 if( isHeroPower && !mHeroPowerUsed && CurrentTurn() > 0 ) { CardPlayed( player, cardId.toStdString() ); mHeroPowerUsed = true; } } // Hero Equip static QRegExp regexHeroEquip( "cardId=(\\w+).*-> (\\w+) PLAY \\(Hero\\)" ); if( regexHeroEquip.indexIn(line) != -1 ) { QStringList captures = regexHeroEquip.capturedTexts(); QString cardId = captures[1]; QString type = captures[2]; // This log line can be emitted when hero swaps (Lord Jaraxxus) // So make sure we only account for the "initial" playable heroes Class hero = CLASS_UNKNOWN; for( int i = 0; i < NUM_HEROES; i++ ) { // startsWith instead of exact match to support // the new reasonably priced hero skins // (e.g. HERO_01a instead of HERO_01) if( cardId.startsWith( HERO_IDS[ i ] ) ) { hero = ( Class )i; } } // Set solo mode when encountering naxxramas/blackrock mountain heroes if( hero == CLASS_UNKNOWN ) { if( cardId.startsWith("NAX") || cardId.startsWith("BRM") ) { HandleGameMode( MODE_SOLO_ADVENTURES ); } } if( hero != CLASS_UNKNOWN ) { if( type == "FRIENDLY" ) { emit HandleMatchStart(); emit HandleOwnClass( hero ); } else { emit HandleOpponentClass( hero ); } } } // Game Mode // Practice, Casual/Ranked, ScreenForge static QRegExp regexMode( "---(\\w+)---" ); if( regexMode.indexIn(line) != -1 ) { QStringList captures = regexMode.capturedTexts(); QString screen = captures[1]; if( screen == "RegisterScreenPractice" ) { HandleGameMode( MODE_SOLO_ADVENTURES ); } else if( screen == "RegisterScreenTourneys") { HandleGameMode( MODE_CASUAL ); // or ranked resp. } else if( screen == "RegisterScreenForge" ) { HandleGameMode( MODE_ARENA ); } else if( screen == "RegisterScreenFriendly" ) { HandleGameMode( MODE_FRIENDLY ); } } // Tavern Brawl static QRegExp regexTavernBrawl( "SAVE --> NetCacheTavernBrawlRecord" ); if( regexTavernBrawl.indexIn(line) != -1 ) { HandleGameMode( MODE_TAVERN_BRAWL ); } // Rank // Rank events via log are unreliable // Legend // Emitted at the end of the game twice, make sure we capture only the first time static QRegExp regexLegend( "legend rank (\\d+)" ); if( !mLegendTracked && regexLegend.indexIn(line) != -1 ) { QStringList captures = regexLegend.capturedTexts(); int legend = captures[1].toInt(); if( legend > 0 ) { mLegendTracked = true; HandleLegend( legend ); } } // Casual/Ranked distinction static QRegExp regexRanked( "name=rank_window" ); if( regexRanked.indexIn(line) != -1 ) { HandleGameMode( MODE_RANKED ); } // flag current GAME as spectated static QRegExp regexBeginSpectating( "Start Spectator Game" ); if( regexBeginSpectating.indexIn(line) != -1 ) { DBG( "Begin spectator game" ); emit HandleSpectating( true ); } // disable spectating flag if we leave the spectator MODE static QRegExp regexEndSpectating( "End Spectator Mode" ); if( regexEndSpectating.indexIn(line) != -1 ) { DBG( "End spectator mode" ); emit HandleSpectating( false ); } }
double Variable<double>::Eval(const ScriptingContext& context) const { const adobe::name_t& property_name = m_property_name.back(); IF_CURRENT_VALUE(float) if (m_ref_type == ValueRef::NON_OBJECT_REFERENCE) { if (property_name == CurrentTurn_name) { return CurrentTurn(); } else if (property_name == UniverseCentreX_name | property_name == UniverseCentreY_name) { return GetUniverse().UniverseWidth() / 2; } // add more non-object reference double functions here Logger().errorStream() << "Variable<double>::Eval unrecognized non-object property: " << ReconstructName(m_property_name, m_ref_type); return 0.0; } const UniverseObject* object = FollowReference(m_property_name.begin(), m_property_name.end(), m_ref_type, context); if (!object) { Logger().errorStream() << "Variable<double>::Eval unable to follow reference: " << ReconstructName(m_property_name, m_ref_type); return 0.0; } MeterType meter_type = NameToMeter(property_name); if (object && meter_type != INVALID_METER_TYPE) { if (object->GetMeter(meter_type)) return object->InitialMeterValue(meter_type); } else if (property_name == TradeStockpile_name) { if (const Empire* empire = Empires().Lookup(object->Owner())) return empire->ResourceStockpile(RE_TRADE); } else if (property_name == DistanceToSource_name) { if (!context.source) { Logger().errorStream() << "ValueRef::Variable<double>::Eval can't find distance to source because no source was passed"; return 0.0; } double delta_x = object->X() - context.source->X(); double delta_y = object->Y() - context.source->Y(); return std::sqrt(delta_x * delta_x + delta_y * delta_y); } else if (property_name == X_name) { return object->X(); } else if (property_name == Y_name) { return object->Y(); } else if (property_name == SizeAsDouble_name) { if (const Planet* planet = universe_object_cast<const Planet*>(object)) return planet->SizeAsInt(); } else if (property_name == DistanceFromOriginalType_name) { if (const Planet* planet = universe_object_cast<const Planet*>(object)) return planet->DistanceFromOriginalType(); } else if (property_name == NextTurnPopGrowth_name) { if (const PopCenter* pop = dynamic_cast<const PopCenter*>(object)) return pop->NextTurnPopGrowth(); } else if (property_name == CurrentTurn_name) { return CurrentTurn(); } Logger().errorStream() << "Variable<double>::Eval unrecognized object property: " << ReconstructName(m_property_name, m_ref_type); return 0.0; }
void ResourceCenter::ClearFocus() { m_focus.clear(); m_last_turn_focus_changed = CurrentTurn(); ResourceCenterChangedSignal(); }
void SitRepPanel::LastClicked() { m_showing_turn = CurrentTurn(); Update(); }