float Ship::TroopCapacity() const { float retval = 0.0f; // find which troop parts are present in design (one copy of name for each instance of a part, allowing duplicate names to appear) const ShipDesign* design = Design(); if (!design) return retval; const std::vector<std::string>& parts = design->Parts(); for (std::vector<std::string>::const_iterator part_it = parts.begin(); part_it != parts.end(); ++part_it) { const std::string& part_name = *part_it; if (part_name.empty()) continue; const PartType* part_type = GetPartType(part_name); if (!part_type) continue; ShipPartClass part_class = part_type->Class(); if (part_class != PC_TROOPS) continue; // add capacity for all instances of colony parts to accumulator retval += this->CurrentPartMeterValue(METER_CAPACITY, part_name); } return retval; }
bool Ship::HasFighters() const { const ShipDesign* design = Design(); if (design) return design->HasFighters(); else return false; }
bool Ship::IsArmed() const { const ShipDesign* design = Design(); if (design) return design->IsArmed(); else return false; }
bool Ship::CanColonize() const { if (m_species_name.empty()) return false; const Species* species = GetSpecies(m_species_name); if (!species) return false; if (!species->CanColonize()) return false; const ShipDesign* design = Design(); if (!design) return false; if (!design->CanColonize()) return false; return true; }
const std::string& Ship::PublicName(int empire_id) const { // Disclose real ship name only to fleet owners. Rationale: a player who // doesn't know the design for a particular ship can easily guess it if the // ship's name is "Scout" // An exception is made for unowned monsters. if (GetUniverse().AllObjectsVisible() || empire_id == ALL_EMPIRES || OwnedBy(empire_id) || (IsMonster() && Owner() == ALL_EMPIRES)) return Name(); const ShipDesign* design = Design(); if (design) return design->Name(); else if (IsMonster()) return UserString("SM_MONSTER"); else if (!Unowned()) return UserString("FW_FOREIGN_SHIP"); else if (Unowned() && GetVisibility(empire_id) > VIS_NO_VISIBILITY) return UserString("FW_ROGUE_SHIP"); else return UserString("OBJ_SHIP"); }
bool Ship::CanHaveTroops() const { const ShipDesign* design = Design(); return design ? design->HasTroops() : false; }
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; } } } }
bool Ship::CanBombard() const { const ShipDesign* design = Design(); return design && design->CanBombard(); }
bool Ship::HasTroops() const { const ShipDesign* design = Design(); return design && design->HasTroops(); }
Ship::Ship(int empire_id, int design_id, const std::string& species_name, int produced_by_empire_id/* = ALL_EMPIRES*/) : 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) { 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)) Logger().debugStream() << "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_BATTLE_SPEED); AddMeter(METER_STARLANE_SPEED); 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) { Logger().errorStream() << "Ship::Ship couldn't get part with name " << part_names[i]; continue; } switch (part->Class()) { case PC_SHORT_RANGE: case PC_POINT_DEFENSE: { m_part_meters[std::make_pair(METER_DAMAGE, part->Name())]; m_part_meters[std::make_pair(METER_ROF, part->Name())]; m_part_meters[std::make_pair(METER_RANGE, part->Name())]; break; } case PC_MISSILES: { std::pair<std::size_t, std::size_t>& part_missiles = m_missiles[part_names[i]]; ++part_missiles.first; part_missiles.second += boost::get<LRStats>(part->Stats()).m_capacity; m_part_meters[std::make_pair(METER_DAMAGE, part->Name())]; m_part_meters[std::make_pair(METER_ROF, part->Name())]; m_part_meters[std::make_pair(METER_RANGE, part->Name())]; m_part_meters[std::make_pair(METER_SPEED, part->Name())]; m_part_meters[std::make_pair(METER_STEALTH, part->Name())]; m_part_meters[std::make_pair(METER_STRUCTURE, part->Name())]; m_part_meters[std::make_pair(METER_CAPACITY, part->Name())]; break; } case PC_FIGHTERS: { std::pair<std::size_t, std::size_t>& part_fighters = m_fighters[part_names[i]]; ++part_fighters.first; part_fighters.second += boost::get<FighterStats>(part->Stats()).m_capacity; m_part_meters[std::make_pair(METER_ANTI_SHIP_DAMAGE, part->Name())]; m_part_meters[std::make_pair(METER_ANTI_FIGHTER_DAMAGE, part->Name())]; m_part_meters[std::make_pair(METER_LAUNCH_RATE, part->Name())]; m_part_meters[std::make_pair(METER_FIGHTER_WEAPON_RANGE,part->Name())]; m_part_meters[std::make_pair(METER_SPEED, part->Name())]; m_part_meters[std::make_pair(METER_STEALTH, part->Name())]; m_part_meters[std::make_pair(METER_STRUCTURE, part->Name())]; m_part_meters[std::make_pair(METER_DETECTION, part->Name())]; m_part_meters[std::make_pair(METER_CAPACITY, part->Name())]; break; } default: break; } } } }