Skip to content

Commit

Permalink
feat(ui): Allow using u or c in the shipyard to sell a ship while sen…
Browse files Browse the repository at this point in the history
…ding all outfits to storage (endless-sky#7154)
  • Loading branch information
kaol authored Nov 20, 2023
1 parent 9843a37 commit 9ca1df6
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 22 deletions.
16 changes: 9 additions & 7 deletions source/Depreciation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,13 @@ void Depreciation::Init(const vector<shared_ptr<Ship>> &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());
Expand Down Expand Up @@ -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<shared_ptr<Ship>> &fleet, int day) const
int64_t Depreciation::Value(const vector<shared_ptr<Ship>> &fleet, int day, bool chassisOnly) const
{
map<const Ship *, int> shipCount;
map<const Outfit *, int> outfitCount;
Expand All @@ -238,8 +239,9 @@ int64_t Depreciation::Value(const vector<shared_ptr<Ship>> &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;
Expand Down
4 changes: 2 additions & 2 deletions source/Depreciation.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ class Depreciation {
void Init(const std::vector<std::shared_ptr<Ship>> &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<std::shared_ptr<Ship>> &fleet, int day) const;
int64_t Value(const std::vector<std::shared_ptr<Ship>> &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.
Expand Down
26 changes: 21 additions & 5 deletions source/PlayerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
2 changes: 1 addition & 1 deletion source/PlayerInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
37 changes: 32 additions & 5 deletions source/ShipyardPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -339,10 +345,17 @@ void ShipyardPanel::Sell(bool toStorage)
vector<shared_ptr<Ship>> 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));
}


Expand Down Expand Up @@ -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> &ship : player.Ships())
Expand Down
4 changes: 3 additions & 1 deletion source/ShipyardPanel.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion source/ShopPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))))
{
Expand Down

0 comments on commit 9ca1df6

Please sign in to comment.