mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Implement markets
This commit is contained in:
parent
333e7d683c
commit
67e6920e23
@ -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};
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user