瀏覽代碼

add mines support

Laserlicht 3 周之前
父節點
當前提交
5ae4db60e3

+ 1 - 1
client/windows/CKingdomInterface.cpp

@@ -619,7 +619,7 @@ void CKingdomInterface::generateMinesList(const std::vector<const CGObjectInstan
 	totalIncome += GAME->interface()->cb->getPlayerState(GAME->interface()->playerID)->valOfBonuses(BonusType::RESOURCES_CONSTANT_BOOST, BonusSubtypeID(GameResID(EGameResID::GOLD))) * playerSettings->handicap.percentIncome / 100;
 	totalIncome += GAME->interface()->cb->getPlayerState(GAME->interface()->playerID)->valOfBonuses(BonusType::RESOURCES_TOWN_MULTIPLYING_BOOST, BonusSubtypeID(GameResID(EGameResID::GOLD))) * towns.size() * playerSettings->handicap.percentIncome / 100;
 
-	for(int i=0; i<7; i++)
+	for(int i=0; i<GameConstants::RESOURCE_QUANTITY; i++) // TODO: configurable resources - show up more mines
 	{
 		std::string value = std::to_string(minesCount[i]);
 		auto data = std::make_shared<InfoBoxCustom>(value, "", AnimationPath::builtin("OVMINES"), i, LIBRARY->generaltexth->translate("core.minename", i));

+ 14 - 7
config/objects/moddables.json

@@ -286,7 +286,8 @@
 				},
 				"sounds" : {
 					"ambient" : ["LOOPLUMB"]
-				}
+				},
+				"resource" : "wood"
 			},
 			"alchemistLab" : {
 				"index" : 1,
@@ -296,7 +297,8 @@
 				},
 				"sounds" : {
 					"ambient" : ["LOOPSTAR"]
-				}
+				},
+				"resource" : "mercury"
 			},
 			"orePit" : {
 				"index" : 2,
@@ -306,7 +308,8 @@
 				},
 				"sounds" : {
 					"ambient" : ["LOOPSULF"]
-				}
+				},
+				"resource" : "ore"
 			},
 			"sulfurDune" : {
 				"index" : 3,
@@ -316,7 +319,8 @@
 				},
 				"sounds" : {
 					"ambient" : ["LOOPSULF"]
-				}
+				},
+				"resource" : "sulfur"
 			},
 			"crystalCavern" : {
 				"index" : 4,
@@ -327,7 +331,8 @@
 				"sounds" : {
 					"ambient" : ["LOOPCRYS"]
 				},
-				"battleground": "subterranean"
+				"battleground": "subterranean",
+				"resource" : "crystal"
 			},
 			"gemPond" : {
 				"index" : 5,
@@ -337,7 +342,8 @@
 				},
 				"sounds" : {
 					"ambient" : ["LOOPGEMP"]
-				}
+				},
+				"resource" : "gems"
 			},
 			"goldMine" : {
 				"index" : 6,
@@ -348,7 +354,8 @@
 				"sounds" : {
 					"ambient" : ["LOOPMINE"]
 				},
-				"battleground": "subterranean"
+				"battleground": "subterranean",
+				"resource" : "gold"
 			},
 			"abandoned" :	{
 				"index" : 7,

+ 1 - 1
lib/mapObjectConstructors/CObjectClassesHandler.cpp

@@ -67,6 +67,7 @@ CObjectClassesHandler::CObjectClassesHandler()
 	SET_HANDLER_CLASS("shipyard", ShipyardInstanceConstructor);
 	SET_HANDLER_CLASS("monster", CreatureInstanceConstructor);
 	SET_HANDLER_CLASS("resource", ResourceInstanceConstructor);
+	SET_HANDLER_CLASS("mine", MineInstanceConstructor);
 
 	SET_HANDLER_CLASS("static", CObstacleConstructor);
 	SET_HANDLER_CLASS("", CObstacleConstructor);
@@ -88,7 +89,6 @@ CObjectClassesHandler::CObjectClassesHandler()
 	SET_HANDLER("heroPlaceholder", CGHeroPlaceholder);
 	SET_HANDLER("keymaster", CGKeymasterTent);
 	SET_HANDLER("magi", CGMagi);
-	SET_HANDLER("mine", CGMine);
 	SET_HANDLER("obelisk", CGObelisk);
 	SET_HANDLER("pandora", CGPandoraBox);
 	SET_HANDLER("prison", CGHeroInstance);

+ 16 - 0
lib/mapObjectConstructors/CommonConstructors.cpp

@@ -90,6 +90,22 @@ void ResourceInstanceConstructor::randomizeObject(CGResource * object, IGameRand
 		object->amount = 5 * getAmountMultiplier();
 }
 
+void MineInstanceConstructor::initTypeData(const JsonNode & input)
+{
+	config = input;
+
+	resourceType = GameResID::NONE; //set up fallback
+	LIBRARY->identifiers()->requestIdentifierIfNotNull("resource", input["resource"], [&](si32 index)
+	{
+		resourceType = GameResID(index);
+	});
+}
+
+GameResID MineInstanceConstructor::getResourceType() const
+{
+	return resourceType;
+}
+
 void CTownInstanceConstructor::initTypeData(const JsonNode & input)
 {
 	LIBRARY->identifiers()->requestIdentifier("faction", input["faction"], [&](si32 index)

+ 10 - 0
lib/mapObjectConstructors/CommonConstructors.h

@@ -62,6 +62,16 @@ public:
 	void randomizeObject(CGResource * object, IGameRandomizer & gameRandomizer) const override;
 };
 
+class DLL_LINKAGE MineInstanceConstructor : public CDefaultObjectTypeHandler<CGMine>
+{
+	JsonNode config;
+	GameResID resourceType;
+public:
+	void initTypeData(const JsonNode & input) override;
+
+	GameResID getResourceType() const;
+};
+
 class CTownInstanceConstructor : public CDefaultObjectTypeHandler<CGTownInstance>
 {
 	JsonNode filtersJson;

+ 1 - 1
lib/mapObjects/CGResource.cpp

@@ -61,7 +61,7 @@ void CGResource::pickRandomObject(IGameRandomizer & gameRandomizer)
 	if (ID == Obj::RANDOM_RESOURCE)
 	{
 		ID = Obj::RESOURCE;
-		subID = gameRandomizer.getDefault().nextInt(EGameResID::WOOD, EGameResID::GOLD); //todo: configurable resource support
+		subID = gameRandomizer.getDefault().nextInt(EGameResID::WOOD, LIBRARY->resourceTypeHandler->getAllObjects().size() - 1);
 		setType(ID, subID);
 
 		amount *= getAmountMultiplier();

+ 2 - 1
lib/mapObjects/CGResource.h

@@ -26,13 +26,14 @@ class DLL_LINKAGE CGResource : public CArmedInstance
 	static constexpr uint32_t RANDOM_AMOUNT = 0;
 	uint32_t amount = RANDOM_AMOUNT; //0 if random
 
-	std::shared_ptr<ResourceInstanceConstructor> getResourceHandler() const;
 	int getAmountMultiplier() const;
 	void collectRes(IGameEventCallback & gameEvents, const PlayerColor & player) const;
 	void serializeJsonOptions(JsonSerializeFormat & handler) override;
 
 public:
 	using CArmedInstance::CArmedInstance;
+	
+	std::shared_ptr<ResourceInstanceConstructor> getResourceHandler() const;
 
 	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 	void initObj(IGameRandomizer & gameRandomizer) override;

+ 21 - 4
lib/mapObjects/MiscObjects.cpp

@@ -30,6 +30,7 @@
 #include "../serializer/JsonSerializeFormat.h"
 #include "../mapObjectConstructors/AObjectTypeHandler.h"
 #include "../mapObjectConstructors/CObjectClassesHandler.h"
+#include "../mapObjectConstructors/CommonConstructors.h"
 #include "../mapObjects/CGHeroInstance.h"
 #include "../networkPacks/PacksForClient.h"
 #include "../networkPacks/PacksForClientBattle.h"
@@ -74,6 +75,13 @@ bool CTeamVisited::wasVisited(const TeamID & team) const
 }
 
 //CGMine
+std::shared_ptr<MineInstanceConstructor> CGMine::getResourceHandler() const
+{
+	const auto & baseHandler = getObjectHandler();
+	const auto & ourHandler = std::dynamic_pointer_cast<MineInstanceConstructor>(baseHandler);
+	return ourHandler;
+}
+
 void CGMine::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	auto relations = cb->getPlayerRelations(h->tempOwner, tempOwner);
@@ -120,14 +128,17 @@ void CGMine::initObj(IGameRandomizer & gameRandomizer)
 	}
 	else
 	{
-		producedResource = GameResID(getObjTypeIndex().getNum());
+		if(getResourceHandler()->getResourceType() == GameResID::NONE) // fallback
+			producedResource = GameResID(getObjTypeIndex().getNum());
+		else
+			producedResource = getResourceHandler()->getResourceType();
 	}
 	producedQuantity = defaultResProduction();
 }
 
 bool CGMine::isAbandoned() const
 {
-	return subID.getNum() >= 7;
+	return subID.getNum() >= 7 && getResourceHandler()->getResourceType() == GameResID::NONE;
 }
 
 const IOwnableObject * CGMine::asOwnable() const
@@ -157,7 +168,10 @@ ResourceSet CGMine::dailyIncome() const
 
 std::string CGMine::getObjectName() const
 {
-	return LIBRARY->generaltexth->translate("core.minename", getObjTypeIndex());
+	if(getResourceHandler()->getResourceType() == GameResID::NONE || getObjTypeIndex() < GameConstants::RESOURCE_QUANTITY)
+		return LIBRARY->generaltexth->translate("core.minename", getObjTypeIndex());
+	else
+		return getResourceHandler()->getResourceType().toResource()->getNameTranslated() + " " + LIBRARY->generaltexth->translate("core.genrltxt.617"); // TODO: new strings for new mines
 }
 
 std::string CGMine::getHoverText(PlayerColor player) const
@@ -184,7 +198,10 @@ void CGMine::flagMine(IGameEventCallback & gameEvents, const PlayerColor & playe
 
 	InfoWindow iw;
 	iw.type = EInfoWindowMode::AUTO;
-	iw.text.appendTextID(TextIdentifier("core.mineevnt", producedResource.getNum()).get()); //not use subID, abandoned mines uses default mine texts
+	if(getResourceHandler()->getResourceType() == GameResID::NONE || getObjTypeIndex() < GameConstants::RESOURCE_QUANTITY)
+		iw.text.appendTextID(TextIdentifier("core.mineevnt", producedResource.getNum()).get()); //not use subID, abandoned mines uses default mine texts
+	else
+		iw.text.appendRawString(getObjectName()); // TODO: new strings for new mines
 	iw.player = player;
 	iw.components.emplace_back(ComponentType::RESOURCE_PER_DAY, producedResource, getProducedQuantity());
 	gameEvents.showInfoDialog(&iw);

+ 3 - 0
lib/mapObjects/MiscObjects.h

@@ -18,6 +18,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 
 class CMap;
 class UpgradeInfo;
+class MineInstanceConstructor;
 
 // This one teleport-specific, but has to be available everywhere in callbacks and netpacks
 // For now it's will be there till teleports code refactored and moved into own file
@@ -144,6 +145,8 @@ public:
 	ui32 producedQuantity;
 	std::set<GameResID> abandonedMineResources;
 	bool isAbandoned() const;
+	
+	std::shared_ptr<MineInstanceConstructor> getResourceHandler() const;
 private:
 	using CArmedInstance::CArmedInstance;
 

+ 5 - 1
mapeditor/inspector/inspector.cpp

@@ -15,6 +15,7 @@
 #include "../lib/CRandomGenerator.h"
 #include "../lib/mapObjectConstructors/AObjectTypeHandler.h"
 #include "../lib/mapObjectConstructors/CObjectClassesHandler.h"
+#include "../lib/mapObjectConstructors/CommonConstructors.h"
 #include "../lib/mapObjects/ObjectTemplate.h"
 #include "../lib/mapping/CMap.h"
 #include "../lib/constants/StringConstants.h"
@@ -228,7 +229,10 @@ void Initializer::initialize(CGMine * o)
 	}
 	else
 	{
-		o->producedResource = GameResID(o->subID);
+		if(o->getResourceHandler()->getResourceType() == GameResID::NONE) // fallback
+			o->producedResource = GameResID(o->subID);
+		else
+			o->producedResource = o->getResourceHandler()->getResourceType();
 		o->producedQuantity = o->defaultResProduction();
 	}
 }

+ 5 - 1
mapeditor/mapcontroller.cpp

@@ -17,6 +17,7 @@
 #include "../lib/entities/hero/CHeroHandler.h"
 #include "../lib/mapObjectConstructors/AObjectTypeHandler.h"
 #include "../lib/mapObjectConstructors/CObjectClassesHandler.h"
+#include "../lib/mapObjectConstructors/CommonConstructors.h"
 #include "../lib/mapObjects/ObjectTemplate.h"
 #include "../lib/mapping/CMapService.h"
 #include "../lib/mapping/CMap.h"
@@ -208,7 +209,10 @@ void MapController::repairMap(CMap * map)
 		{
 			if(!mine->isAbandoned())
 			{
-				mine->producedResource = GameResID(mine->subID);
+				if(mine->getResourceHandler()->getResourceType() == GameResID::NONE) // fallback
+					mine->producedResource = GameResID(mine->subID);
+				else
+					mine->producedResource = mine->getResourceHandler()->getResourceType();
 				mine->producedQuantity = mine->defaultResProduction();
 			}
 		}