mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-17 20:58:07 +02:00
Merge pull request #4463 from SoundSSGood/IMarket-refactoring
IMarket refactoring
This commit is contained in:
commit
11e8b04ac5
@ -1491,7 +1491,7 @@ void AIGateway::tryRealize(Goals::Trade & g) //trade
|
||||
//TODO trade only as much as needed
|
||||
if (toGive) //don't try to sell 0 resources
|
||||
{
|
||||
cb->trade(m, EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
|
||||
cb->trade(m->getObjInstanceID(), EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
|
||||
acquiredResources = static_cast<int>(toGet * (it->resVal / toGive));
|
||||
logAi->debug("Traded %d of %s for %d of %s at %s", toGive, res, acquiredResources, g.resID, obj->getObjectName());
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ bool BuildingManager::getBuildingOptions(const CGTownInstance * t)
|
||||
return true;
|
||||
|
||||
//workaround for mantis #2696 - build capitol with separate algorithm if it is available
|
||||
if(vstd::contains(t->builtBuildings, BuildingID::CITY_HALL) && getMaxPossibleGoldBuilding(t) == BuildingID::CAPITOL)
|
||||
if(t->hasBuilt(BuildingID::CITY_HALL) && getMaxPossibleGoldBuilding(t) == BuildingID::CAPITOL)
|
||||
{
|
||||
if(tryBuildNextStructure(t, capitolAndRequirements))
|
||||
return true;
|
||||
|
@ -2130,7 +2130,7 @@ void VCAI::tryRealize(Goals::Trade & g) //trade
|
||||
//TODO trade only as much as needed
|
||||
if (toGive) //don't try to sell 0 resources
|
||||
{
|
||||
cb->trade(m, EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
|
||||
cb->trade(m->getObjInstanceID(), EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
|
||||
acquiredResources = static_cast<int>(toGet * (it->resVal / toGive));
|
||||
logAi->debug("Traded %d of %s for %d of %s at %s", toGive, res, acquiredResources, g.resID, obj->getObjectName());
|
||||
}
|
||||
|
@ -266,15 +266,15 @@ void CCallback::buyArtifact(const CGHeroInstance *hero, ArtifactID aid)
|
||||
sendRequest(&pack);
|
||||
}
|
||||
|
||||
void CCallback::trade(const IMarket * market, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero)
|
||||
void CCallback::trade(const ObjectInstanceID marketId, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero)
|
||||
{
|
||||
trade(market, mode, std::vector(1, id1), std::vector(1, id2), std::vector(1, val1), hero);
|
||||
trade(marketId, mode, std::vector(1, id1), std::vector(1, id2), std::vector(1, val1), hero);
|
||||
}
|
||||
|
||||
void CCallback::trade(const IMarket * market, EMarketMode mode, const std::vector<TradeItemSell> & id1, const std::vector<TradeItemBuy> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero)
|
||||
void CCallback::trade(const ObjectInstanceID marketId, EMarketMode mode, const std::vector<TradeItemSell> & id1, const std::vector<TradeItemBuy> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero)
|
||||
{
|
||||
TradeOnMarketplace pack;
|
||||
pack.marketId = dynamic_cast<const CGObjectInstance *>(market)->id;
|
||||
pack.marketId = marketId;
|
||||
pack.heroId = hero ? hero->id : ObjectInstanceID();
|
||||
pack.mode = mode;
|
||||
pack.r1 = id1;
|
||||
|
@ -34,7 +34,6 @@ class IBattleEventsReceiver;
|
||||
class IGameEventsReceiver;
|
||||
struct ArtifactLocation;
|
||||
class BattleStateInfoForRetreat;
|
||||
class IMarket;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
@ -81,8 +80,8 @@ public:
|
||||
virtual bool upgradeCreature(const CArmedInstance *obj, SlotID stackPos, CreatureID newID=CreatureID::NONE)=0; //if newID==-1 then best possible upgrade will be made
|
||||
virtual void swapGarrisonHero(const CGTownInstance *town)=0;
|
||||
|
||||
virtual void trade(const IMarket * market, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero = nullptr)=0; //mode==0: sell val1 units of id1 resource for id2 resiurce
|
||||
virtual void trade(const IMarket * market, EMarketMode mode, const std::vector<TradeItemSell> & id1, const std::vector<TradeItemBuy> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero = nullptr)=0;
|
||||
virtual void trade(const ObjectInstanceID marketId, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero)=0; //mode==0: sell val1 units of id1 resource for id2 resiurce
|
||||
virtual void trade(const ObjectInstanceID marketId, EMarketMode mode, const std::vector<TradeItemSell> & id1, const std::vector<TradeItemBuy> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero)=0;
|
||||
|
||||
virtual int selectionMade(int selection, QueryID queryID) =0;
|
||||
virtual int sendQueryReply(std::optional<int32_t> reply, QueryID queryID) =0;
|
||||
@ -190,8 +189,8 @@ public:
|
||||
void endTurn() override;
|
||||
void swapGarrisonHero(const CGTownInstance *town) override;
|
||||
void buyArtifact(const CGHeroInstance *hero, ArtifactID aid) override;
|
||||
void trade(const IMarket * market, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero = nullptr) override;
|
||||
void trade(const IMarket * market, EMarketMode mode, const std::vector<TradeItemSell> & id1, const std::vector<TradeItemBuy> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero = nullptr) override;
|
||||
void trade(const ObjectInstanceID marketId, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero = nullptr) override;
|
||||
void trade(const ObjectInstanceID marketId, EMarketMode mode, const std::vector<TradeItemSell> & id1, const std::vector<TradeItemBuy> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero = nullptr) override;
|
||||
void setFormation(const CGHeroInstance * hero, EArmyFormation mode) override;
|
||||
void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero, const HeroTypeID & nextHero=HeroTypeID::NONE) override;
|
||||
void save(const std::string &fname) override;
|
||||
|
@ -1633,14 +1633,14 @@ void CPlayerInterface::battleNewRoundFirst(const BattleID & battleID)
|
||||
battleInt->newRoundFirst();
|
||||
}
|
||||
|
||||
void CPlayerInterface::showMarketWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID)
|
||||
void CPlayerInterface::showMarketWindow(const IMarket * market, const CGHeroInstance * visitor, QueryID queryID)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
auto onWindowClosed = [this, queryID](){
|
||||
cb->selectionMade(0, queryID);
|
||||
};
|
||||
|
||||
if (market->allowsTrade(EMarketMode::ARTIFACT_EXP) && dynamic_cast<const CGArtifactsAltar*>(market) == nullptr)
|
||||
if (market->allowsTrade(EMarketMode::ARTIFACT_EXP) && market->getArtifactsStorage() == nullptr)
|
||||
{
|
||||
// compatibility check, safe to remove for 1.6
|
||||
// 1.4 saves loaded in 1.5 will not be able to visit Altar of Sacrifice due to Altar now requiring different map object class
|
||||
@ -1655,8 +1655,17 @@ void CPlayerInterface::showMarketWindow(const IMarket *market, const CGHeroInsta
|
||||
GH.windows().createAndPushWindow<CMarketWindow>(market, visitor, onWindowClosed, EMarketMode::CREATURE_EXP);
|
||||
else if(market->allowsTrade(EMarketMode::CREATURE_UNDEAD))
|
||||
GH.windows().createAndPushWindow<CTransformerWindow>(market, visitor, onWindowClosed);
|
||||
else if(!market->availableModes().empty())
|
||||
GH.windows().createAndPushWindow<CMarketWindow>(market, visitor, onWindowClosed, market->availableModes().front());
|
||||
else if (!market->availableModes().empty())
|
||||
for(auto mode = EMarketMode::RESOURCE_RESOURCE; mode != EMarketMode::MARKET_AFTER_LAST_PLACEHOLDER; mode = vstd::next(mode, 1))
|
||||
{
|
||||
if(vstd::contains(market->availableModes(), mode))
|
||||
{
|
||||
GH.windows().createAndPushWindow<CMarketWindow>(market, visitor, onWindowClosed, mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
onWindowClosed();
|
||||
}
|
||||
|
||||
void CPlayerInterface::showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID)
|
||||
|
@ -120,7 +120,7 @@ protected: // Call-ins from server, should not be called directly, but only via
|
||||
void showTeleportDialog(const CGHeroInstance * hero, TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
|
||||
void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override;
|
||||
void showMapObjectSelectDialog(QueryID askID, const Component & icon, const MetaString & title, const MetaString & description, const std::vector<ObjectInstanceID> & objects) override;
|
||||
void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID) override;
|
||||
void showMarketWindow(const IMarket * market, const CGHeroInstance * visitor, QueryID queryID) override;
|
||||
void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID) override;
|
||||
void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) override;
|
||||
void advmapSpellCast(const CGHeroInstance * caster, SpellID spellID) override; //called when a hero casts a spell
|
||||
|
@ -999,7 +999,7 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
|
||||
case EOpenWindowMode::UNIVERSITY_WINDOW:
|
||||
{
|
||||
//displays University window (when hero enters University on adventure map)
|
||||
const auto * market = dynamic_cast<const IMarket*>(cl.getObj(ObjectInstanceID(pack.object)));
|
||||
const auto * market = cl.getMarket(ObjectInstanceID(pack.object));
|
||||
const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
|
||||
callInterfaceIfPresent(cl, hero->tempOwner, &IGameEventsReceiver::showUniversityWindow, market, hero, pack.queryID);
|
||||
}
|
||||
@ -1009,7 +1009,7 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
|
||||
//displays Thieves' Guild window (when hero enters Den of Thieves)
|
||||
const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.object));
|
||||
const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
|
||||
const auto *market = dynamic_cast<const IMarket*>(obj);
|
||||
const auto market = cl.getMarket(pack.object);
|
||||
callInterfaceIfPresent(cl, cl.getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::showMarketWindow, market, hero, pack.queryID);
|
||||
}
|
||||
break;
|
||||
|
@ -464,7 +464,7 @@ void CInteractableTownTooltip::init(const CGTownInstance * town)
|
||||
std::vector<const CGTownInstance*> towns = LOCPLINT->cb->getTownsInfo(true);
|
||||
for(auto & town : towns)
|
||||
{
|
||||
if(town->id == townId && town->builtBuildings.count(BuildingID::TAVERN))
|
||||
if(town->id == townId && town->hasBuilt(BuildingID::TAVERN))
|
||||
LOCPLINT->showTavernWindow(town, nullptr, QueryID::NONE);
|
||||
}
|
||||
}, [town]{
|
||||
@ -476,7 +476,7 @@ void CInteractableTownTooltip::init(const CGTownInstance * town)
|
||||
std::vector<const CGTownInstance*> towns = LOCPLINT->cb->getTownsInfo(true);
|
||||
for(auto & town : towns)
|
||||
{
|
||||
if(town->builtBuildings.count(BuildingID::MARKETPLACE))
|
||||
if(town->hasBuilt(BuildingID::MARKETPLACE))
|
||||
{
|
||||
GH.windows().createAndPushWindow<CMarketWindow>(town, nullptr, nullptr, EMarketMode::RESOURCE_RESOURCE);
|
||||
return;
|
||||
|
@ -24,16 +24,15 @@
|
||||
#include "../../../lib/networkPacks/ArtifactLocation.h"
|
||||
#include "../../../lib/texts/CGeneralTextHandler.h"
|
||||
#include "../../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../../lib/mapObjects/CGMarket.h"
|
||||
#include "../../../lib/mapObjects/IMarket.h"
|
||||
|
||||
CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance * hero)
|
||||
: CMarketBase(market, hero)
|
||||
{
|
||||
OBJECT_CONSTRUCTION;
|
||||
|
||||
assert(dynamic_cast<const CGArtifactsAltar*>(market));
|
||||
auto altarObj = dynamic_cast<const CGArtifactsAltar*>(market);
|
||||
altarArtifacts = altarObj;
|
||||
assert(market->getArtifactsStorage());
|
||||
altarArtifactsStorage = market->getArtifactsStorage();
|
||||
|
||||
deal = std::make_shared<CButton>(Point(269, 520), AnimationPath::builtin("ALTSACR.DEF"),
|
||||
CGI->generaltexth->zelp[585], [this]() {CAltarArtifacts::makeDeal(); }, EShortcut::MARKET_DEAL);
|
||||
@ -51,7 +50,7 @@ CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance *
|
||||
// Hero's artifacts
|
||||
heroArts = std::make_shared<CArtifactsOfHeroAltar>(Point(-365, -11));
|
||||
heroArts->setHero(hero);
|
||||
heroArts->altarId = altarObj->id;
|
||||
heroArts->altarId = market->getObjInstanceID();
|
||||
|
||||
// Altar
|
||||
offerTradePanel = std::make_shared<ArtifactsAltarPanel>([this](const std::shared_ptr<CTradeableItem> & altarSlot)
|
||||
@ -104,7 +103,7 @@ void CAltarArtifacts::makeDeal()
|
||||
{
|
||||
positions.push_back(artInst->getId());
|
||||
}
|
||||
LOCPLINT->cb->trade(market, EMarketMode::ARTIFACT_EXP, positions, std::vector<TradeItemBuy>(), std::vector<ui32>(), hero);
|
||||
LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::ARTIFACT_EXP, positions, std::vector<TradeItemBuy>(), std::vector<ui32>(), hero);
|
||||
deselect();
|
||||
}
|
||||
|
||||
@ -125,7 +124,7 @@ std::shared_ptr<CArtifactsOfHeroAltar> CAltarArtifacts::getAOHset() const
|
||||
|
||||
void CAltarArtifacts::updateAltarSlots()
|
||||
{
|
||||
assert(altarArtifacts->artifactsInBackpack.size() <= GameConstants::ALTAR_ARTIFACTS_SLOTS);
|
||||
assert(altarArtifactsStorage->artifactsInBackpack.size() <= GameConstants::ALTAR_ARTIFACTS_SLOTS);
|
||||
assert(tradeSlotsMap.size() <= GameConstants::ALTAR_ARTIFACTS_SLOTS);
|
||||
|
||||
auto tradeSlotsMapNewArts = tradeSlotsMap;
|
||||
@ -146,12 +145,12 @@ void CAltarArtifacts::updateAltarSlots()
|
||||
for(auto & tradeSlot : tradeSlotsMapNewArts)
|
||||
{
|
||||
assert(tradeSlot.first->id == -1);
|
||||
assert(altarArtifacts->getArtPos(tradeSlot.second) != ArtifactPosition::PRE_FIRST);
|
||||
assert(altarArtifactsStorage->getArtPos(tradeSlot.second) != ArtifactPosition::PRE_FIRST);
|
||||
tradeSlot.first->setID(tradeSlot.second->getTypeId().num);
|
||||
tradeSlot.first->subtitle->setText(std::to_string(calcExpCost(tradeSlot.second->getTypeId())));
|
||||
}
|
||||
|
||||
auto newArtsFromBulkMove = altarArtifacts->artifactsInBackpack;
|
||||
auto newArtsFromBulkMove = altarArtifactsStorage->artifactsInBackpack;
|
||||
for(const auto & [altarSlot, art] : tradeSlotsMap)
|
||||
{
|
||||
newArtsFromBulkMove.erase(std::remove_if(newArtsFromBulkMove.begin(), newArtsFromBulkMove.end(), [artForRemove = art](auto & slotInfo)
|
||||
@ -179,7 +178,7 @@ void CAltarArtifacts::putBackArtifacts()
|
||||
{
|
||||
// TODO: If the backpack capacity limit is enabled, artifacts may remain on the altar.
|
||||
// Perhaps should be erased in CGameHandler::objectVisitEnded if id of visited object will be available
|
||||
if(!altarArtifacts->artifactsInBackpack.empty())
|
||||
if(!altarArtifactsStorage->artifactsInBackpack.empty())
|
||||
LOCPLINT->cb->bulkMoveArtifacts(heroArts->altarId, heroArts->getHero()->id, false, true, true);
|
||||
}
|
||||
|
||||
@ -200,7 +199,7 @@ void CAltarArtifacts::onSlotClickPressed(const std::shared_ptr<CTradeableItem> &
|
||||
|
||||
if(const auto pickedArtInst = heroArts->getPickedArtifact())
|
||||
{
|
||||
if(pickedArtInst->canBePutAt(altarArtifacts))
|
||||
if(pickedArtInst->canBePutAt(altarArtifactsStorage.get()))
|
||||
{
|
||||
if(pickedArtInst->artType->isTradable())
|
||||
{
|
||||
@ -221,7 +220,7 @@ void CAltarArtifacts::onSlotClickPressed(const std::shared_ptr<CTradeableItem> &
|
||||
else if(altarSlot->id != -1)
|
||||
{
|
||||
assert(tradeSlotsMap.at(altarSlot));
|
||||
const auto slot = altarArtifacts->getArtPos(tradeSlotsMap.at(altarSlot));
|
||||
const auto slot = altarArtifactsStorage->getArtPos(tradeSlotsMap.at(altarSlot));
|
||||
assert(slot != ArtifactPosition::PRE_FIRST);
|
||||
LOCPLINT->cb->swapArtifacts(ArtifactLocation(heroArts->altarId, slot),
|
||||
ArtifactLocation(hero->id, GH.isKeyboardCtrlDown() ? ArtifactPosition::FIRST_AVAILABLE : ArtifactPosition::TRANSITION_POS));
|
||||
|
@ -26,7 +26,7 @@ public:
|
||||
void putBackArtifacts();
|
||||
|
||||
private:
|
||||
const CArtifactSet * altarArtifacts;
|
||||
std::shared_ptr<CArtifactSet> altarArtifactsStorage;
|
||||
std::shared_ptr<CButton> sacrificeBackpackButton;
|
||||
std::shared_ptr<CArtifactsOfHeroAltar> heroArts;
|
||||
std::map<std::shared_ptr<CTradeableItem>, const CArtifactInstance*> tradeSlotsMap;
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#include "../../../lib/texts/CGeneralTextHandler.h"
|
||||
#include "../../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../../lib/mapObjects/CGMarket.h"
|
||||
#include "../../../lib/mapObjects/IMarket.h"
|
||||
|
||||
CAltarCreatures::CAltarCreatures(const IMarket * market, const CGHeroInstance * hero)
|
||||
: CMarketBase(market, hero)
|
||||
@ -157,7 +157,7 @@ void CAltarCreatures::makeDeal()
|
||||
}
|
||||
}
|
||||
|
||||
LOCPLINT->cb->trade(market, EMarketMode::CREATURE_EXP, ids, {}, toSacrifice, hero);
|
||||
LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::CREATURE_EXP, ids, {}, toSacrifice, hero);
|
||||
|
||||
for(int & units : unitsOnAltar)
|
||||
units = 0;
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "StdInc.h"
|
||||
#include "CArtifactsBuying.h"
|
||||
|
||||
#include "../../gui/CGuiHandler.h"
|
||||
#include "../../gui/Shortcut.h"
|
||||
#include "../../widgets/Buttons.h"
|
||||
#include "../../widgets/TextControls.h"
|
||||
@ -21,24 +20,16 @@
|
||||
|
||||
#include "../../../CCallback.h"
|
||||
|
||||
#include "../../../lib/entities/building/CBuilding.h"
|
||||
#include "../../../lib/entities/faction/CTownHandler.h"
|
||||
#include "../../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../../lib/mapObjects/CGMarket.h"
|
||||
#include "../../../lib/mapObjects/CGTownInstance.h"
|
||||
#include "../../../lib/mapObjects/IMarket.h"
|
||||
#include "../../../lib/texts/CGeneralTextHandler.h"
|
||||
|
||||
CArtifactsBuying::CArtifactsBuying(const IMarket * market, const CGHeroInstance * hero)
|
||||
CArtifactsBuying::CArtifactsBuying(const IMarket * market, const CGHeroInstance * hero, const std::string & title)
|
||||
: CMarketBase(market, hero)
|
||||
, CResourcesSelling([this](const std::shared_ptr<CTradeableItem> & heroSlot){CArtifactsBuying::onSlotClickPressed(heroSlot, bidTradePanel);})
|
||||
{
|
||||
OBJECT_CONSTRUCTION;
|
||||
|
||||
std::string title;
|
||||
if(auto townMarket = dynamic_cast<const CGTownInstance*>(market))
|
||||
title = (*CGI->townh)[townMarket->getFaction()]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->getNameTranslated();
|
||||
else
|
||||
title = CGI->generaltexth->allTexts[349];
|
||||
labels.emplace_back(std::make_shared<CLabel>(titlePos.x, titlePos.y, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW, title));
|
||||
deal = std::make_shared<CButton>(dealButtonPos, AnimationPath::builtin("TPMRKB.DEF"),
|
||||
CGI->generaltexth->zelp[595], [this](){CArtifactsBuying::makeDeal();}, EShortcut::MARKET_DEAL);
|
||||
@ -77,7 +68,7 @@ void CArtifactsBuying::makeDeal()
|
||||
{
|
||||
if(ArtifactID(offerTradePanel->getSelectedItemId()).toArtifact()->canBePutAt(hero))
|
||||
{
|
||||
LOCPLINT->cb->trade(market, EMarketMode::RESOURCE_ARTIFACT, GameResID(bidTradePanel->getSelectedItemId()),
|
||||
LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::RESOURCE_ARTIFACT, GameResID(bidTradePanel->getSelectedItemId()),
|
||||
ArtifactID(offerTradePanel->getSelectedItemId()), offerQty, hero);
|
||||
CMarketTraderText::makeDeal();
|
||||
deselect();
|
||||
|
@ -14,7 +14,7 @@
|
||||
class CArtifactsBuying : public CResourcesSelling, public CMarketTraderText
|
||||
{
|
||||
public:
|
||||
CArtifactsBuying(const IMarket * market, const CGHeroInstance * hero);
|
||||
CArtifactsBuying(const IMarket * market, const CGHeroInstance * hero, const std::string & title);
|
||||
void deselect() override;
|
||||
void makeDeal() override;
|
||||
|
||||
|
@ -22,14 +22,11 @@
|
||||
#include "../../../CCallback.h"
|
||||
|
||||
#include "../../../lib/CArtifactInstance.h"
|
||||
#include "../../../lib/entities/building/CBuilding.h"
|
||||
#include "../../../lib/entities/faction/CTownHandler.h"
|
||||
#include "../../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../../lib/mapObjects/CGMarket.h"
|
||||
#include "../../../lib/mapObjects/CGTownInstance.h"
|
||||
#include "../../../lib/mapObjects/IMarket.h"
|
||||
#include "../../../lib/texts/CGeneralTextHandler.h"
|
||||
|
||||
CArtifactsSelling::CArtifactsSelling(const IMarket * market, const CGHeroInstance * hero)
|
||||
CArtifactsSelling::CArtifactsSelling(const IMarket * market, const CGHeroInstance * hero, const std::string & title)
|
||||
: CMarketBase(market, hero)
|
||||
, CResourcesBuying(
|
||||
[this](const std::shared_ptr<CTradeableItem> & resSlot){CArtifactsSelling::onSlotClickPressed(resSlot, offerTradePanel);},
|
||||
@ -37,12 +34,6 @@ CArtifactsSelling::CArtifactsSelling(const IMarket * market, const CGHeroInstanc
|
||||
{
|
||||
OBJECT_CONSTRUCTION;
|
||||
|
||||
std::string title;
|
||||
if(const auto townMarket = dynamic_cast<const CGTownInstance*>(market))
|
||||
title = (*CGI->townh)[townMarket->getFaction()]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->getNameTranslated();
|
||||
else if(const auto mapMarket = dynamic_cast<const CGMarket*>(market))
|
||||
title = mapMarket->title;
|
||||
|
||||
labels.emplace_back(std::make_shared<CLabel>(titlePos.x, titlePos.y, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW, title));
|
||||
labels.push_back(std::make_shared<CLabel>(155, 56, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, boost::str(boost::format(CGI->generaltexth->allTexts[271]) % hero->getNameTranslated())));
|
||||
deal = std::make_shared<CButton>(dealButtonPos, AnimationPath::builtin("TPMRKB.DEF"),
|
||||
@ -87,7 +78,8 @@ void CArtifactsSelling::makeDeal()
|
||||
{
|
||||
const auto art = hero->getArt(selectedHeroSlot);
|
||||
assert(art);
|
||||
LOCPLINT->cb->trade(market, EMarketMode::ARTIFACT_RESOURCE, art->getId(), GameResID(offerTradePanel->getSelectedItemId()), offerQty, hero);
|
||||
LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::ARTIFACT_RESOURCE, art->getId(),
|
||||
GameResID(offerTradePanel->getSelectedItemId()), offerQty, hero);
|
||||
CMarketTraderText::makeDeal();
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
class CArtifactsSelling : public CResourcesBuying, public CMarketTraderText
|
||||
{
|
||||
public:
|
||||
CArtifactsSelling(const IMarket * market, const CGHeroInstance * hero);
|
||||
CArtifactsSelling(const IMarket * market, const CGHeroInstance * hero, const std::string & title);
|
||||
void deselect() override;
|
||||
void makeDeal() override;
|
||||
void updateShowcases() override;
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#include "../../../lib/texts/CGeneralTextHandler.h"
|
||||
#include "../../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../../lib/mapObjects/CGMarket.h"
|
||||
#include "../../../lib/mapObjects/IMarket.h"
|
||||
|
||||
CFreelancerGuild::CFreelancerGuild(const IMarket * market, const CGHeroInstance * hero)
|
||||
: CMarketBase(market, hero)
|
||||
@ -69,7 +69,7 @@ void CFreelancerGuild::makeDeal()
|
||||
{
|
||||
if(auto toTrade = offerSlider->getValue(); toTrade != 0)
|
||||
{
|
||||
LOCPLINT->cb->trade(market, EMarketMode::CREATURE_RESOURCE, SlotID(bidTradePanel->highlightedSlot->serial), GameResID(offerTradePanel->getSelectedItemId()), bidQty * toTrade, hero);
|
||||
LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::CREATURE_RESOURCE, SlotID(bidTradePanel->highlightedSlot->serial), GameResID(offerTradePanel->getSelectedItemId()), bidQty * toTrade, hero);
|
||||
CMarketTraderText::makeDeal();
|
||||
deselect();
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "../../../CCallback.h"
|
||||
|
||||
#include "../../../lib/texts/CGeneralTextHandler.h"
|
||||
#include "../../../lib/mapObjects/CGMarket.h"
|
||||
#include "../../../lib/mapObjects/IMarket.h"
|
||||
|
||||
CMarketResources::CMarketResources(const IMarket * market, const CGHeroInstance * hero)
|
||||
: CMarketBase(market, hero)
|
||||
@ -60,7 +60,7 @@ void CMarketResources::makeDeal()
|
||||
{
|
||||
if(auto toTrade = offerSlider->getValue(); toTrade != 0)
|
||||
{
|
||||
LOCPLINT->cb->trade(market, EMarketMode::RESOURCE_RESOURCE, GameResID(bidTradePanel->getSelectedItemId()),
|
||||
LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::RESOURCE_RESOURCE, GameResID(bidTradePanel->getSelectedItemId()),
|
||||
GameResID(offerTradePanel->highlightedSlot->id), bidQty * toTrade, hero);
|
||||
CMarketTraderText::makeDeal();
|
||||
deselect();
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "../../../CCallback.h"
|
||||
|
||||
#include "../../../lib/texts/CGeneralTextHandler.h"
|
||||
#include "../../../lib/mapObjects/IMarket.h"
|
||||
#include "../../../lib/texts/MetaString.h"
|
||||
|
||||
CTransferResources::CTransferResources(const IMarket * market, const CGHeroInstance * hero)
|
||||
@ -63,7 +64,7 @@ void CTransferResources::makeDeal()
|
||||
{
|
||||
if(auto toTrade = offerSlider->getValue(); toTrade != 0)
|
||||
{
|
||||
LOCPLINT->cb->trade(market, EMarketMode::RESOURCE_PLAYER, GameResID(bidTradePanel->getSelectedItemId()),
|
||||
LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::RESOURCE_PLAYER, GameResID(bidTradePanel->getSelectedItemId()),
|
||||
PlayerColor(offerTradePanel->getSelectedItemId()), toTrade, hero);
|
||||
CMarketTraderText::makeDeal();
|
||||
deselect();
|
||||
|
@ -586,9 +586,9 @@ void CCastleBuildings::recreate()
|
||||
|
||||
//Generate buildings list
|
||||
|
||||
auto buildingsCopy = town->builtBuildings;// a bit modified copy of built buildings
|
||||
auto buildingsCopy = town->getBuildings();// a bit modified copy of built buildings
|
||||
|
||||
if(vstd::contains(town->builtBuildings, BuildingID::SHIPYARD))
|
||||
if(town->hasBuilt(BuildingID::SHIPYARD))
|
||||
{
|
||||
auto bayPos = town->bestLocation();
|
||||
if(!bayPos.valid())
|
||||
@ -996,7 +996,7 @@ void CCastleBuildings::enterMagesGuild()
|
||||
void CCastleBuildings::enterTownHall()
|
||||
{
|
||||
if(town->visitingHero && town->visitingHero->hasArt(ArtifactID::GRAIL) &&
|
||||
!vstd::contains(town->builtBuildings, BuildingID::GRAIL)) //hero has grail, but town does not have it
|
||||
!town->hasBuilt(BuildingID::GRAIL)) //hero has grail, but town does not have it
|
||||
{
|
||||
if(!vstd::contains(town->forbiddenBuildings, BuildingID::GRAIL))
|
||||
{
|
||||
@ -1033,7 +1033,7 @@ void CCastleBuildings::enterAnyThievesGuild()
|
||||
std::vector<const CGTownInstance*> towns = LOCPLINT->cb->getTownsInfo(true);
|
||||
for(auto & ownedTown : towns)
|
||||
{
|
||||
if(ownedTown->builtBuildings.count(BuildingID::TAVERN))
|
||||
if(ownedTown->hasBuilt(BuildingID::TAVERN))
|
||||
{
|
||||
LOCPLINT->showThievesGuildWindow(ownedTown);
|
||||
return;
|
||||
@ -1059,7 +1059,7 @@ void CCastleBuildings::enterBank()
|
||||
|
||||
void CCastleBuildings::enterAnyMarket()
|
||||
{
|
||||
if(town->builtBuildings.count(BuildingID::MARKETPLACE))
|
||||
if(town->hasBuilt(BuildingID::MARKETPLACE))
|
||||
{
|
||||
GH.windows().createAndPushWindow<CMarketWindow>(town, nullptr, nullptr, EMarketMode::RESOURCE_RESOURCE);
|
||||
return;
|
||||
@ -1068,7 +1068,7 @@ void CCastleBuildings::enterAnyMarket()
|
||||
std::vector<const CGTownInstance*> towns = LOCPLINT->cb->getTownsInfo(true);
|
||||
for(auto & town : towns)
|
||||
{
|
||||
if(town->builtBuildings.count(BuildingID::MARKETPLACE))
|
||||
if(town->hasBuilt(BuildingID::MARKETPLACE))
|
||||
{
|
||||
GH.windows().createAndPushWindow<CMarketWindow>(town, nullptr, nullptr, EMarketMode::RESOURCE_RESOURCE);
|
||||
return;
|
||||
@ -1385,7 +1385,7 @@ void CCastleInterface::recreateIcons()
|
||||
fastMarket = std::make_shared<LRClickableArea>(Rect(163, 410, 64, 42), [this]() { builds->enterAnyMarket(); });
|
||||
fastTavern = std::make_shared<LRClickableArea>(Rect(15, 387, 58, 64), [&]()
|
||||
{
|
||||
if(town->builtBuildings.count(BuildingID::TAVERN))
|
||||
if(town->hasBuilt(BuildingID::TAVERN))
|
||||
LOCPLINT->showTavernWindow(town, nullptr, QueryID::NONE);
|
||||
}, [this]{
|
||||
if(!town->town->faction->getDescriptionTranslated().empty())
|
||||
@ -1563,7 +1563,7 @@ CHallInterface::CHallInterface(const CGTownInstance * Town):
|
||||
}
|
||||
|
||||
const CBuilding * current = town->town->buildings.at(buildingID);
|
||||
if(vstd::contains(town->builtBuildings, buildingID))
|
||||
if(town->hasBuilt(buildingID))
|
||||
{
|
||||
building = current;
|
||||
}
|
||||
@ -1776,7 +1776,7 @@ CFortScreen::CFortScreen(const CGTownInstance * town):
|
||||
{
|
||||
BuildingID dwelling = BuildingID::getDwellingFromLevel(i, 1);
|
||||
|
||||
if(vstd::contains(town->builtBuildings, dwelling))
|
||||
if(town->hasBuilt(dwelling))
|
||||
buildingID = BuildingID(BuildingID::getDwellingFromLevel(i, 1));
|
||||
else
|
||||
buildingID = BuildingID(BuildingID::getDwellingFromLevel(i, 0));
|
||||
@ -1841,7 +1841,7 @@ CFortScreen::RecruitArea::RecruitArea(int posX, int posY, const CGTownInstance *
|
||||
buildingIcon = std::make_shared<CAnimImage>(town->town->clientInfo.buildingsIcons, getMyBuilding()->bid, 0, 4, 21);
|
||||
buildingName = std::make_shared<CLabel>(78, 101, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, getMyBuilding()->getNameTranslated(), 152);
|
||||
|
||||
if(vstd::contains(town->builtBuildings, getMyBuilding()->bid))
|
||||
if(town->hasBuilt(getMyBuilding()->bid))
|
||||
{
|
||||
ui32 available = town->creatures[level].first;
|
||||
std::string availableText = CGI->generaltexth->allTexts[217]+ std::to_string(available);
|
||||
|
@ -822,7 +822,7 @@ CTownItem::CTownItem(const CGTownInstance * Town)
|
||||
|
||||
fastTavern = std::make_shared<LRClickableArea>(Rect(5, 6, 58, 64), [&]()
|
||||
{
|
||||
if(town->builtBuildings.count(BuildingID::TAVERN))
|
||||
if(town->hasBuilt(BuildingID::TAVERN))
|
||||
LOCPLINT->showTavernWindow(town, nullptr, QueryID::NONE);
|
||||
}, [&]{
|
||||
if(!town->town->faction->getDescriptionTranslated().empty())
|
||||
@ -833,7 +833,7 @@ CTownItem::CTownItem(const CGTownInstance * Town)
|
||||
std::vector<const CGTownInstance*> towns = LOCPLINT->cb->getTownsInfo(true);
|
||||
for(auto & town : towns)
|
||||
{
|
||||
if(town->builtBuildings.count(BuildingID::MARKETPLACE))
|
||||
if(town->hasBuilt(BuildingID::MARKETPLACE))
|
||||
{
|
||||
GH.windows().createAndPushWindow<CMarketWindow>(town, nullptr, nullptr, EMarketMode::RESOURCE_RESOURCE);
|
||||
return;
|
||||
|
@ -27,11 +27,14 @@
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
|
||||
#include "../../lib/entities/building/CBuilding.h"
|
||||
#include "../../lib/texts/CGeneralTextHandler.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
#include "../../lib/mapObjects/CGMarket.h"
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
|
||||
CMarketWindow::CMarketWindow(const IMarket * market, const CGHeroInstance * hero, const std::function<void()> & onWindowClosed, EMarketMode mode)
|
||||
: CWindowObject(PLAYER_COLORED)
|
||||
, windowClosedCallback(onWindowClosed)
|
||||
@ -111,6 +114,11 @@ void CMarketWindow::createChangeModeButtons(EMarketMode currentMode, const IMark
|
||||
if(!market->allowsTrade(modeButton))
|
||||
return false;
|
||||
|
||||
if(currentMode == EMarketMode::ARTIFACT_EXP && modeButton != EMarketMode::CREATURE_EXP)
|
||||
return false;
|
||||
if(currentMode == EMarketMode::CREATURE_EXP && modeButton != EMarketMode::ARTIFACT_EXP)
|
||||
return false;
|
||||
|
||||
if(modeButton == EMarketMode::RESOURCE_RESOURCE || modeButton == EMarketMode::RESOURCE_PLAYER)
|
||||
{
|
||||
if(const auto town = dynamic_cast<const CGTownInstance*>(market))
|
||||
@ -175,12 +183,28 @@ void CMarketWindow::initWidgetInternals(const EMarketMode mode, const std::pair<
|
||||
redraw();
|
||||
}
|
||||
|
||||
std::string CMarketWindow::getMarketTitle(const ObjectInstanceID marketId, const EMarketMode mode) const
|
||||
{
|
||||
assert(LOCPLINT->cb->getMarket(marketId));
|
||||
assert(vstd::contains(LOCPLINT->cb->getMarket(marketId)->availableModes(), mode));
|
||||
|
||||
if(const auto town = LOCPLINT->cb->getTown(marketId))
|
||||
{
|
||||
for(const auto & buildingId : town->getBuildings())
|
||||
{
|
||||
if(const auto building = town->town->buildings.at(buildingId); vstd::contains(building->marketModes, mode))
|
||||
return building->getNameTranslated();
|
||||
}
|
||||
}
|
||||
return LOCPLINT->cb->getObj(marketId)->getObjectName();
|
||||
}
|
||||
|
||||
void CMarketWindow::createArtifactsBuying(const IMarket * market, const CGHeroInstance * hero)
|
||||
{
|
||||
OBJECT_CONSTRUCTION;
|
||||
|
||||
background = createBg(ImagePath::builtin("TPMRKABS.bmp"), PLAYER_COLORED);
|
||||
marketWidget = std::make_shared<CArtifactsBuying>(market, hero);
|
||||
marketWidget = std::make_shared<CArtifactsBuying>(market, hero, getMarketTitle(market->getObjInstanceID(), EMarketMode::RESOURCE_ARTIFACT));
|
||||
initWidgetInternals(EMarketMode::RESOURCE_ARTIFACT, CGI->generaltexth->zelp[600]);
|
||||
}
|
||||
|
||||
@ -192,13 +216,13 @@ void CMarketWindow::createArtifactsSelling(const IMarket * market, const CGHeroI
|
||||
// Create image that copies part of background containing slot MISC_1 into position of slot MISC_5
|
||||
artSlotBack = std::make_shared<CPicture>(background->getSurface(), Rect(20, 187, 47, 47), 0, 0);
|
||||
artSlotBack->moveTo(pos.topLeft() + Point(18, 339));
|
||||
auto artsSellingMarket = std::make_shared<CArtifactsSelling>(market, hero);
|
||||
auto artsSellingMarket = std::make_shared<CArtifactsSelling>(market, hero, getMarketTitle(market->getObjInstanceID(), EMarketMode::ARTIFACT_RESOURCE));
|
||||
artSets.clear();
|
||||
const auto heroArts = artsSellingMarket->getAOHset();
|
||||
heroArts->showPopupCallback = [this, heroArts](CArtPlace & artPlace, const Point & cursorPosition){showArifactInfo(*heroArts, artPlace, cursorPosition);};
|
||||
addSet(heroArts);
|
||||
marketWidget = artsSellingMarket;
|
||||
initWidgetInternals(EMarketMode::ARTIFACT_RESOURCE, CGI->generaltexth->zelp[600]);
|
||||
initWidgetInternals(EMarketMode::ARTIFACT_RESOURCE, CGI->generaltexth->zelp[600]);
|
||||
}
|
||||
|
||||
void CMarketWindow::createMarketResources(const IMarket * market, const CGHeroInstance * hero)
|
||||
@ -233,10 +257,10 @@ void CMarketWindow::createAltarArtifacts(const IMarket * market, const CGHeroIns
|
||||
OBJECT_CONSTRUCTION;
|
||||
|
||||
background = createBg(ImagePath::builtin("ALTRART2.bmp"), PLAYER_COLORED);
|
||||
auto altarArtifacts = std::make_shared<CAltarArtifacts>(market, hero);
|
||||
marketWidget = altarArtifacts;
|
||||
auto altarArtifactsStorage = std::make_shared<CAltarArtifacts>(market, hero);
|
||||
marketWidget = altarArtifactsStorage;
|
||||
artSets.clear();
|
||||
const auto heroArts = altarArtifacts->getAOHset();
|
||||
const auto heroArts = altarArtifactsStorage->getAOHset();
|
||||
heroArts->clickPressedCallback = [this, heroArts](const CArtPlace & artPlace, const Point & cursorPosition)
|
||||
{
|
||||
clickPressedOnArtPlace(heroArts->getHero(), artPlace.slot, true, true, false);
|
||||
@ -252,7 +276,7 @@ void CMarketWindow::createAltarArtifacts(const IMarket * market, const CGHeroIns
|
||||
addSet(heroArts);
|
||||
initWidgetInternals(EMarketMode::ARTIFACT_EXP, CGI->generaltexth->zelp[568]);
|
||||
updateExperience();
|
||||
quitButton->addCallback([altarArtifacts](){altarArtifacts->putBackArtifacts();});
|
||||
quitButton->addCallback([altarArtifactsStorage](){altarArtifactsStorage->putBackArtifacts();});
|
||||
}
|
||||
|
||||
void CMarketWindow::createAltarCreatures(const IMarket * market, const CGHeroInstance * hero)
|
||||
|
@ -27,6 +27,7 @@ public:
|
||||
private:
|
||||
void createChangeModeButtons(EMarketMode currentMode, const IMarket * market, const CGHeroInstance * hero);
|
||||
void initWidgetInternals(const EMarketMode mode, const std::pair<std::string, std::string> & quitButtonHelpContainer);
|
||||
std::string getMarketTitle(const ObjectInstanceID marketId, const EMarketMode mode) const;
|
||||
|
||||
void createArtifactsBuying(const IMarket * market, const CGHeroInstance * hero);
|
||||
void createArtifactsSelling(const IMarket * market, const CGHeroInstance * hero);
|
||||
|
@ -819,7 +819,7 @@ void CTransformerWindow::makeDeal()
|
||||
for(auto & elem : items)
|
||||
{
|
||||
if(!elem->left)
|
||||
LOCPLINT->cb->trade(market, EMarketMode::CREATURE_UNDEAD, SlotID(elem->id), {}, {}, hero);
|
||||
LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::CREATURE_UNDEAD, SlotID(elem->id), {}, {}, hero);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1005,7 +1005,7 @@ void CUniversityWindow::updateSecondarySkills()
|
||||
|
||||
void CUniversityWindow::makeDeal(SecondarySkill skill)
|
||||
{
|
||||
LOCPLINT->cb->trade(market, EMarketMode::RESOURCE_SKILL, GameResID(GameResID::GOLD), skill, 1, hero);
|
||||
LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::RESOURCE_SKILL, GameResID(GameResID::GOLD), skill, 1, hero);
|
||||
}
|
||||
|
||||
CUnivConfirmWindow::CUnivConfirmWindow(CUniversityWindow * owner_, SecondarySkill SKILL, bool available)
|
||||
|
@ -166,7 +166,7 @@
|
||||
"townHall": { },
|
||||
"cityHall": { },
|
||||
"capitol": { },
|
||||
"marketplace": { },
|
||||
"marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
|
||||
"resourceSilo": { "produce": { "ore": 1, "wood": 1 } },
|
||||
"blacksmith": { },
|
||||
|
||||
|
@ -171,11 +171,11 @@
|
||||
"townHall": { },
|
||||
"cityHall": { },
|
||||
"capitol": { },
|
||||
"marketplace": { },
|
||||
"marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
|
||||
"resourceSilo": { "produce": { "mercury": 1 } },
|
||||
"blacksmith": { },
|
||||
|
||||
"special1": { "type" : "artifactMerchant", "requires" : [ "marketplace" ] },
|
||||
"special1": { "type" : "artifactMerchant", "requires" : [ "marketplace" ], "marketModes" : ["resource-artifact", "artifact-resource"] },
|
||||
"horde1": { "id" : 18, "upgrades" : "dwellingLvl1" },
|
||||
"horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl1", "requires" : [ "horde1" ], "mode" : "auto" },
|
||||
"ship": { "id" : 20, "upgrades" : "shipyard" },
|
||||
|
@ -167,11 +167,11 @@
|
||||
"townHall": { },
|
||||
"cityHall": { },
|
||||
"capitol": { },
|
||||
"marketplace": { },
|
||||
"marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
|
||||
"resourceSilo": { "produce": { "sulfur": 1 } },
|
||||
"blacksmith": { },
|
||||
|
||||
"special1": { "type" : "artifactMerchant", "requires" : [ "marketplace" ] },
|
||||
"special1": { "type" : "artifactMerchant", "requires" : [ "marketplace" ], "marketModes" : ["resource-artifact", "artifact-resource"] },
|
||||
"horde1": { "id" : 18, "upgrades" : "dwellingLvl1" },
|
||||
"horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl1", "requires" : [ "horde1" ], "mode" : "auto" },
|
||||
"special2": {
|
||||
|
@ -165,7 +165,7 @@
|
||||
"townHall": { },
|
||||
"cityHall": { },
|
||||
"capitol": { },
|
||||
"marketplace": { },
|
||||
"marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
|
||||
"resourceSilo": { "produce": { "wood": 1, "ore": 1 } },
|
||||
"blacksmith": { },
|
||||
|
||||
|
@ -167,7 +167,7 @@
|
||||
"townHall": { },
|
||||
"cityHall": { },
|
||||
"capitol": { },
|
||||
"marketplace": { },
|
||||
"marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
|
||||
"resourceSilo": { "produce": { "mercury": 1 } },
|
||||
"blacksmith": { },
|
||||
|
||||
|
@ -172,7 +172,7 @@
|
||||
"townHall": { },
|
||||
"cityHall": { },
|
||||
"capitol": { },
|
||||
"marketplace": { },
|
||||
"marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
|
||||
"resourceSilo": { "produce": { "ore": 1, "wood": 1 } },
|
||||
"blacksmith": { },
|
||||
|
||||
@ -182,7 +182,7 @@
|
||||
"ship": { "id" : 20, "upgrades" : "shipyard" },
|
||||
"special2": { "requires" : [ "mageGuild1" ],
|
||||
"bonuses": [ { "type": "UNDEAD_RAISE_PERCENTAGE", "val": 10, "propagator": "PLAYER_PROPAGATOR" } ] },
|
||||
"special3": { "type" : "creatureTransformer", "requires" : [ "dwellingLvl1" ] },
|
||||
"special3": { "type" : "creatureTransformer", "requires" : [ "dwellingLvl1" ], "marketModes" : ["creature-undead"] },
|
||||
"grail": { "id" : 26, "mode" : "grail", "produce": { "gold": 5000 },
|
||||
"bonuses": [ { "type": "UNDEAD_RAISE_PERCENTAGE", "val": 20, "propagator": "PLAYER_PROPAGATOR" } ] },
|
||||
|
||||
|
@ -170,7 +170,7 @@
|
||||
"townHall": { },
|
||||
"cityHall": { },
|
||||
"capitol": { },
|
||||
"marketplace": { },
|
||||
"marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
|
||||
"resourceSilo": { "produce": { "crystal": 1 } },
|
||||
"blacksmith": { },
|
||||
|
||||
|
@ -162,14 +162,14 @@
|
||||
"townHall": { },
|
||||
"cityHall": { },
|
||||
"capitol": { },
|
||||
"marketplace": { },
|
||||
"marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
|
||||
"resourceSilo": { "produce": { "ore": 1, "wood": 1 } },
|
||||
"blacksmith": { },
|
||||
|
||||
"special1": { "type" : "escapeTunnel", "requires" : [ "fort" ] },
|
||||
"horde1": { "id" : 18, "upgrades" : "dwellingLvl1" },
|
||||
"horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl1", "requires" : [ "horde1" ], "mode" : "auto" },
|
||||
"special2": { "type" : "freelancersGuild", "requires" : [ "marketplace" ] },
|
||||
"special2": { "type" : "freelancersGuild", "requires" : [ "marketplace" ], "marketModes" : ["creature-resource"] },
|
||||
"special3": { "type" : "ballistaYard", "requires" : [ "blacksmith" ] },
|
||||
"special4": {
|
||||
"requires" : [ "fort" ],
|
||||
|
@ -165,11 +165,11 @@
|
||||
"townHall": { },
|
||||
"cityHall": { },
|
||||
"capitol": { },
|
||||
"marketplace": { },
|
||||
"marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
|
||||
"resourceSilo": { "produce" : { "gems": 1 } },
|
||||
"blacksmith": { },
|
||||
|
||||
"special1": { "type" : "artifactMerchant", "requires" : [ "marketplace" ] },
|
||||
"special1": { "type" : "artifactMerchant", "requires" : [ "marketplace" ], "marketModes" : ["resource-artifact", "artifact-resource"] },
|
||||
"horde1": { "id" : 18, "upgrades" : "dwellingLvl2" },
|
||||
"horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl2", "requires" : [ "horde1" ], "mode" : "auto" },
|
||||
"special2": { "height" : "high", "requires" : [ "fort" ] },
|
||||
|
@ -97,6 +97,11 @@
|
||||
"type" : "array",
|
||||
"description" : "Bonuses that are provided by this building in any town where this building has been built. Only affects town itself (including siege), to propagate effect to player or team please use bonus propagators",
|
||||
"items" : { "$ref" : "bonus.json" }
|
||||
},
|
||||
"marketModes" : {
|
||||
"type" : "array",
|
||||
"enum" : [ "resource-resource", "resource-player", "creature-resource", "resource-artifact", "artifact-resource", "artifact-experience", "creature-experience", "creature-undead", "resource-skill"],
|
||||
"description" : "List of modes available in this market"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -171,6 +171,9 @@ These are just a couple of examples of what can be done in VCMI. See vcmi config
|
||||
|
||||
// If set to true, this building will replace all bonuses from base building, leaving only bonuses defined by this building"
|
||||
"upgradeReplacesBonuses" : false,
|
||||
|
||||
// If the building is a market, it requires market mode.
|
||||
"marketModes" : [ "resource-resource", "resource-player" ],
|
||||
}
|
||||
```
|
||||
|
||||
@ -217,7 +220,6 @@ Following HotA buildings can be used as unique building for a town. Functionalit
|
||||
#### Custom buildings
|
||||
In addition to above, it is possible to use same format as [Rewardable](../Map_Objects/Rewardable.md) map objects for town buildings. In order to do that, configuration of a rewardable object must be placed into `configuration` json node in building config.
|
||||
|
||||
```
|
||||
|
||||
### Town Structure node
|
||||
|
||||
@ -248,3 +250,17 @@ In addition to above, it is possible to use same format as [Rewardable](../Map_O
|
||||
"hidden" : false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### Markets in towns
|
||||
Market buildings require list of available [modes](../Map_Objects/Market.md)
|
||||
|
||||
##### Marketplace
|
||||
```jsonc
|
||||
"marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
|
||||
```
|
||||
|
||||
##### Artifact merchant
|
||||
```jsonc
|
||||
"special1": { "type" : "artifactMerchant", "requires" : [ "marketplace" ], "marketModes" : ["resource-artifact", "artifact-resource"] },
|
||||
```
|
@ -174,6 +174,15 @@ const CGTownInstance* CGameInfoCallback::getTown(ObjectInstanceID objid) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const IMarket * CGameInfoCallback::getMarket(ObjectInstanceID objid) const
|
||||
{
|
||||
const CGObjectInstance * obj = getObj(objid, false);
|
||||
if(obj)
|
||||
return dynamic_cast<const IMarket*>(obj);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CGameInfoCallback::fillUpgradeInfo(const CArmedInstance *obj, SlotID stackPos, UpgradeInfo &out) const
|
||||
{
|
||||
//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
|
||||
|
@ -48,6 +48,7 @@ class CGHeroInstance;
|
||||
class CGDwelling;
|
||||
class CGTeleport;
|
||||
class CGTownInstance;
|
||||
class IMarket;
|
||||
|
||||
class DLL_LINKAGE IGameInfoCallback : boost::noncopyable
|
||||
{
|
||||
@ -189,6 +190,7 @@ public:
|
||||
virtual std::vector <const CGObjectInstance * > getFlaggableObjects(int3 pos) const;
|
||||
virtual const CGObjectInstance * getTopObj (int3 pos) const;
|
||||
virtual PlayerColor getOwner(ObjectInstanceID heroID) const;
|
||||
virtual const IMarket * getMarket(ObjectInstanceID objid) const;
|
||||
|
||||
//map
|
||||
virtual int3 guardingCreaturePosition (int3 pos) const;
|
||||
|
@ -287,18 +287,16 @@ CArtifactSet * CNonConstInfoCallback::getArtSet(const ArtifactLocation & loc)
|
||||
return hero;
|
||||
}
|
||||
}
|
||||
else if(auto market = getMarket(loc.artHolder))
|
||||
{
|
||||
if(auto artSet = market->getArtifactsStorage())
|
||||
return artSet.get();
|
||||
}
|
||||
else if(auto army = getArmyInstance(loc.artHolder))
|
||||
{
|
||||
return army->getStackPtr(loc.creature.value());
|
||||
}
|
||||
else if(auto market = dynamic_cast<CGArtifactsAltar*>(getObjInstance(loc.artHolder)))
|
||||
{
|
||||
return market;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool IGameCallback::isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, const CGHeroInstance *hero)
|
||||
|
@ -109,7 +109,7 @@ public:
|
||||
|
||||
virtual void showPuzzleMap(){};
|
||||
virtual void viewWorldMap(){};
|
||||
virtual void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID){};
|
||||
virtual void showMarketWindow(const IMarket * market, const CGHeroInstance * visitor, QueryID queryID){};
|
||||
virtual void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID){};
|
||||
virtual void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor){};
|
||||
virtual void showThievesGuildWindow (const CGObjectInstance * obj){};
|
||||
|
@ -34,6 +34,7 @@ public:
|
||||
TResources resources;
|
||||
TResources produce;
|
||||
TRequired requirements;
|
||||
std::set<EMarketMode> marketModes;
|
||||
|
||||
BuildingID bid; //structure ID
|
||||
BuildingID upgrade; /// indicates that building "upgrade" can be improved by this, -1 = empty
|
||||
@ -85,7 +86,7 @@ public:
|
||||
STRONG_INLINE
|
||||
bool IsTradeBuilding() const
|
||||
{
|
||||
return bid == BuildingID::MARKETPLACE || subId == BuildingSubID::ARTIFACT_MERCHANT || subId == BuildingSubID::FREELANCERS_GUILD;
|
||||
return !marketModes.empty();
|
||||
}
|
||||
|
||||
void addNewBonus(const std::shared_ptr<Bonus> & b, BonusList & bonusList) const;
|
||||
|
@ -342,6 +342,11 @@ void CTownHandler::loadBuilding(CTown * town, const std::string & stringID, cons
|
||||
ret->upgrade = BuildingID::NONE;
|
||||
|
||||
ret->town->buildings[ret->bid] = ret;
|
||||
for(const auto & element : source["marketModes"].Vector())
|
||||
{
|
||||
if(MappedKeys::MARKET_NAMES_TO_TYPES.count(element.String()))
|
||||
ret->marketModes.insert(MappedKeys::MARKET_NAMES_TO_TYPES.at(element.String()));
|
||||
}
|
||||
|
||||
registerObject(source.getModScope(), ret->town->getBuildingScope(), ret->identifier, ret->bid.getNum());
|
||||
}
|
||||
|
@ -808,12 +808,12 @@ void CGameState::initTowns()
|
||||
constexpr std::array hordes = { BuildingID::HORDE_PLACEHOLDER1, BuildingID::HORDE_PLACEHOLDER2, BuildingID::HORDE_PLACEHOLDER3, BuildingID::HORDE_PLACEHOLDER4, BuildingID::HORDE_PLACEHOLDER5, BuildingID::HORDE_PLACEHOLDER6, BuildingID::HORDE_PLACEHOLDER7, BuildingID::HORDE_PLACEHOLDER8 };
|
||||
|
||||
//init buildings
|
||||
if(vstd::contains(vti->builtBuildings, BuildingID::DEFAULT)) //give standard set of buildings
|
||||
if(vti->hasBuilt(BuildingID::DEFAULT)) //give standard set of buildings
|
||||
{
|
||||
vti->builtBuildings.erase(BuildingID::DEFAULT);
|
||||
vti->builtBuildings.insert(BuildingID::VILLAGE_HALL);
|
||||
vti->removeBuilding(BuildingID::DEFAULT);
|
||||
vti->addBuilding(BuildingID::VILLAGE_HALL);
|
||||
if(vti->tempOwner != PlayerColor::NEUTRAL)
|
||||
vti->builtBuildings.insert(BuildingID::TAVERN);
|
||||
vti->addBuilding(BuildingID::TAVERN);
|
||||
|
||||
auto definesBuildingsChances = VLC->settings()->getVector(EGameSettings::TOWNS_STARTING_DWELLING_CHANCES);
|
||||
|
||||
@ -821,48 +821,49 @@ void CGameState::initTowns()
|
||||
{
|
||||
if((getRandomGenerator().nextInt(1,100) <= definesBuildingsChances[i]))
|
||||
{
|
||||
vti->builtBuildings.insert(basicDwellings[i]);
|
||||
vti->addBuilding(basicDwellings[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// village hall must always exist
|
||||
vti->builtBuildings.insert(BuildingID::VILLAGE_HALL);
|
||||
vti->addBuilding(BuildingID::VILLAGE_HALL);
|
||||
|
||||
//init hordes
|
||||
for (int i = 0; i < vti->town->creatures.size(); i++)
|
||||
{
|
||||
if (vstd::contains(vti->builtBuildings, hordes[i])) //if we have horde for this level
|
||||
if(vti->hasBuilt(hordes[i])) //if we have horde for this level
|
||||
{
|
||||
vti->builtBuildings.erase(hordes[i]);//remove old ID
|
||||
vti->removeBuilding(hordes[i]);//remove old ID
|
||||
if (vti->getTown()->hordeLvl.at(0) == i)//if town first horde is this one
|
||||
{
|
||||
vti->builtBuildings.insert(BuildingID::HORDE_1);//add it
|
||||
vti->addBuilding(BuildingID::HORDE_1);//add it
|
||||
//if we have upgraded dwelling as well
|
||||
if (vstd::contains(vti->builtBuildings, upgradedDwellings[i]))
|
||||
vti->builtBuildings.insert(BuildingID::HORDE_1_UPGR);//add it as well
|
||||
if(vti->hasBuilt(upgradedDwellings[i]))
|
||||
vti->addBuilding(BuildingID::HORDE_1_UPGR);//add it as well
|
||||
}
|
||||
if (vti->getTown()->hordeLvl.at(1) == i)//if town second horde is this one
|
||||
{
|
||||
vti->builtBuildings.insert(BuildingID::HORDE_2);
|
||||
if (vstd::contains(vti->builtBuildings, upgradedDwellings[i]))
|
||||
vti->builtBuildings.insert(BuildingID::HORDE_2_UPGR);
|
||||
vti->addBuilding(BuildingID::HORDE_2);
|
||||
if(vti->hasBuilt(upgradedDwellings[i]))
|
||||
vti->addBuilding(BuildingID::HORDE_2_UPGR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//#1444 - remove entries that don't have buildings defined (like some unused extra town hall buildings)
|
||||
//But DO NOT remove horde placeholders before they are replaced
|
||||
vstd::erase_if(vti->builtBuildings, [vti](const BuildingID & bid)
|
||||
{
|
||||
return !vti->getTown()->buildings.count(bid) || !vti->getTown()->buildings.at(bid);
|
||||
});
|
||||
for(const auto & building : vti->getBuildings())
|
||||
{
|
||||
if(!vti->getTown()->buildings.count(building) || !vti->getTown()->buildings.at(building))
|
||||
vti->removeBuilding(building);
|
||||
}
|
||||
|
||||
if (vstd::contains(vti->builtBuildings, BuildingID::SHIPYARD) && vti->shipyardStatus()==IBoatGenerator::TILE_BLOCKED)
|
||||
vti->builtBuildings.erase(BuildingID::SHIPYARD);//if we have harbor without water - erase it (this is H3 behaviour)
|
||||
if(vti->hasBuilt(BuildingID::SHIPYARD) && vti->shipyardStatus()==IBoatGenerator::TILE_BLOCKED)
|
||||
vti->removeBuilding(BuildingID::SHIPYARD);//if we have harbor without water - erase it (this is H3 behaviour)
|
||||
|
||||
//Early check for #1444-like problems
|
||||
for([[maybe_unused]] const auto & building : vti->builtBuildings)
|
||||
for([[maybe_unused]] const auto & building : vti->getBuildings())
|
||||
{
|
||||
assert(vti->getTown()->buildings.at(building) != nullptr);
|
||||
}
|
||||
|
@ -656,7 +656,7 @@ void CGameStateCampaign::initTowns()
|
||||
if(gameState->scenarioOps->campState->formatVCMI())
|
||||
newBuilding = BuildingID(chosenBonus->info1);
|
||||
else
|
||||
newBuilding = CBuildingHandler::campToERMU(chosenBonus->info1, town->getFaction(), town->builtBuildings);
|
||||
newBuilding = CBuildingHandler::campToERMU(chosenBonus->info1, town->getFaction(), town->getBuildings());
|
||||
|
||||
// Build granted building & all prerequisites - e.g. Mages Guild Lvl 3 should also give Mages Guild Lvl 1 & 2
|
||||
while(true)
|
||||
@ -664,10 +664,10 @@ void CGameStateCampaign::initTowns()
|
||||
if (newBuilding == BuildingID::NONE)
|
||||
break;
|
||||
|
||||
if (town->builtBuildings.count(newBuilding) != 0)
|
||||
if(town->hasBuilt(newBuilding))
|
||||
break;
|
||||
|
||||
town->builtBuildings.insert(newBuilding);
|
||||
town->addBuilding(newBuilding);
|
||||
|
||||
auto building = town->town->buildings.at(newBuilding);
|
||||
newBuilding = building->upgrade;
|
||||
|
@ -372,7 +372,7 @@ float Statistic::getTownBuiltRatio(const PlayerState * ps)
|
||||
|
||||
for(const auto & t : ps->towns)
|
||||
{
|
||||
built += t->builtBuildings.size();
|
||||
built += t->getBuildings().size();
|
||||
for(const auto & b : t->town->buildings)
|
||||
if(!t->forbiddenBuildings.count(b.first))
|
||||
total += 1;
|
||||
|
@ -33,7 +33,7 @@ HighScoreParameter HighScore::prepareHighScores(const CGameState * gs, PlayerCol
|
||||
if(h->hasArt(ArtifactID::GRAIL))
|
||||
param.hasGrail = true;
|
||||
for(const CGTownInstance * t : playerState->towns)
|
||||
if(t->builtBuildings.count(BuildingID::GRAIL))
|
||||
if(t->hasBuilt(BuildingID::GRAIL))
|
||||
param.hasGrail = true;
|
||||
param.allEnemiesDefeated = true;
|
||||
for (PlayerColor otherPlayer(0); otherPlayer < PlayerColor::PLAYER_LIMIT; ++otherPlayer)
|
||||
|
@ -238,25 +238,23 @@ CGMarket * MarketInstanceConstructor::createObject(IGameCallback * cb) const
|
||||
return new CGUniversity(cb);
|
||||
}
|
||||
}
|
||||
else if(marketModes.size() == 2)
|
||||
{
|
||||
if(vstd::contains(marketModes, EMarketMode::ARTIFACT_EXP))
|
||||
return new CGArtifactsAltar(cb);
|
||||
}
|
||||
return new CGMarket(cb);
|
||||
}
|
||||
|
||||
void MarketInstanceConstructor::initializeObject(CGMarket * market) const
|
||||
{
|
||||
market->marketModes = marketModes;
|
||||
market->addMarketMode(marketModes);
|
||||
market->marketEfficiency = marketEfficiency;
|
||||
|
||||
market->title = market->getObjectName();
|
||||
if(!title.empty())
|
||||
market->title = VLC->generaltexth->translate(title);
|
||||
|
||||
if (!speech.empty())
|
||||
market->speech = VLC->generaltexth->translate(speech);
|
||||
if(auto university = dynamic_cast<CGUniversity*>(market))
|
||||
{
|
||||
university->title = market->getObjectName();
|
||||
if(!title.empty())
|
||||
university->title = VLC->generaltexth->translate(title);
|
||||
|
||||
if(!speech.empty())
|
||||
university->speech = VLC->generaltexth->translate(speech);
|
||||
}
|
||||
}
|
||||
|
||||
void MarketInstanceConstructor::randomizeObject(CGMarket * object, vstd::RNG & rng) const
|
||||
|
@ -23,6 +23,11 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
ObjectInstanceID CGMarket::getObjInstanceID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
void CGMarket::initObj(vstd::RNG & rand)
|
||||
{
|
||||
getObjectHandler()->configureObject(this, rand);
|
||||
@ -38,23 +43,11 @@ int CGMarket::getMarketEfficiency() const
|
||||
return marketEfficiency;
|
||||
}
|
||||
|
||||
bool CGMarket::allowsTrade(EMarketMode mode) const
|
||||
{
|
||||
return marketModes.count(mode);
|
||||
}
|
||||
|
||||
int CGMarket::availableUnits(EMarketMode mode, int marketItemSerial) const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::vector<TradeItemBuy> CGMarket::availableItemsIds(EMarketMode mode) const
|
||||
{
|
||||
if(allowsTrade(mode))
|
||||
return IMarket::availableItemsIds(mode);
|
||||
return std::vector<TradeItemBuy>();
|
||||
}
|
||||
|
||||
CGMarket::CGMarket(IGameCallback *cb):
|
||||
CGObjectInstance(cb)
|
||||
{}
|
||||
@ -63,8 +56,6 @@ std::vector<TradeItemBuy> CGBlackMarket::availableItemsIds(EMarketMode mode) con
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case EMarketMode::ARTIFACT_RESOURCE:
|
||||
return IMarket::availableItemsIds(mode);
|
||||
case EMarketMode::RESOURCE_ARTIFACT:
|
||||
{
|
||||
std::vector<TradeItemBuy> ret;
|
||||
@ -113,9 +104,4 @@ void CGUniversity::onHeroVisit(const CGHeroInstance * h) const
|
||||
cb->showObjectWindow(this, EOpenWindowMode::UNIVERSITY_WINDOW, h, true);
|
||||
}
|
||||
|
||||
ArtBearer::ArtBearer CGArtifactsAltar::bearerType() const
|
||||
{
|
||||
return ArtBearer::ALTAR;
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -18,32 +18,23 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
class DLL_LINKAGE CGMarket : public CGObjectInstance, public IMarket
|
||||
{
|
||||
public:
|
||||
|
||||
std::set<EMarketMode> marketModes;
|
||||
int marketEfficiency;
|
||||
|
||||
//window variables
|
||||
std::string title;
|
||||
std::string speech; //currently shown only in university
|
||||
|
||||
CGMarket(IGameCallback *cb);
|
||||
///IObjectInterface
|
||||
void onHeroVisit(const CGHeroInstance * h) const override; //open trading window
|
||||
void initObj(vstd::RNG & rand) override;//set skills for trade
|
||||
|
||||
///IMarket
|
||||
ObjectInstanceID getObjInstanceID() const override;
|
||||
int getMarketEfficiency() const override;
|
||||
bool allowsTrade(EMarketMode mode) const override;
|
||||
int availableUnits(EMarketMode mode, int marketItemSerial) const override; //-1 if unlimited
|
||||
std::vector<TradeItemBuy> availableItemsIds(EMarketMode mode) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
h & marketModes;
|
||||
h & static_cast<IMarket&>(*this);
|
||||
h & marketEfficiency;
|
||||
h & title;
|
||||
h & speech;
|
||||
}
|
||||
};
|
||||
|
||||
@ -68,6 +59,8 @@ class DLL_LINKAGE CGUniversity : public CGMarket
|
||||
{
|
||||
public:
|
||||
using CGMarket::CGMarket;
|
||||
std::string speech; //currently shown only in university
|
||||
std::string title;
|
||||
|
||||
std::vector<TradeItemBuy> skills; //available skills
|
||||
|
||||
@ -78,20 +71,8 @@ public:
|
||||
{
|
||||
h & static_cast<CGMarket&>(*this);
|
||||
h & skills;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGArtifactsAltar : public CGMarket, public CArtifactSet
|
||||
{
|
||||
public:
|
||||
using CGMarket::CGMarket;
|
||||
|
||||
ArtBearer::ArtBearer bearerType() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & static_cast<CGMarket&>(*this);
|
||||
h & static_cast<CArtifactSet&>(*this);
|
||||
h & speech;
|
||||
h & title;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -690,35 +690,6 @@ int CGTownInstance::getMarketEfficiency() const
|
||||
return marketCount;
|
||||
}
|
||||
|
||||
bool CGTownInstance::allowsTrade(EMarketMode mode) const
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case EMarketMode::RESOURCE_RESOURCE:
|
||||
case EMarketMode::RESOURCE_PLAYER:
|
||||
return hasBuilt(BuildingID::MARKETPLACE);
|
||||
|
||||
case EMarketMode::ARTIFACT_RESOURCE:
|
||||
case EMarketMode::RESOURCE_ARTIFACT:
|
||||
return hasBuilt(BuildingSubID::ARTIFACT_MERCHANT);
|
||||
|
||||
case EMarketMode::CREATURE_RESOURCE:
|
||||
return hasBuilt(BuildingSubID::FREELANCERS_GUILD);
|
||||
|
||||
case EMarketMode::CREATURE_UNDEAD:
|
||||
return hasBuilt(BuildingSubID::CREATURE_TRANSFORMER);
|
||||
|
||||
case EMarketMode::RESOURCE_SKILL:
|
||||
return hasBuilt(BuildingSubID::MAGIC_UNIVERSITY);
|
||||
case EMarketMode::CREATURE_EXP:
|
||||
case EMarketMode::ARTIFACT_EXP:
|
||||
return false;
|
||||
default:
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<TradeItemBuy> CGTownInstance::availableItemsIds(EMarketMode mode) const
|
||||
{
|
||||
if(mode == EMarketMode::RESOURCE_ARTIFACT)
|
||||
@ -739,6 +710,11 @@ std::vector<TradeItemBuy> CGTownInstance::availableItemsIds(EMarketMode mode) co
|
||||
return IMarket::availableItemsIds(mode);
|
||||
}
|
||||
|
||||
ObjectInstanceID CGTownInstance::getObjInstanceID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
void CGTownInstance::updateAppearance()
|
||||
{
|
||||
auto terrain = cb->gameState()->getTile(visitablePos())->terType->getId();
|
||||
@ -932,12 +908,7 @@ const CArmedInstance * CGTownInstance::getUpperArmy() const
|
||||
|
||||
bool CGTownInstance::hasBuiltSomeTradeBuilding() const
|
||||
{
|
||||
for(const auto & bid : builtBuildings)
|
||||
{
|
||||
if(town->buildings.at(bid)->IsTradeBuilding())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return availableModes().empty() ? false : true;
|
||||
}
|
||||
|
||||
bool CGTownInstance::hasBuilt(BuildingSubID::EBuildingSubID buildingID) const
|
||||
@ -962,6 +933,42 @@ bool CGTownInstance::hasBuilt(const BuildingID & buildingID, FactionID townID) c
|
||||
return false;
|
||||
}
|
||||
|
||||
void CGTownInstance::addBuilding(const BuildingID & buildingID)
|
||||
{
|
||||
if(buildingID == BuildingID::NONE)
|
||||
return;
|
||||
|
||||
const auto townType = (*VLC->townh)[getFaction()]->town;
|
||||
if(const auto & building = townType->buildings.find(buildingID); building != townType->buildings.end())
|
||||
{
|
||||
builtBuildings.insert(buildingID);
|
||||
addMarketMode(building->second->marketModes);
|
||||
}
|
||||
}
|
||||
|
||||
void CGTownInstance::removeBuilding(const BuildingID & buildingID)
|
||||
{
|
||||
if(!vstd::contains(builtBuildings, buildingID))
|
||||
return;
|
||||
|
||||
if(const auto & building = town->buildings.find(buildingID); building != town->buildings.end())
|
||||
{
|
||||
builtBuildings.erase(buildingID);
|
||||
removeMarketMode(building->second->marketModes);
|
||||
}
|
||||
}
|
||||
|
||||
void CGTownInstance::removeAllBuildings()
|
||||
{
|
||||
builtBuildings.clear();
|
||||
removeAllMarketModes();
|
||||
}
|
||||
|
||||
std::set<BuildingID> CGTownInstance::getBuildings() const
|
||||
{
|
||||
return builtBuildings;
|
||||
}
|
||||
|
||||
TResources CGTownInstance::getBuildingCost(const BuildingID & buildingID) const
|
||||
{
|
||||
if (vstd::contains(town->buildings, buildingID))
|
||||
@ -1132,23 +1139,23 @@ void CGTownInstance::serializeJsonOptions(JsonSerializeFormat & handler)
|
||||
{
|
||||
handler.serializeLIC("buildings", buildingsLIC);
|
||||
|
||||
builtBuildings.insert(BuildingID::VILLAGE_HALL);
|
||||
addBuilding(BuildingID::VILLAGE_HALL);
|
||||
|
||||
if(buildingsLIC.none.empty() && buildingsLIC.all.empty())
|
||||
{
|
||||
builtBuildings.insert(BuildingID::DEFAULT);
|
||||
addBuilding(BuildingID::DEFAULT);
|
||||
|
||||
bool hasFort = false;
|
||||
handler.serializeBool("hasFort",hasFort);
|
||||
if(hasFort)
|
||||
builtBuildings.insert(BuildingID::FORT);
|
||||
addBuilding(BuildingID::FORT);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(const si32 item : buildingsLIC.none)
|
||||
forbiddenBuildings.insert(BuildingID(item));
|
||||
for(const si32 item : buildingsLIC.all)
|
||||
builtBuildings.insert(BuildingID(item));
|
||||
addBuilding(BuildingID(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,8 @@ class DLL_LINKAGE CGTownInstance : public CGDwelling, public IShipyard, public I
|
||||
std::string nameTextId; // name of town
|
||||
|
||||
std::map<BuildingID, TownRewardableBuildingInstance*> convertOldBuildings(std::vector<TownRewardableBuildingInstance*> oldVector);
|
||||
std::set<BuildingID> builtBuildings;
|
||||
|
||||
public:
|
||||
using CGDwelling::getPosition;
|
||||
|
||||
@ -65,7 +67,6 @@ public:
|
||||
ui32 identifier; //special identifier from h3m (only > RoE maps)
|
||||
PlayerColor alignmentToPlayer; // if set to non-neutral, random town will have same faction as specified player
|
||||
std::set<BuildingID> forbiddenBuildings;
|
||||
std::set<BuildingID> builtBuildings;
|
||||
std::map<BuildingID, TownRewardableBuildingInstance*> rewardableBuildings;
|
||||
std::vector<SpellID> possibleSpells, obligatorySpells;
|
||||
std::vector<std::vector<SpellID> > spells; //spells[level] -> vector of spells, first will be available in guild
|
||||
@ -76,6 +77,7 @@ public:
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & static_cast<CGDwelling&>(*this);
|
||||
h & static_cast<IMarket&>(*this);
|
||||
h & nameTextId;
|
||||
h & built;
|
||||
h & destroyed;
|
||||
@ -152,9 +154,8 @@ public:
|
||||
EGeneratorState shipyardStatus() const override;
|
||||
const IObjectInterface * getObject() const override;
|
||||
int getMarketEfficiency() const override; //=market count
|
||||
bool allowsTrade(EMarketMode mode) const override;
|
||||
std::vector<TradeItemBuy> availableItemsIds(EMarketMode mode) const override;
|
||||
|
||||
ObjectInstanceID getObjInstanceID() const override;
|
||||
void updateAppearance();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -174,6 +175,10 @@ public:
|
||||
//checks if building is constructed and town has same subID
|
||||
bool hasBuilt(const BuildingID & buildingID) const;
|
||||
bool hasBuilt(const BuildingID & buildingID, FactionID townID) const;
|
||||
void addBuilding(const BuildingID & buildingID);
|
||||
void removeBuilding(const BuildingID & buildingID);
|
||||
void removeAllBuildings();
|
||||
std::set<BuildingID> getBuildings() const;
|
||||
|
||||
TResources getBuildingCost(const BuildingID & buildingID) const;
|
||||
TResources dailyIncome() const; //calculates daily income of this town
|
||||
|
@ -20,6 +20,11 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
bool IMarket::allowsTrade(const EMarketMode mode) const
|
||||
{
|
||||
return vstd::contains(marketModes, mode);
|
||||
}
|
||||
|
||||
bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode) const
|
||||
{
|
||||
switch(mode)
|
||||
@ -122,12 +127,7 @@ bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IMarket::allowsTrade(EMarketMode mode) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int IMarket::availableUnits(EMarketMode mode, int marketItemSerial) const
|
||||
int IMarket::availableUnits(const EMarketMode mode, const int marketItemSerial) const
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
@ -140,7 +140,45 @@ int IMarket::availableUnits(EMarketMode mode, int marketItemSerial) const
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<TradeItemBuy> IMarket::availableItemsIds(EMarketMode mode) const
|
||||
void IMarket::addMarketMode(const EMarketMode mode)
|
||||
{
|
||||
marketModes.insert(mode);
|
||||
|
||||
if(mode == EMarketMode::ARTIFACT_EXP)
|
||||
altarArtifactsStorage = std::make_shared<CArtifactSetAltar>();
|
||||
}
|
||||
|
||||
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)
|
||||
altarArtifactsStorage.reset();
|
||||
}
|
||||
|
||||
void IMarket::removeMarketMode(const std::set<EMarketMode> & modes)
|
||||
{
|
||||
for(const auto & mode : modes)
|
||||
removeMarketMode(mode);
|
||||
}
|
||||
|
||||
void IMarket::removeAllMarketModes()
|
||||
{
|
||||
marketModes.clear();
|
||||
}
|
||||
|
||||
std::shared_ptr<CArtifactSet> IMarket::getArtifactsStorage() const
|
||||
{
|
||||
return altarArtifactsStorage;
|
||||
}
|
||||
|
||||
std::vector<TradeItemBuy> IMarket::availableItemsIds(const EMarketMode mode) const
|
||||
{
|
||||
std::vector<TradeItemBuy> ret;
|
||||
switch(mode)
|
||||
@ -148,24 +186,15 @@ std::vector<TradeItemBuy> IMarket::availableItemsIds(EMarketMode mode) const
|
||||
case EMarketMode::RESOURCE_RESOURCE:
|
||||
case EMarketMode::ARTIFACT_RESOURCE:
|
||||
case EMarketMode::CREATURE_RESOURCE:
|
||||
for (auto res : GameResID::ALL_RESOURCES())
|
||||
for(const auto & res : GameResID::ALL_RESOURCES())
|
||||
ret.push_back(res);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
IMarket::IMarket()
|
||||
std::set<EMarketMode> IMarket::availableModes() const
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<EMarketMode> IMarket::availableModes() const
|
||||
{
|
||||
std::vector<EMarketMode> ret;
|
||||
for (EMarketMode i = static_cast<EMarketMode>(0); i < EMarketMode::MARKET_AFTER_LAST_PLACEHOLDER; i = vstd::next(i, 1))
|
||||
if(allowsTrade(i))
|
||||
ret.push_back(i);
|
||||
|
||||
return ret;
|
||||
return marketModes;
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -11,24 +11,44 @@
|
||||
|
||||
#include "../networkPacks/TradeItem.h"
|
||||
#include "../constants/Enumerations.h"
|
||||
#include "../CArtHandler.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class CGObjectInstance;
|
||||
|
||||
class DLL_LINKAGE IMarket
|
||||
class DLL_LINKAGE IMarket : public virtual Serializeable
|
||||
{
|
||||
public:
|
||||
IMarket();
|
||||
virtual ~IMarket() {}
|
||||
class CArtifactSetAltar : public CArtifactSet
|
||||
{
|
||||
public:
|
||||
ArtBearer::ArtBearer bearerType() const override {return ArtBearer::ALTAR;};
|
||||
};
|
||||
|
||||
virtual ObjectInstanceID getObjInstanceID() const = 0; // The market is always an object on the map
|
||||
virtual int getMarketEfficiency() const = 0;
|
||||
virtual bool allowsTrade(EMarketMode mode) const;
|
||||
virtual int availableUnits(EMarketMode mode, int marketItemSerial) const; //-1 if unlimited
|
||||
virtual std::vector<TradeItemBuy> availableItemsIds(EMarketMode mode) const;
|
||||
|
||||
virtual bool allowsTrade(const EMarketMode mode) const;
|
||||
virtual int availableUnits(const EMarketMode mode, const int marketItemSerial) const; //-1 if unlimited
|
||||
virtual std::vector<TradeItemBuy> availableItemsIds(const EMarketMode mode) const;
|
||||
void addMarketMode(const EMarketMode mode);
|
||||
void addMarketMode(const std::set<EMarketMode> & modes);
|
||||
void removeMarketMode(const EMarketMode mode);
|
||||
void removeMarketMode(const std::set<EMarketMode> & modes);
|
||||
void removeAllMarketModes();
|
||||
std::set<EMarketMode> availableModes() const;
|
||||
std::shared_ptr<CArtifactSet> getArtifactsStorage() const;
|
||||
bool getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode) const; //val1 - how many units of id1 player has to give to receive val2 units
|
||||
std::vector<EMarketMode> availableModes() const;
|
||||
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & marketModes;
|
||||
|
||||
if(h.loadingGamestate && vstd::contains(marketModes, EMarketMode::ARTIFACT_EXP))
|
||||
altarArtifactsStorage = std::make_shared<CArtifactSetAltar>();
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<CArtifactSetAltar> altarArtifactsStorage;
|
||||
std::set<EMarketMode> marketModes;
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -2198,7 +2198,11 @@ CGObjectInstance * CMapLoaderH3M::readTown(const int3 & position, std::shared_pt
|
||||
bool hasCustomBuildings = reader->readBool();
|
||||
if(hasCustomBuildings)
|
||||
{
|
||||
reader->readBitmaskBuildings(object->builtBuildings, faction);
|
||||
object->subID = faction.value();
|
||||
std::set<BuildingID> builtBuildings;
|
||||
reader->readBitmaskBuildings(builtBuildings, faction);
|
||||
for(const auto & building : builtBuildings)
|
||||
object->addBuilding(building);
|
||||
reader->readBitmaskBuildings(object->forbiddenBuildings, faction);
|
||||
}
|
||||
// Standard buildings
|
||||
@ -2206,10 +2210,10 @@ CGObjectInstance * CMapLoaderH3M::readTown(const int3 & position, std::shared_pt
|
||||
{
|
||||
bool hasFort = reader->readBool();
|
||||
if(hasFort)
|
||||
object->builtBuildings.insert(BuildingID::FORT);
|
||||
object->addBuilding(BuildingID::FORT);
|
||||
|
||||
//means that set of standard building should be included
|
||||
object->builtBuildings.insert(BuildingID::DEFAULT);
|
||||
object->addBuilding(BuildingID::DEFAULT);
|
||||
}
|
||||
|
||||
if(features.levelAB)
|
||||
|
@ -1332,7 +1332,7 @@ void NewStructures::applyGs(CGameState *gs)
|
||||
for(const auto & id : bid)
|
||||
{
|
||||
assert(t->town->buildings.at(id) != nullptr);
|
||||
t->builtBuildings.insert(id);
|
||||
t->addBuilding(id);
|
||||
}
|
||||
t->updateAppearance();
|
||||
t->built = built;
|
||||
@ -1344,7 +1344,7 @@ void RazeStructures::applyGs(CGameState *gs)
|
||||
CGTownInstance *t = gs->getTown(tid);
|
||||
for(const auto & id : bid)
|
||||
{
|
||||
t->builtBuildings.erase(id);
|
||||
t->removeBuilding(id);
|
||||
|
||||
t->updateAppearance();
|
||||
}
|
||||
|
@ -132,8 +132,7 @@ void registerTypesMapObjects(Serializer &s)
|
||||
|
||||
//s.template registerType<CObstacleInstance>();
|
||||
s.template registerType<CObstacleInstance, SpellCreatedObstacle>();
|
||||
|
||||
s.template registerType<CGMarket, CGArtifactsAltar>();
|
||||
s.template registerType<IMarket, CGMarket>();
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -79,8 +79,8 @@ void TownPlacer::placeTowns(ObjectManager & manager)
|
||||
|
||||
CGTownInstance * town = dynamic_cast<CGTownInstance *>(townFactory->create(map.mapInstance->cb, nullptr));
|
||||
town->tempOwner = player;
|
||||
town->builtBuildings.insert(BuildingID::FORT);
|
||||
town->builtBuildings.insert(BuildingID::DEFAULT);
|
||||
town->addBuilding(BuildingID::FORT);
|
||||
town->addBuilding(BuildingID::DEFAULT);
|
||||
|
||||
|
||||
for(auto spellID : VLC->spellh->getDefaultAllowed()) //add all regular spells to town
|
||||
@ -203,8 +203,8 @@ void TownPlacer::addNewTowns(int count, bool hasFort, const PlayerColor & player
|
||||
|
||||
town->tempOwner = player;
|
||||
if (hasFort)
|
||||
town->builtBuildings.insert(BuildingID::FORT);
|
||||
town->builtBuildings.insert(BuildingID::DEFAULT);
|
||||
town->addBuilding(BuildingID::FORT);
|
||||
town->addBuilding(BuildingID::DEFAULT);
|
||||
|
||||
for(auto spellID : VLC->spellh->getDefaultAllowed()) //add all regular spells to town
|
||||
town->possibleSpells.push_back(spellID);
|
||||
|
@ -166,12 +166,12 @@ void Initializer::initialize(CGTownInstance * o)
|
||||
|
||||
const std::vector<std::string> castleLevels{"village", "fort", "citadel", "castle", "capitol"};
|
||||
int lvl = vstd::find_pos(castleLevels, o->appearance->stringID);
|
||||
o->builtBuildings.insert(BuildingID::DEFAULT);
|
||||
if(lvl > -1) o->builtBuildings.insert(BuildingID::TAVERN);
|
||||
if(lvl > 0) o->builtBuildings.insert(BuildingID::FORT);
|
||||
if(lvl > 1) o->builtBuildings.insert(BuildingID::CITADEL);
|
||||
if(lvl > 2) o->builtBuildings.insert(BuildingID::CASTLE);
|
||||
if(lvl > 3) o->builtBuildings.insert(BuildingID::CAPITOL);
|
||||
o->addBuilding(BuildingID::DEFAULT);
|
||||
if(lvl > -1) o->addBuilding(BuildingID::TAVERN);
|
||||
if(lvl > 0) o->addBuilding(BuildingID::FORT);
|
||||
if(lvl > 1) o->addBuilding(BuildingID::CITADEL);
|
||||
if(lvl > 2) o->addBuilding(BuildingID::CASTLE);
|
||||
if(lvl > 3) o->addBuilding(BuildingID::CAPITOL);
|
||||
|
||||
for(auto const & spell : VLC->spellh->objects) //add all regular spells to town
|
||||
{
|
||||
|
@ -166,7 +166,7 @@ QStandardItem * TownBuildingsWidget::addBuilding(const CTown & ctown, int bId, s
|
||||
|
||||
checks << new QStandardItem;
|
||||
checks.back()->setCheckable(true);
|
||||
checks.back()->setCheckState(town.builtBuildings.count(buildingId) ? Qt::Checked : Qt::Unchecked);
|
||||
checks.back()->setCheckState(town.hasBuilt(buildingId) ? Qt::Checked : Qt::Unchecked);
|
||||
checks.back()->setData(bId, MapEditorRoles::BuildingIDRole);
|
||||
|
||||
if(building->getBase() == buildingId)
|
||||
@ -350,7 +350,9 @@ void TownBuildingsDelegate::setModelData(QWidget *editor, QAbstractItemModel *mo
|
||||
if(auto * ed = qobject_cast<TownBuildingsWidget *>(editor))
|
||||
{
|
||||
town.forbiddenBuildings = ed->getForbiddenBuildings();
|
||||
town.builtBuildings = ed->getBuiltBuildings();
|
||||
town.removeAllBuildings();
|
||||
for(const auto & building : ed->getBuiltBuildings())
|
||||
town.addBuilding(building);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -174,10 +174,11 @@ void MapController::repairMap(CMap * map) const
|
||||
{
|
||||
if(tnh->getTown())
|
||||
{
|
||||
vstd::erase_if(tnh->builtBuildings, [tnh](BuildingID bid)
|
||||
for(const auto & building : tnh->getBuildings())
|
||||
{
|
||||
return !tnh->getTown()->buildings.count(bid);
|
||||
});
|
||||
if(!tnh->getTown()->buildings.count(building))
|
||||
tnh->removeBuilding(building);
|
||||
}
|
||||
vstd::erase_if(tnh->forbiddenBuildings, [tnh](BuildingID bid)
|
||||
{
|
||||
return !tnh->getTown()->buildings.count(bid);
|
||||
|
@ -2525,7 +2525,7 @@ bool CGameHandler::razeStructure (ObjectInstanceID tid, BuildingID bid)
|
||||
{
|
||||
///incomplete, simply erases target building
|
||||
const CGTownInstance * t = getTown(tid);
|
||||
if (!vstd::contains(t->builtBuildings, bid))
|
||||
if(!t->hasBuilt(bid))
|
||||
return false;
|
||||
RazeStructures rs;
|
||||
rs.tid = tid;
|
||||
@ -3565,9 +3565,9 @@ bool CGameHandler::isAllowedExchange(ObjectInstanceID id1, ObjectInstanceID id2)
|
||||
return true;
|
||||
}
|
||||
|
||||
auto market = dynamic_cast<const IMarket*>(o1);
|
||||
auto market = getMarket(id1);
|
||||
if(market == nullptr)
|
||||
market = dynamic_cast<const IMarket*>(o2);
|
||||
market = getMarket(id2);
|
||||
if(market)
|
||||
return market->allowsTrade(EMarketMode::ARTIFACT_EXP);
|
||||
|
||||
@ -3916,15 +3916,15 @@ bool CGameHandler::sacrificeCreatures(const IMarket * market, const CGHeroInstan
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGameHandler::sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, const std::vector<ArtifactInstanceID> & arts)
|
||||
bool CGameHandler::sacrificeArtifact(const IMarket * market, const CGHeroInstance * hero, const std::vector<ArtifactInstanceID> & arts)
|
||||
{
|
||||
if (!hero)
|
||||
COMPLAIN_RET("You need hero to sacrifice artifact!");
|
||||
if(hero->getAlignment() == EAlignment::EVIL)
|
||||
COMPLAIN_RET("Evil hero can't sacrifice artifact!");
|
||||
|
||||
assert(m);
|
||||
auto altarObj = dynamic_cast<const CGArtifactsAltar*>(m);
|
||||
assert(market);
|
||||
const auto artSet = market->getArtifactsStorage();
|
||||
|
||||
int expSum = 0;
|
||||
auto finish = [this, &hero, &expSum]()
|
||||
@ -3934,15 +3934,15 @@ bool CGameHandler::sacrificeArtifact(const IMarket * m, const CGHeroInstance * h
|
||||
|
||||
for(const auto & artInstId : arts)
|
||||
{
|
||||
if(auto art = altarObj->getArtByInstanceId(artInstId))
|
||||
if(auto art = artSet->getArtByInstanceId(artInstId))
|
||||
{
|
||||
if(art->artType->isTradable())
|
||||
{
|
||||
int dmp;
|
||||
int expToGive;
|
||||
m->getOffer(art->getTypeId(), 0, dmp, expToGive, EMarketMode::ARTIFACT_EXP);
|
||||
market->getOffer(art->getTypeId(), 0, dmp, expToGive, EMarketMode::ARTIFACT_EXP);
|
||||
expSum += expToGive;
|
||||
removeArtifact(ArtifactLocation(altarObj->id, altarObj->getArtPos(art)));
|
||||
removeArtifact(ArtifactLocation(market->getObjInstanceID(), artSet->getArtPos(art)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -282,7 +282,7 @@ public:
|
||||
|
||||
void start(bool resume);
|
||||
void tick(int millisecondsPassed);
|
||||
bool sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, const std::vector<ArtifactInstanceID> & arts);
|
||||
bool sacrificeArtifact(const IMarket * market, const CGHeroInstance * hero, const std::vector<ArtifactInstanceID> & arts);
|
||||
void spawnWanderingMonsters(CreatureID creatureID);
|
||||
|
||||
// Check for victory and loss conditions
|
||||
|
@ -184,7 +184,7 @@ void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & pack)
|
||||
|
||||
void ApplyGhNetPackVisitor::visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack)
|
||||
{
|
||||
if(dynamic_cast<const IMarket*>(gh.getObj(pack.srcHero)) == nullptr)
|
||||
if(gh.getMarket(pack.srcHero) == nullptr)
|
||||
gh.throwIfWrongOwner(&pack, pack.srcHero);
|
||||
if(pack.swap)
|
||||
gh.throwIfWrongOwner(&pack, pack.dstHero);
|
||||
@ -250,7 +250,7 @@ void ApplyGhNetPackVisitor::visitTradeOnMarketplace(TradeOnMarketplace & pack)
|
||||
{
|
||||
const CGObjectInstance * object = gh.getObj(pack.marketId);
|
||||
const CGHeroInstance * hero = gh.getHero(pack.heroId);
|
||||
const auto * market = dynamic_cast<const IMarket*>(object);
|
||||
const auto * market = gh.getMarket(pack.marketId);
|
||||
|
||||
gh.throwIfWrongPlayer(&pack);
|
||||
gh.throwIfPlayerNotActive(&pack);
|
||||
|
@ -64,7 +64,7 @@ TEST_F(CatapultTest, NotApplicableInVillage)
|
||||
TEST_F(CatapultTest, NotApplicableForDefenderIfSmart)
|
||||
{
|
||||
auto fakeTown = std::make_shared<CGTownInstance>(nullptr);
|
||||
fakeTown->builtBuildings.insert(BuildingID::FORT);
|
||||
fakeTown->addBuilding(BuildingID::FORT);
|
||||
mechanicsMock.casterSide = BattleSide::DEFENDER;
|
||||
|
||||
EXPECT_CALL(*battleFake, getDefendedTown()).WillRepeatedly(Return(fakeTown.get()));
|
||||
@ -78,7 +78,7 @@ TEST_F(CatapultTest, NotApplicableForDefenderIfSmart)
|
||||
TEST_F(CatapultTest, DISABLED_ApplicableInTown)
|
||||
{
|
||||
auto fakeTown = std::make_shared<CGTownInstance>(nullptr);
|
||||
fakeTown->builtBuildings.insert(BuildingID::FORT);
|
||||
fakeTown->addBuilding(BuildingID::FORT);
|
||||
|
||||
EXPECT_CALL(*battleFake, getDefendedTown()).WillRepeatedly(Return(fakeTown.get()));
|
||||
EXPECT_CALL(mechanicsMock, adaptProblem(_, _)).Times(0);
|
||||
@ -108,7 +108,7 @@ protected:
|
||||
{
|
||||
EffectFixture::setUp();
|
||||
fakeTown = std::make_shared<CGTownInstance>(nullptr);
|
||||
fakeTown->builtBuildings.insert(BuildingID::FORT);
|
||||
fakeTown->addBuilding(BuildingID::FORT);
|
||||
}
|
||||
private:
|
||||
std::shared_ptr<CGTownInstance> fakeTown;
|
||||
|
Loading…
x
Reference in New Issue
Block a user