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); }
BuildingsPanel::BuildingsPanel(GG::X w, int columns, int planet_id) : AccordionPanel(w), m_planet_id(planet_id), m_columns(columns), m_building_indicators() { SetName("BuildingsPanel"); if (m_columns < 1) { ErrorLogger() << "Attempted to create a BuidingsPanel with less than 1 column"; m_columns = 1; } GG::Connect(m_expand_button->LeftClickedSignal, &BuildingsPanel::ExpandCollapseButtonPressed, this); // get owner, connect its production queue changed signal to update this panel TemporaryPtr<const UniverseObject> planet = GetUniverseObject(m_planet_id); if (planet) { if (const Empire* empire = GetEmpire(planet->Owner())) { const ProductionQueue& queue = empire->GetProductionQueue(); GG::Connect(queue.ProductionQueueChangedSignal, &BuildingsPanel::Refresh, this); } } Refresh(); }
void ResourcePanel::Update() { // remove any old browse wnds for (auto& meter_stat : m_meter_stats) { meter_stat.second->ClearBrowseInfoWnd(); m_multi_icon_value_indicator->ClearToolTip(meter_stat.first); } auto obj = GetUniverseObject(m_rescenter_id); if (!obj) { ErrorLogger() << "BuildingPanel::Update couldn't get object with id " << m_rescenter_id; return; } // meter bar displays resource stats m_multi_meter_status_bar->Update(); m_multi_icon_value_indicator->Update(); // tooltips for (auto& meter_stat : m_meter_stats) { meter_stat.second->SetValue(obj->InitialMeterValue(meter_stat.first)); auto browse_wnd = GG::Wnd::Create<MeterBrowseWnd>(m_rescenter_id, meter_stat.first, AssociatedMeterType(meter_stat.first)); meter_stat.second->SetBrowseInfoWnd(browse_wnd); m_multi_icon_value_indicator->SetToolTip(meter_stat.first, browse_wnd); } std::sort(m_meter_stats.begin(), m_meter_stats.end(), SortByMeterValue); }
void MultiMeterStatusBar::Update() { m_initial_values.clear(); // initial value of .first MeterTypes at the start of this turn m_projected_values.clear(); // projected current value of .first MeterTypes for the start of next turn m_target_max_values.clear();// current values of the .second MeterTypes in m_meter_types TemporaryPtr<const UniverseObject> obj = GetUniverseObject(m_object_id); if (!obj) { ErrorLogger() << "MultiMeterStatusBar couldn't get object with id " << m_object_id; return; } int num_bars = 0; // count number of valid bars' data added for (std::vector<std::pair<MeterType, MeterType> >::const_iterator meter_pairs_it = m_meter_types.begin(); meter_pairs_it != m_meter_types.end(); ++meter_pairs_it) { const std::pair<MeterType, MeterType>& meter_types_pair = *meter_pairs_it; const Meter* actual_meter = obj->GetMeter(meter_types_pair.first); const Meter* target_max_meter = obj->GetMeter(meter_types_pair.second); boost::tuple<float, float, float> current_projected_target = DualMeter::CurrentProjectedTarget( *obj, meter_types_pair.first, meter_types_pair.second); if (actual_meter || target_max_meter) { ++num_bars; m_initial_values.push_back(boost::get<0>(current_projected_target)); m_projected_values.push_back(boost::get<1>(current_projected_target)); m_target_max_values.push_back(boost::get<2>(current_projected_target)); m_bar_colours.push_back(MeterColor(meter_types_pair.first)); } } // calculate height from number of bars to be shown const GG::Y HEIGHT = num_bars*BAR_HEIGHT + (num_bars - 1)*BAR_PAD + 2*EDGE_PAD - 2; Resize(GG::Pt(Width(), HEIGHT)); }
UniverseObject* GetEmpireKnownObject(int object_id, int empire_id) { #ifdef FREEORION_BUILD_SERVER return EmpireKnownObjects(empire_id).Object(object_id); #else return GetUniverseObject(object_id);// as of this writing, players don't have info about what other players know about objects #endif }
void Fleet::SetSystem(int sys) { //Logger().debugStream() << "Fleet::SetSystem(int sys)"; UniverseObject::SetSystem(sys); for (iterator it = begin(); it != end(); ++it) if (UniverseObject* obj = GetUniverseObject(*it)) obj->SetSystem(sys); }
void ResourcePanel::Update() { // remove any old browse wnds for (std::vector<std::pair<MeterType, StatisticIcon*> >::iterator it = m_meter_stats.begin(); it != m_meter_stats.end(); ++it) { it->second->ClearBrowseInfoWnd(); m_multi_icon_value_indicator->ClearToolTip(it->first); } TemporaryPtr<const UniverseObject> obj = GetUniverseObject(m_rescenter_id); if (!obj) { ErrorLogger() << "BuildingPanel::Update couldn't get object with id " << m_rescenter_id; return; } // meter bar displays resource stats m_multi_meter_status_bar->Update(); m_multi_icon_value_indicator->Update(); // tooltips boost::shared_ptr<GG::BrowseInfoWnd> browse_wnd; for (std::vector<std::pair<MeterType, StatisticIcon*> >::iterator it = m_meter_stats.begin(); it != m_meter_stats.end(); ++it) { it->second->SetValue(obj->InitialMeterValue(it->first)); browse_wnd = boost::shared_ptr<GG::BrowseInfoWnd>(new MeterBrowseWnd(m_rescenter_id, it->first, AssociatedMeterType(it->first))); it->second->SetBrowseInfoWnd(browse_wnd); m_multi_icon_value_indicator->SetToolTip(it->first, browse_wnd); } std::sort(m_meter_stats.begin(), m_meter_stats.end(), sortByMeterValue); }
SitRepEntry CreateCombatDamagedObjectSitRep(int object_id, int combat_system_id, int empire_id) { TemporaryPtr<const UniverseObject> obj = GetUniverseObject(object_id); if (!obj) return GenericCombatDamagedObjectSitrep(combat_system_id); SitRepEntry sitrep; if (TemporaryPtr<const Ship> ship = boost::dynamic_pointer_cast<const Ship>(obj)) { if (ship->Unowned()) sitrep = SitRepEntry(UserStringNop("SITREP_UNOWNED_SHIP_DAMAGED_AT_SYSTEM"), "icons/sitrep/combat_damage.png"); else sitrep = SitRepEntry(UserStringNop("SITREP_SHIP_DAMAGED_AT_SYSTEM"), "icons/sitrep/combat_damage.png"); sitrep.AddVariable(VarText::SHIP_ID_TAG, boost::lexical_cast<std::string>(object_id)); sitrep.AddVariable(VarText::DESIGN_ID_TAG, boost::lexical_cast<std::string>(ship->DesignID())); } else if (TemporaryPtr<const Planet> planet = boost::dynamic_pointer_cast<const Planet>(obj)) { if (planet->Unowned()) sitrep = SitRepEntry(UserStringNop("SITREP_UNOWNED_PLANET_BOMBARDED_AT_SYSTEM"), "icons/sitrep/colony_bombarded.png"); else sitrep = SitRepEntry(UserStringNop("SITREP_PLANET_BOMBARDED_AT_SYSTEM"), "icons/sitrep/colony_bombarded_own.png"); sitrep.AddVariable(VarText::PLANET_ID_TAG, boost::lexical_cast<std::string>(object_id)); } else { sitrep = GenericCombatDestroyedObjectSitrep(combat_system_id); } sitrep.AddVariable(VarText::EMPIRE_ID_TAG, boost::lexical_cast<std::string>(obj->Owner())); sitrep.AddVariable(VarText::SYSTEM_ID_TAG, boost::lexical_cast<std::string>(combat_system_id)); return sitrep; }
std::vector<UniverseObject*> Planet::FindObjects() const { std::vector<UniverseObject*> retval; // add buildings on this planet for (std::set<int>::const_iterator it = m_buildings.begin(); it != m_buildings.end(); ++it) retval.push_back(GetUniverseObject(*it)); return retval; }
int IssueScrapOrder(const std::vector<int>& object_ids) { if (object_ids.empty()) { Logger().errorStream() << "AIInterface::IssueScrapOrder : passed empty vector of object_ids"; return 0; } int empire_id = AIClientApp::GetApp()->EmpireID(); // make sure all objects exist and are owned just by this player for (std::vector<int>::const_iterator it = object_ids.begin(); it != object_ids.end(); ++it) { TemporaryPtr<const UniverseObject> obj = GetUniverseObject(*it); if (!obj) { Logger().errorStream() << "AIInterface::IssueScrapOrder : passed an invalid object_id"; return 0; } if (!obj->OwnedBy(empire_id)) { Logger().errorStream() << "AIInterface::IssueScrapOrder : passed object_id of object not owned by player"; return 0; } AIClientApp::GetApp()->Orders().IssueOrder(OrderPtr(new ScrapOrder(empire_id, *it))); } return 1; }
bool UniverseObject::ContainedBy(int object_id) const { const UniverseObject* object = GetUniverseObject(object_id); if (object) return object->Contains(m_id); else return false; }
void Moderator::SetOwner::Execute() const { TemporaryPtr<UniverseObject> obj = GetUniverseObject(m_object_id); if (!obj) { Logger().errorStream() << "Moderator::SetOwner::Execute couldn't get object with id: " << m_object_id; return; } obj->SetOwner(m_new_owner_empire_id); }
void Species::AddHomeworld(int homeworld_id) { if (!GetUniverseObject(homeworld_id)) Logger().debugStream() << "Species asked to add homeworld id " << homeworld_id << " but there is no such object in the Universe"; if (m_homeworlds.find(homeworld_id) != m_homeworlds.end()) return; m_homeworlds.insert(homeworld_id); // TODO if needed: StateChangedSignal(); }
std::vector<UniverseObject*> Fleet::FindObjects() const { std::vector<UniverseObject*> retval; // add ships in this fleet for (ShipIDSet::const_iterator it = m_ships.begin(); it != m_ships.end(); ++it) if (UniverseObject* obj = GetUniverseObject(*it)) retval.push_back(obj); return retval; }
int IssueGiveObjectToEmpireOrder(int object_id, int recipient_id) { int empire_id = AIClientApp::GetApp()->EmpireID(); if (Empires().Lookup(recipient_id) == 0) { Logger().errorStream() << "AIInterface::IssueGiveObjectToEmpireOrder : given invalid recipient empire id"; return 0; } if (Empires().GetDiplomaticStatus(empire_id, recipient_id) != DIPLO_PEACE) { Logger().errorStream() << "AIInterface::IssueGiveObjectToEmpireOrder : attempting to give to empire not at peace"; return 0; } TemporaryPtr<UniverseObject> obj = GetUniverseObject(object_id); if (!obj) { Logger().errorStream() << "AIInterface::IssueGiveObjectToEmpireOrder : passed invalid object id"; return 0; } if (!obj->OwnedBy(empire_id)) { Logger().errorStream() << "AIInterface::IssueGiveObjectToEmpireOrder : passed object not owned by player"; return 0; } if (obj->ObjectType() != OBJ_FLEET && obj->ObjectType() != OBJ_PLANET) { Logger().errorStream() << "AIInterface::IssueGiveObjectToEmpireOrder : passed object that is not a fleet or planet"; return 0; } TemporaryPtr<System> system = GetSystem(obj->SystemID()); if (!system) { Logger().errorStream() << "AIInterface::IssueGiveObjectToEmpireOrder : couldn't get system of object"; return 0; } // can only give to empires with something present to receive the gift bool recipient_has_something_here = false; std::vector<TemporaryPtr<const UniverseObject> > system_objects = Objects().FindObjects<const UniverseObject>(system->ObjectIDs()); for (std::vector<TemporaryPtr<const UniverseObject> >::const_iterator it = system_objects.begin(); it != system_objects.end(); ++it) { TemporaryPtr<const UniverseObject> obj = *it; if (obj->Owner() == recipient_id) { recipient_has_something_here = true; break; } } if (!recipient_has_something_here) { Logger().errorStream() << "AIInterface::IssueGiveObjectToEmpireOrder : recipient empire has nothing in system"; return 0; } AIClientApp::GetApp()->Orders().IssueOrder(OrderPtr( new GiveObjectToEmpireOrder(empire_id, object_id, recipient_id))); return 1; }
void Fleet::MoveTo(double x, double y) { //Logger().debugStream() << "Fleet::MoveTo(double x, double y)"; // move fleet itself UniverseObject::MoveTo(x, y); // move ships in fleet for (iterator it = begin(); it != end(); ++it) if (UniverseObject* obj = GetUniverseObject(*it)) obj->UniverseObject::MoveTo(x, y); }
PopulationPanel::PopulationPanel(GG::X w, int object_id) : AccordionPanel(w, GG::Y(ClientUI::Pts()*2)), m_popcenter_id(object_id), m_meter_stats(), m_multi_icon_value_indicator(nullptr), m_multi_meter_status_bar(nullptr) { SetName("PopulationPanel"); std::shared_ptr<const PopCenter> pop = GetPopCenter(); if (!pop) throw std::invalid_argument("Attempted to construct a PopulationPanel with an object id is not a PopCenter"); m_expand_button->LeftClickedSignal.connect( boost::bind(&PopulationPanel::ExpandCollapseButtonPressed, this)); const auto obj = GetUniverseObject(m_popcenter_id); if (!obj) { ErrorLogger() << "Invalid object id " << m_popcenter_id; return; } // small meter indicators - for use when panel is collapsed m_meter_stats.push_back( std::make_pair(METER_POPULATION, new StatisticIcon(ClientUI::SpeciesIcon(pop->SpeciesName()), obj->InitialMeterValue(METER_POPULATION), 3, false, MeterIconSize().x, MeterIconSize().y))); m_meter_stats.push_back( std::make_pair(METER_HAPPINESS, new StatisticIcon(ClientUI::MeterIcon(METER_HAPPINESS), obj->InitialMeterValue(METER_HAPPINESS), 3, false, MeterIconSize().x, MeterIconSize().y))); m_meter_stats.push_back( std::make_pair(METER_CONSTRUCTION, new StatisticIcon(ClientUI::MeterIcon(METER_CONSTRUCTION), obj->InitialMeterValue(METER_CONSTRUCTION), 3, false, MeterIconSize().x, MeterIconSize().y))); // meter and production indicators std::vector<std::pair<MeterType, MeterType>> meters; for (std::pair<MeterType, StatisticIcon*>& meter_stat : m_meter_stats) { meter_stat.second->InstallEventFilter(this); AttachChild(meter_stat.second); meters.push_back(std::make_pair(meter_stat.first, AssociatedMeterType(meter_stat.first))); } // attach and show meter bars and large resource indicators m_multi_icon_value_indicator = new MultiIconValueIndicator(Width() - 2*EDGE_PAD, m_popcenter_id, meters); m_multi_meter_status_bar = new MultiMeterStatusBar(Width() - 2*EDGE_PAD, m_popcenter_id, meters); // determine if this panel has been created yet. std::map<int, bool>::iterator it = s_expanded_map.find(m_popcenter_id); if (it == s_expanded_map.end()) s_expanded_map[m_popcenter_id] = false; // if not, default to collapsed state Refresh(); }
void Planet::SetSystem(int sys) { //Logger().debugStream() << "Planet::MoveTo(UniverseObject* object)"; UniverseObject::SetSystem(sys); for (std::set<int>::const_iterator it = m_buildings.begin(); it != m_buildings.end(); ++it) { UniverseObject* obj = GetUniverseObject(*it); if (!obj) { Logger().errorStream() << "Planet::SetSystem couldn't get building object with id " << *it; continue; } obj->SetSystem(sys); } }
float Special::InitialCapacity(int object_id) const { if (!m_initial_capacity) return 0.0f; auto obj = GetUniverseObject(object_id); if (!obj) return 0.0f; ScriptingContext context(obj); return m_initial_capacity->Eval(context); }
TemporaryPtr<const ResourceCenter> ResourcePanel::GetResCenter() const { TemporaryPtr<const UniverseObject> obj = GetUniverseObject(m_rescenter_id); if (!obj) { ErrorLogger() << "ResourcePanel tried to get an object with an invalid m_rescenter_id"; return TemporaryPtr<const ResourceCenter>(); } TemporaryPtr<const ResourceCenter> res = boost::dynamic_pointer_cast<const ResourceCenter>(obj); if (!res) { ErrorLogger() << "ResourcePanel failed casting an object pointer to a ResourceCenter pointer"; return TemporaryPtr<const ResourceCenter>(); } return res; }
TemporaryPtr<const PopCenter> PopulationPanel::GetPopCenter() const { TemporaryPtr<const UniverseObject> obj = GetUniverseObject(m_popcenter_id); if (!obj) { ErrorLogger() << "PopulationPanel tried to get an object with an invalid m_popcenter_id"; return TemporaryPtr<const PopCenter>(); } TemporaryPtr<const PopCenter> pop = boost::dynamic_pointer_cast<const PopCenter>(obj); if (!pop) { ErrorLogger() << "PopulationPanel failed casting an object pointer to a PopCenter pointer"; return TemporaryPtr<const PopCenter>(); } return pop; }
TemporaryPtr<const Planet> MilitaryPanel::GetPlanet() const { TemporaryPtr<const UniverseObject> obj = GetUniverseObject(m_planet_id); if (!obj) { ErrorLogger() << "MilitaryPanel tried to get an object with an invalid m_planet_id"; return TemporaryPtr<const Planet>(); } TemporaryPtr<const Planet> planet = boost::dynamic_pointer_cast<const Planet>(obj); if (!planet) { ErrorLogger() << "MilitaryPanel failed casting an object pointer to a Planet pointer"; return TemporaryPtr<const Planet>(); } return planet; }
void Planet::MoveTo(double x, double y) { //Logger().debugStream() << "Planet::MoveTo(double x, double y)"; // move planet itself UniverseObject::MoveTo(x, y); // move buildings for (std::set<int>::const_iterator it = m_buildings.begin(); it != m_buildings.end(); ++it) { UniverseObject* obj = GetUniverseObject(*it); if (!obj) { Logger().errorStream() << "Planet::MoveTo couldn't get building object with id " << *it; continue; } obj->UniverseObject::MoveTo(x, y); } }
bool BuildingType::EnqueueLocation(int empire_id, int location_id) const { if (!m_enqueue_location) return ProductionLocation(empire_id, location_id); std::shared_ptr<const UniverseObject> location = GetUniverseObject(location_id); if (!location) return false; std::shared_ptr<const UniverseObject> source = Empires().GetSource(empire_id); if (!source) return false; return m_enqueue_location->Eval(ScriptingContext(source), location); }
void ProductionWnd::UpdateInfoPanel() { const Empire* empire = GetEmpire(m_empire_shown_id); if (!empire) { m_production_info_panel->SetName(UserString("PRODUCTION_WND_TITLE")); m_production_info_panel->ClearLocalInfo(); return; } else { m_production_info_panel->SetEmpireID(m_empire_shown_id); } const ProductionQueue& queue = empire->GetProductionQueue(); float PPs = empire->ProductionPoints(); float total_queue_cost = queue.TotalPPsSpent(); m_production_info_panel->SetTotalPointsCost(PPs, total_queue_cost); // find if there is a local location int prod_loc_id = this->SelectedPlanetID(); TemporaryPtr<UniverseObject> loc_obj = GetUniverseObject(prod_loc_id); if (loc_obj) { // extract available and allocated PP at production location std::map<std::set<int>, float> available_pp = queue.AvailablePP(empire->GetResourcePool(RE_INDUSTRY)); const std::map<std::set<int>, float>& allocated_pp = queue.AllocatedPP(); float available_pp_at_loc = 0.0f, allocated_pp_at_loc = 0.0f; // for the resource sharing group containing the selected production location for (std::map<std::set<int>, float>::const_iterator map_it = available_pp.begin(); map_it != available_pp.end(); ++map_it) { if (map_it->first.find(prod_loc_id) != map_it->first.end()) { available_pp_at_loc = map_it->second; break; } } for (std::map<std::set<int>, float>::const_iterator map_it = allocated_pp.begin(); map_it != allocated_pp.end(); ++map_it) { if (map_it->first.find(prod_loc_id) != map_it->first.end()) { allocated_pp_at_loc = map_it->second; break; } } m_production_info_panel->SetLocalPointsCost(available_pp_at_loc, allocated_pp_at_loc, loc_obj->Name()); } else { // else clear local info... m_production_info_panel->ClearLocalInfo(); } }
float HullType::ProductionCost(int empire_id, int location_id) const { if (CHEAP_AND_FAST_SHIP_PRODUCTION || !m_production_cost) { return 1.0f; } else { if (ValueRef::ConstantExpr(m_production_cost)) return static_cast<float>(m_production_cost->Eval()); TemporaryPtr<UniverseObject> location = GetUniverseObject(location_id); if (!location) return 999999.9f; // arbitrary large number TemporaryPtr<const UniverseObject> source = SourceForEmpire(empire_id); ScriptingContext context(source, location); return static_cast<float>(m_production_cost->Eval(context)); } }
int HullType::ProductionTime(int empire_id, int location_id) const { if (CHEAP_AND_FAST_SHIP_PRODUCTION || !m_production_time) { return 1; } else { if (ValueRef::ConstantExpr(m_production_time)) return m_production_time->Eval(); UniverseObject* location = GetUniverseObject(location_id); if (!location) return 9999; // arbitrary large number const UniverseObject* source = SourceForEmpire(empire_id); ScriptingContext context(source, location); return m_production_time->Eval(context); } }
void ResourcePanel::CompleteConstruction() { AccordionPanel::CompleteConstruction(); SetName("ResourcePanel"); auto res = GetResCenter(); if (!res) throw std::invalid_argument("Attempted to construct a ResourcePanel with an UniverseObject that is not a ResourceCenter"); m_expand_button->LeftClickedSignal.connect( boost::bind(&ResourcePanel::ExpandCollapseButtonPressed, this)); const auto obj = GetUniverseObject(m_rescenter_id); if (!obj) { ErrorLogger() << "Invalid object id " << m_rescenter_id; return; } // meter and production indicators std::vector<std::pair<MeterType, MeterType>> meters; // small meter indicators - for use when panel is collapsed for (MeterType meter : {METER_INDUSTRY, METER_RESEARCH, METER_SUPPLY, METER_STOCKPILE}) { auto stat = GG::Wnd::Create<StatisticIcon>( ClientUI::MeterIcon(meter), obj->InitialMeterValue(meter), 3, false, MeterIconSize().x, MeterIconSize().y); stat->InstallEventFilter(shared_from_this()); AttachChild(stat); m_meter_stats.push_back({meter, stat}); meters.push_back({meter, AssociatedMeterType(meter)}); } // attach and show meter bars and large resource indicators m_multi_meter_status_bar = GG::Wnd::Create<MultiMeterStatusBar>(Width() - 2*EDGE_PAD, m_rescenter_id, meters); m_multi_icon_value_indicator = GG::Wnd::Create<MultiIconValueIndicator>(Width() - 2*EDGE_PAD, m_rescenter_id, meters); // determine if this panel has been created yet. auto it = s_expanded_map.find(m_rescenter_id); if (it == s_expanded_map.end()) s_expanded_map[m_rescenter_id] = false; // if not, default to collapsed state Refresh(); }
RenameOrder::RenameOrder(int empire, int object, const std::string& name) : Order(empire), m_object(object), m_name(name) { TemporaryPtr<const UniverseObject> obj = GetUniverseObject(object); if (!obj) { ErrorLogger() << "RenameOrder::RenameOrder() : Attempted to rename nonexistant object with id " << object; return; } if (m_name.empty()) { ErrorLogger() << "RenameOrder::RenameOrder() : Attempted to name an object \"\"."; // make order do nothing m_object = INVALID_OBJECT_ID; return; } }
int PartType::ProductionTime(int empire_id, int location_id) const { if (CHEAP_AND_FAST_SHIP_PRODUCTION || !m_production_time) { return 1; } else { if (ValueRef::ConstantExpr(m_production_time)) return m_production_time->Eval(); TemporaryPtr<UniverseObject> location = GetUniverseObject(location_id); if (!location) return 9999; // arbitrary large number TemporaryPtr<const UniverseObject> source = SourceForEmpire(empire_id); if (!source && !m_production_time->SourceInvariant()) return 9999; ScriptingContext context(source, location); return m_production_time->Eval(context); } }