Browse Source

Configurable Conflux University

Ivan Savenko 6 months ago
parent
commit
f71db8af07

+ 10 - 1
config/factions/conflux.json

@@ -178,7 +178,16 @@
 				"horde1":         { "id" : 18, "upgrades" : "dwellingLvl1" },
 				"horde1Upgr":     { "id" : 19, "upgrades" : "dwellingUpLvl1", "requires" : [ "horde1" ], "mode" : "auto" },
 				"ship":           { "id" : 20, "upgrades" : "shipyard" },
-				"special2":       { "requires" : [ "mageGuild1" ], "marketModes" : ["resource-skill"] },
+				"special2":       {
+					"requires" : [ "mageGuild1" ],
+					"marketModes" : ["resource-skill"],
+					"marketOffer" : [
+						"fireMagic",
+						"airMagic",
+						"waterMagic",
+						"earthMagic"
+					]
+				},
 				"grail":          { "id" : 26, "mode" : "grail", "produce": { "gold": 5000 }},
 				"extraTownHall":  { "id" : 27, "requires" : [ "townHall" ], "mode" : "auto" },
 				"extraCityHall":  { "id" : 28, "requires" : [ "cityHall" ], "mode" : "auto" },

+ 8 - 0
config/schemas/townBuilding.json

@@ -134,5 +134,13 @@
 			},
 			"description" : "List of modes available in this market"
 		}
+		
+		"marketOffer" : {
+			"type" : "array",
+			"items" : {
+				"type" : "string"
+			},
+			"description" : "List of predefined items available on market from this building"
+		}
 	}
 }

+ 4 - 0
docs/modders/Entities_Format/Town_Building_Format.md

@@ -213,6 +213,10 @@ These are just a couple of examples of what can be done in VCMI. See vcmi config
 	
 	// If the building is a market, it requires market mode.
 	"marketModes" : [ "resource-resource", "resource-player" ],
+	
+	// Required if building offers resource-skill trade.
+	// NOTE: multiple resource-skill buildings in the same town are not supported
+	"marketOffer" : [ "fireMagic", "airMagic", "waterMagic", "earthMagic" ],
 }
 ```
 

+ 2 - 0
lib/entities/building/CBuilding.h

@@ -15,6 +15,7 @@
 #include "../../LogicalExpression.h"
 #include "../../ResourceSet.h"
 #include "../../bonuses/BonusList.h"
+#include "../../networkPacks/TradeItem.h"
 #include "../../rewardable/Info.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
@@ -39,6 +40,7 @@ public:
 	ArtifactID warMachine;
 	TownFortifications fortifications;
 	std::set<EMarketMode> marketModes;
+	std::vector<TradeItemBuy> marketOffer;
 
 	BuildingID bid; //structure ID
 	BuildingID upgrade; /// indicates that building "upgrade" can be improved by this, -1 = empty

+ 17 - 1
lib/entities/faction/CTownHandler.cpp

@@ -386,7 +386,23 @@ void CTownHandler::loadBuilding(CTown * town, const std::string & stringID, cons
 	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()));
+		{
+			auto mode = MappedKeys::MARKET_NAMES_TO_TYPES.at(element.String());
+			ret->marketModes.insert(mode);
+
+			if (mode == EMarketMode::RESOURCE_SKILL)
+			{
+				const auto & items = source["marketOffer"].Vector();
+				ret->marketOffer.resize(items.size());
+				for (int i = 0; i < items.size(); ++i)
+				{
+					LIBRARY->identifiers()->requestIdentifier("secondarySkill", items[i], [ret, i](si32 identifier)
+					{
+						ret->marketOffer[i] = SecondarySkill(identifier);
+					});
+				}
+			}
+		}
 	}
 
 	registerObject(source.getModScope(), ret->town->getBuildingScope(), ret->identifier, ret->bid.getNum());

+ 0 - 6
lib/gameState/CGameState.cpp

@@ -787,12 +787,6 @@ void CGameState::initTowns(vstd::RNG & randomGenerator)
 	if (campaign)
 		campaign->initTowns();
 
-	map->townUniversitySkills.clear();
-	map->townUniversitySkills.push_back(SecondarySkill(SecondarySkill::FIRE_MAGIC));
-	map->townUniversitySkills.push_back(SecondarySkill(SecondarySkill::AIR_MAGIC));
-	map->townUniversitySkills.push_back(SecondarySkill(SecondarySkill::WATER_MAGIC));
-	map->townUniversitySkills.push_back(SecondarySkill(SecondarySkill::EARTH_MAGIC));
-
 	for (const auto & townID : map->getAllTowns())
 	{
 		auto vti = getTown(townID);

+ 9 - 1
lib/mapObjects/CGTownInstance.cpp

@@ -683,7 +683,15 @@ std::vector<TradeItemBuy> CGTownInstance::availableItemsIds(EMarketMode mode) co
 	}
 	else if ( mode == EMarketMode::RESOURCE_SKILL )
 	{
-		return cb->gameState().getMap().townUniversitySkills;
+		for (const auto & buildingID : builtBuildings)
+		{
+			const auto * buildingPtr = getTown()->buildings.at(buildingID).get();
+			if (vstd::contains(buildingPtr->marketModes, mode))
+				return buildingPtr->marketOffer;
+		}
+
+		logMod->warn("Town has resource-skill trade but has no skills to offer!");
+		return {};
 	}
 	else
 		return IMarket::availableItemsIds(mode);

+ 5 - 2
lib/mapping/CMap.h

@@ -272,7 +272,6 @@ public:
 	std::map<TeamID, ui8> obelisksVisited; //map: team_id => how many obelisks has been visited
 
 	std::vector<ArtifactID> townMerchantArtifacts;
-	std::vector<TradeItemBuy> townUniversitySkills;
 
 	void overrideGameSettings(const JsonNode & input);
 	void overrideGameSetting(EGameSettings option, const JsonNode & input);
@@ -345,7 +344,11 @@ public:
 		h & obeliskCount;
 		h & obelisksVisited;
 		h & townMerchantArtifacts;
-		h & townUniversitySkills;
+		if (!h.hasFeature(Handler::Version::STORE_UID_COUNTER_IN_CMAP))
+		{
+			std::vector<TradeItemBuy> townUniversitySkills;
+			h & townUniversitySkills;
+		}
 
 		h & instanceNames;
 		h & *gameSettings;

+ 2 - 1
lib/serializer/ESerializationVersion.h

@@ -45,8 +45,9 @@ enum class ESerializationVersion : int32_t
 	CUSTOM_BONUS_ICONS, // support for custom icons in bonuses
 	SERVER_STATISTICS, // statistics now only saved on server
 	OPPOSITE_SIDE_LIMITER_OWNER, // opposite side limiter no longer stores owner in itself
+	UNIVERSITY_CONFIG, // town university is configurable
 
-	CURRENT = OPPOSITE_SIDE_LIMITER_OWNER,
+	CURRENT = UNIVERSITY_CONFIG,
 };
 
 static_assert(ESerializationVersion::MINIMAL <= ESerializationVersion::CURRENT, "Invalid serialization version definition!");