1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Implemented identifiers mapping for town buildings

This commit is contained in:
Ivan Savenko 2023-05-23 15:07:44 +03:00
parent de769a04d6
commit ffd7144df8
13 changed files with 279 additions and 166 deletions

View File

@ -90,6 +90,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
${MAIN_LIB_DIR}/mapping/CMapOperation.cpp ${MAIN_LIB_DIR}/mapping/CMapOperation.cpp
${MAIN_LIB_DIR}/mapping/CMapService.cpp ${MAIN_LIB_DIR}/mapping/CMapService.cpp
${MAIN_LIB_DIR}/mapping/MapEditUtils.cpp ${MAIN_LIB_DIR}/mapping/MapEditUtils.cpp
${MAIN_LIB_DIR}/mapping/MapIdentifiersH3M.cpp
${MAIN_LIB_DIR}/mapping/MapFeaturesH3M.cpp ${MAIN_LIB_DIR}/mapping/MapFeaturesH3M.cpp
${MAIN_LIB_DIR}/mapping/MapFormatH3M.cpp ${MAIN_LIB_DIR}/mapping/MapFormatH3M.cpp
${MAIN_LIB_DIR}/mapping/MapReaderH3M.cpp ${MAIN_LIB_DIR}/mapping/MapReaderH3M.cpp
@ -386,6 +387,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
${MAIN_LIB_DIR}/mapping/CMapOperation.h ${MAIN_LIB_DIR}/mapping/CMapOperation.h
${MAIN_LIB_DIR}/mapping/CMapService.h ${MAIN_LIB_DIR}/mapping/CMapService.h
${MAIN_LIB_DIR}/mapping/MapEditUtils.h ${MAIN_LIB_DIR}/mapping/MapEditUtils.h
${MAIN_LIB_DIR}/mapping/MapIdentifiersH3M.h
${MAIN_LIB_DIR}/mapping/MapFeaturesH3M.h ${MAIN_LIB_DIR}/mapping/MapFeaturesH3M.h
${MAIN_LIB_DIR}/mapping/MapFormatH3M.h ${MAIN_LIB_DIR}/mapping/MapFormatH3M.h
${MAIN_LIB_DIR}/mapping/MapReaderH3M.h ${MAIN_LIB_DIR}/mapping/MapReaderH3M.h

View File

@ -1,61 +0,0 @@
{
// Conversion table of buildings between vcmi and H3
"table": [
{ "town": -1, "h3": 0, "vcmi": 11 },
{ "town": -1, "h3": 1, "vcmi": 12 },
{ "town": -1, "h3": 2, "vcmi": 13 },
{ "town": -1, "h3": 3, "vcmi": 7 },
{ "town": -1, "h3": 4, "vcmi": 8 },
{ "town": -1, "h3": 5, "vcmi": 9 },
{ "town": -1, "h3": 6, "vcmi": 5 },
{ "town": -1, "h3": 7, "vcmi": 16 },
{ "town": -1, "h3": 8, "vcmi": 14 },
{ "town": -1, "h3": 9, "vcmi": 15 },
{ "town": -1, "h3": 10, "vcmi": 17 },
{ "town": -1, "h3": 11, "vcmi": 0 },
{ "town": -1, "h3": 12, "vcmi": 1 },
{ "town": -1, "h3": 13, "vcmi": 2 },
{ "town": -1, "h3": 14, "vcmi": 3 },
{ "town": -1, "h3": 15, "vcmi": 4 },
{ "town": -1, "h3": 16, "vcmi": 6 },
{ "town": -1, "h3": 17, "vcmi": 26 },
{ "town": -1, "h3": 18, "vcmi": 17 },
{ "town": -1, "h3": 19, "vcmi": 22 },
{ "town": -1, "h3": 20, "vcmi": 22 },
{ "town": -1, "h3": 21, "vcmi": 23 },
{ "town": -1, "h3": 22, "vcmi": 30 },
{ "town": -1, "h3": 23, "vcmi": 37 },
{ "town": -1, "h3": 24, "vcmi": -1 },
{ "town": -1, "h3": 25, "vcmi": 31 },
{ "town": -1, "h3": 26, "vcmi": 38 },
{ "town": -1, "h3": 27, "vcmi": -2 },
{ "town": -1, "h3": 28, "vcmi": 32 },
{ "town": -1, "h3": 29, "vcmi": 39 },
{ "town": -1, "h3": 30, "vcmi": -3 },
{ "town": -1, "h3": 31, "vcmi": 33 },
{ "town": -1, "h3": 32, "vcmi": 40 },
{ "town": -1, "h3": 33, "vcmi": -4 },
{ "town": -1, "h3": 34, "vcmi": 34 },
{ "town": -1, "h3": 35, "vcmi": 41 },
{ "town": -1, "h3": 36, "vcmi": -5 },
{ "town": -1, "h3": 37, "vcmi": 35 },
{ "town": -1, "h3": 38, "vcmi": 42 },
{ "town": -1, "h3": 39, "vcmi": 36 },
{ "town": -1, "h3": 40, "vcmi": 43 },
{ "town": 0, "h3": 20, "vcmi": 21 },
{ "town": 1, "h3": 19, "vcmi": 21 },
{ "town": 2, "h3": 18, "vcmi": 22 },
{ "town": 2, "h3": 19, "vcmi": 23 },
{ "town": 2, "h3": 20, "vcmi": 21 },
{ "town": 3, "h3": 20, "vcmi": 23 },
{ "town": 3, "h3": 18, "vcmi": 21 },
{ "town": 4, "h3": 19, "vcmi": 21 },
{ "town": 5, "h3": 20, "vcmi": 23 },
{ "town": 5, "h3": 18, "vcmi": 21 },
{ "town": 6, "h3": 19, "vcmi": 21 },
{ "town": 7, "h3": 20, "vcmi": 17 },
{ "town": 7, "h3": 18, "vcmi": 22 },
{ "town": 7, "h3": 19, "vcmi": 21 },
{ "town": 8, "h3": 18, "vcmi": 21 }
]
}

View File

@ -127,11 +127,108 @@
"mapFormat" : { "mapFormat" : {
"restorationOfErathia" : { "restorationOfErathia" : {
"supported" : true, "supported" : true,
"iconIndex" : 0 "iconIndex" : 0,
"buildingsCommon": {
"townHall" : 0,
"cityHall" : 1,
"capitol" : 2,
"fort" : 3,
"citadel" : 4,
"castle" : 5,
"tavern" : 6,
"blacksmith" : 7,
"marketplace" : 8,
"resourceSilo" : 9,
"mageGuild1" : 11,
"mageGuild2" : 12,
"mageGuild3" : 13,
"mageGuild4" : 14,
"mageGuild5" : 15,
"shipyard" : 16,
"grail" : 17,
"dwellingLvl1" : 22,
"dwellingUpLvl1" : 23,
"horde1" : 24,
"dwellingLvl2" : 25,
"dwellingUpLvl2" : 26,
"horde2" : 27,
"dwellingLvl3" : 28,
"dwellingUpLvl3" : 29,
"horde3" : 30,
"dwellingLvl4" : 31,
"dwellingUpLvl4" : 32,
"horde4" : 33,
"dwellingLvl5" : 34,
"dwellingUpLvl5" : 35,
"horde5" : 36,
"dwellingLvl6" : 37,
"dwellingUpLvl6" : 38,
"dwellingLvl7" : 39,
"dwellingUpLvl7" : 40
},
"buildings" : {
"castle" : {
"special1" : 18, // lighthouse
"special2" : 20, // stables
"special3" : 19 // brotherhoodOfSword
},
"rampart" : {
"special1" : 18, // mysticPond
"special2" : 19, // fountainOfFortune
"special3" : 20 // treasury
},
"tower" : {
"special1" : 10, // artifactMerchants
"special2" : 20, // lookoutTower
"special3" : 18, // library
"special4" : 19 // wallOfKnowledge
},
"inferno" : {
"special2" : 18, // brimstoneStormclouds
"special3" : 19, // castleGate
"special4" : 20 // orderOfFire
},
"necropolis" : {
"special1" : 18, // coverOfDarkness
"special2" : 19, // necromancyAmplifier
"special3" : 20 // skeletonTransformer
},
"dungeon" : {
"special1" : 10, // artifactMerchants
"special2" : 18, // manaVortex
"special3" : 19, // portalOfSummoning
"special4" : 20 // battleScholarAcademy
},
"stronghold" : {
"special1" : 18, // escapeTunnel
"special2" : 19, // freelancersGuild
"special3" : 20, // ballistaYard
"special4" : 21 // hallOfValhalla
},
"fortress" : {
"special1" : 20, // cageOfWarlords
"special2" : 19, // bloodObelisk
"special3" : 18 // glyphsOfFear
}
}
}, },
"armageddonsBlade" : { "armageddonsBlade" : {
"supported" : true, "supported" : true,
"iconIndex" : 1 "iconIndex" : 1,
"buildings" : {
"conflux" : {
"special1" : 10, // artifactMerchants
"special2" : 18 // magicUniversity
}
}
}, },
"shadowOfDeath" : { "shadowOfDeath" : {
"supported" : true, "supported" : true,

View File

@ -1752,6 +1752,10 @@ void CGameState::initTowns()
vti->setNameTranslated(vti->getTown()->getRandomNameTranslated(nameID)); vti->setNameTranslated(vti->getTown()->getRandomNameTranslated(nameID));
} }
static const BuildingID basicDwellings[] = { BuildingID::DWELL_FIRST, BuildingID::DWELL_LVL_2, BuildingID::DWELL_LVL_3, BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7 };
static const BuildingID upgradedDwellings[] = { BuildingID::DWELL_UP_FIRST, BuildingID::DWELL_LVL_2_UP, BuildingID::DWELL_LVL_3_UP, BuildingID::DWELL_LVL_4_UP, BuildingID::DWELL_LVL_5_UP, BuildingID::DWELL_LVL_6_UP, BuildingID::DWELL_LVL_7_UP };
static const BuildingID hordes[] = { BuildingID::HORDE_PLACEHOLDER1, BuildingID::HORDE_PLACEHOLDER2, BuildingID::HORDE_PLACEHOLDER3, BuildingID::HORDE_PLACEHOLDER4, BuildingID::HORDE_PLACEHOLDER5, BuildingID::HORDE_PLACEHOLDER6, BuildingID::HORDE_PLACEHOLDER7 };
//init buildings //init buildings
if(vstd::contains(vti->builtBuildings, BuildingID::DEFAULT)) //give standard set of buildings if(vstd::contains(vti->builtBuildings, BuildingID::DEFAULT)) //give standard set of buildings
{ {
@ -1762,8 +1766,6 @@ void CGameState::initTowns()
auto definesBuildingsChances = VLC->settings()->getVector(EGameSettings::TOWNS_STARTING_DWELLING_CHANCES); auto definesBuildingsChances = VLC->settings()->getVector(EGameSettings::TOWNS_STARTING_DWELLING_CHANCES);
BuildingID basicDwellings[] = { BuildingID::DWELL_FIRST, BuildingID::DWELL_LVL_2, BuildingID::DWELL_LVL_3, BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7 };
for(int i = 0; i < definesBuildingsChances.size(); i++) for(int i = 0; i < definesBuildingsChances.size(); i++)
{ {
if((getRandomGenerator().nextInt(1,100) <= definesBuildingsChances[i])) if((getRandomGenerator().nextInt(1,100) <= definesBuildingsChances[i]))
@ -1773,23 +1775,26 @@ void CGameState::initTowns()
} }
} }
// village hall must always exist
vti->builtBuildings.insert(BuildingID::VILLAGE_HALL);
//init hordes //init hordes
for (int i = 0; i < GameConstants::CREATURES_PER_TOWN; i++) for (int i = 0; i < GameConstants::CREATURES_PER_TOWN; i++)
{ {
if (vstd::contains(vti->builtBuildings, (BuildingID::HORDE_PLACEHOLDER1 - i))) //if we have horde for this level if (vstd::contains(vti->builtBuildings, hordes[i])) //if we have horde for this level
{ {
vti->builtBuildings.erase(BuildingID(BuildingID::HORDE_PLACEHOLDER1 - i));//remove old ID vti->builtBuildings.erase(hordes[i]);//remove old ID
if (vti->getTown()->hordeLvl.at(0) == i)//if town first horde is this one if (vti->getTown()->hordeLvl.at(0) == i)//if town first horde is this one
{ {
vti->builtBuildings.insert(BuildingID::HORDE_1);//add it vti->builtBuildings.insert(BuildingID::HORDE_1);//add it
//if we have upgraded dwelling as well //if we have upgraded dwelling as well
if (vstd::contains(vti->builtBuildings, (BuildingID::DWELL_UP_FIRST + i))) if (vstd::contains(vti->builtBuildings, upgradedDwellings[i]))
vti->builtBuildings.insert(BuildingID::HORDE_1_UPGR);//add it as well vti->builtBuildings.insert(BuildingID::HORDE_1_UPGR);//add it as well
} }
if (vti->getTown()->hordeLvl.at(1) == i)//if town second horde is this one if (vti->getTown()->hordeLvl.at(1) == i)//if town second horde is this one
{ {
vti->builtBuildings.insert(BuildingID::HORDE_2); vti->builtBuildings.insert(BuildingID::HORDE_2);
if (vstd::contains(vti->builtBuildings, (BuildingID::DWELL_UP_FIRST + i))) if (vstd::contains(vti->builtBuildings, upgradedDwellings[i]))
vti->builtBuildings.insert(BuildingID::HORDE_2_UPGR); vti->builtBuildings.insert(BuildingID::HORDE_2_UPGR);
} }
} }
@ -1815,9 +1820,9 @@ void CGameState::initTowns()
for(CCastleEvent &ev : vti->events) for(CCastleEvent &ev : vti->events)
{ {
for (int i = 0; i<GameConstants::CREATURES_PER_TOWN; i++) for (int i = 0; i<GameConstants::CREATURES_PER_TOWN; i++)
if (vstd::contains(ev.buildings,(-31-i))) //if we have horde for this level if (vstd::contains(ev.buildings,hordes[i])) //if we have horde for this level
{ {
ev.buildings.erase(BuildingID(-31-i)); ev.buildings.erase(hordes[i]);
if (vti->getTown()->hordeLvl.at(0) == i) if (vti->getTown()->hordeLvl.at(0) == i)
ev.buildings.insert(BuildingID::HORDE_1); ev.buildings.insert(BuildingID::HORDE_1);
if (vti->getTown()->hordeLvl.at(1) == i) if (vti->getTown()->hordeLvl.at(1) == i)

View File

@ -477,7 +477,6 @@ public:
HORDE_PLACEHOLDER3 = -32, HORDE_PLACEHOLDER3 = -32,
HORDE_PLACEHOLDER2 = -31, HORDE_PLACEHOLDER2 = -31,
HORDE_PLACEHOLDER1 = -30, HORDE_PLACEHOLDER1 = -30,
HORDE_BUILDING_CONVERTER = -29, //-1 => -30
NONE = -1, NONE = -1,
FIRST_REGULAR_ID = 0, FIRST_REGULAR_ID = 0,
MAGES_GUILD_1 = 0, MAGES_GUILD_2, MAGES_GUILD_3, MAGES_GUILD_4, MAGES_GUILD_5, MAGES_GUILD_1 = 0, MAGES_GUILD_2, MAGES_GUILD_3, MAGES_GUILD_4, MAGES_GUILD_5,

View File

@ -56,14 +56,14 @@ namespace EBuildingType
{ {
const std::string names [44] = const std::string names [44] =
{ {
"mageGuild1", "mageGuild2", "mageGuild3", "mageGuild4", "mageGuild5", "mageGuild1", "mageGuild2", "mageGuild3", "mageGuild4", "mageGuild5", // 5
"tavern", "shipyard", "fort", "citadel", "castle", "tavern", "shipyard", "fort", "citadel", "castle", // 10
"villageHall", "townHall", "cityHall", "capitol", "marketplace", "villageHall", "townHall", "cityHall", "capitol", "marketplace", // 15
"resourceSilo", "blacksmith", "special1", "horde1", "horde1Upgr", "resourceSilo", "blacksmith", "special1", "horde1", "horde1Upgr", // 20
"ship", "special2", "special3", "special4", "horde2", "ship", "special2", "special3", "special4", "horde2", // 25
"horde2Upgr", "grail", "extraTownHall", "extraCityHall", "extraCapitol", "horde2Upgr", "grail", "extraTownHall", "extraCityHall", "extraCapitol", // 30
"dwellingLvl1", "dwellingLvl2", "dwellingLvl3", "dwellingLvl4", "dwellingLvl5", "dwellingLvl1", "dwellingLvl2", "dwellingLvl3", "dwellingLvl4", "dwellingLvl5", // 35
"dwellingLvl6", "dwellingLvl7", "dwellingUpLvl1", "dwellingUpLvl2", "dwellingUpLvl3", "dwellingLvl6", "dwellingLvl7", "dwellingUpLvl1", "dwellingUpLvl2", "dwellingUpLvl3", // 40
"dwellingUpLvl4", "dwellingUpLvl5", "dwellingUpLvl6", "dwellingUpLvl7" "dwellingUpLvl4", "dwellingUpLvl5", "dwellingUpLvl6", "dwellingUpLvl7"
}; };
} }

View File

@ -57,7 +57,7 @@ MapFormatFeaturesH3M MapFormatFeaturesH3M::getFeaturesROE()
result.skillsCount = 28; result.skillsCount = 28;
result.terrainsCount = 10; result.terrainsCount = 10;
result.artifactSlotsCount = 18; result.artifactSlotsCount = 18;
result.buildingsCount = 40; result.buildingsCount = 41;
result.heroIdentifierInvalid = 0xff; result.heroIdentifierInvalid = 0xff;
result.artifactIdentifierInvalid = 0xff; result.artifactIdentifierInvalid = 0xff;

View File

@ -19,6 +19,7 @@
#include "../CHeroHandler.h" #include "../CHeroHandler.h"
#include "../CSkillHandler.h" #include "../CSkillHandler.h"
#include "../CStopWatch.h" #include "../CStopWatch.h"
#include "../GameSettings.h"
#include "../RiverHandler.h" #include "../RiverHandler.h"
#include "../RoadHandler.h" #include "../RoadHandler.h"
#include "../TerrainHandler.h" #include "../TerrainHandler.h"
@ -123,7 +124,7 @@ void CMapLoaderH3M::readHeader()
{ {
uint32_t hotaVersion = reader->readUInt32(); uint32_t hotaVersion = reader->readUInt32();
features = MapFormatFeaturesH3M::find(mapHeader->version, hotaVersion); features = MapFormatFeaturesH3M::find(mapHeader->version, hotaVersion);
reader->setFormatLevel(mapHeader->version, hotaVersion); reader->setFormatLevel(features);
if(hotaVersion > 0) if(hotaVersion > 0)
{ {
@ -145,9 +146,23 @@ void CMapLoaderH3M::readHeader()
else else
{ {
features = MapFormatFeaturesH3M::find(mapHeader->version, 0); features = MapFormatFeaturesH3M::find(mapHeader->version, 0);
reader->setFormatLevel(mapHeader->version, 0); reader->setFormatLevel(features);
} }
MapIdentifiersH3M identifierMapper;
if (features.levelROE)
identifierMapper.loadMapping(VLC->settings()->getValue(EGameSettings::MAP_FORMAT_RESTORATION_OF_ERATHIA));
if (features.levelAB)
identifierMapper.loadMapping(VLC->settings()->getValue(EGameSettings::MAP_FORMAT_ARMAGEDDONS_BLADE));
if (features.levelSOD)
identifierMapper.loadMapping(VLC->settings()->getValue(EGameSettings::MAP_FORMAT_SHADOW_OF_DEATH));
if (features.levelWOG)
identifierMapper.loadMapping(VLC->settings()->getValue(EGameSettings::MAP_FORMAT_IN_THE_WAKE_OF_GODS));
if (features.levelHOTA0)
identifierMapper.loadMapping(VLC->settings()->getValue(EGameSettings::MAP_FORMAT_HORN_OF_THE_ABYSS));
reader->setIdentifierRemapper(identifierMapper);
// include basic mod // include basic mod
if(mapHeader->version == EMapFormat::WOG) if(mapHeader->version == EMapFormat::WOG)
mapHeader->mods["wake-of-gods"]; mapHeader->mods["wake-of-gods"];
@ -2004,11 +2019,8 @@ CGObjectInstance * CMapLoaderH3M::readTown(const int3 & position, std::shared_pt
bool hasCustomBuildings = reader->readBool(); bool hasCustomBuildings = reader->readBool();
if(hasCustomBuildings) if(hasCustomBuildings)
{ {
reader->readBitmask(object->builtBuildings, features.buildingsBytes, features.buildingsCount, false); reader->readBitmaskBuildings(object->builtBuildings, FactionID(objectTemplate->subid));
reader->readBitmask(object->forbiddenBuildings, features.buildingsBytes, features.buildingsCount, false); reader->readBitmaskBuildings(object->forbiddenBuildings, FactionID(objectTemplate->subid));
object->builtBuildings = convertBuildings(object->builtBuildings, objectTemplate->subid);
object->forbiddenBuildings = convertBuildings(object->forbiddenBuildings, objectTemplate->subid);
} }
// Standard buildings // Standard buildings
else else
@ -2074,10 +2086,7 @@ CGObjectInstance * CMapLoaderH3M::readTown(const int3 & position, std::shared_pt
reader->skipZero(17); reader->skipZero(17);
// New buildings // New buildings
reader->readBitmaskBuildings(event.buildings, FactionID(objectTemplate->subid));
reader->readBitmask(event.buildings, features.buildingsBytes, features.buildingsCount, false);
event.buildings = convertBuildings(event.buildings, objectTemplate->subid, false);
event.creatures.resize(7); event.creatures.resize(7);
for(int i = 0; i < 7; ++i) for(int i = 0; i < 7; ++i)
@ -2123,67 +2132,6 @@ CGObjectInstance * CMapLoaderH3M::readTown(const int3 & position, std::shared_pt
return object; return object;
} }
std::set<BuildingID> CMapLoaderH3M::convertBuildings(const std::set<BuildingID> & h3m, int castleID, bool addAuxiliary) const
{
std::map<int, BuildingID> helperMap;
std::set<BuildingID> ret;
// Note: this file is parsed many times.
static const JsonNode config(ResourceID("config/buildings5.json"));
for(const JsonNode & entry : config["table"].Vector())
{
int town = static_cast<int>(entry["town"].Float());
if(town == castleID || town == -1)
{
helperMap[static_cast<int>(entry["h3"].Float())] = BuildingID(static_cast<si32>(entry["vcmi"].Float()));
}
}
for(const auto & elem : h3m)
{
if(helperMap[elem] >= BuildingID::FIRST_REGULAR_ID)
{
ret.insert(helperMap[elem]);
}
// horde buildings use indexes from -1 to -5, where creature level is 1 to 5
else if(helperMap[elem] >= (-GameConstants::CREATURES_PER_TOWN))
{
int level = (helperMap[elem]);
//(-30)..(-36) - horde buildings (for game loading only)
//They will be replaced in CGameState::initTowns()
ret.insert(BuildingID(level + BuildingID::HORDE_BUILDING_CONVERTER)); //-1 => -30
}
else
{
logGlobal->warn("Conversion warning: unknown building %d in castle %d", elem.num, castleID);
}
}
if(addAuxiliary)
{
//village hall is always present
ret.insert(BuildingID::VILLAGE_HALL);
if(ret.find(BuildingID::CITY_HALL) != ret.end())
{
ret.insert(BuildingID::EXTRA_CITY_HALL);
}
if(ret.find(BuildingID::TOWN_HALL) != ret.end())
{
ret.insert(BuildingID::EXTRA_TOWN_HALL);
}
if(ret.find(BuildingID::CAPITOL) != ret.end())
{
ret.insert(BuildingID::EXTRA_CAPITOL);
}
}
return ret;
}
void CMapLoaderH3M::readEvents() void CMapLoaderH3M::readEvents()
{ {
uint32_t eventsCount = reader->readUInt32(); uint32_t eventsCount = reader->readUInt32();

View File

@ -209,16 +209,6 @@ private:
void readSeerHutQuest(CGSeerHut * hut, const int3 & position); void readSeerHutQuest(CGSeerHut * hut, const int3 & position);
/**
* Converts buildings to the specified castle id.
*
* @param h3m the ids of the buildings
* @param castleID the castle id
* @param addAuxiliary true if the village hall should be added
* @return the converted buildings
*/
std::set<BuildingID> convertBuildings(const std::set<BuildingID> & h3m, int castleID, bool addAuxiliary = true) const;
/** /**
* Reads events. * Reads events.
*/ */

View File

@ -0,0 +1,70 @@
/*
* MapIdentifiersH3M.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "StdInc.h"
#include "MapIdentifiersH3M.h"
#include "../JsonNode.h"
#include "../VCMI_Lib.h"
#include "../CModHandler.h"
#include "../CTownHandler.h"
VCMI_LIB_NAMESPACE_BEGIN
void MapIdentifiersH3M::loadMapping(const JsonNode & mapping)
{
for (auto entry : mapping["buildingsCommon"].Struct())
{
BuildingID sourceID (entry.second.Integer());
BuildingID targetID (*VLC->modh->identifiers.getIdentifier(VLC->modh->scopeGame(), "building.core:random", entry.first));
mappingBuilding[sourceID] = targetID;
}
for (auto entryFaction : mapping["buildings"].Struct())
{
FactionID factionID (*VLC->modh->identifiers.getIdentifier(VLC->modh->scopeGame(), "faction", entryFaction.first));
auto buildingMap = entryFaction.second;
for (auto entryBuilding : buildingMap.Struct())
{
BuildingID sourceID (entryBuilding.second.Integer());
BuildingID targetID (*VLC->modh->identifiers.getIdentifier(VLC->modh->scopeGame(), "building." + VLC->factions()->getById(factionID)->getJsonKey(), entryBuilding.first));
mappingFactionBuilding[factionID][sourceID] = targetID;
}
}
}
BuildingID MapIdentifiersH3M::remapBuilding(FactionID owner, BuildingID input) const
{
if (mappingFactionBuilding.count(owner))
{
auto submap = mappingFactionBuilding.at(owner);
if (submap.count(input))
return submap.at(input);
}
if (mappingBuilding.count(input))
return mappingBuilding.at(input);
logGlobal->warn("Not mapped building ID %d found for faction %d!", input, owner);
return input;
}
BuildingID MapIdentifiersH3M::remapBuilding(BuildingID input) const
{
if (mappingBuilding.count(input))
return mappingBuilding.at(input);
logGlobal->warn("Not mapped building ID %d found!");
return input;
}
VCMI_LIB_NAMESPACE_END

View File

@ -0,0 +1,44 @@
/*
* MapIdentifiersH3M.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "../GameConstants.h"
VCMI_LIB_NAMESPACE_BEGIN
class JsonNode;
class MapIdentifiersH3M
{
std::map<BuildingID, BuildingID> mappingBuilding;
std::map<FactionID, std::map<BuildingID, BuildingID>> mappingFactionBuilding;
//std::map<FactionID, FactionID> mappingFaction;
//std::map<CreatureID, CreatureID> mappingCreature;
//std::map<HeroTypeID, HeroTypeID> mappingHeroType;
//std::map<HeroClassID, HeroClassID> mappingHeroClass;
//std::map<TerrainId, TerrainId> mappingTerrain;
//std::map<ArtifactID, ArtifactID> mappingArtifact;
//std::map<SecondarySkill, SecondarySkill> mappingSecondarySkill;
public:
void loadMapping(const JsonNode & mapping);
BuildingID remapBuilding(FactionID owner, BuildingID input) const;
BuildingID remapBuilding(BuildingID input) const;
//FactionID remapFaction(FactionID input) const;
//CreatureID remapCreature(CreatureID input) const;
//HeroTypeID remapHeroType(HeroTypeID input) const;
//HeroClassID remapHeroClass(HeroClassID input) const;
//TerrainId remapTerrain(TerrainId input) const;
//ArtifactID remapArtifact(ArtifactID input) const;
//SecondarySkill remapSecondarySkill(SecondarySkill input) const;
};
VCMI_LIB_NAMESPACE_END

View File

@ -21,9 +21,14 @@ MapReaderH3M::MapReaderH3M(CInputStream * stream)
{ {
} }
void MapReaderH3M::setFormatLevel(EMapFormat newFormat, uint8_t hotaVersion) void MapReaderH3M::setFormatLevel(const MapFormatFeaturesH3M & newFeatures)
{ {
features = MapFormatFeaturesH3M::find(newFormat, hotaVersion); features = newFeatures;
}
void MapReaderH3M::setIdentifierRemapper(const MapIdentifiersH3M & newRemapper)
{
remapper = newRemapper;
} }
ArtifactID MapReaderH3M::readArtifact() ArtifactID MapReaderH3M::readArtifact()
@ -160,6 +165,15 @@ PlayerColor MapReaderH3M::readPlayer32()
return result; return result;
} }
void MapReaderH3M::readBitmaskBuildings(std::set<BuildingID> & dest, FactionID faction)
{
std::set<BuildingID> h3m;
readBitmask(h3m, features.buildingsBytes, features.buildingsCount, false);
for (auto const & h3mEntry : h3m)
dest.insert(remapper.remapBuilding(faction, h3mEntry));
}
void MapReaderH3M::readBitmask(std::vector<bool> & dest, const int bytesToRead, const int objectsToRead, bool invert) void MapReaderH3M::readBitmask(std::vector<bool> & dest, const int bytesToRead, const int objectsToRead, bool invert)
{ {
for(int byte = 0; byte < bytesToRead; ++byte) for(int byte = 0; byte < bytesToRead; ++byte)

View File

@ -13,6 +13,7 @@
#include "../GameConstants.h" #include "../GameConstants.h"
#include "../ResourceSet.h" #include "../ResourceSet.h"
#include "MapFeaturesH3M.h" #include "MapFeaturesH3M.h"
#include "MapIdentifiersH3M.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -27,7 +28,8 @@ class MapReaderH3M
public: public:
explicit MapReaderH3M(CInputStream * stream); explicit MapReaderH3M(CInputStream * stream);
void setFormatLevel(EMapFormat format, uint8_t hotaVersion); void setFormatLevel(const MapFormatFeaturesH3M & features);
void setIdentifierRemapper(const MapIdentifiersH3M & remapper);
ArtifactID readArtifact(); ArtifactID readArtifact();
ArtifactID readArtifact32(); ArtifactID readArtifact32();
@ -54,6 +56,8 @@ public:
dest.insert(static_cast<Identifier>(i)); dest.insert(static_cast<Identifier>(i));
} }
void readBitmaskBuildings(std::set<BuildingID> & dest, FactionID faction);
/** Reads bitmask to boolean vector /** Reads bitmask to boolean vector
* @param dest destination vector, shall be filed with "true" values * @param dest destination vector, shall be filed with "true" values
* @param byteCount size in bytes of bimask * @param byteCount size in bytes of bimask
@ -87,6 +91,7 @@ public:
private: private:
MapFormatFeaturesH3M features; MapFormatFeaturesH3M features;
MapIdentifiersH3M remapper;
std::unique_ptr<CBinaryReader> reader; std::unique_ptr<CBinaryReader> reader;
}; };