1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Implement markets

This commit is contained in:
nordsoft 2023-04-28 05:16:10 +04:00
parent 333e7d683c
commit 67e6920e23
7 changed files with 148 additions and 72 deletions

View File

@ -585,6 +585,16 @@ namespace BuildingSubID
};
}
namespace EMarketMode
{
enum EMarketMode
{
RESOURCE_RESOURCE, RESOURCE_PLAYER, CREATURE_RESOURCE, RESOURCE_ARTIFACT,
ARTIFACT_RESOURCE, ARTIFACT_EXP, CREATURE_EXP, CREATURE_UNDEAD, RESOURCE_SKILL,
MARTKET_AFTER_LAST_PLACEHOLDER
};
}
namespace MappedKeys
{
@ -634,6 +644,19 @@ namespace MappedKeys
{ "lighthouse", BuildingSubID::LIGHTHOUSE },
{ "treasury", BuildingSubID::TREASURY }
};
static const std::map<std::string, EMarketMode::EMarketMode> MARKET_NAMES_TO_TYPES =
{
{ "resource-resource", EMarketMode::RESOURCE_RESOURCE },
{ "resource-player", EMarketMode::RESOURCE_PLAYER },
{ "creature-resource", EMarketMode::CREATURE_RESOURCE },
{ "resource-artifact", EMarketMode::RESOURCE_ARTIFACT },
{ "artifact-resource", EMarketMode::ARTIFACT_RESOURCE },
{ "artifact-experience", EMarketMode::ARTIFACT_EXP },
{ "creature-experience", EMarketMode::CREATURE_EXP },
{ "creature-undead", EMarketMode::CREATURE_UNDEAD },
{ "resource-skill", EMarketMode::RESOURCE_SKILL },
};
}
namespace EAiTactic
@ -670,16 +693,6 @@ namespace ESpellCastProblem
};
}
namespace EMarketMode
{
enum EMarketMode
{
RESOURCE_RESOURCE, RESOURCE_PLAYER, CREATURE_RESOURCE, RESOURCE_ARTIFACT,
ARTIFACT_RESOURCE, ARTIFACT_EXP, CREATURE_EXP, CREATURE_UNDEAD, RESOURCE_SKILL,
MARTKET_AFTER_LAST_PLACEHOLDER
};
}
namespace ECommander
{
enum SecondarySkills {ATTACK, DEFENSE, HEALTH, DAMAGE, SPEED, SPELL_POWER, CASTS, RESISTANCE};

View File

@ -19,6 +19,7 @@
#include "CGTownInstance.h"
#include "../GameSettings.h"
#include "../CSkillHandler.h"
#include "CObjectClassesHandler.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -158,23 +159,10 @@ std::vector<int> IMarket::availableItemsIds(EMarketMode::EMarketMode mode) const
const IMarket * IMarket::castFrom(const CGObjectInstance *obj, bool verbose)
{
switch(obj->ID)
{
case Obj::TOWN:
return dynamic_cast<const CGTownInstance *>(obj);
case Obj::ALTAR_OF_SACRIFICE:
case Obj::BLACK_MARKET:
case Obj::TRADING_POST:
case Obj::TRADING_POST_SNOW:
case Obj::FREELANCERS_GUILD:
return dynamic_cast<const CGMarket *>(obj);
case Obj::UNIVERSITY:
return dynamic_cast<const CGUniversity *>(obj);
default:
if(verbose)
logGlobal->error("Cannot cast to IMarket object with ID %d", obj->ID);
return nullptr;
}
auto * imarket = dynamic_cast<const IMarket *>(obj);
if(verbose && !imarket)
logGlobal->error("Cannot cast to IMarket object type %s", obj->typeName);
return imarket;
}
IMarket::IMarket()
@ -191,43 +179,24 @@ std::vector<EMarketMode::EMarketMode> IMarket::availableModes() const
return ret;
}
void CGMarket::initObj(CRandomGenerator & rand)
{
VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, rand);
}
void CGMarket::onHeroVisit(const CGHeroInstance * h) const
{
openWindow(EOpenWindowMode::MARKET_WINDOW,id.getNum(),h->id.getNum());
openWindow(EOpenWindowMode::MARKET_WINDOW, id.getNum(), h->id.getNum());
}
int CGMarket::getMarketEfficiency() const
{
return 5;
return marketEfficacy;
}
bool CGMarket::allowsTrade(EMarketMode::EMarketMode mode) const
{
switch(mode)
{
case EMarketMode::RESOURCE_RESOURCE:
case EMarketMode::RESOURCE_PLAYER:
switch(ID)
{
case Obj::TRADING_POST:
case Obj::TRADING_POST_SNOW:
return true;
default:
return false;
}
case EMarketMode::CREATURE_RESOURCE:
return ID == Obj::FREELANCERS_GUILD;
//case ARTIFACT_RESOURCE:
case EMarketMode::RESOURCE_ARTIFACT:
return ID == Obj::BLACK_MARKET;
case EMarketMode::ARTIFACT_EXP:
case EMarketMode::CREATURE_EXP:
return ID == Obj::ALTAR_OF_SACRIFICE; //TODO? check here for alignment of visiting hero? - would not be coherent with other checks here
case EMarketMode::RESOURCE_SKILL:
return ID == Obj::UNIVERSITY;
default:
return false;
}
return marketModes.count(mode);
}
int CGMarket::availableUnits(EMarketMode::EMarketMode mode, int marketItemSerial) const
@ -237,14 +206,9 @@ int CGMarket::availableUnits(EMarketMode::EMarketMode mode, int marketItemSerial
std::vector<int> CGMarket::availableItemsIds(EMarketMode::EMarketMode mode) const
{
switch(mode)
{
case EMarketMode::RESOURCE_RESOURCE:
case EMarketMode::RESOURCE_PLAYER:
if(allowsTrade(mode))
return IMarket::availableItemsIds(mode);
default:
return std::vector<int>();
}
return std::vector<int>();
}
CGMarket::CGMarket()
@ -290,22 +254,26 @@ void CGBlackMarket::newTurn(CRandomGenerator & rand) const
void CGUniversity::initObj(CRandomGenerator & rand)
{
CGMarket::initObj(rand);
std::vector<int> toChoose;
int skillsNeeded = skillsTotal - skills.size();
for(int i = 0; i < VLC->skillh->size(); ++i)
{
if(cb->isAllowed(2, i))
if(!vstd::contains(skills, i) && cb->isAllowed(2, i))
{
toChoose.push_back(i);
}
}
if(toChoose.size() < 4)
if(toChoose.size() < skillsNeeded)
{
logGlobal->warn("Warning: less then 4 available skills was found by University initializer!");
logGlobal->warn("Warning: less then %d available skills was found by University initializer!", skillsTotal);
return;
}
// get 4 skills
for(int i = 0; i < 4; ++i)
// get 4 skills, excluding predefined
for(int i = 0; i < skillsNeeded; ++i)
{
// move randomly one skill to selected and remove from list
auto it = RandomGeneratorUtil::nextItem(toChoose, rand);
@ -322,7 +290,7 @@ std::vector<int> CGUniversity::availableItemsIds(EMarketMode::EMarketMode mode)
return skills;
default:
return std::vector <int> ();
return std::vector<int>();
}
}

View File

@ -33,9 +33,14 @@ public:
class DLL_LINKAGE CGMarket : public CGObjectInstance, public IMarket
{
public:
std::set<EMarketMode::EMarketMode> marketModes;
int marketEfficacy = 5;
CGMarket();
///IObjectIntercae
///IObjectInterface
void onHeroVisit(const CGHeroInstance * h) const override; //open trading window
void initObj(CRandomGenerator & rand) override;//set skills for trade
///IMarket
int getMarketEfficiency() const override;
@ -46,6 +51,8 @@ public:
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CGObjectInstance&>(*this);
h & marketModes;
h & marketEfficacy;
}
};
@ -67,7 +74,12 @@ public:
class DLL_LINKAGE CGUniversity : public CGMarket
{
public:
int skillsTotal = 4;
std::vector<int> skills; //available skills
//window variables
std::string title;
std::string speech;
std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const override;
void initObj(CRandomGenerator & rand) override;//set skills for trade
@ -77,6 +89,8 @@ public:
{
h & static_cast<CGMarket&>(*this);
h & skills;
h & title;
h & speech;
}
};

View File

@ -40,6 +40,7 @@ CObjectClassesHandler::CObjectClassesHandler()
SET_HANDLER_CLASS("town", CTownInstanceConstructor);
SET_HANDLER_CLASS("bank", CBankInstanceConstructor);
SET_HANDLER_CLASS("boat", BoatInstanceConstructor);
SET_HANDLER_CLASS("market", MarketInstanceConstructor);
SET_HANDLER_CLASS("static", CObstacleConstructor);
SET_HANDLER_CLASS("", CObstacleConstructor);
@ -54,7 +55,6 @@ CObjectClassesHandler::CObjectClassesHandler()
SET_HANDLER("generic", CGObjectInstance);
SET_HANDLER("cartographer", CCartographer);
SET_HANDLER("artifact", CGArtifact);
SET_HANDLER("blackMarket", CGBlackMarket);
SET_HANDLER("borderGate", CGBorderGate);
SET_HANDLER("borderGuard", CGBorderGuard);
SET_HANDLER("monster", CGCreature);
@ -65,7 +65,6 @@ CObjectClassesHandler::CObjectClassesHandler()
SET_HANDLER("keymaster", CGKeymasterTent);
SET_HANDLER("lighthouse", CGLighthouse);
SET_HANDLER("magi", CGMagi);
SET_HANDLER("market", CGMarket);
SET_HANDLER("mine", CGMine);
SET_HANDLER("obelisk", CGObelisk);
SET_HANDLER("observatory", CGObservatory);
@ -82,7 +81,6 @@ CObjectClassesHandler::CObjectClassesHandler()
SET_HANDLER("monolith", CGMonolith);
SET_HANDLER("subterraneanGate", CGSubterraneanGate);
SET_HANDLER("whirlpool", CGWhirlpool);
SET_HANDLER("university", CGUniversity);
SET_HANDLER("witch", CGWitchHut);
SET_HANDLER("terrain", CGTerrainPatch);

View File

@ -291,6 +291,66 @@ void BoatInstanceConstructor::configureObject(CGObjectInstance * object, CRandom
}
void MarketInstanceConstructor::initTypeData(const JsonNode & input)
{
for(auto & element : input["modes"].Vector())
{
if(MappedKeys::MARKET_NAMES_TO_TYPES.count(element.String()))
marketModes.insert(MappedKeys::MARKET_NAMES_TO_TYPES.at(element.String()));
}
marketEfficacy = input["efficacy"].isNull() ? -1 : input["efficacy"].Integer();
predefinedOffer = input["offer"];
title = input["title"].String();
speech = input["speech"].String();
}
CGObjectInstance * MarketInstanceConstructor::create(std::shared_ptr<const ObjectTemplate> tmpl) const
{
CGMarket * market = nullptr;
if(marketModes.size() == 1)
{
switch(*marketModes.begin())
{
case EMarketMode::ARTIFACT_RESOURCE:
case EMarketMode::RESOURCE_ARTIFACT:
market = new CGBlackMarket;
break;
case EMarketMode::RESOURCE_SKILL:
market = new CGUniversity;
break;
}
}
if(!market)
market = new CGMarket;
preInitObject(market);
if(tmpl)
market->appearance = tmpl;
market->marketModes = marketModes;
if(marketEfficacy >= 0)
market->marketEfficacy = marketEfficacy;
return market;
}
void MarketInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator & rng) const
{
if(auto * university = dynamic_cast<CGUniversity *>(object))
{
for(auto skill : JsonRandom::loadSecondary(predefinedOffer, rng))
university->skills.push_back(skill.first.getNum());
university->title = VLC->generaltexth->translate(title);
university->speech = VLC->generaltexth->translate(speech);
}
}
bool CBankInstanceConstructor::hasNameTextID() const
{
return true;

View File

@ -255,4 +255,27 @@ public:
}
};
class MarketInstanceConstructor : public CDefaultObjectTypeHandler<CGMarket>
{
protected:
void initTypeData(const JsonNode & config) override;
std::set<EMarketMode::EMarketMode> marketModes;
JsonNode predefinedOffer;
int marketEfficacy;
std::string title, speech;
public:
CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override;
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CDefaultObjectTypeHandler<CGMarket>&>(*this);
h & marketModes;
h & marketEfficacy;
}
};
VCMI_LIB_NAMESPACE_END

View File

@ -89,12 +89,12 @@ void registerTypesMapObjectTypes(Serializer &s)
s.template registerType<AObjectTypeHandler, CDwellingInstanceConstructor>();
s.template registerType<AObjectTypeHandler, CBankInstanceConstructor>();
s.template registerType<AObjectTypeHandler, BoatInstanceConstructor>();
s.template registerType<AObjectTypeHandler, MarketInstanceConstructor>();
s.template registerType<AObjectTypeHandler, CObstacleConstructor>();
#define REGISTER_GENERIC_HANDLER(TYPENAME) s.template registerType<AObjectTypeHandler, CDefaultObjectTypeHandler<TYPENAME> >()
REGISTER_GENERIC_HANDLER(CGObjectInstance);
REGISTER_GENERIC_HANDLER(CGMarket);
REGISTER_GENERIC_HANDLER(CCartographer);
REGISTER_GENERIC_HANDLER(CGArtifact);
REGISTER_GENERIC_HANDLER(CGBlackMarket);