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

HotA maps up to objects block can be parsed

Ivan Savenko 2 роки тому
батько
коміт
c0e9eb6eb1

+ 8 - 3
lib/mapping/MapFeaturesH3M.cpp

@@ -15,7 +15,7 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-MapFormatFeaturesH3M MapFormatFeaturesH3M::find(EMapFormat format)
+MapFormatFeaturesH3M MapFormatFeaturesH3M::find(EMapFormat format, uint8_t hotaVersion)
 {
 	switch(format)
 	{
@@ -30,7 +30,7 @@ MapFormatFeaturesH3M MapFormatFeaturesH3M::find(EMapFormat format)
 		//case EMapFormat::HOTA1: //TODO: find such maps? Not present in current HotA release (1.6)
 		//case EMapFormat::HOTA2:
 		case EMapFormat::HOTA3:
-			return getFeaturesHOTA();
+			return getFeaturesHOTA(hotaVersion);
 		default:
 			throw std::runtime_error("Invalid map format!");
 	}
@@ -113,11 +113,16 @@ MapFormatFeaturesH3M MapFormatFeaturesH3M::getFeaturesWOG()
 	return result;
 }
 
-MapFormatFeaturesH3M MapFormatFeaturesH3M::getFeaturesHOTA()
+MapFormatFeaturesH3M MapFormatFeaturesH3M::getFeaturesHOTA(uint8_t hotaVersion)
 {
 	MapFormatFeaturesH3M result = getFeaturesSOD();
 	result.levelHOTA = true;
+	result.levelHOTA3 = hotaVersion == 3;
 
+	result.artifactsBytes = 21;
+
+	result.terrainsCount = 12; // +Highlands +Wasteland
+	result.skillsCount = 29; // + Interference
 	result.factionsCount = 10; // + Cove
 	result.creaturesCount = 162; // + Cove + neutrals
 	result.artifactsCount = 161; // + HotA artifacts

+ 3 - 2
lib/mapping/MapFeaturesH3M.h

@@ -17,12 +17,12 @@ enum class EMapFormat : uint8_t;
 struct MapFormatFeaturesH3M
 {
 public:
-	static MapFormatFeaturesH3M find(EMapFormat format);
+	static MapFormatFeaturesH3M find(EMapFormat format, uint8_t hotaVersion);
 	static MapFormatFeaturesH3M getFeaturesROE();
 	static MapFormatFeaturesH3M getFeaturesAB();
 	static MapFormatFeaturesH3M getFeaturesSOD();
 	static MapFormatFeaturesH3M getFeaturesWOG();
-	static MapFormatFeaturesH3M getFeaturesHOTA();
+	static MapFormatFeaturesH3M getFeaturesHOTA(uint8_t hotaVersion);
 
 	MapFormatFeaturesH3M() = default;
 
@@ -64,6 +64,7 @@ public:
 	bool levelSOD = false;
 	bool levelWOG = false;
 	bool levelHOTA = false;
+	bool levelHOTA3 = false;
 };
 
 VCMI_LIB_NAMESPACE_END

+ 51 - 10
lib/mapping/MapFormatH3M.cpp

@@ -116,6 +116,8 @@ void CMapLoaderH3M::init()
 	readDisposedHeroes();
 	times.emplace_back("disposed heroes", sw.getDiff());
 
+	readMapOptions();
+
 	readAllowedArtifacts();
 	times.emplace_back("allowed artifacts", sw.getDiff());
 
@@ -151,12 +153,11 @@ void CMapLoaderH3M::readHeader()
 	// Map version
 	mapHeader->version = static_cast<EMapFormat>(reader->readUInt32());
 
-	features = MapFormatFeaturesH3M::find(mapHeader->version);
-	reader->setFormatLevel(mapHeader->version);
-
 	if(mapHeader->version == EMapFormat::HOTA1 || mapHeader->version == EMapFormat::HOTA2 || mapHeader->version == EMapFormat::HOTA3)
 	{
 		uint8_t hotaVersion = reader->readUInt8();
+		features = MapFormatFeaturesH3M::find(mapHeader->version, hotaVersion);
+		reader->setFormatLevel(mapHeader->version, hotaVersion);
 
 		reader->skipZero(5);
 		if (hotaVersion == 3)
@@ -166,6 +167,11 @@ void CMapLoaderH3M::readHeader()
 			reader->skipZero(3);
 		}
 	}
+	else
+	{
+		features = MapFormatFeaturesH3M::find(mapHeader->version, 0);
+		reader->setFormatLevel(mapHeader->version, 0);
+	}
 
 	// Read map name, description, dimensions,...
 	mapHeader->areAnyPlayers = reader->readBool();
@@ -613,9 +619,7 @@ void CMapLoaderH3M::readAllowedHeroes()
 	uint32_t heroesCount = features.heroesCount;
 
 	if (features.levelHOTA)
-	{
 		heroesCount = reader->readUInt32();
-	}
 
 	assert(heroesCount <= features.heroesCount);
 
@@ -644,16 +648,46 @@ void CMapLoaderH3M::readDisposedHeroes()
 			map->disposedHeroes[g].players = reader->readUInt8();
 		}
 	}
+}
 
+void CMapLoaderH3M::readMapOptions()
+{
 	//omitting NULLS
 	reader->skipZero(31);
+
+	if (features.levelHOTA)
+	{
+		std::vector<uint8_t> unknown(13);
+		for (size_t i = 0; i < 13; ++i)
+			unknown[i] = reader->readUInt8();
+
+		assert(unknown[0] == 0); // allowSpecialWeeks?
+		assert(unknown[1] == 0);
+		assert(unknown[2] == 0);
+		assert(unknown[3] == 16);
+		assert(unknown[4] == 0);
+		assert(unknown[5] == 0);
+		assert(unknown[6] == 0);
+		assert(unknown[7] == 0);
+		assert(unknown[8] == 0);
+		assert(unknown[9] == 163);
+		assert(unknown[10] == 0);
+		assert(unknown[11] == 0);
+		assert(unknown[12] == 0);
+	}
+
+	if (features.levelHOTA3)
+	{
+		uint32_t roundLimit = reader->readUInt32();
+		logGlobal->error("%s -> roundLimit of %d is not implemented!", mapName, roundLimit);
+	}
 }
 
 void CMapLoaderH3M::readAllowedArtifacts()
 {
 	map->allowedArtifact = VLC->arth->getDefaultAllowed();
 
-	// Reading allowed artifacts:  17 or 18 bytes
+	// Reading allowed artifacts
 	if(features.levelAB)
 		reader->readBitmask(map->allowedArtifact, features.artifactsBytes, features.artifactsCount, true);
 
@@ -707,9 +741,9 @@ void CMapLoaderH3M::readAllowedSpellsAbilities()
 
 void CMapLoaderH3M::readRumors()
 {
-	int rumNr = reader->readUInt32();
+	uint32_t rumorsCount = reader->readUInt32();
 
-	for(int it = 0; it < rumNr; it++)
+	for(int it = 0; it < rumorsCount; it++)
 	{
 		Rumor ourRumor;
 		ourRumor.name = readBasicString();
@@ -723,7 +757,14 @@ void CMapLoaderH3M::readPredefinedHeroes()
 	if (!features.levelSOD)
 		return;
 
-	for(int z = 0; z < features.heroesCount; z++)
+	uint32_t heroesCount = features.heroesCount;
+
+	if (features.levelHOTA)
+		heroesCount = reader->readUInt32();
+
+	assert(heroesCount <= features.heroesCount);
+
+	for(int z = 0; z < heroesCount; z++)
 	{
 		bool custom =  reader->readBool();
 		if(!custom)
@@ -1333,7 +1374,7 @@ void CMapLoaderH3M::readObjects()
 				}
 				else
 				{
-					logGlobal->warn("Unrecognized object: %d:%d at %s on map %s", objTempl->id.toEnum(), objTempl->subid, objPos.toString(), map->name);
+					logGlobal->warn("Unrecognized object: %d:%d ('%s') at %s on map '%s'", objTempl->id.toEnum(), objTempl->subid, objTempl->animationFile, objPos.toString(), map->name);
 					nobj = new CGObjectInstance();
 				}
 				break;

+ 5 - 0
lib/mapping/MapFormatH3M.h

@@ -87,6 +87,11 @@ private:
 	 */
 	void readTeamInfo();
 
+	/**
+	 * Reads the list of map flags.
+	 */
+	void readMapOptions();
+
 	/**
 	 * Reads the list of allowed heroes.
 	 */

+ 2 - 2
lib/mapping/MapReaderH3M.cpp

@@ -21,9 +21,9 @@ MapReaderH3M::MapReaderH3M(CInputStream * stream)
 {
 }
 
-void MapReaderH3M::setFormatLevel(EMapFormat newFormat)
+void MapReaderH3M::setFormatLevel(EMapFormat newFormat, uint8_t hotaVersion)
 {
-	features = MapFormatFeaturesH3M::find(newFormat);
+	features = MapFormatFeaturesH3M::find(newFormat, hotaVersion);
 }
 
 ArtifactID MapReaderH3M::readArtifact()

+ 1 - 1
lib/mapping/MapReaderH3M.h

@@ -27,7 +27,7 @@ class MapReaderH3M
 public:
 	explicit MapReaderH3M(CInputStream * stream);
 
-	void setFormatLevel(EMapFormat format);
+	void setFormatLevel(EMapFormat format, uint8_t hotaVersion);
 
 	ArtifactID readArtifact();
 	CreatureID readCreature();