From c68f2da977787f853e2e663d4324b2d747318c08 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 17 Jun 2024 20:08:07 +0000 Subject: [PATCH 1/5] Fix initialization of gold pile from random resource with fixed amount --- lib/mapObjects/MiscObjects.cpp | 5 ++++- lib/mapObjects/MiscObjects.h | 5 +++-- lib/mapping/MapFormatH3M.cpp | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp index 598ff9787..21b0cd0d9 100644 --- a/lib/mapObjects/MiscObjects.cpp +++ b/lib/mapObjects/MiscObjects.cpp @@ -263,6 +263,9 @@ void CGResource::pickRandomObject(CRandomGenerator & rand) ID = Obj::RESOURCE; subID = rand.nextInt(EGameResID::WOOD, EGameResID::GOLD); setType(ID, subID); + + if (subID == EGameResID::GOLD && amount != CGResource::RANDOM_AMOUNT) + amount *= CGResource::GOLD_AMOUNT_MULTIPLIER; } } @@ -275,7 +278,7 @@ void CGResource::initObj(CRandomGenerator & rand) switch(resourceID().toEnum()) { case EGameResID::GOLD: - amount = rand.nextInt(5, 10) * 100; + amount = rand.nextInt(5, 10) * CGResource::GOLD_AMOUNT_MULTIPLIER; break; case EGameResID::WOOD: case EGameResID::ORE: amount = rand.nextInt(6, 10); diff --git a/lib/mapObjects/MiscObjects.h b/lib/mapObjects/MiscObjects.h index 6b74fc402..6ed869895 100644 --- a/lib/mapObjects/MiscObjects.h +++ b/lib/mapObjects/MiscObjects.h @@ -122,8 +122,9 @@ class DLL_LINKAGE CGResource : public CArmedInstance public: using CArmedInstance::CArmedInstance; - static constexpr ui32 RANDOM_AMOUNT = 0; - ui32 amount = RANDOM_AMOUNT; //0 if random + static constexpr uint32_t RANDOM_AMOUNT = 0; + static constexpr uint32_t GOLD_AMOUNT_MULTIPLIER = 100; + uint32_t amount = RANDOM_AMOUNT; //0 if random MetaString message; diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index e2bb899bd..dcbf09371 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -1315,7 +1315,7 @@ CGObjectInstance * CMapLoaderH3M::readResource(const int3 & mapPosition, std::sh if(GameResID(objectTemplate->subid) == GameResID(EGameResID::GOLD)) { // Gold is multiplied by 100. - object->amount *= 100; + object->amount *= CGResource::GOLD_AMOUNT_MULTIPLIER; } reader->skipZero(4); return object; From 4e7809d934cf83d01f051d2becc3f6d8fc8bfa11 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 17 Jun 2024 20:18:34 +0000 Subject: [PATCH 2/5] Take resources on quest completion instead of giving them --- lib/mapObjects/CQuest.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/mapObjects/CQuest.cpp b/lib/mapObjects/CQuest.cpp index 98084443c..dfb97696b 100644 --- a/lib/mapObjects/CQuest.cpp +++ b/lib/mapObjects/CQuest.cpp @@ -141,6 +141,8 @@ bool CQuest::checkQuest(const CGHeroInstance * h) const void CQuest::completeQuest(IGameCallback * cb, const CGHeroInstance *h) const { + // FIXME: this should be part of 'reward', and not hacking into limiter state that should only limit access to such reward + for(auto & elem : mission.artifacts) { if(h->hasArt(elem)) @@ -164,9 +166,9 @@ void CQuest::completeQuest(IGameCallback * cb, const CGHeroInstance *h) const } } } - + cb->takeCreatures(h->id, mission.creatures); - cb->giveResources(h->getOwner(), mission.resources); + cb->giveResources(h->getOwner(), -mission.resources); } void CQuest::addTextReplacements(IGameCallback * cb, MetaString & text, std::vector & components) const From 38bee87cf4d972454992d59e374449525819052b Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 17 Jun 2024 20:22:24 +0000 Subject: [PATCH 3/5] Do not activate mana vortex if hero already has double mana --- lib/mapObjects/CGTownBuilding.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/mapObjects/CGTownBuilding.cpp b/lib/mapObjects/CGTownBuilding.cpp index 19c373653..6efd84e31 100644 --- a/lib/mapObjects/CGTownBuilding.cpp +++ b/lib/mapObjects/CGTownBuilding.cpp @@ -181,13 +181,14 @@ void COPWBonus::onHeroVisit (const CGHeroInstance * h) const if(visitors.empty()) { if(h->mana < h->manaLimit() * 2) + { cb->setManaPoints (heroID, 2 * h->manaLimit()); - //TODO: investigate line below - //cb->setObjProperty (town->id, ObjProperty::VISITED, true); - iw.text.appendRawString(getVisitingBonusGreeting()); - cb->showInfoDialog(&iw); - //extra visit penalty if hero alredy had double mana points (or even more?!) - town->addHeroToStructureVisitors(h, indexOnTV); + //TODO: investigate line below + //cb->setObjProperty (town->id, ObjProperty::VISITED, true); + iw.text.appendRawString(getVisitingBonusGreeting()); + cb->showInfoDialog(&iw); + town->addHeroToStructureVisitors(h, indexOnTV); + } } break; } From 6a0768aae673ece214970dc292e39bda7465186b Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 17 Jun 2024 20:46:47 +0000 Subject: [PATCH 4/5] Fix allied towns missing from town portal dialog --- client/CPlayerInterface.cpp | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index a09cb8166..f9bf8bcd4 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -1093,18 +1093,20 @@ void CPlayerInterface::showMapObjectSelectDialog(QueryID askID, const Component { EVENT_HANDLER_CALLED_BY_CLIENT; - std::vector tmpObjects; - if(objects.size() && dynamic_cast(cb->getObj(objects[0]))) - { - // sorting towns (like in client) - std::vector Towns = LOCPLINT->localState->getOwnedTowns(); - for(auto town : Towns) - for(auto item : objects) - if(town == cb->getObj(item)) - tmpObjects.push_back(item); - } - else // other object list than town - tmpObjects = objects; + std::vector objectGuiOrdered = objects; + + std::map townOrder; + auto ownedTowns = localState->getOwnedTowns(); + + for (int i = 0; i < ownedTowns.size(); ++i) + townOrder[ownedTowns[i]->id] = i; + + auto townComparator = [&townOrder](const ObjectInstanceID & left, const ObjectInstanceID & right){ + uint32_t leftIndex= townOrder.count(left) ? townOrder.at(left) : std::numeric_limits::max(); + uint32_t rightIndex = townOrder.count(right) ? townOrder.at(right) : std::numeric_limits::max(); + return leftIndex < rightIndex; + }; + std::stable_sort(objectGuiOrdered.begin(), objectGuiOrdered.end(), townComparator); auto selectCallback = [=](int selection) { @@ -1120,9 +1122,9 @@ void CPlayerInterface::showMapObjectSelectDialog(QueryID askID, const Component const std::string localDescription = description.toString(); std::vector tempList; - tempList.reserve(tmpObjects.size()); + tempList.reserve(objectGuiOrdered.size()); - for(auto item : tmpObjects) + for(auto item : objectGuiOrdered) tempList.push_back(item.getNum()); CComponent localIconC(icon); @@ -1131,7 +1133,7 @@ void CPlayerInterface::showMapObjectSelectDialog(QueryID askID, const Component localIconC.removeChild(localIcon.get(), false); std::vector> images; - for(auto & obj : tmpObjects) + for(auto & obj : objectGuiOrdered) { if(!settings["general"]["enableUiEnhancements"].Bool()) break; @@ -1146,8 +1148,8 @@ void CPlayerInterface::showMapObjectSelectDialog(QueryID askID, const Component auto wnd = std::make_shared(tempList, localIcon, localTitle, localDescription, selectCallback, 0, images); wnd->onExit = cancelCallback; - wnd->onPopup = [this, tmpObjects](int index) { CRClickPopup::createAndPush(cb->getObj(tmpObjects[index]), GH.getCursorPosition()); }; - wnd->onClicked = [this, tmpObjects](int index) { adventureInt->centerOnObject(cb->getObj(tmpObjects[index])); GH.windows().totalRedraw(); }; + wnd->onPopup = [this, objectGuiOrdered](int index) { CRClickPopup::createAndPush(cb->getObj(objectGuiOrdered[index]), GH.getCursorPosition()); }; + wnd->onClicked = [this, objectGuiOrdered](int index) { adventureInt->centerOnObject(cb->getObj(objectGuiOrdered[index])); GH.windows().totalRedraw(); }; GH.windows().pushWindow(wnd); } From 76bb32536f852c1a7bd19198e331f2fd1911282c Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 17 Jun 2024 20:58:04 +0000 Subject: [PATCH 5/5] Correctly iterate over allowed spells set (was vector originally) --- lib/IGameCallback.cpp | 8 ++++---- lib/rmg/RmgMap.cpp | 7 +------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/lib/IGameCallback.cpp b/lib/IGameCallback.cpp index ae7df063b..4dc1a1c3c 100644 --- a/lib/IGameCallback.cpp +++ b/lib/IGameCallback.cpp @@ -158,17 +158,17 @@ void CPrivilegedInfoCallback::pickAllowedArtsSet(std::vector void CPrivilegedInfoCallback::getAllowedSpells(std::vector & out, std::optional level) { - for (ui32 i = 0; i < gs->map->allowedSpells.size(); i++) //spellh size appears to be greater (?) + for (auto const & spellID : gs->map->allowedSpells) { - const spells::Spell * spell = SpellID(i).toSpell(); + const auto * spell = spellID.toEntity(VLC); - if (!isAllowed(spell->getId())) + if (!isAllowed(spellID)) continue; if (level.has_value() && spell->getLevel() != level) continue; - out.push_back(spell->getId()); + out.push_back(spellID); } } diff --git a/lib/rmg/RmgMap.cpp b/lib/rmg/RmgMap.cpp index 1eaffb1e3..c889e720a 100644 --- a/lib/rmg/RmgMap.cpp +++ b/lib/rmg/RmgMap.cpp @@ -368,12 +368,7 @@ ui32 RmgMap::getTotalZoneCount() const bool RmgMap::isAllowedSpell(const SpellID & sid) const { assert(sid.getNum() >= 0); - if (sid.getNum() < mapInstance->allowedSpells.size()) - { - return mapInstance->allowedSpells.count(sid); - } - else - return false; + return mapInstance->allowedSpells.count(sid); } void RmgMap::dump(bool zoneId) const