mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
IMarket now able to store artifacts
This commit is contained in:
parent
fd45b5144d
commit
39bb6d5f39
@ -804,10 +804,10 @@ void CGameState::initTowns()
|
||||
//init buildings
|
||||
if(vstd::contains(vti->builtBuildings, 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);
|
||||
|
||||
@ -815,32 +815,32 @@ 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
|
||||
{
|
||||
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
|
||||
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);
|
||||
vti->addBuilding(BuildingID::HORDE_2);
|
||||
if (vstd::contains(vti->builtBuildings, upgradedDwellings[i]))
|
||||
vti->builtBuildings.insert(BuildingID::HORDE_2_UPGR);
|
||||
vti->addBuilding(BuildingID::HORDE_2_UPGR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -853,7 +853,7 @@ void CGameState::initTowns()
|
||||
});
|
||||
|
||||
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)
|
||||
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)
|
||||
|
@ -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;
|
||||
|
@ -248,7 +248,7 @@ CGMarket * MarketInstanceConstructor::createObject(IGameCallback * cb) const
|
||||
|
||||
void MarketInstanceConstructor::initializeObject(CGMarket * market) const
|
||||
{
|
||||
market->marketModes = marketModes;
|
||||
market->addMarketMode(marketModes);
|
||||
market->marketEfficiency = marketEfficiency;
|
||||
|
||||
if(auto univercity = dynamic_cast<CGUniversity*>(market))
|
||||
|
@ -38,11 +38,6 @@ 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;
|
||||
|
@ -18,8 +18,6 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
class DLL_LINKAGE CGMarket : public CGObjectInstance, public IMarket
|
||||
{
|
||||
public:
|
||||
|
||||
std::set<EMarketMode> marketModes;
|
||||
int marketEfficiency;
|
||||
|
||||
CGMarket(IGameCallback *cb);
|
||||
@ -29,7 +27,6 @@ public:
|
||||
|
||||
///IMarket
|
||||
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;
|
||||
|
||||
@ -37,7 +34,6 @@ public:
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
h & static_cast<IMarket&>(*this);
|
||||
h & marketModes;
|
||||
h & marketEfficiency;
|
||||
}
|
||||
};
|
||||
|
@ -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)
|
||||
@ -962,6 +933,55 @@ bool CGTownInstance::hasBuilt(const BuildingID & buildingID, FactionID townID) c
|
||||
return false;
|
||||
}
|
||||
|
||||
void CGTownInstance::addBuilding(const BuildingID & buildingID)
|
||||
{
|
||||
if(buildingID == BuildingID::NONE)
|
||||
return;
|
||||
|
||||
builtBuildings.insert(buildingID);
|
||||
marketBuildingModeMapper(buildingID, [this](const EMarketMode mode) {addMarketMode(mode);});
|
||||
}
|
||||
|
||||
void CGTownInstance::removeBuilding(const BuildingID & buildingID)
|
||||
{
|
||||
if(!vstd::contains(builtBuildings, buildingID))
|
||||
return;
|
||||
|
||||
builtBuildings.erase(buildingID);
|
||||
marketBuildingModeMapper(buildingID, [this](const EMarketMode mode) {removeMarketMode(mode);});
|
||||
}
|
||||
|
||||
void CGTownInstance::marketBuildingModeMapper(const BuildingID & buildingID, const std::function<void(const EMarketMode)> & func)
|
||||
{
|
||||
const auto townType = (*VLC->townh)[getFaction()]->town;
|
||||
if(townType->buildings.find(buildingID) == townType->buildings.end())
|
||||
return;
|
||||
|
||||
// TODO how to remove hardcoded buildings?
|
||||
if(buildingID == BuildingID::MARKETPLACE)
|
||||
{
|
||||
func(EMarketMode::RESOURCE_RESOURCE);
|
||||
func(EMarketMode::RESOURCE_PLAYER);
|
||||
}
|
||||
else if(townType->buildings.at(buildingID)->subId == BuildingSubID::ARTIFACT_MERCHANT)
|
||||
{
|
||||
func(EMarketMode::ARTIFACT_RESOURCE);
|
||||
func(EMarketMode::RESOURCE_ARTIFACT);
|
||||
}
|
||||
else if(townType->buildings.at(buildingID)->subId == BuildingSubID::FREELANCERS_GUILD)
|
||||
{
|
||||
func(EMarketMode::CREATURE_RESOURCE);
|
||||
}
|
||||
else if(townType->buildings.at(buildingID)->subId == BuildingSubID::CREATURE_TRANSFORMER)
|
||||
{
|
||||
func(EMarketMode::CREATURE_UNDEAD);
|
||||
}
|
||||
else if(townType->buildings.at(buildingID)->subId == BuildingSubID::MAGIC_UNIVERSITY)
|
||||
{
|
||||
func(EMarketMode::RESOURCE_SKILL);
|
||||
}
|
||||
}
|
||||
|
||||
TResources CGTownInstance::getBuildingCost(const BuildingID & buildingID) const
|
||||
{
|
||||
if (vstd::contains(town->buildings, buildingID))
|
||||
@ -1132,23 +1152,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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +153,6 @@ 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;
|
||||
|
||||
void updateAppearance();
|
||||
@ -175,6 +174,8 @@ 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);
|
||||
|
||||
TResources getBuildingCost(const BuildingID & buildingID) const;
|
||||
TResources dailyIncome() const; //calculates daily income of this town
|
||||
@ -227,6 +228,7 @@ protected:
|
||||
void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
|
||||
void serializeJsonOptions(JsonSerializeFormat & handler) override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override;
|
||||
void marketBuildingModeMapper(const BuildingID & buildingID, const std::function<void(const EMarketMode)> & func);
|
||||
|
||||
private:
|
||||
FactionID randomizeFaction(vstd::RNG & rand);
|
||||
|
@ -20,6 +20,11 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
bool IMarket::allowsTrade(const EMarketMode mode) const
|
||||
{
|
||||
return marketModes.count(mode) > 0;
|
||||
}
|
||||
|
||||
bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode) const
|
||||
{
|
||||
switch(mode)
|
||||
@ -135,6 +140,28 @@ int IMarket::availableUnits(const EMarketMode mode, const int marketItemSerial)
|
||||
}
|
||||
}
|
||||
|
||||
void IMarket::addMarketMode(const EMarketMode mode)
|
||||
{
|
||||
marketModes.insert(mode);
|
||||
|
||||
if(mode == EMarketMode::ARTIFACT_EXP)
|
||||
altarArtifacts = 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)
|
||||
altarArtifacts.reset();
|
||||
}
|
||||
|
||||
std::vector<TradeItemBuy> IMarket::availableItemsIds(const EMarketMode mode) const
|
||||
{
|
||||
std::vector<TradeItemBuy> ret;
|
||||
|
@ -25,22 +25,27 @@ public:
|
||||
};
|
||||
|
||||
virtual int getMarketEfficiency() const = 0;
|
||||
virtual bool allowsTrade(const EMarketMode mode) const = 0;
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
if(h.loadingGamestate)
|
||||
{
|
||||
}
|
||||
h & marketModes;
|
||||
|
||||
if(h.loadingGamestate && vstd::contains(marketModes, EMarketMode::ARTIFACT_EXP))
|
||||
altarArtifacts = std::make_shared<CArtifactSetAltar>();
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<CArtifactSetAltar> altarArtifacts;
|
||||
std::set<EMarketMode> marketModes;
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -2198,18 +2198,20 @@ CGObjectInstance * CMapLoaderH3M::readTown(const int3 & position, std::shared_pt
|
||||
bool hasCustomBuildings = reader->readBool();
|
||||
if(hasCustomBuildings)
|
||||
{
|
||||
reader->readBitmaskBuildings(object->builtBuildings, faction);
|
||||
reader->readBitmaskBuildings(object->forbiddenBuildings, faction);
|
||||
object->subID = faction.value();
|
||||
for(const auto & building : reader->readBitmaskBuildings(faction))
|
||||
object->addBuilding(building);
|
||||
object->forbiddenBuildings = reader->readBitmaskBuildings(faction);
|
||||
}
|
||||
// Standard buildings
|
||||
else
|
||||
{
|
||||
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)
|
||||
@ -2257,7 +2259,7 @@ CGObjectInstance * CMapLoaderH3M::readTown(const int3 & position, std::shared_pt
|
||||
reader->skipZero(17);
|
||||
|
||||
// New buildings
|
||||
reader->readBitmaskBuildings(event.buildings, faction);
|
||||
event.buildings = reader->readBitmaskBuildings(faction);
|
||||
|
||||
event.creatures.resize(7);
|
||||
for(int i = 0; i < 7; ++i)
|
||||
|
@ -257,9 +257,10 @@ PlayerColor MapReaderH3M::readPlayer32()
|
||||
return PlayerColor(value);
|
||||
}
|
||||
|
||||
void MapReaderH3M::readBitmaskBuildings(std::set<BuildingID> & dest, std::optional<FactionID> faction)
|
||||
std::set<BuildingID> MapReaderH3M::readBitmaskBuildings(std::optional<FactionID> faction)
|
||||
{
|
||||
std::set<BuildingID> h3m;
|
||||
std::set<BuildingID> dest;
|
||||
readBitmask(h3m, features.buildingsBytes, features.buildingsCount, false);
|
||||
|
||||
for (auto const & h3mEntry : h3m)
|
||||
@ -269,6 +270,7 @@ void MapReaderH3M::readBitmaskBuildings(std::set<BuildingID> & dest, std::option
|
||||
if (mapped != BuildingID::NONE) // artifact merchant may be set in random town, but not present in actual town
|
||||
dest.insert(mapped);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
void MapReaderH3M::readBitmaskFactions(std::set<FactionID> & dest, bool invert)
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
PlayerColor readPlayer();
|
||||
PlayerColor readPlayer32();
|
||||
|
||||
void readBitmaskBuildings(std::set<BuildingID> & dest, std::optional<FactionID> faction);
|
||||
std::set<BuildingID> readBitmaskBuildings(std::optional<FactionID> faction);
|
||||
void readBitmaskFactions(std::set<FactionID> & dest, bool invert);
|
||||
void readBitmaskPlayers(std::set<PlayerColor> & dest, bool invert);
|
||||
void readBitmaskResources(std::set<GameResID> & dest, bool invert);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user