diff --git a/source/Depreciation.cpp b/source/Depreciation.cpp index 4a19200f18b8..1527201fe79e 100644 --- a/source/Depreciation.cpp +++ b/source/Depreciation.cpp @@ -164,12 +164,13 @@ void Depreciation::Init(const vector> &fleet, int day) // Add a ship, and all its outfits, to the depreciation record. -void Depreciation::Buy(const Ship &ship, int day, Depreciation *source) +void Depreciation::Buy(const Ship &ship, int day, Depreciation *source, bool chassisOnly) { // First, add records for all outfits the ship is carrying. - for(const auto &it : ship.Outfits()) - for(int i = 0; i < it.second; ++i) - Buy(it.first, day, source); + if(!chassisOnly) + for(const auto &it : ship.Outfits()) + for(int i = 0; i < it.second; ++i) + Buy(it.first, day, source); // Then, check the base day for the ship chassis itself. const Ship *base = GameData::Ships().Get(ship.TrueModelName()); @@ -228,7 +229,7 @@ void Depreciation::Buy(const Outfit *outfit, int day, Depreciation *source) // Get the value of an entire fleet. -int64_t Depreciation::Value(const vector> &fleet, int day) const +int64_t Depreciation::Value(const vector> &fleet, int day, bool chassisOnly) const { map shipCount; map outfitCount; @@ -238,8 +239,9 @@ int64_t Depreciation::Value(const vector> &fleet, int day) cons const Ship *base = GameData::Ships().Get(ship->TrueModelName()); ++shipCount[base]; - for(const auto &it : ship->Outfits()) - outfitCount[it.first] += it.second; + if(!chassisOnly) + for(const auto &it : ship->Outfits()) + outfitCount[it.first] += it.second; } int64_t value = 0; diff --git a/source/Depreciation.h b/source/Depreciation.h index 3e56fe6427f1..fa76a2eb4d2d 100644 --- a/source/Depreciation.h +++ b/source/Depreciation.h @@ -49,12 +49,12 @@ class Depreciation { void Init(const std::vector> &fleet, int day); // Add a ship, and all its outfits, to the depreciation record. - void Buy(const Ship &ship, int day, Depreciation *source = nullptr); + void Buy(const Ship &ship, int day, Depreciation *source = nullptr, bool chassisOnly = false); // Add a single outfit to the depreciation record. void Buy(const Outfit *outfit, int day, Depreciation *source = nullptr); // Get the value of an entire fleet. - int64_t Value(const std::vector> &fleet, int day) const; + int64_t Value(const std::vector> &fleet, int day, bool chassisOnly = false) const; // Get the value of a ship, along with all its outfits. int64_t Value(const Ship &ship, int day) const; // Get the value just of the chassis of a ship. diff --git a/source/PlayerInfo.cpp b/source/PlayerInfo.cpp index 31e6aaa7e869..76d1a024af66 100644 --- a/source/PlayerInfo.cpp +++ b/source/PlayerInfo.cpp @@ -1205,18 +1205,34 @@ const Ship *PlayerInfo::GiftShip(const Ship *model, const string &name, const st // Sell the given ship (if it belongs to the player). -void PlayerInfo::SellShip(const Ship *selected) +void PlayerInfo::SellShip(const Ship *selected, bool storeOutfits) { for(auto it = ships.begin(); it != ships.end(); ++it) if(it->get() == selected) { int day = date.DaysSinceEpoch(); - int64_t cost = depreciation.Value(*selected, day); + int64_t cost; + + // Passing a pointer to Value gets only the hull cost. Passing a reference + // gets hull and outfit costs. + if(storeOutfits) + cost = depreciation.Value(selected, day); + else + cost = depreciation.Value(*selected, day); // Record the transfer of this ship in the depreciation and stock info. - stockDepreciation.Buy(*selected, day, &depreciation); - for(const auto &it : selected->Outfits()) - stock[it.first] += it.second; + stockDepreciation.Buy(*selected, day, &depreciation, storeOutfits); + if(storeOutfits) + { + CargoHold &storage = Storage(); + for(const auto &it : selected->Outfits()) + storage.Add(it.first, it.second); + } + else + { + for(const auto &it : selected->Outfits()) + stock[it.first] += it.second; + } accounts.AddCredits(cost); ForgetGiftedShip(*it->get()); diff --git a/source/PlayerInfo.h b/source/PlayerInfo.h index d41518691413..58d41edd3c17 100644 --- a/source/PlayerInfo.h +++ b/source/PlayerInfo.h @@ -167,7 +167,7 @@ class PlayerInfo { // In the case of a gift, return a pointer to the newly instantiated ship. void BuyShip(const Ship *model, const std::string &name); const Ship *GiftShip(const Ship *model, const std::string &name, const std::string &id); - void SellShip(const Ship *selected); + void SellShip(const Ship *selected, bool storeOutfits = false); // Take the ship from the player, if a model is specified this will permanently remove outfits in said model, // instead of allowing the player to buy them back by putting them in the stock. void TakeShip(const Ship *shipToTake, const Ship *model = nullptr, bool takeOutfits = false); diff --git a/source/ShipyardPanel.cpp b/source/ShipyardPanel.cpp index edc394f299cf..a904aa0a8d46 100644 --- a/source/ShipyardPanel.cpp +++ b/source/ShipyardPanel.cpp @@ -306,7 +306,13 @@ void ShipyardPanel::Sell(bool toStorage) int count = playerShips.size(); int initialCount = count; - string message = "Sell the "; + string message; + if(!toStorage) + message = "Sell the "; + else if(count == 1) + message = "Sell the hull of the "; + else + message = "Sell the hulls of the "; if(count == 1) message += playerShip->Name(); else if(count <= MAX_LIST) @@ -339,10 +345,17 @@ void ShipyardPanel::Sell(bool toStorage) vector> toSell; for(const auto &it : playerShips) toSell.push_back(it->shared_from_this()); - int64_t total = player.FleetDepreciation().Value(toSell, day); + int64_t total = player.FleetDepreciation().Value(toSell, day, toStorage); message += ((initialCount > 2) ? "\nfor " : " for ") + Format::CreditString(total) + "?"; - GetUI()->Push(new Dialog(this, &ShipyardPanel::SellShip, message, Truncate::MIDDLE)); + + if(toStorage) + { + message += " Any outfits will be placed in storage."; + GetUI()->Push(new Dialog(this, &ShipyardPanel::SellShipChassis, message, Truncate::MIDDLE)); + } + else + GetUI()->Push(new Dialog(this, &ShipyardPanel::SellShipAndOutfits, message, Truncate::MIDDLE)); } @@ -386,10 +399,24 @@ void ShipyardPanel::BuyShip(const string &name) -void ShipyardPanel::SellShip() +void ShipyardPanel::SellShipAndOutfits() +{ + SellShip(false); +} + + + +void ShipyardPanel::SellShipChassis() +{ + SellShip(true); +} + + + +void ShipyardPanel::SellShip(bool toStorage) { for(Ship *ship : playerShips) - player.SellShip(ship); + player.SellShip(ship, toStorage); playerShips.clear(); playerShip = nullptr; for(const shared_ptr &ship : player.Ships()) diff --git a/source/ShipyardPanel.h b/source/ShipyardPanel.h index f680137d3003..7bec569a30e4 100644 --- a/source/ShipyardPanel.h +++ b/source/ShipyardPanel.h @@ -56,7 +56,9 @@ class ShipyardPanel : public ShopPanel { private: void BuyShip(const std::string &name); - void SellShip(); + void SellShipAndOutfits(); + void SellShipChassis(); + void SellShip(bool toStorage); private: diff --git a/source/ShopPanel.cpp b/source/ShopPanel.cpp index 2dda201a7bbe..97440f6b106b 100644 --- a/source/ShopPanel.cpp +++ b/source/ShopPanel.cpp @@ -292,7 +292,7 @@ void ShopPanel::ToggleCargo() // Only override the ones you need; the default action is to return false. bool ShopPanel::KeyDown(SDL_Keycode key, Uint16 mod, const Command &command, bool isNewPress) { - bool toStorage = selectedOutfit && (key == 'r' || key == 'u'); + bool toStorage = planet && planet->HasOutfitter() && (key == 'r' || key == 'u'); if(key == 'l' || key == 'd' || key == SDLK_ESCAPE || (key == 'w' && (mod & (KMOD_CTRL | KMOD_GUI)))) {