Skip to content

Commit

Permalink
Most of the way toward ship support
Browse files Browse the repository at this point in the history
Checks are failing on one problem and don't seem to be giving an error message.
  • Loading branch information
TheGiraffe3 authored Nov 4, 2024
1 parent 767b9df commit 6eb5d7d
Show file tree
Hide file tree
Showing 17 changed files with 649 additions and 75 deletions.
6 changes: 4 additions & 2 deletions source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,12 @@ target_sources(EndlessSkyLib PRIVATE
ConversationPanel.h
CoreStartData.cpp
CoreStartData.h
CustomSale.cpp
CustomSale.h
CustomOutfitSale.cpp
CustomOutfitSale.h
CustomSaleManager.cpp
CustomSaleManager.h
CustomShipSale.cpp
CustomShipSale.h
DamageDealt.h
DamageProfile.cpp
DamageProfile.h
Expand Down
35 changes: 17 additions & 18 deletions source/CustomSale.cpp → source/CustomOutfitSale.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* CustomSale.cpp
/* CustomOutfitSale.cpp
Copyright (c) 2024 by Hurleveur
Endless Sky is free software: you can redistribute it and/or modify it under the
Expand All @@ -13,7 +13,7 @@ You should have received a copy of the GNU General Public License along with
this program. If not, see <https://www.gnu.org/licenses/>.
*/

#include "CustomSale.h"
#include "CustomOutfitSale.h"

#include "ConditionsStore.h"
#include "DataNode.h"
Expand All @@ -27,9 +27,9 @@ using namespace std;

namespace
{
const auto show = map<CustomSale::SellType, const string> {
{CustomSale::SellType::DEFAULT, ""},
{CustomSale::SellType::IMPORT, "import"}
const auto show = map<CustomOutfitSale::SellType, const string> {
{CustomOutfitSale::SellType::DEFAULT, ""},
{CustomOutfitSale::SellType::IMPORT, "import"}
};
// Initially put values at this to know if we found what we're looking for,
// whilst allowing 0 in the searched list.
Expand All @@ -38,7 +38,7 @@ namespace



void CustomSale::Load(const DataNode &node, bool eventChange)
void CustomOutfitSale::Load(const DataNode &node, bool eventChange)
{
const Set<Sale<Outfit>> &items = GameData::Outfitters();
const Set<Outfit> &outfits = GameData::Outfits();
Expand Down Expand Up @@ -159,8 +159,7 @@ void CustomSale::Load(const DataNode &node, bool eventChange)
conditions = ConditionSet{};
conditions.Load(child);
}
// CustomSales are separated between outfits and outfitters in the data files.
// This mode could apply to other things like shipyards and ships, later on.
// CustomOutfitSales are separated between outfits and outfitters in the data files.
else if(mode == "outfits")
{
if(!add)
Expand Down Expand Up @@ -219,7 +218,7 @@ void CustomSale::Load(const DataNode &node, bool eventChange)



void CustomSale::FinishLoading()
void CustomOutfitSale::FinishLoading()
{
for(const auto &it : toConvert)
if(it.first->Cost() != 0)
Expand Down Expand Up @@ -255,7 +254,7 @@ void CustomSale::FinishLoading()



bool CustomSale::Add(const CustomSale &other, const Planet &planet, const ConditionsStore &store)
bool CustomOutfitSale::Add(const CustomOutfitSale &other, const Planet &planet, const ConditionsStore &store)
{
cacheValid = false;
if(!Matches(planet, store))
Expand Down Expand Up @@ -311,7 +310,7 @@ bool CustomSale::Add(const CustomSale &other, const Planet &planet, const Condit



double CustomSale::GetRelativeCost(const Outfit &item) const
double CustomOutfitSale::GetRelativeCost(const Outfit &item) const
{
// Outfit prices have priority over outfitter prices, so consider them first,
// and only consider the outfitter prices if the outfits have no set price.
Expand Down Expand Up @@ -345,21 +344,21 @@ double CustomSale::GetRelativeCost(const Outfit &item) const



CustomSale::SellType CustomSale::GetSellType() const
CustomOutfitSale::SellType CustomOutfitSale::GetSellType() const
{
return sellType;
}



const string &CustomSale::GetShown(CustomSale::SellType sellType)
const string &CustomOutfitSale::GetShown(CustomOutfitSale::SellType sellType)
{
return show.find(sellType)->second;
}



bool CustomSale::Has(const Outfit &item) const
bool CustomOutfitSale::Has(const Outfit &item) const
{
if(relativeOutfitPrices.find(&item) != relativeOutfitPrices.end())
return true;
Expand All @@ -376,23 +375,23 @@ bool CustomSale::Has(const Outfit &item) const



bool CustomSale::Matches(const Planet &planet, const ConditionsStore &playerConditions) const
bool CustomOutfitSale::Matches(const Planet &planet, const ConditionsStore &playerConditions) const
{
return (location ? location == &planet : locationFilter.Matches(&planet)) &&
(conditions.IsEmpty() || conditions.Test(playerConditions));
}



bool CustomSale::IsEmpty()
bool CustomOutfitSale::IsEmpty()
{
return relativePrices.empty() && relativeOffsets.empty() &&
relativeOutfitPrices.empty() && relativeOutfitOffsets.empty();
}



void CustomSale::Clear()
void CustomOutfitSale::Clear()
{
*this = CustomSale{};
*this = CustomOutfitSale{};
}
14 changes: 7 additions & 7 deletions source/CustomSale.h → source/CustomOutfitSale.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* CustomSale.h
/* CustomOutfitSale.h
Copyright (c) 2024 by Hurleveur
Endless Sky is free software: you can redistribute it and/or modify it under the
Expand Down Expand Up @@ -33,8 +33,8 @@ class Outfit;


// Class used to stock Outfits and their local changes, being prices and sell types,
// linked by outfit or by group of outfits (aka outfitters).
class CustomSale {
// linked by an outfit or group of outfits (aka outfitters).
class CustomOutfitSale {
public:
// Sell types: none is meant to be default, meaning the visibility depends on the outfitter,
// import means it is shown whilst still not being buyable.
Expand All @@ -52,8 +52,8 @@ class CustomSale {
void Load(const DataNode &node, bool eventChange = false);
void FinishLoading();

// Adds another CustomSale to this one if the conditions allow it.
bool Add(const CustomSale &other, const Planet &planet, const ConditionsStore &store);
// Adds another CustomOutfitSale to this one if the conditions allow it.
bool Add(const CustomOutfitSale &other, const Planet &planet, const ConditionsStore &store);

// Get the price of the item.
// Does not check conditions are met or the location is matched.
Expand All @@ -66,7 +66,7 @@ class CustomSale {

bool Has(const Outfit &item) const;

// Check if this planet with the given conditions of the player match the conditions of the CustomSale.
// Check if this planet with the given conditions of the player match the conditions of the CustomOutfitSale.
bool Matches(const Planet &planet, const ConditionsStore &playerConditions) const;

bool IsEmpty();
Expand All @@ -88,7 +88,7 @@ class CustomSale {
std::map<const Outfit *, double> relativeOutfitPrices;
std::map<const Outfit *, double> relativeOutfitOffsets;

// All outfits this customSale has, kept in cache.
// All outfits this CustomOutfitSale has, kept in cache.
Sale<Outfit> seen;
bool cacheValid = false;

Expand Down
91 changes: 72 additions & 19 deletions source/CustomSaleManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,47 @@ this program. If not, see <https://www.gnu.org/licenses/>.

using namespace std;

map<CustomSale::SellType, CustomSale> CustomSaleManager::customSales = {};


void CustomOutfitSaleManager::Refresh(const Planet *planet, const ConditionsStore &conditions)
{
Clear();
if(!planet)
return;
for(const auto &sale : GameData::CustomOutfitSales())
customOutfitSales[sale.second.GetSellType()].Add(sale.second, *planet, conditions);
}



void CustomOutfitSaleManager::Refresh(const System *system, const ConditionsStore &conditions)
{
Clear();
if(!system)
return;
for(const StellarObject &object : system->Objects())
if(object.HasSprite() && object.HasValidPlanet())
{
const Planet &planet = *object.GetPlanet();
for(const auto &sale : GameData::CustomOutfitSales())
customOutfitSales[sale.second.GetSellType()].Add(sale.second, planet, conditions);
}
}


void CustomSaleManager::Refresh(const Planet *planet, const ConditionsStore &conditions)

void CustomShipSaleManager::Refresh(const Planet *planet, const ConditionsStore &conditions)
{
Clear();
if(!planet)
return;
for(const auto &sale : GameData::CustomSales())
customSales[sale.second.GetSellType()].Add(sale.second, *planet, conditions);
for(const auto &sale : GameData::CustomShipSales())
customShipSales[sale.second.GetSellType()].Add(sale.second, *planet, conditions);
}



void CustomSaleManager::Refresh(const System *system, const ConditionsStore &conditions)
void CustomShipSaleManager::Refresh(const System *system, const ConditionsStore &conditions)
{
Clear();
if(!system)
Expand All @@ -49,52 +74,80 @@ void CustomSaleManager::Refresh(const System *system, const ConditionsStore &con
if(object.HasSprite() && object.HasValidPlanet())
{
const Planet &planet = *object.GetPlanet();
for(const auto &sale : GameData::CustomSales())
customSales[sale.second.GetSellType()].Add(sale.second, planet, conditions);
for(const auto &sale : GameData::CustomShipSales())
customShipSales[sale.second.GetSellType()].Add(sale.second, planet, conditions);
}
}



bool CustomSaleManager::CanBuy(const Outfit &outfit)
bool CustomOutfitSaleManager::CanBuy(const Outfit &outfit)
{
const auto &it = customSales.find(CustomSale::SellType::IMPORT);
return it == customSales.end() || !it->second.Has(outfit);
const auto &it = customOutfitSales.find(CustomOutfitSale::SellType::IMPORT);
return it == customOutfitSales.end() || !it->second.Has(outfit);
}



int64_t CustomSaleManager::OutfitCost(const Outfit &outfit)
int64_t CustomOutfitSaleManager::OutfitCost(const Outfit &outfit)
{
return OutfitRelativeCost(outfit) * outfit.Cost();
}



double CustomSaleManager::OutfitRelativeCost(const Outfit &outfit)
double CustomOutfitSaleManager::OutfitRelativeCost(const Outfit &outfit)
{
if(customSales.empty())
if(customOutfitSales.empty())
return 1.;
// Iterate in the opposite order, since any higher customSale has priority.
for(auto &&selling = customSales.rbegin(); selling != customSales.rend(); ++selling)
for(auto &&selling = customOutfitSales.rbegin(); selling != customOutfitSales.rend(); ++selling)
if(selling->second.Has(outfit))
return selling->second.GetRelativeCost(outfit);
return 1.;
}



int64_t CustomSaleManager::ShipCost(const Ship &ship)
bool CustomShipSaleManager::CanBuy(const Ship &ship)
{
const auto &it = customShipSales.find(CustomShipSale::SellType::IMPORT);
return it == customShipSales.end() || !it->second.Has(ship);
}



double CustomShipSaleManager::ShipRelativeCost(const Ship &ship)
{
if(customShipSales.empty())
return 1.;
// Iterate in the opposite order, since any higher customSale has priority.
for(auto &&selling = customShipSales.rbegin(); selling != customShipSales.rend(); ++selling)
if(selling->second.Has(ship))
return selling->second.GetRelativeCost(ship);
return 1.;
}



int64_t CustomShipSaleManager::ShipCost(const Ship &ship)
{
int64_t localCost = ship.ChassisCost();
for(auto &&it : ship.Outfits())
localCost += OutfitCost(*it.first) * it.second;
for(auto it : ship.Outfits())
localCost += (CustomOutfitSaleManager::OutfitCost(*it.first) * it.second);
return localCost;
}



void CustomSaleManager::Clear()
void CustomOutfitSaleManager::Clear()
{
customOutfitSales = {};
}



void CustomShipSaleManager::Clear()
{
customSales = {};
customShipSales = {};
}
30 changes: 26 additions & 4 deletions source/CustomSaleManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ this program. If not, see <https://www.gnu.org/licenses/>.

#pragma once

#include "CustomSale.h"
#include "CustomOutfitSale.h"
#include "CustomShipSale.h"

#include <map>

Expand All @@ -27,7 +28,7 @@ class System;



class CustomSaleManager {
class CustomOutfitSaleManager {
public:
// Refresh the active CustomSales to correspond to the planet and conditions.
static void Refresh(const Planet *planet, const ConditionsStore &conditions);
Expand All @@ -36,14 +37,35 @@ class CustomSaleManager {
// Return if can be bought. And imported item will still be shown but not be buyable.
static bool CanBuy(const Outfit &outfit);

// Get the full/relative cost of the outfit/ship with the last cached conditions.
// Get the full/relative cost of the outfit with the last cached conditions.
static int64_t OutfitCost(const Outfit &outfit);
static double OutfitRelativeCost(const Outfit &outfit);
// Delete all cached data.
static void Clear();


private:
static std::map<CustomOutfitSale::SellType, CustomOutfitSale> customOutfitSales;
};



class CustomShipSaleManager {
public:
// Refresh the active CustomSales to correspond to the planet and conditions.
static void Refresh(const Planet *planet, const ConditionsStore &conditions);
// Or to all planets in this system.
static void Refresh(const System *system, const ConditionsStore &conditions);
// Return if can be bought. And imported item will still be shown but not be buyable.
static bool CanBuy(const Ship &ship);

// Get the full/relative cost of the ship with the last cached conditions.
static int64_t ShipCost(const Ship &ship);
static double ShipRelativeCost(const Ship &ship);
// Delete all cached data.
static void Clear();


private:
static std::map<CustomSale::SellType, CustomSale> customSales;
static std::map<CustomShipSale::SellType, CustomShipSale> customShipSales;
};
Loading

0 comments on commit 6eb5d7d

Please sign in to comment.