2023-06-02 20:47:37 +02:00
|
|
|
/*
|
|
|
|
* IMarket.cpp, part of VCMI engine
|
|
|
|
*
|
|
|
|
* Authors: listed in file AUTHORS in main folder
|
|
|
|
*
|
|
|
|
* License: GNU General Public License v2.0 or later
|
|
|
|
* Full text of license available in license.txt file, in main folder
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "StdInc.h"
|
|
|
|
#include "IMarket.h"
|
|
|
|
|
|
|
|
#include "CArtHandler.h"
|
|
|
|
#include "CCreatureHandler.h"
|
|
|
|
#include "CGObjectInstance.h"
|
|
|
|
#include "CObjectHandler.h"
|
|
|
|
|
|
|
|
#include "../VCMI_Lib.h"
|
|
|
|
|
2023-06-02 21:00:44 +02:00
|
|
|
VCMI_LIB_NAMESPACE_BEGIN
|
|
|
|
|
2024-08-16 17:00:02 +02:00
|
|
|
bool IMarket::allowsTrade(const EMarketMode mode) const
|
|
|
|
{
|
2024-08-20 16:15:50 +02:00
|
|
|
return vstd::contains(marketModes, mode);
|
2024-08-16 17:00:02 +02:00
|
|
|
}
|
|
|
|
|
2023-08-19 20:43:50 +02:00
|
|
|
bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode) const
|
2023-06-02 20:47:37 +02:00
|
|
|
{
|
|
|
|
switch(mode)
|
|
|
|
{
|
|
|
|
case EMarketMode::RESOURCE_RESOURCE:
|
|
|
|
{
|
|
|
|
double effectiveness = std::min((getMarketEfficiency() + 1.0) / 20.0, 0.5);
|
|
|
|
|
|
|
|
double r = VLC->objh->resVals[id1]; //value of given resource
|
|
|
|
double g = VLC->objh->resVals[id2] / effectiveness; //value of wanted resource
|
|
|
|
|
|
|
|
if(r>g) //if given resource is more expensive than wanted
|
|
|
|
{
|
|
|
|
val2 = static_cast<int>(ceil(r / g));
|
|
|
|
val1 = 1;
|
|
|
|
}
|
|
|
|
else //if wanted resource is more expensive
|
|
|
|
{
|
|
|
|
val1 = static_cast<int>((g / r) + 0.5);
|
|
|
|
val2 = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EMarketMode::CREATURE_RESOURCE:
|
|
|
|
{
|
|
|
|
const double effectivenessArray[] = {0.0, 0.3, 0.45, 0.50, 0.65, 0.7, 0.85, 0.9, 1.0};
|
|
|
|
double effectiveness = effectivenessArray[std::min(getMarketEfficiency(), 8)];
|
|
|
|
|
|
|
|
double r = VLC->creatures()->getByIndex(id1)->getRecruitCost(EGameResID::GOLD); //value of given creature in gold
|
|
|
|
double g = VLC->objh->resVals[id2] / effectiveness; //value of wanted resource
|
|
|
|
|
|
|
|
if(r>g) //if given resource is more expensive than wanted
|
|
|
|
{
|
|
|
|
val2 = static_cast<int>(ceil(r / g));
|
|
|
|
val1 = 1;
|
|
|
|
}
|
|
|
|
else //if wanted resource is more expensive
|
|
|
|
{
|
|
|
|
val1 = static_cast<int>((g / r) + 0.5);
|
|
|
|
val2 = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EMarketMode::RESOURCE_PLAYER:
|
|
|
|
val1 = 1;
|
|
|
|
val2 = 1;
|
|
|
|
break;
|
|
|
|
case EMarketMode::RESOURCE_ARTIFACT:
|
|
|
|
{
|
|
|
|
double effectiveness = std::min((getMarketEfficiency() + 3.0) / 20.0, 0.6);
|
|
|
|
double r = VLC->objh->resVals[id1]; //value of offered resource
|
|
|
|
double g = VLC->artifacts()->getByIndex(id2)->getPrice() / effectiveness; //value of bought artifact in gold
|
|
|
|
|
|
|
|
if(id1 != 6) //non-gold prices are doubled
|
|
|
|
r /= 2;
|
|
|
|
|
|
|
|
val1 = std::max(1, static_cast<int>((g / r) + 0.5)); //don't sell arts for less than 1 resource
|
|
|
|
val2 = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EMarketMode::ARTIFACT_RESOURCE:
|
|
|
|
{
|
|
|
|
double effectiveness = std::min((getMarketEfficiency() + 3.0) / 20.0, 0.6);
|
|
|
|
double r = VLC->artifacts()->getByIndex(id1)->getPrice() * effectiveness;
|
|
|
|
double g = VLC->objh->resVals[id2];
|
|
|
|
|
|
|
|
// if(id2 != 6) //non-gold prices are doubled
|
|
|
|
// r /= 2;
|
|
|
|
|
|
|
|
val1 = 1;
|
|
|
|
val2 = std::max(1, static_cast<int>((r / g) + 0.5)); //at least one resource is given in return
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EMarketMode::CREATURE_EXP:
|
|
|
|
{
|
|
|
|
val1 = 1;
|
2024-01-16 19:06:41 +02:00
|
|
|
val2 = (CreatureID(id1).toEntity(VLC)->getAIValue() / 40) * 5;
|
2023-06-02 20:47:37 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EMarketMode::ARTIFACT_EXP:
|
|
|
|
{
|
|
|
|
val1 = 1;
|
|
|
|
|
2024-01-16 19:06:41 +02:00
|
|
|
int givenClass = ArtifactID(id1).toArtifact()->getArtClassSerial();
|
2023-06-02 20:47:37 +02:00
|
|
|
if(givenClass < 0 || givenClass > 3)
|
|
|
|
{
|
|
|
|
val2 = 0;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static constexpr int expPerClass[] = {1000, 1500, 3000, 6000};
|
|
|
|
val2 = expPerClass[givenClass];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-08-12 16:38:30 +02:00
|
|
|
int IMarket::availableUnits(const EMarketMode mode, const int marketItemSerial) const
|
2023-06-02 20:47:37 +02:00
|
|
|
{
|
|
|
|
switch(mode)
|
|
|
|
{
|
|
|
|
case EMarketMode::RESOURCE_RESOURCE:
|
|
|
|
case EMarketMode::ARTIFACT_RESOURCE:
|
|
|
|
case EMarketMode::CREATURE_RESOURCE:
|
|
|
|
return -1;
|
|
|
|
default:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-16 17:00:02 +02:00
|
|
|
void IMarket::addMarketMode(const EMarketMode mode)
|
|
|
|
{
|
|
|
|
marketModes.insert(mode);
|
|
|
|
|
|
|
|
if(mode == EMarketMode::ARTIFACT_EXP)
|
2024-08-17 19:19:48 +02:00
|
|
|
altarArtifactsStorage = std::make_shared<CArtifactSetAltar>();
|
2024-08-16 17:00:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void IMarket::addMarketMode(const std::set<EMarketMode> & modes)
|
|
|
|
{
|
|
|
|
for(const auto & mode : modes)
|
|
|
|
addMarketMode(mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
void IMarket::removeMarketMode(const EMarketMode mode)
|
|
|
|
{
|
|
|
|
marketModes.erase(mode);
|
|
|
|
|
|
|
|
if(mode == EMarketMode::ARTIFACT_EXP)
|
2024-08-17 19:19:48 +02:00
|
|
|
altarArtifactsStorage.reset();
|
|
|
|
}
|
|
|
|
|
2024-08-20 22:36:31 +02:00
|
|
|
void IMarket::removeMarketMode(const std::set<EMarketMode> & modes)
|
|
|
|
{
|
|
|
|
for(const auto & mode : modes)
|
|
|
|
removeMarketMode(mode);
|
|
|
|
}
|
|
|
|
|
2024-08-17 21:06:48 +02:00
|
|
|
void IMarket::removeAllMarketModes()
|
|
|
|
{
|
|
|
|
marketModes.clear();
|
|
|
|
}
|
|
|
|
|
2024-08-17 19:19:48 +02:00
|
|
|
std::shared_ptr<CArtifactSet> IMarket::getArtifactsStorage() const
|
|
|
|
{
|
|
|
|
return altarArtifactsStorage;
|
2024-08-16 17:00:02 +02:00
|
|
|
}
|
|
|
|
|
2024-08-12 16:38:30 +02:00
|
|
|
std::vector<TradeItemBuy> IMarket::availableItemsIds(const EMarketMode mode) const
|
2023-06-02 20:47:37 +02:00
|
|
|
{
|
2023-11-08 17:49:08 +02:00
|
|
|
std::vector<TradeItemBuy> ret;
|
2023-06-02 20:47:37 +02:00
|
|
|
switch(mode)
|
|
|
|
{
|
|
|
|
case EMarketMode::RESOURCE_RESOURCE:
|
|
|
|
case EMarketMode::ARTIFACT_RESOURCE:
|
|
|
|
case EMarketMode::CREATURE_RESOURCE:
|
2024-08-20 16:15:50 +02:00
|
|
|
for(const auto & res : GameResID::ALL_RESOURCES())
|
2023-11-08 17:49:08 +02:00
|
|
|
ret.push_back(res);
|
2023-06-02 20:47:37 +02:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2024-08-17 19:19:48 +02:00
|
|
|
std::set<EMarketMode> IMarket::availableModes() const
|
2023-06-02 20:47:37 +02:00
|
|
|
{
|
2024-08-17 19:19:48 +02:00
|
|
|
return marketModes;
|
2023-06-02 20:47:37 +02:00
|
|
|
}
|
2023-06-02 21:00:44 +02:00
|
|
|
|
|
|
|
VCMI_LIB_NAMESPACE_END
|