From d58ea6f28d4018652afc221fce130b8964ef4ad2 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Tue, 21 Nov 2023 16:38:09 +0200 Subject: [PATCH 1/7] Fix keymaster visitation status tracking --- lib/mapObjects/CQuest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mapObjects/CQuest.cpp b/lib/mapObjects/CQuest.cpp index 944efa994..3f4275a3a 100644 --- a/lib/mapObjects/CQuest.cpp +++ b/lib/mapObjects/CQuest.cpp @@ -778,7 +778,7 @@ void CGQuestGuard::serializeJsonOptions(JsonSerializeFormat & handler) bool CGKeys::wasMyColorVisited(const PlayerColor & player) const { - return cb->getPlayerState(player)->visitedObjectsGlobal.count({ID, subID}) != 0; + return cb->getPlayerState(player)->visitedObjectsGlobal.count({Obj::KEYMASTER, subID}) != 0; } std::string CGKeys::getHoverText(PlayerColor player) const From 83ca09f48379a5eaad3b293ead40c8134402a283 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Tue, 21 Nov 2023 17:23:46 +0200 Subject: [PATCH 2/7] Fix loading of allowed heroes from h3m maps --- lib/mapping/MapFormatH3M.cpp | 7 +------ lib/mapping/MapReaderH3M.cpp | 2 ++ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index 0edefb82c..8387885b0 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -678,8 +678,6 @@ void CMapLoaderH3M::readTeamInfo() void CMapLoaderH3M::readAllowedHeroes() { - mapHeader->allowedHeroes = VLC->heroh->getDefaultAllowed(); - if(features.levelHOTA0) reader->readBitmaskHeroesSized(mapHeader->allowedHeroes, false); else @@ -749,8 +747,6 @@ void CMapLoaderH3M::readMapOptions() void CMapLoaderH3M::readAllowedArtifacts() { - map->allowedArtifact = VLC->arth->getDefaultAllowed(); - if(features.levelAB) { if(features.levelHOTA0) @@ -1827,9 +1823,8 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec logGlobal->debug("Hero %s subID=%d has spells set twice (in map properties and on adventure map instance). Using the latter set...", object->getNameTextID(), object->subID); } - object->spells.insert(SpellID::PRESET); //placeholder "preset spells" - reader->readBitmaskSpells(object->spells, false); + object->spells.insert(SpellID::PRESET); //placeholder "preset spells" } } else if(features.levelAB) diff --git a/lib/mapping/MapReaderH3M.cpp b/lib/mapping/MapReaderH3M.cpp index e0ee0a83c..5626b53d5 100644 --- a/lib/mapping/MapReaderH3M.cpp +++ b/lib/mapping/MapReaderH3M.cpp @@ -325,6 +325,8 @@ void MapReaderH3M::readBitmaskSkills(std::set & dest, bool inver template void MapReaderH3M::readBitmask(std::set & dest, int bytesToRead, int objectsToRead, bool invert) { + dest.clear(); + for(int byte = 0; byte < bytesToRead; ++byte) { const ui8 mask = reader->readUInt8(); From d0e320723c62c2bb1c5415c7fbbc0eb3f790810f Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Tue, 21 Nov 2023 18:31:43 +0200 Subject: [PATCH 3/7] Remove no longer relevant assertion --- lib/serializer/JsonSerializer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/serializer/JsonSerializer.cpp b/lib/serializer/JsonSerializer.cpp index aa1553e3a..430a6809a 100644 --- a/lib/serializer/JsonSerializer.cpp +++ b/lib/serializer/JsonSerializer.cpp @@ -97,7 +97,6 @@ void JsonSerializer::serializeInternal(int64_t & value) void JsonSerializer::serializeLIC(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const std::set & standard, std::set & value) { - assert(standard.size() == value.size()); if(standard == value) return; From e96cde291a961e632ffab09c40fbc551c6749c58 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Tue, 21 Nov 2023 18:32:07 +0200 Subject: [PATCH 4/7] Fix generation of additional monolith types for RMG --- .../CObjectClassesHandler.cpp | 14 ++++++++++---- lib/mapObjectConstructors/CObjectClassesHandler.h | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/mapObjectConstructors/CObjectClassesHandler.cpp b/lib/mapObjectConstructors/CObjectClassesHandler.cpp index ad23e9fcb..928a72a29 100644 --- a/lib/mapObjectConstructors/CObjectClassesHandler.cpp +++ b/lib/mapObjectConstructors/CObjectClassesHandler.cpp @@ -36,6 +36,7 @@ #include "../mapObjects/CGTownInstance.h" #include "../modding/IdentifierStorage.h" #include "../modding/CModHandler.h" +#include "../modding/ModScope.h" VCMI_LIB_NAMESPACE_BEGIN @@ -267,6 +268,10 @@ ObjectClass * CObjectClassesHandler::loadFromJson(const std::string & scope, con else loadSubObject(subData.second.meta, subData.first, subData.second, obj); } + + if (obj->id == MapObjectID::MONOLITH_TWO_WAY) + generateExtraMonolithsForRMG(obj); + return obj; } @@ -413,14 +418,12 @@ void CObjectClassesHandler::afterLoadFinalization() logGlobal->warn("No templates found for %s:%s", entry->getJsonKey(), obj->getJsonKey()); } } - - generateExtraMonolithsForRMG(); } -void CObjectClassesHandler::generateExtraMonolithsForRMG() +void CObjectClassesHandler::generateExtraMonolithsForRMG(ObjectClass * container) { //duplicate existing two-way portals to make reserve for RMG - auto& portalVec = objects[Obj::MONOLITH_TWO_WAY]->objects; + auto& portalVec = container->objects; //FIXME: Monoliths in this vector can be already not useful for every terrain const size_t portalCount = portalVec.size(); @@ -449,7 +452,10 @@ void CObjectClassesHandler::generateExtraMonolithsForRMG() newPortal->type = portal->getIndex(); newPortal->subtype = portalVec.size(); //indexes must be unique, they are returned as a set + portalVec.push_back(newPortal); + + registerObject(ModScope::scopeGame(), container->getJsonKey(), newPortal->subTypeName, newPortal->subtype); } } diff --git a/lib/mapObjectConstructors/CObjectClassesHandler.h b/lib/mapObjectConstructors/CObjectClassesHandler.h index 8e8b2ae28..173fe8748 100644 --- a/lib/mapObjectConstructors/CObjectClassesHandler.h +++ b/lib/mapObjectConstructors/CObjectClassesHandler.h @@ -84,7 +84,7 @@ class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase ObjectClass * loadFromJson(const std::string & scope, const JsonNode & json, const std::string & name, size_t index); - void generateExtraMonolithsForRMG(); + void generateExtraMonolithsForRMG(ObjectClass * container); public: CObjectClassesHandler(); From 07e7d6cc14ca5192791a7fc4b6fb0cbcb3c59e3f Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Tue, 21 Nov 2023 20:32:07 +0200 Subject: [PATCH 5/7] Do not allow fleeing from cities without fort --- lib/battle/CBattleInfoEssentials.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/battle/CBattleInfoEssentials.cpp b/lib/battle/CBattleInfoEssentials.cpp index 2b69caa29..b7761a6f8 100644 --- a/lib/battle/CBattleInfoEssentials.cpp +++ b/lib/battle/CBattleInfoEssentials.cpp @@ -282,7 +282,7 @@ bool CBattleInfoEssentials::battleCanFlee(const PlayerColor & player) const return false; //we are besieged defender - if(side == BattleSide::DEFENDER && battleGetSiegeLevel()) + if(side == BattleSide::DEFENDER && getBattle()->getDefendedTown() != nullptr) { const auto * town = battleGetDefendedTown(); if(!town->hasBuilt(BuildingSubID::ESCAPE_TUNNEL)) @@ -357,7 +357,7 @@ bool CBattleInfoEssentials::battleCanSurrender(const PlayerColor & player) const const auto side = playerToSide(player); if(!side) return false; - bool iAmSiegeDefender = (side.value() == BattleSide::DEFENDER && battleGetSiegeLevel()); + bool iAmSiegeDefender = (side.value() == BattleSide::DEFENDER && getBattle()->getDefendedTown() != nullptr); //conditions like for fleeing (except escape tunnel presence) + enemy must have a hero return battleCanFlee(player) && !iAmSiegeDefender && battleHasHero(otherSide(side.value())); } From 9d298f42c3d57652f4a236741f090f2bbd396bc3 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Tue, 21 Nov 2023 21:22:17 +0200 Subject: [PATCH 6/7] Do not allow special spells such as Titan Bolt as a reward --- lib/JsonRandom.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/JsonRandom.cpp b/lib/JsonRandom.cpp index 69d0636f4..f99a678fb 100644 --- a/lib/JsonRandom.cpp +++ b/lib/JsonRandom.cpp @@ -406,7 +406,7 @@ namespace JsonRandom { std::set defaultSpells; for(const auto & spell : VLC->spellh->objects) - if (IObjectInterface::cb->isAllowed(spell->getId())) + if (IObjectInterface::cb->isAllowed(spell->getId()) && !spell->isSpecial()) defaultSpells.insert(spell->getId()); std::set potentialPicks = filterKeys(value, defaultSpells, variables); From 26d22d0d9d714ffeff383acf744199e794a3093d Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Tue, 21 Nov 2023 21:24:06 +0200 Subject: [PATCH 7/7] Fix guards composition of Pyramids --- config/objects/creatureBanks.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/config/objects/creatureBanks.json b/config/objects/creatureBanks.json index 2e117356c..cfcaf2a7a 100644 --- a/config/objects/creatureBanks.json +++ b/config/objects/creatureBanks.json @@ -1055,9 +1055,8 @@ { "chance": 100, "guards": [ - { "amount": 20, "type": "goldGolem" }, + { "amount": 40, "type": "goldGolem" }, { "amount": 10, "type": "diamondGolem" }, - { "amount": 20, "type": "goldGolem" }, { "amount": 10, "type": "diamondGolem" } ], "combat_value": 786,