1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-09-16 09:26:28 +02:00

Loading market modes from json

This commit is contained in:
SoundSSGood
2024-08-20 23:36:31 +03:00
parent 2e3e6b1553
commit 0c5022cae8
19 changed files with 63 additions and 54 deletions

View File

@@ -80,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 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 swapGarrisonHero(const CGTownInstance *town)=0;
virtual void trade(const ObjectInstanceID marketId, 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 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 = nullptr)=0; 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 selectionMade(int selection, QueryID queryID) =0;
virtual int sendQueryReply(std::optional<int32_t> reply, QueryID queryID) =0; virtual int sendQueryReply(std::optional<int32_t> reply, QueryID queryID) =0;

View File

@@ -166,7 +166,7 @@
"townHall": { }, "townHall": { },
"cityHall": { }, "cityHall": { },
"capitol": { }, "capitol": { },
"marketplace": { }, "marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
"resourceSilo": { "produce": { "ore": 1, "wood": 1 } }, "resourceSilo": { "produce": { "ore": 1, "wood": 1 } },
"blacksmith": { }, "blacksmith": { },

View File

@@ -171,11 +171,11 @@
"townHall": { }, "townHall": { },
"cityHall": { }, "cityHall": { },
"capitol": { }, "capitol": { },
"marketplace": { }, "marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
"resourceSilo": { "produce": { "mercury": 1 } }, "resourceSilo": { "produce": { "mercury": 1 } },
"blacksmith": { }, "blacksmith": { },
"special1": { "type" : "artifactMerchant", "requires" : [ "marketplace" ] }, "special1": { "type" : "artifactMerchant", "requires" : [ "marketplace" ], "marketModes" : ["resource-artifact", "artifact-resource"] },
"horde1": { "id" : 18, "upgrades" : "dwellingLvl1" }, "horde1": { "id" : 18, "upgrades" : "dwellingLvl1" },
"horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl1", "requires" : [ "horde1" ], "mode" : "auto" }, "horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl1", "requires" : [ "horde1" ], "mode" : "auto" },
"ship": { "id" : 20, "upgrades" : "shipyard" }, "ship": { "id" : 20, "upgrades" : "shipyard" },

View File

@@ -167,11 +167,11 @@
"townHall": { }, "townHall": { },
"cityHall": { }, "cityHall": { },
"capitol": { }, "capitol": { },
"marketplace": { }, "marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
"resourceSilo": { "produce": { "sulfur": 1 } }, "resourceSilo": { "produce": { "sulfur": 1 } },
"blacksmith": { }, "blacksmith": { },
"special1": { "type" : "artifactMerchant", "requires" : [ "marketplace" ] }, "special1": { "type" : "artifactMerchant", "requires" : [ "marketplace" ], "marketModes" : ["resource-artifact", "artifact-resource"] },
"horde1": { "id" : 18, "upgrades" : "dwellingLvl1" }, "horde1": { "id" : 18, "upgrades" : "dwellingLvl1" },
"horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl1", "requires" : [ "horde1" ], "mode" : "auto" }, "horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl1", "requires" : [ "horde1" ], "mode" : "auto" },
"special2": { "special2": {

View File

@@ -165,7 +165,7 @@
"townHall": { }, "townHall": { },
"cityHall": { }, "cityHall": { },
"capitol": { }, "capitol": { },
"marketplace": { }, "marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
"resourceSilo": { "produce": { "wood": 1, "ore": 1 } }, "resourceSilo": { "produce": { "wood": 1, "ore": 1 } },
"blacksmith": { }, "blacksmith": { },

View File

@@ -167,7 +167,7 @@
"townHall": { }, "townHall": { },
"cityHall": { }, "cityHall": { },
"capitol": { }, "capitol": { },
"marketplace": { }, "marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
"resourceSilo": { "produce": { "mercury": 1 } }, "resourceSilo": { "produce": { "mercury": 1 } },
"blacksmith": { }, "blacksmith": { },

View File

@@ -172,7 +172,7 @@
"townHall": { }, "townHall": { },
"cityHall": { }, "cityHall": { },
"capitol": { }, "capitol": { },
"marketplace": { }, "marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
"resourceSilo": { "produce": { "ore": 1, "wood": 1 } }, "resourceSilo": { "produce": { "ore": 1, "wood": 1 } },
"blacksmith": { }, "blacksmith": { },
@@ -182,7 +182,7 @@
"ship": { "id" : 20, "upgrades" : "shipyard" }, "ship": { "id" : 20, "upgrades" : "shipyard" },
"special2": { "requires" : [ "mageGuild1" ], "special2": { "requires" : [ "mageGuild1" ],
"bonuses": [ { "type": "UNDEAD_RAISE_PERCENTAGE", "val": 10, "propagator": "PLAYER_PROPAGATOR" } ] }, "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 }, "grail": { "id" : 26, "mode" : "grail", "produce": { "gold": 5000 },
"bonuses": [ { "type": "UNDEAD_RAISE_PERCENTAGE", "val": 20, "propagator": "PLAYER_PROPAGATOR" } ] }, "bonuses": [ { "type": "UNDEAD_RAISE_PERCENTAGE", "val": 20, "propagator": "PLAYER_PROPAGATOR" } ] },

View File

@@ -170,7 +170,7 @@
"townHall": { }, "townHall": { },
"cityHall": { }, "cityHall": { },
"capitol": { }, "capitol": { },
"marketplace": { }, "marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
"resourceSilo": { "produce": { "crystal": 1 } }, "resourceSilo": { "produce": { "crystal": 1 } },
"blacksmith": { }, "blacksmith": { },

View File

@@ -162,14 +162,14 @@
"townHall": { }, "townHall": { },
"cityHall": { }, "cityHall": { },
"capitol": { }, "capitol": { },
"marketplace": { }, "marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
"resourceSilo": { "produce": { "ore": 1, "wood": 1 } }, "resourceSilo": { "produce": { "ore": 1, "wood": 1 } },
"blacksmith": { }, "blacksmith": { },
"special1": { "type" : "escapeTunnel", "requires" : [ "fort" ] }, "special1": { "type" : "escapeTunnel", "requires" : [ "fort" ] },
"horde1": { "id" : 18, "upgrades" : "dwellingLvl1" }, "horde1": { "id" : 18, "upgrades" : "dwellingLvl1" },
"horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl1", "requires" : [ "horde1" ], "mode" : "auto" }, "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" ] }, "special3": { "type" : "ballistaYard", "requires" : [ "blacksmith" ] },
"special4": { "special4": {
"requires" : [ "fort" ], "requires" : [ "fort" ],

View File

@@ -165,11 +165,11 @@
"townHall": { }, "townHall": { },
"cityHall": { }, "cityHall": { },
"capitol": { }, "capitol": { },
"marketplace": { }, "marketplace": { "marketModes" : ["resource-resource", "resource-player"] },
"resourceSilo": { "produce" : { "gems": 1 } }, "resourceSilo": { "produce" : { "gems": 1 } },
"blacksmith": { }, "blacksmith": { },
"special1": { "type" : "artifactMerchant", "requires" : [ "marketplace" ] }, "special1": { "type" : "artifactMerchant", "requires" : [ "marketplace" ], "marketModes" : ["resource-artifact", "artifact-resource"] },
"horde1": { "id" : 18, "upgrades" : "dwellingLvl2" }, "horde1": { "id" : 18, "upgrades" : "dwellingLvl2" },
"horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl2", "requires" : [ "horde1" ], "mode" : "auto" }, "horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl2", "requires" : [ "horde1" ], "mode" : "auto" },
"special2": { "height" : "high", "requires" : [ "fort" ] }, "special2": { "height" : "high", "requires" : [ "fort" ] },

View File

@@ -98,5 +98,10 @@
"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", "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" } "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"
}
} }
} }

View File

@@ -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" // If set to true, this building will replace all bonuses from base building, leaving only bonuses defined by this building"
"upgradeReplacesBonuses" : false, "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 #### 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. 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 ### Town Structure node
@@ -248,3 +250,17 @@ In addition to above, it is possible to use same format as [Rewardable](../Map_O
"hidden" : false "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"] },
```

View File

@@ -34,6 +34,7 @@ public:
TResources resources; TResources resources;
TResources produce; TResources produce;
TRequired requirements; TRequired requirements;
std::set<EMarketMode> marketModes;
BuildingID bid; //structure ID BuildingID bid; //structure ID
BuildingID upgrade; /// indicates that building "upgrade" can be improved by this, -1 = empty BuildingID upgrade; /// indicates that building "upgrade" can be improved by this, -1 = empty

View File

@@ -342,6 +342,11 @@ void CTownHandler::loadBuilding(CTown * town, const std::string & stringID, cons
ret->upgrade = BuildingID::NONE; ret->upgrade = BuildingID::NONE;
ret->town->buildings[ret->bid] = ret; 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()); registerObject(source.getModScope(), ret->town->getBuildingScope(), ret->identifier, ret->bid.getNum());
} }

View File

@@ -943,8 +943,12 @@ void CGTownInstance::addBuilding(const BuildingID & buildingID)
if(buildingID == BuildingID::NONE) if(buildingID == BuildingID::NONE)
return; return;
const auto townType = (*VLC->townh)[getFaction()]->town;
if(const auto & building = townType->buildings.find(buildingID); building != townType->buildings.end())
{
builtBuildings.insert(buildingID); builtBuildings.insert(buildingID);
marketBuildingModeMapper(buildingID, [this](const EMarketMode mode) {addMarketMode(mode);}); addMarketMode(building->second->marketModes);
}
} }
void CGTownInstance::removeBuilding(const BuildingID & buildingID) void CGTownInstance::removeBuilding(const BuildingID & buildingID)
@@ -952,8 +956,11 @@ void CGTownInstance::removeBuilding(const BuildingID & buildingID)
if(!vstd::contains(builtBuildings, buildingID)) if(!vstd::contains(builtBuildings, buildingID))
return; return;
if(const auto & building = town->buildings.find(buildingID); building != town->buildings.end())
{
builtBuildings.erase(buildingID); builtBuildings.erase(buildingID);
marketBuildingModeMapper(buildingID, [this](const EMarketMode mode) {removeMarketMode(mode);}); removeMarketMode(building->second->marketModes);
}
} }
void CGTownInstance::removeAllBuildings() void CGTownInstance::removeAllBuildings()
@@ -967,37 +974,6 @@ std::set<BuildingID> CGTownInstance::getBuildings() const
return builtBuildings; return builtBuildings;
} }
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 TResources CGTownInstance::getBuildingCost(const BuildingID & buildingID) const
{ {
if (vstd::contains(town->buildings, buildingID)) if (vstd::contains(town->buildings, buildingID))

View File

@@ -231,7 +231,6 @@ protected:
void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override; void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
void serializeJsonOptions(JsonSerializeFormat & handler) override; void serializeJsonOptions(JsonSerializeFormat & handler) override;
void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override; void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override;
void marketBuildingModeMapper(const BuildingID & buildingID, const std::function<void(const EMarketMode)> & func);
private: private:
FactionID randomizeFaction(vstd::RNG & rand); FactionID randomizeFaction(vstd::RNG & rand);

View File

@@ -162,6 +162,12 @@ void IMarket::removeMarketMode(const EMarketMode mode)
altarArtifactsStorage.reset(); altarArtifactsStorage.reset();
} }
void IMarket::removeMarketMode(const std::set<EMarketMode> & modes)
{
for(const auto & mode : modes)
removeMarketMode(mode);
}
void IMarket::removeAllMarketModes() void IMarket::removeAllMarketModes()
{ {
marketModes.clear(); marketModes.clear();

View File

@@ -32,6 +32,7 @@ public:
void addMarketMode(const EMarketMode mode); void addMarketMode(const EMarketMode mode);
void addMarketMode(const std::set<EMarketMode> & modes); void addMarketMode(const std::set<EMarketMode> & modes);
void removeMarketMode(const EMarketMode mode); void removeMarketMode(const EMarketMode mode);
void removeMarketMode(const std::set<EMarketMode> & modes);
void removeAllMarketModes(); void removeAllMarketModes();
std::set<EMarketMode> availableModes() const; std::set<EMarketMode> availableModes() const;
std::shared_ptr<CArtifactSet> getArtifactsStorage() const; std::shared_ptr<CArtifactSet> getArtifactsStorage() const;

View File

@@ -55,7 +55,6 @@ void registerTypesMapObjects(Serializer &s)
s.template registerType<CGMarket, CGBlackMarket>(); s.template registerType<CGMarket, CGBlackMarket>();
s.template registerType<CGMarket, CGUniversity>(); s.template registerType<CGMarket, CGUniversity>();
s.template registerType<CGObjectInstance, CGHeroPlaceholder>(); s.template registerType<CGObjectInstance, CGHeroPlaceholder>();
s.template registerType<IMarket, CGMarket>();
s.template registerType<CGObjectInstance, CArmedInstance>(); s.template registerType<CBonusSystemNode, CArmedInstance>(); s.template registerType<CCreatureSet, CArmedInstance>(); s.template registerType<CGObjectInstance, CArmedInstance>(); s.template registerType<CBonusSystemNode, CArmedInstance>(); s.template registerType<CCreatureSet, CArmedInstance>();
@@ -133,6 +132,7 @@ void registerTypesMapObjects(Serializer &s)
//s.template registerType<CObstacleInstance>(); //s.template registerType<CObstacleInstance>();
s.template registerType<CObstacleInstance, SpellCreatedObstacle>(); s.template registerType<CObstacleInstance, SpellCreatedObstacle>();
s.template registerType<IMarket, CGMarket>();
} }
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END