فهرست منبع

Native terrain is now required for faction, opt-out with value "none"

Ivan Savenko 2 سال پیش
والد
کامیت
633b9ef3be
5فایلهای تغییر یافته به همراه10 افزوده شده و 5 حذف شده
  1. 1 0
      config/factions/neutral.json
  2. 1 1
      config/schemas/faction.json
  3. 5 1
      lib/CTownHandler.cpp
  4. 1 1
      lib/GameConstants.h
  5. 2 2
      lib/mapObjects/ObjectTemplate.cpp

+ 1 - 0
config/factions/neutral.json

@@ -3,6 +3,7 @@
 	{
 		"name" : "Neutral",
 		"index" : 9,
+		"nativeTerrain" : "none",
 		"alignment" : "neutral",
 		"creatureBackground" :
 		{

+ 1 - 1
config/schemas/faction.json

@@ -31,7 +31,7 @@
 	"$schema": "http://json-schema.org/draft-04/schema",
 	"title" : "VCMI faction format",
 	"description": "Json format for defining new faction (aka towns) in VCMI",
-	"required" : [ "name", "alignment", "creatureBackground" ],
+	"required" : [ "name", "alignment", "creatureBackground", "nativeTerrain" ],
 	"dependencies" : {
 		"town" : [ "puzzleMap" ]
 	},

+ 5 - 1
lib/CTownHandler.cpp

@@ -967,8 +967,12 @@ CFaction * CTownHandler::loadFromJson(const std::string & scope, const JsonNode
 	auto preferUndergound = source["preferUndergroundPlacement"];
 	faction->preferUndergroundPlacement = preferUndergound.isNull() ? false : preferUndergound.Bool();
 
+	// NOTE: semi-workaround - normally, towns are supposed to have native terrains.
+	// Towns without one are exceptions. So, vcmi requires nativeTerrain to be defined
+	// But allows it to be defined with explicit value of "none" if town should not have native terrain
+	// This is better than allowing such terrain-less towns silently, leading to issues with RMG
 	faction->nativeTerrain = ETerrainId::NONE;
-	if ( !source["nativeTerrain"].isNull())
+	if ( !source["nativeTerrain"].isNull() && source["nativeTerrain"].String() != "none")
 	{
 		VLC->modh->identifiers.requestIdentifier("terrain", source["nativeTerrain"], [=](int32_t index){
 			faction->nativeTerrain = TerrainId(index);

+ 1 - 1
lib/GameConstants.h

@@ -1234,7 +1234,7 @@ enum class ETerrainId {
 	LAVA,
 	WATER,
 	ROCK,
-	ORIGINAL_TERRAIN_COUNT
+	ORIGINAL_REGULAR_TERRAIN_COUNT = ROCK
 };
 
 using TerrainId = Identifier<ETerrainId>;

+ 2 - 2
lib/mapObjects/ObjectTemplate.cpp

@@ -158,7 +158,7 @@ void ObjectTemplate::readTxt(CLegacyConfigParser & parser)
 	std::string & terrStr = strings[4]; // allowed terrains, 1 = object can be placed on this terrain
 
 	assert(terrStr.size() == TerrainId(ETerrainId::ROCK).getNum()); // all terrains but rock - counting from 0
-	for(TerrainId i = TerrainId(0); i < ETerrainId::ROCK; ++i)
+	for(TerrainId i = TerrainId(0); i < ETerrainId::ORIGINAL_REGULAR_TERRAIN_COUNT; ++i)
 	{
 		if (terrStr[8-i.getNum()] == '1')
 			allowedTerrains.insert(i);
@@ -224,7 +224,7 @@ void ObjectTemplate::readMap(CBinaryReader & reader)
 
 	reader.readUInt16();
 	ui16 terrMask = reader.readUInt16();
-	for(TerrainId i = ETerrainId::FIRST_REGULAR_TERRAIN; i < ETerrainId::ORIGINAL_TERRAIN_COUNT; ++i)
+	for(TerrainId i = ETerrainId::FIRST_REGULAR_TERRAIN; i < ETerrainId::ORIGINAL_REGULAR_TERRAIN_COUNT; ++i)
 	{
 		if (((terrMask >> i.getNum()) & 1 ) != 0)
 			allowedTerrains.insert(i);