mirror of
https://github.com/vcmi/vcmi.git
synced 2025-06-04 23:17:41 +02:00
Implemented parsing of HotA h3m header
This commit is contained in:
parent
f93335d678
commit
838d45b32c
@ -253,13 +253,15 @@ struct DLL_LINKAGE DisposedHero
|
|||||||
enum class EMapFormat: uint8_t
|
enum class EMapFormat: uint8_t
|
||||||
{
|
{
|
||||||
INVALID = 0,
|
INVALID = 0,
|
||||||
// HEX DEC
|
// HEX DEC
|
||||||
ROE = 0x0e, // 14
|
ROE = 0x0e, // 14
|
||||||
AB = 0x15, // 21
|
AB = 0x15, // 21
|
||||||
SOD = 0x1c, // 28
|
SOD = 0x1c, // 28
|
||||||
HOTA = 0x1e, // 30
|
HOTA1 = 0x1e, // 30
|
||||||
WOG = 0x33, // 51
|
HOTA2 = 0x1f, // 31
|
||||||
VCMI = 0xF0
|
HOTA3 = 0x20, // 32
|
||||||
|
WOG = 0x33, // 51
|
||||||
|
VCMI = 0xF0
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The map header holds information about loss/victory condition,map format, version, players, height, width,...
|
/// The map header holds information about loss/victory condition,map format, version, players, height, width,...
|
||||||
|
@ -124,6 +124,9 @@ std::unique_ptr<IMapLoader> CMapService::getMapLoader(std::unique_ptr<CInputStre
|
|||||||
case static_cast<int>(EMapFormat::AB) :
|
case static_cast<int>(EMapFormat::AB) :
|
||||||
case static_cast<int>(EMapFormat::ROE) :
|
case static_cast<int>(EMapFormat::ROE) :
|
||||||
case static_cast<int>(EMapFormat::SOD) :
|
case static_cast<int>(EMapFormat::SOD) :
|
||||||
|
case static_cast<int>(EMapFormat::HOTA1) :
|
||||||
|
case static_cast<int>(EMapFormat::HOTA2) :
|
||||||
|
case static_cast<int>(EMapFormat::HOTA3) :
|
||||||
return std::unique_ptr<IMapLoader>(new CMapLoaderH3M(mapName, modName, encoding, stream.get()));
|
return std::unique_ptr<IMapLoader>(new CMapLoaderH3M(mapName, modName, encoding, stream.get()));
|
||||||
default :
|
default :
|
||||||
throw std::runtime_error("Unknown map format");
|
throw std::runtime_error("Unknown map format");
|
||||||
|
@ -27,7 +27,9 @@ MapFormatFeaturesH3M MapFormatFeaturesH3M::find(EMapFormat format)
|
|||||||
return getFeaturesSOD();
|
return getFeaturesSOD();
|
||||||
case EMapFormat::WOG:
|
case EMapFormat::WOG:
|
||||||
return getFeaturesWOG();
|
return getFeaturesWOG();
|
||||||
case EMapFormat::HOTA:
|
//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();
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Invalid map format!");
|
throw std::runtime_error("Invalid map format!");
|
||||||
@ -116,6 +118,14 @@ MapFormatFeaturesH3M MapFormatFeaturesH3M::getFeaturesHOTA()
|
|||||||
MapFormatFeaturesH3M result = getFeaturesSOD();
|
MapFormatFeaturesH3M result = getFeaturesSOD();
|
||||||
result.levelHOTA = true;
|
result.levelHOTA = true;
|
||||||
|
|
||||||
|
result.factionsCount = 10; // + Cove
|
||||||
|
result.creaturesCount = 162; // + Cove + neutrals
|
||||||
|
result.artifactsCount = 161; // + HotA artifacts
|
||||||
|
|
||||||
|
result.heroesBytes = 24;
|
||||||
|
result.heroesCount = 179; // + Cove
|
||||||
|
result.heroesPortraitsCount = 186; // + Cove
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,22 +154,17 @@ void CMapLoaderH3M::readHeader()
|
|||||||
features = MapFormatFeaturesH3M::find(mapHeader->version);
|
features = MapFormatFeaturesH3M::find(mapHeader->version);
|
||||||
reader->setFormatLevel(mapHeader->version);
|
reader->setFormatLevel(mapHeader->version);
|
||||||
|
|
||||||
if (mapHeader->version == EMapFormat::HOTA)
|
if(mapHeader->version == EMapFormat::HOTA1 || mapHeader->version == EMapFormat::HOTA2 || mapHeader->version == EMapFormat::HOTA3)
|
||||||
{
|
{
|
||||||
//unknown values
|
uint8_t hotaVersion = reader->readUInt8();
|
||||||
std::vector<uint8_t> bytes;
|
|
||||||
for(int i = 0; i < 10; ++i)
|
reader->skipZero(5);
|
||||||
bytes.push_back(reader->readInt8());
|
if (hotaVersion == 3)
|
||||||
assert(bytes[0] == 3);
|
{
|
||||||
assert(bytes[1] == 0);
|
uint8_t unknown = reader->readUInt8();
|
||||||
assert(bytes[2] == 0);
|
logGlobal->error("%s -> header unknown: %d", mapName, int(unknown));
|
||||||
assert(bytes[3] == 0);
|
reader->skipZero(3);
|
||||||
assert(bytes[4] == 0);
|
}
|
||||||
assert(bytes[5] == 0);
|
|
||||||
assert(bytes[6] == 12);
|
|
||||||
assert(bytes[7] == 0);
|
|
||||||
assert(bytes[8] == 0);
|
|
||||||
assert(bytes[9] == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read map name, description, dimensions,...
|
// Read map name, description, dimensions,...
|
||||||
@ -268,22 +263,37 @@ void CMapLoaderH3M::readPlayerInfo()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace EVictoryConditionType
|
enum class EVictoryConditionType : uint8_t
|
||||||
{
|
{
|
||||||
enum EVictoryConditionType { ARTIFACT, GATHERTROOP, GATHERRESOURCE, BUILDCITY, BUILDGRAIL, BEATHERO,
|
ARTIFACT = 0,
|
||||||
CAPTURECITY, BEATMONSTER, TAKEDWELLINGS, TAKEMINES, TRANSPORTITEM, WINSTANDARD = 255 };
|
GATHERTROOP = 1,
|
||||||
}
|
GATHERRESOURCE = 2,
|
||||||
|
BUILDCITY = 3,
|
||||||
|
BUILDGRAIL = 4,
|
||||||
|
BEATHERO = 5,
|
||||||
|
CAPTURECITY = 6,
|
||||||
|
BEATMONSTER = 7,
|
||||||
|
TAKEDWELLINGS = 8,
|
||||||
|
TAKEMINES = 9,
|
||||||
|
TRANSPORTITEM = 10,
|
||||||
|
HOTA_ELIMINATE_ALL_MONSTERS = 11,
|
||||||
|
HOTA_SURVIVE_FOR_DAYS = 12,
|
||||||
|
WINSTANDARD = 255
|
||||||
|
};
|
||||||
|
|
||||||
namespace ELossConditionType
|
enum class ELossConditionType : uint8_t
|
||||||
{
|
{
|
||||||
enum ELossConditionType { LOSSCASTLE, LOSSHERO, TIMEEXPIRES, LOSSSTANDARD = 255 };
|
LOSSCASTLE,
|
||||||
}
|
LOSSHERO,
|
||||||
|
TIMEEXPIRES,
|
||||||
|
LOSSSTANDARD = 255
|
||||||
|
};
|
||||||
|
|
||||||
void CMapLoaderH3M::readVictoryLossConditions()
|
void CMapLoaderH3M::readVictoryLossConditions()
|
||||||
{
|
{
|
||||||
mapHeader->triggeredEvents.clear();
|
mapHeader->triggeredEvents.clear();
|
||||||
|
|
||||||
auto vicCondition = static_cast<EVictoryConditionType::EVictoryConditionType>(reader->readUInt8());
|
auto vicCondition = static_cast<EVictoryConditionType>(reader->readUInt8());
|
||||||
|
|
||||||
EventCondition victoryCondition(EventCondition::STANDARD_WIN);
|
EventCondition victoryCondition(EventCondition::STANDARD_WIN);
|
||||||
EventCondition defeatCondition(EventCondition::DAYS_WITHOUT_TOWN);
|
EventCondition defeatCondition(EventCondition::DAYS_WITHOUT_TOWN);
|
||||||
@ -464,6 +474,15 @@ void CMapLoaderH3M::readVictoryLossConditions()
|
|||||||
specialVictory.trigger = EventExpression(cond);
|
specialVictory.trigger = EventExpression(cond);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case EVictoryConditionType::HOTA_ELIMINATE_ALL_MONSTERS:
|
||||||
|
logGlobal->error("Map %s - victory condition 'Eliminate all monsters' is not supported!", mapName);
|
||||||
|
//TODO: HOTA
|
||||||
|
break;
|
||||||
|
case EVictoryConditionType::HOTA_SURVIVE_FOR_DAYS:
|
||||||
|
logGlobal->error("Map %s - victory condition 'Survive for certain time' is not supported!", mapName);
|
||||||
|
//TODO: HOTA
|
||||||
|
reader->readUInt32(); // Number of days
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
@ -490,7 +509,7 @@ void CMapLoaderH3M::readVictoryLossConditions()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read loss conditions
|
// Read loss conditions
|
||||||
auto lossCond = static_cast<ELossConditionType::ELossConditionType>(reader->readUInt8());
|
auto lossCond = static_cast<ELossConditionType>(reader->readUInt8());
|
||||||
if (lossCond == ELossConditionType::LOSSSTANDARD)
|
if (lossCond == ELossConditionType::LOSSSTANDARD)
|
||||||
{
|
{
|
||||||
mapHeader->defeatIconIndex = 3;
|
mapHeader->defeatIconIndex = 3;
|
||||||
@ -591,7 +610,16 @@ void CMapLoaderH3M::readAllowedHeroes()
|
|||||||
{
|
{
|
||||||
mapHeader->allowedHeroes = VLC->heroh->getDefaultAllowed();
|
mapHeader->allowedHeroes = VLC->heroh->getDefaultAllowed();
|
||||||
|
|
||||||
reader->readBitmask(mapHeader->allowedHeroes, features.heroesBytes, features.heroesCount, false);
|
uint32_t heroesCount = features.heroesCount;
|
||||||
|
|
||||||
|
if (features.levelHOTA)
|
||||||
|
{
|
||||||
|
heroesCount = reader->readUInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(heroesCount <= features.heroesCount);
|
||||||
|
|
||||||
|
reader->readBitmask(mapHeader->allowedHeroes, features.heroesBytes, heroesCount, false);
|
||||||
|
|
||||||
//TODO: unknown value. Check meaning? Only present in campaign maps.
|
//TODO: unknown value. Check meaning? Only present in campaign maps.
|
||||||
if(features.levelAB)
|
if(features.levelAB)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user