Переглянути джерело

Option to allow / ban certain types of town in a template.

DjWarmonger 11 роки тому
батько
коміт
530a3e69bf

+ 4 - 3
client/windows/GUIClasses.cpp

@@ -1378,14 +1378,15 @@ CHillFortWindow::CHillFortWindow(const CGHeroInstance *visitor, const CGObjectIn
 	costs.resize(slotsCount);
 	totalSumm.resize(GameConstants::RESOURCE_QUANTITY);
 
-	for (int i=0; i<slotsCount; i++)
+	for (int i = 0; i < slotsCount; i++)
 	{
 		currState[i] = getState(SlotID(i));
-		upgrade[i] = new CButton(Point(107+i*76, 171), "", CButton::tooltip(getTextForSlot(SlotID(i))), [&]{ makeDeal(SlotID(i));}, SDLK_1+i);
-		upgrade[i]->block(currState[i] == -1);
+		upgrade[i] = new CButton(Point(107 + i * 76, 171), "", CButton::tooltip(getTextForSlot(SlotID(i))), [&]{ makeDeal(SlotID(i)); }, SDLK_1 + i);
 		for (auto image : { "APHLF1R.DEF", "APHLF1Y.DEF", "APHLF1G.DEF" })
 			upgrade[i]->addImage(image);
+		upgrade[i]->block(currState[i] == -1);
 	}
+
 	currState[slotsCount] = getState(SlotID(slotsCount));
 	upgradeAll = new CButton(Point(30, 231), "", CButton::tooltip(CGI->generaltexth->allTexts[432]), [&]{ makeDeal(SlotID(slotsCount));}, SDLK_0);
 	for (auto image : { "APHLF4R.DEF", "APHLF4Y.DEF", "APHLF4G.DEF" })

+ 5 - 0
config/rmg.json

@@ -252,6 +252,7 @@
 				"type" : "playerStart", "size" : 30, "owner" : 1,
 				"playerTowns" : { "castles" : 1 },
 				"neutralTowns" : { "towns" : 2 },
+				"bannedTowns" : ["necropolis", "conflux"],
 				"monsters" : "weak",
 				"mines" : {"wood" : 4, "ore" : 4, "gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1, "gold" : 2},
 				"treasure" : [
@@ -265,6 +266,7 @@
 				"type" : "playerStart", "size" : 30, "owner" : 2,
 				"playerTowns" : { "castles" : 1 },
 				"neutralTowns" : { "towns" : 2 },
+				"bannedTowns" : ["necropolis", "conflux"],
 				"monsters" : "weak",
 				"minesLikeZone" : 1,
 				"treasureLikeZone" : 1
@@ -274,6 +276,7 @@
 				"type" : "playerStart", "size" : 30, "owner" : 3,
 				"playerTowns" : { "castles" : 1 },
 				"neutralTowns" : { "towns" : 2 },
+				"bannedTowns" : ["necropolis", "conflux"],
 				"monsters" : "weak",
 				"minesLikeZone" : 1,
 				"treasureLikeZone" : 1
@@ -283,6 +286,7 @@
 				"type" : "playerStart", "size" : 30, "owner" : 4,
 				"playerTowns" : { "castles" : 1 },
 				"neutralTowns" : { "towns" : 2 },
+				"bannedTowns" : ["necropolis", "conflux"],
 				"monsters" : "weak",
 				"minesLikeZone" : 1,
 				"treasureLikeZone" : 1
@@ -292,6 +296,7 @@
 				"type" : "treasure", "size" : 40,
 				"neutralTowns" : { "castles" : 2 },
 				"terrainTypes" : [ "sand" ], "matchTerrainToTown" : false,
+				"bannedTowns" : ["necropolis", "conflux"],
 				"monsters" : "strong",
 				"mines" : {"gold" : 4},
 				"treasure" : [

+ 4 - 2
lib/VCMI_Lib.cpp

@@ -115,12 +115,14 @@ void LibClasses::init()
 
 	createHandler(terviewh, "Terrain view pattern", pomtime);
 
-	createHandler(tplh, "Template", pomtime);
-
 	logGlobal->infoStream()<<"\tInitializing handlers: "<< totalTime.getDiff();
 
 	modh->load();
+
+	createHandler(tplh, "Template", pomtime); //templates need already resolved identifiers (refactor?)
+
 	modh->afterLoad();
+
 	//FIXME: make sure that everything is ok after game restart
 	//TODO: This should be done every time mod config changes
 

+ 28 - 1
lib/rmg/CRmgTemplateStorage.cpp

@@ -18,6 +18,7 @@
 #include "../JsonNode.h"
 #include "../mapping/CMap.h"
 #include "../VCMI_Lib.h"
+#include "../CModHandler.h"
 #include "../CTownHandler.h"
 #include "../GameConstants.h"
 #include "../StringConstants.h"
@@ -59,12 +60,38 @@ void CJsonRmgTemplateLoader::loadTemplates()
 
 				zone->setPlayerTowns(parseTemplateZoneTowns(zoneNode["playerTowns"]));
 				zone->setNeutralTowns(parseTemplateZoneTowns(zoneNode["neutralTowns"]));
-				zone->setTownTypes(parseTownTypes(zoneNode["townTypes"].Vector(), zone->getDefaultTownTypes()));
 				if (!zoneNode["matchTerrainToTown"].isNull()) //default : true
 					zone->setMatchTerrainToTown(zoneNode["matchTerrainToTown"].Bool());
 				zone->setTerrainTypes(parseTerrainTypes(zoneNode["terrainTypes"].Vector(), zone->getDefaultTerrainTypes()));
 				zone->setTownsAreSameType((zoneNode["townsAreSameType"].Bool()));
 
+				std::set<TFaction> allowedTownTypes;
+				if (zoneNode["allowedTowns"].isNull())
+					allowedTownTypes = zone->getDefaultTownTypes();
+				else
+				{
+					for (const JsonNode & allowedTown : zoneNode["allowedTowns"].Vector())
+					{
+						//complain if the town type is not present in our game
+						boost::optional<si32> id = VLC->modh->identifiers.getIdentifier("faction", allowedTown, false);
+						if (id.is_initialized())
+							allowedTownTypes.insert (id.get());
+					}
+				}
+
+				if (!zoneNode["bannedTowns"].isNull())
+				{
+					for (const JsonNode & bannedTown : zoneNode["bannedTowns"].Vector())
+					{
+						//erase unindentified towns silently
+						boost::optional<si32> id = VLC->modh->identifiers.getIdentifier("faction", bannedTown, true);
+						if (id.is_initialized())
+							vstd::erase_if_present(allowedTownTypes, id.get());
+					}
+				}
+				assert(allowedTownTypes.size());
+				zone->setTownTypes (allowedTownTypes);
+
 				const std::string monsterStrength = zoneNode["monsters"].String();
 				if (monsterStrength == "weak")
 					zone->setMonsterStrength(EMonsterStrength::ZONE_WEAK);

+ 3 - 4
lib/rmg/CRmgTemplateZone.cpp

@@ -141,7 +141,6 @@ CRmgTemplateZone::CRmgTemplateZone() :
 	zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL),
 	totalDensity(0)
 {
-	townTypes = getDefaultTownTypes();
 	terrainTypes = getDefaultTerrainTypes();
 }
 
@@ -951,7 +950,7 @@ void CRmgTemplateZone::initTownType (CMapGenerator* gen)
 			if (this->townsAreSameType)
 				town->subID = townType;
 			else
-				town->subID = *RandomGeneratorUtil::nextItem(VLC->townh->getAllowedFactions(), gen->rand); //TODO: check allowed town types for this zone
+				town->subID = *RandomGeneratorUtil::nextItem(townTypes, gen->rand);
 
 			town->tempOwner = player;
 			if (hasFort)
@@ -992,8 +991,8 @@ void CRmgTemplateZone::initTownType (CMapGenerator* gen)
 			PlayerColor player(player_id);
 			townType = gen->mapGenOptions->getPlayersSettings().find(player)->second.getStartingTown();
 
-			if(townType == CMapGenOptions::CPlayerSettings::RANDOM_TOWN)
-				townType = *RandomGeneratorUtil::nextItem(VLC->townh->getAllowedFactions(), gen->rand); // all possible towns, skip neutral
+			if (townType == CMapGenOptions::CPlayerSettings::RANDOM_TOWN)
+				townType = *RandomGeneratorUtil::nextItem(townTypes, gen->rand);
 			
 			auto  town = new CGTownInstance();
 			town->ID = Obj::TOWN;