2
0
Эх сурвалжийг харах

Fix parsing of hota 1.7.3 maps/campaigns

Ivan Savenko 4 сар өмнө
parent
commit
5ccb32aa4e

+ 16 - 4
lib/campaign/CampaignHandler.cpp

@@ -552,12 +552,24 @@ void CampaignHandler::readHeaderFromMemory( CampaignHeader & ret, CBinaryReader
 
 	if (ret.version == CampaignVersion::HotA)
 	{
-		[[maybe_unused]] int32_t unknownA = reader.readInt32();
-		[[maybe_unused]] int32_t unknownB = reader.readInt32();
-		[[maybe_unused]] int32_t unknownC = reader.readInt8();
+		int32_t formatVersion = reader.readInt32();
+
+		if (formatVersion == 2)
+		{
+			int hotaVersionMajor = reader.readUInt32();
+			int hotaVersionMinor = reader.readUInt32();
+			int hotaVersionPatch = reader.readUInt32();
+			logGlobal->trace("Loading HotA campaign, version %d.%d.%d", hotaVersionMajor, hotaVersionMinor, hotaVersionPatch);
+
+			bool forceMatchingVersion = reader.readBool();
+			if (forceMatchingVersion)
+				logGlobal->warn("Map '%s': This map is forced to use specific hota version!", filename);
+		}
+
+		[[maybe_unused]] int32_t unknownB = reader.readInt8();
+		[[maybe_unused]] int32_t unknownC = reader.readInt32();
 		ret.numberOfScenarios = reader.readInt32();
 
-		assert(unknownA == 1);
 		assert(unknownB == 1);
 		assert(unknownC == 0);
 		assert(ret.numberOfScenarios <= 8);

+ 2 - 1
lib/mapping/MapFeaturesH3M.cpp

@@ -131,7 +131,7 @@ MapFormatFeaturesH3M MapFormatFeaturesH3M::getFeaturesHOTA(uint32_t hotaVersion)
 {
 	// even if changes are minimal, we might not be able to parse map header in map selection screen
 	// throw exception - to be caught by map selection screen & excluded as invalid
-	if(hotaVersion > 7)
+	if(hotaVersion > 8)
 		throw std::runtime_error("Invalid map format!");
 
 	MapFormatFeaturesH3M result = getFeaturesSOD();
@@ -142,6 +142,7 @@ MapFormatFeaturesH3M MapFormatFeaturesH3M::getFeaturesHOTA(uint32_t hotaVersion)
 	result.levelHOTA5 = hotaVersion > 4;
 	result.levelHOTA6 = hotaVersion > 5;
 	result.levelHOTA7 = hotaVersion > 6;
+	result.levelHOTA8 = hotaVersion > 7;
 
 	result.artifactsBytes = 21;
 	result.heroesBytes = 23;

+ 1 - 0
lib/mapping/MapFeaturesH3M.h

@@ -75,6 +75,7 @@ public:
 	bool levelHOTA5 = false; // 1.7.0
 	bool levelHOTA6 = false; // 1.7.1
 	bool levelHOTA7 = false; // 1.7.2
+	bool levelHOTA8 = false; // 1.7.3
 };
 
 VCMI_LIB_NAMESPACE_END

+ 17 - 1
lib/mapping/MapFormatH3M.cpp

@@ -168,6 +168,14 @@ void CMapLoaderH3M::readHeader()
 		features = MapFormatFeaturesH3M::find(mapHeader->version, hotaVersion);
 		reader->setFormatLevel(features);
 
+		if(features.levelHOTA8)
+		{
+			int hotaVersionMajor = reader->readUInt32();
+			int hotaVersionMinor = reader->readUInt32();
+			int hotaVersionPatch = reader->readUInt32();
+			logGlobal->trace("Loading HotA map, version %d.%d.%d", hotaVersionMajor, hotaVersionMinor, hotaVersionPatch);
+		}
+
 		if(features.levelHOTA1)
 		{
 			bool isMirrorMap = reader->readBool();
@@ -211,6 +219,13 @@ void CMapLoaderH3M::readHeader()
 			if (!canHireDefeatedHeroes)
 				logGlobal->warn("Map '%s': Option to block hiring of defeated heroes is not implemented!", mapName);
 		}
+
+		if(features.levelHOTA8)
+		{
+			bool forceMatchingVersion = reader->readBool();
+			if (forceMatchingVersion)
+				logGlobal->warn("Map '%s': This map is forced to use specific hota version!", mapName);
+		}
 	}
 	else
 	{
@@ -2401,7 +2416,8 @@ EQuestMission CMapLoaderH3M::readQuest(IQuestObject * guard, const int3 & positi
 		case EQuestMission::KILL_HERO:
 		case EQuestMission::KILL_CREATURE:
 		{
-			assert(questsToResolve.count(guard) == 0);
+			// NOTE: assert might fail on multi-quest seers
+			//assert(questsToResolve.count(guard) == 0);
 			questsToResolve[guard] = reader->readUInt32();
 			break;
 		}