From 6625831cf6d8f9fe9453775677d269fa64f125ed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?=
Date: Tue, 31 Oct 2023 09:07:53 +0100
Subject: [PATCH 01/29] Use the object templates with least terrains allowed.
---
lib/rmg/RmgObject.cpp | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/lib/rmg/RmgObject.cpp b/lib/rmg/RmgObject.cpp
index 9934602a5..de3706839 100644
--- a/lib/rmg/RmgObject.cpp
+++ b/lib/rmg/RmgObject.cpp
@@ -130,6 +130,16 @@ void Object::Instance::setTemplate(TerrainId terrain, CRandomGenerator & rng)
auto terrainName = VLC->terrainTypeHandler->getById(terrain)->getNameTranslated();
throw rmgException(boost::str(boost::format("Did not find graphics for object (%d,%d) at %s") % dObject.ID % dObject.subID % terrainName));
}
+ //Get terrain-specific template if possible
+ int leastTerrains = (*boost::min_element(templates, [](const std::shared_ptr & tmp1, const std::shared_ptr & tmp2)
+ {
+ return tmp1->getAllowedTerrains().size() < tmp2->getAllowedTerrains().size();
+ }))->getAllowedTerrains().size();
+
+ vstd::erase_if(templates, [leastTerrains](const std::shared_ptr & tmp)
+ {
+ return tmp->getAllowedTerrains().size() > leastTerrains;
+ });
dObject.appearance = *RandomGeneratorUtil::nextItem(templates, rng);
dAccessibleAreaCache.clear();
From 38847094f04f1f808653f0b6f66bb3438d3389ca Mon Sep 17 00:00:00 2001
From: DjWarmonger
Date: Sat, 9 Dec 2023 08:15:36 +0100
Subject: [PATCH 02/29] Update Readme.md
Added some vanilla screenshots
---
docs/Readme.md | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/docs/Readme.md b/docs/Readme.md
index 6902f1bf6..a9b93d8a2 100644
--- a/docs/Readme.md
+++ b/docs/Readme.md
@@ -4,7 +4,16 @@
# VCMI Project
-VCMI is work-in-progress attempt to recreate engine for Heroes III, giving it new and extended possibilities.
+VCMI is an open-source recreation of Heroes of Might & Magic III engine, giving it new and extended possibilities.
+
+
+
+
+
+
+
+
+
## Links
@@ -27,6 +36,14 @@ Please see corresponding installation guide articles for details for your platfo
- [Android](players/Installation_Android.md)
- [iOS](players/Installation_iOS.md)
+
+
+
+
+
+
+
+
## Documentation and guidelines for players
- [General information about VCMI Project](players/Manual.md)
From 842856f79a44081eb1919ce95e7231428168ffc9 Mon Sep 17 00:00:00 2001
From: DjWarmonger
Date: Sat, 9 Dec 2023 08:21:37 +0100
Subject: [PATCH 03/29] Update Readme.md
---
docs/Readme.md | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/docs/Readme.md b/docs/Readme.md
index a9b93d8a2..38631e529 100644
--- a/docs/Readme.md
+++ b/docs/Readme.md
@@ -9,7 +9,6 @@ VCMI is an open-source recreation of Heroes of Might & Magic III engine, giving
-
@@ -40,8 +39,7 @@ Please see corresponding installation guide articles for details for your platfo
-
-
+
## Documentation and guidelines for players
From 0f23dde85d1853e0208a1c49d93e8e0a743e4fe7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?=
Date: Sat, 9 Dec 2023 14:25:03 +0100
Subject: [PATCH 04/29] Fixed crash due to incorrect monolith id scopes
---
lib/mapObjectConstructors/CObjectClassesHandler.cpp | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/lib/mapObjectConstructors/CObjectClassesHandler.cpp b/lib/mapObjectConstructors/CObjectClassesHandler.cpp
index 928a72a29..169cc2753 100644
--- a/lib/mapObjectConstructors/CObjectClassesHandler.cpp
+++ b/lib/mapObjectConstructors/CObjectClassesHandler.cpp
@@ -452,10 +452,14 @@ void CObjectClassesHandler::generateExtraMonolithsForRMG(ObjectClass * container
newPortal->type = portal->getIndex();
newPortal->subtype = portalVec.size(); //indexes must be unique, they are returned as a set
+ newPortal->blockVisit = portal->blockVisit;
+ newPortal->removable = portal->removable;
portalVec.push_back(newPortal);
- registerObject(ModScope::scopeGame(), container->getJsonKey(), newPortal->subTypeName, newPortal->subtype);
+
+ registerObject(newPortal->modScope, container->getJsonKey(), newPortal->subTypeName, newPortal->subtype);
+ //registerObject(ModScope::scopeBuiltin(), container->getJsonKey(), newPortal->subTypeName, newPortal->subtype);
}
}
From cef25cca03ff2a423d44da8a7f7d2f90d82dbfde Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?=
Date: Sat, 9 Dec 2023 14:59:09 +0100
Subject: [PATCH 05/29] Fix for starting hero being passable
---
lib/mapObjects/CGHeroInstance.cpp | 7 +++++++
lib/mapObjects/CGHeroInstance.h | 1 +
2 files changed, 8 insertions(+)
diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp
index 4037cec39..de08279d0 100644
--- a/lib/mapObjects/CGHeroInstance.cpp
+++ b/lib/mapObjects/CGHeroInstance.cpp
@@ -150,6 +150,11 @@ bool CGHeroInstance::isCoastVisitable() const
return true;
}
+bool CGHeroInstance::isBlockedVisitable() const
+{
+ return true;
+}
+
BattleField CGHeroInstance::getBattlefield() const
{
return BattleField::NONE;
@@ -281,6 +286,7 @@ CGHeroInstance::CGHeroInstance():
ID = Obj::HERO;
secSkills.emplace_back(SecondarySkill::NONE, -1);
blockVisit = true;
+ removable = true;
}
PlayerColor CGHeroInstance::getOwner() const
@@ -301,6 +307,7 @@ void CGHeroInstance::setHeroType(HeroTypeID heroType)
void CGHeroInstance::initHero(CRandomGenerator & rand, const HeroTypeID & SUBID)
{
+ blockVisit = true;
subID = SUBID.getNum();
initHero(rand);
}
diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h
index 208ea27be..9f2484733 100644
--- a/lib/mapObjects/CGHeroInstance.h
+++ b/lib/mapObjects/CGHeroInstance.h
@@ -301,6 +301,7 @@ public:
void updateFrom(const JsonNode & data) override;
bool isCoastVisitable() const override;
+ bool isBlockedVisitable() const override;
BattleField getBattlefield() const override;
protected:
void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;//synchr
From 134f78113ef03dbbf50930da230fed5268f637dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?=
Date: Sat, 9 Dec 2023 15:20:11 +0100
Subject: [PATCH 06/29] Remove unneccessary code
---
lib/mapObjects/CGHeroInstance.cpp | 3 ---
1 file changed, 3 deletions(-)
diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp
index de08279d0..697d4f162 100644
--- a/lib/mapObjects/CGHeroInstance.cpp
+++ b/lib/mapObjects/CGHeroInstance.cpp
@@ -285,8 +285,6 @@ CGHeroInstance::CGHeroInstance():
setNodeType(HERO);
ID = Obj::HERO;
secSkills.emplace_back(SecondarySkill::NONE, -1);
- blockVisit = true;
- removable = true;
}
PlayerColor CGHeroInstance::getOwner() const
@@ -307,7 +305,6 @@ void CGHeroInstance::setHeroType(HeroTypeID heroType)
void CGHeroInstance::initHero(CRandomGenerator & rand, const HeroTypeID & SUBID)
{
- blockVisit = true;
subID = SUBID.getNum();
initHero(rand);
}
From d15e9f886c6cf7b5e4970eabd04fe7638f4cc475 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?=
Date: Sat, 9 Dec 2023 15:35:32 +0100
Subject: [PATCH 07/29] Cleanup
---
lib/mapObjectConstructors/CObjectClassesHandler.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/lib/mapObjectConstructors/CObjectClassesHandler.cpp b/lib/mapObjectConstructors/CObjectClassesHandler.cpp
index 169cc2753..d2a4907f1 100644
--- a/lib/mapObjectConstructors/CObjectClassesHandler.cpp
+++ b/lib/mapObjectConstructors/CObjectClassesHandler.cpp
@@ -457,9 +457,7 @@ void CObjectClassesHandler::generateExtraMonolithsForRMG(ObjectClass * container
portalVec.push_back(newPortal);
-
registerObject(newPortal->modScope, container->getJsonKey(), newPortal->subTypeName, newPortal->subtype);
- //registerObject(ModScope::scopeBuiltin(), container->getJsonKey(), newPortal->subTypeName, newPortal->subtype);
}
}
From df78c9c6f19e84345f957e8f1573d4ae554b705a Mon Sep 17 00:00:00 2001
From: Ivan Savenko
Date: Sat, 9 Dec 2023 18:08:22 +0200
Subject: [PATCH 08/29] Added workaround for crashes with outdated mods
---
lib/mapObjectConstructors/CommonConstructors.cpp | 2 +-
lib/spells/effects/Summon.cpp | 6 ++++++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/lib/mapObjectConstructors/CommonConstructors.cpp b/lib/mapObjectConstructors/CommonConstructors.cpp
index 13f286cbf..6a558b96a 100644
--- a/lib/mapObjectConstructors/CommonConstructors.cpp
+++ b/lib/mapObjectConstructors/CommonConstructors.cpp
@@ -133,7 +133,7 @@ void CHeroInstanceConstructor::afterLoadFinalization()
{
filters[entry.first] = LogicalExpression(entry.second, [](const JsonNode & node)
{
- return HeroTypeID(VLC->identifiers()->getIdentifier("hero", node.Vector()[0]).value());
+ return HeroTypeID(VLC->identifiers()->getIdentifier("hero", node.Vector()[0]).value_or(-1));
});
}
}
diff --git a/lib/spells/effects/Summon.cpp b/lib/spells/effects/Summon.cpp
index ac3c0206b..39b4dceca 100644
--- a/lib/spells/effects/Summon.cpp
+++ b/lib/spells/effects/Summon.cpp
@@ -42,6 +42,12 @@ void Summon::adjustTargetTypes(std::vector & types) const
bool Summon::applicable(Problem & problem, const Mechanics * m) const
{
+ if (creature == CreatureID::NONE)
+ {
+ logMod->error("Attempt to summon non-existing creature!");
+ return m->adaptGenericProblem(problem);
+ }
+
if(exclusive)
{
//check if there are summoned creatures of other type
From 902db091da25f4f2963678c87eb9bdb5819167ab Mon Sep 17 00:00:00 2001
From: Ivan Savenko
Date: Sat, 9 Dec 2023 18:09:10 +0200
Subject: [PATCH 09/29] Simple fix for slider activation when clicking on
left/right buttons
---
client/widgets/Slider.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/client/widgets/Slider.cpp b/client/widgets/Slider.cpp
index b8dfc98bf..8a37b6f46 100644
--- a/client/widgets/Slider.cpp
+++ b/client/widgets/Slider.cpp
@@ -156,6 +156,11 @@ void CSlider::clickPressed(const Point & cursorPosition)
bool CSlider::receiveEvent(const Point &position, int eventType) const
{
+ if (eventType == LCLICK)
+ {
+ return pos.isInside(position) && !left->pos.isInside(position) && !right->pos.isInside(position);
+ }
+
if(eventType != WHEEL && eventType != GESTURE)
{
return CIntObject::receiveEvent(position, eventType);
From 2261298d09f54cd2f8030b5a85e6db914a5ab540 Mon Sep 17 00:00:00 2001
From: Ivan Savenko
Date: Sat, 9 Dec 2023 18:09:38 +0200
Subject: [PATCH 10/29] Revert U-turns block. Actually possible in H3 and has
unintended side effects
---
lib/pathfinder/CPathfinder.cpp | 3 ---
1 file changed, 3 deletions(-)
diff --git a/lib/pathfinder/CPathfinder.cpp b/lib/pathfinder/CPathfinder.cpp
index 46d4f564b..28d510ee9 100644
--- a/lib/pathfinder/CPathfinder.cpp
+++ b/lib/pathfinder/CPathfinder.cpp
@@ -162,9 +162,6 @@ void CPathfinder::calculatePaths()
if(neighbour->locked)
continue;
- if (source.node->theNodeBefore && source.node->theNodeBefore->coord == neighbour->coord )
- continue; // block U-turns
-
if(!hlp->isLayerAvailable(neighbour->layer))
continue;
From 2de7a3939a4de12b59de0dc44e1e3314ef2ef7ba Mon Sep 17 00:00:00 2001
From: Ivan Savenko
Date: Sat, 9 Dec 2023 18:09:57 +0200
Subject: [PATCH 11/29] Fix text identifier for generic signs without custom
text
---
lib/mapObjects/MiscObjects.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp
index 11c532f13..872e57ba4 100644
--- a/lib/mapObjects/MiscObjects.cpp
+++ b/lib/mapObjects/MiscObjects.cpp
@@ -937,7 +937,7 @@ void CGSignBottle::initObj(CRandomGenerator & rand)
{
auto vector = VLC->generaltexth->findStringsWithPrefix("core.randsign");
std::string messageIdentifier = *RandomGeneratorUtil::nextItem(vector, rand);
- message.appendTextID(TextIdentifier("core", "randsign", messageIdentifier).get());
+ message.appendTextID(messageIdentifier);
}
if(ID == Obj::OCEAN_BOTTLE)
From b8e40978a077389bf2ef894964f9903c3cbbd1d4 Mon Sep 17 00:00:00 2001
From: Laserlicht <13953785+Laserlicht@users.noreply.github.com>
Date: Sat, 9 Dec 2023 17:29:57 +0100
Subject: [PATCH 12/29] stop smooth scroll when using window borders to scroll
---
client/mapView/MapView.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/client/mapView/MapView.cpp b/client/mapView/MapView.cpp
index b39c8a6f5..d1375f1df 100644
--- a/client/mapView/MapView.cpp
+++ b/client/mapView/MapView.cpp
@@ -122,7 +122,10 @@ void MapView::onMapLevelSwitched()
void MapView::onMapScrolled(const Point & distance)
{
if(!isGesturing())
+ {
+ postSwipeSpeed = 0.0;
controller->setViewCenter(model->getMapViewCenter() + distance, model->getLevel());
+ }
}
void MapView::onMapSwiped(const Point & viewPosition)
From 9a52131c82f48fd1a6c454cdca333e749f14a2e0 Mon Sep 17 00:00:00 2001
From: Ivan Savenko
Date: Sat, 9 Dec 2023 18:48:53 +0200
Subject: [PATCH 13/29] Use battle side instead of player color for fire shield
damage formula
---
server/battles/BattleActionProcessor.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/battles/BattleActionProcessor.cpp b/server/battles/BattleActionProcessor.cpp
index 56878c270..07180c913 100644
--- a/server/battles/BattleActionProcessor.cpp
+++ b/server/battles/BattleActionProcessor.cpp
@@ -1032,7 +1032,7 @@ void BattleActionProcessor::makeAttack(const CBattleInfoCallback & battle, const
const CStack * actor = item.first;
int64_t rawDamage = item.second;
- const CGHeroInstance * actorOwner = battle.battleGetFightingHero(actor->unitOwner());
+ const CGHeroInstance * actorOwner = battle.battleGetFightingHero(actor->unitSide());
if(actorOwner)
{
From adb720c8ea41892179c0630c1ad903a409f04160 Mon Sep 17 00:00:00 2001
From: Ivan Savenko
Date: Sat, 9 Dec 2023 19:03:05 +0200
Subject: [PATCH 14/29] Bump version to 1.4.1
---
Mods/vcmi/mod.json | 2 +-
android/vcmi-app/build.gradle | 4 ++--
cmake_modules/VersionDefinition.cmake | 2 +-
debian/changelog | 6 ++++++
launcher/eu.vcmi.VCMI.metainfo.xml | 1 +
5 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/Mods/vcmi/mod.json b/Mods/vcmi/mod.json
index cedf5bf5b..7d57c29d3 100644
--- a/Mods/vcmi/mod.json
+++ b/Mods/vcmi/mod.json
@@ -98,7 +98,7 @@
]
},
- "version" : "1.3",
+ "version" : "1.4",
"author" : "VCMI Team",
"contact" : "http://forum.vcmi.eu/index.php",
"modType" : "Graphical",
diff --git a/android/vcmi-app/build.gradle b/android/vcmi-app/build.gradle
index 3b7d295ea..f46b2f8e8 100644
--- a/android/vcmi-app/build.gradle
+++ b/android/vcmi-app/build.gradle
@@ -10,8 +10,8 @@ android {
applicationId "is.xyz.vcmi"
minSdk 19
targetSdk 33
- versionCode 1400
- versionName "1.4.0"
+ versionCode 1410
+ versionName "1.4.1"
setProperty("archivesBaseName", "vcmi")
}
diff --git a/cmake_modules/VersionDefinition.cmake b/cmake_modules/VersionDefinition.cmake
index f9fdb6992..666d32737 100644
--- a/cmake_modules/VersionDefinition.cmake
+++ b/cmake_modules/VersionDefinition.cmake
@@ -1,6 +1,6 @@
set(VCMI_VERSION_MAJOR 1)
set(VCMI_VERSION_MINOR 4)
-set(VCMI_VERSION_PATCH 0)
+set(VCMI_VERSION_PATCH 1)
add_definitions(
-DVCMI_VERSION_MAJOR=${VCMI_VERSION_MAJOR}
-DVCMI_VERSION_MINOR=${VCMI_VERSION_MINOR}
diff --git a/debian/changelog b/debian/changelog
index 0c7935b15..253546373 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+vcmi (1.4.1) jammy; urgency=medium
+
+ * New upstream release
+
+ -- Ivan Savenko Fri, 22 Dec 2023 16:00:00 +0200
+
vcmi (1.4.0) jammy; urgency=medium
* New upstream release
diff --git a/launcher/eu.vcmi.VCMI.metainfo.xml b/launcher/eu.vcmi.VCMI.metainfo.xml
index 26ef16ef5..e7190b565 100644
--- a/launcher/eu.vcmi.VCMI.metainfo.xml
+++ b/launcher/eu.vcmi.VCMI.metainfo.xml
@@ -68,6 +68,7 @@
StrategyGame
+
From 91ebac3c2eb636f812e29885a2f948e75c694c66 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?=
Date: Sun, 10 Dec 2023 09:46:20 +0100
Subject: [PATCH 15/29] Fix incorrect check
---
lib/rmg/CMapGenOptions.cpp | 6 ------
1 file changed, 6 deletions(-)
diff --git a/lib/rmg/CMapGenOptions.cpp b/lib/rmg/CMapGenOptions.cpp
index 72d9e786c..0e147a621 100644
--- a/lib/rmg/CMapGenOptions.cpp
+++ b/lib/rmg/CMapGenOptions.cpp
@@ -730,12 +730,6 @@ std::vector CMapGenOptions::getPossibleTemplates() const
return true;
}
- if(compOnlyPlayerCount != CMapGenOptions::RANDOM_SIZE)
- {
- if (!tmpl->getHumanPlayers().isInRange(compOnlyPlayerCount))
- return true;
- }
-
return false;
});
From d0e100c1bbf582c8dd5d1426946fed6c98bcb73e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?=
Date: Sun, 10 Dec 2023 09:50:25 +0100
Subject: [PATCH 16/29] Fix unused variable
---
lib/rmg/CMapGenOptions.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/rmg/CMapGenOptions.cpp b/lib/rmg/CMapGenOptions.cpp
index 0e147a621..4f89f7398 100644
--- a/lib/rmg/CMapGenOptions.cpp
+++ b/lib/rmg/CMapGenOptions.cpp
@@ -580,7 +580,7 @@ void CMapGenOptions::finalize(CRandomGenerator & rand)
}
logGlobal->trace("Player %d: %s", player.second.getColor(), playerType);
}
- logGlobal->info("Final player config: %d total, %d cpu-only", players.size(), static_cast(getCompOnlyPlayerCount()));
+ logGlobal->info("Final player config: %d total, %d cpu-only", players.size(), cpuOnlyPlayers);
}
void CMapGenOptions::updatePlayers()
From e74c2262c3e2b0b28632bb70dcea3a524dc64cec Mon Sep 17 00:00:00 2001
From: Laserlicht <13953785+Laserlicht@users.noreply.github.com>
Date: Sun, 10 Dec 2023 13:38:58 +0100
Subject: [PATCH 17/29] add option to gui to disable smooth dragging
---
Mods/vcmi/config/vcmi/english.json | 2 ++
Mods/vcmi/config/vcmi/german.json | 2 ++
client/windows/settings/AdventureOptionsTab.cpp | 8 ++++++++
config/widgets/settings/adventureOptionsTab.json | 5 +++++
4 files changed, 17 insertions(+)
diff --git a/Mods/vcmi/config/vcmi/english.json b/Mods/vcmi/config/vcmi/english.json
index 242099ee7..557628769 100644
--- a/Mods/vcmi/config/vcmi/english.json
+++ b/Mods/vcmi/config/vcmi/english.json
@@ -129,6 +129,8 @@
"vcmi.adventureOptions.infoBarCreatureManagement.help" : "{Info Panel Creature Management}\n\nAllows rearranging creatures in info panel instead of cycling between default components.",
"vcmi.adventureOptions.leftButtonDrag.hover" : "Left Click Drag Map",
"vcmi.adventureOptions.leftButtonDrag.help" : "{Left Click Drag Map}\n\nWhen enabled, moving mouse with left button pressed will drag adventure map view.",
+ "vcmi.adventureOptions.smoothDragging.hover" : "Smooth Map Dragging",
+ "vcmi.adventureOptions.smoothDragging.help" : "{Smooth Map Dragging}\n\nWhen enabled, map dragging has a modern run out effect.",
"vcmi.adventureOptions.mapScrollSpeed1.hover": "",
"vcmi.adventureOptions.mapScrollSpeed5.hover": "",
"vcmi.adventureOptions.mapScrollSpeed6.hover": "",
diff --git a/Mods/vcmi/config/vcmi/german.json b/Mods/vcmi/config/vcmi/german.json
index 07d13f06d..f2a2ed91c 100644
--- a/Mods/vcmi/config/vcmi/german.json
+++ b/Mods/vcmi/config/vcmi/german.json
@@ -129,6 +129,8 @@
"vcmi.adventureOptions.infoBarCreatureManagement.help" : "{Info-Panel Kreaturenmanagement}\n\nErmöglicht die Neuanordnung von Kreaturen im Info-Panel, anstatt zwischen den Standardkomponenten zu wechseln",
"vcmi.adventureOptions.leftButtonDrag.hover" : "Ziehen der Karte mit Links",
"vcmi.adventureOptions.leftButtonDrag.help" : "{Ziehen der Karte mit Links}\n\nWenn aktiviert, wird die Maus bei gedrückter linker Taste in die Kartenansicht gezogen",
+ "vcmi.adventureOptions.smoothDragging.hover" : "Nahtloses Ziehen der Karte",
+ "vcmi.adventureOptions.smoothDragging.help" : "{Nahtloses Ziehen der Karte}\n\nWenn aktiviert hat das Ziehen der Karte einen sanften Auslaufeffekt.",
"vcmi.adventureOptions.mapScrollSpeed1.hover": "",
"vcmi.adventureOptions.mapScrollSpeed5.hover": "",
"vcmi.adventureOptions.mapScrollSpeed6.hover": "",
diff --git a/client/windows/settings/AdventureOptionsTab.cpp b/client/windows/settings/AdventureOptionsTab.cpp
index 90db19c93..67e7adbd4 100644
--- a/client/windows/settings/AdventureOptionsTab.cpp
+++ b/client/windows/settings/AdventureOptionsTab.cpp
@@ -126,6 +126,10 @@ AdventureOptionsTab::AdventureOptionsTab()
{
return setBoolSetting("adventure", "leftButtonDrag", value);
});
+ addCallback("smoothDraggingChanged", [](bool value)
+ {
+ return setBoolSetting("adventure", "smoothDragging", value);
+ });
build(config);
std::shared_ptr playerHeroSpeedToggle = widget("heroMovementSpeedPicker");
@@ -164,4 +168,8 @@ AdventureOptionsTab::AdventureOptionsTab()
std::shared_ptr leftButtonDragCheckbox = widget("leftButtonDragCheckbox");
if (leftButtonDragCheckbox)
leftButtonDragCheckbox->setSelected(settings["adventure"]["leftButtonDrag"].Bool());
+
+ std::shared_ptr smoothDraggingCheckbox = widget("smoothDraggingCheckbox");
+ if (smoothDraggingCheckbox)
+ smoothDraggingCheckbox->setSelected(settings["adventure"]["smoothDragging"].Bool());
}
diff --git a/config/widgets/settings/adventureOptionsTab.json b/config/widgets/settings/adventureOptionsTab.json
index cee89b6eb..c2f742062 100644
--- a/config/widgets/settings/adventureOptionsTab.json
+++ b/config/widgets/settings/adventureOptionsTab.json
@@ -391,6 +391,11 @@
"help": "vcmi.adventureOptions.leftButtonDrag",
"callback": "leftButtonDragChanged",
"created" : "desktop"
+ },
+ {
+ "name": "smoothDraggingCheckbox",
+ "help": "vcmi.adventureOptions.smoothDragging",
+ "callback": "smoothDraggingChanged"
}
]
}
From 76bd3dde7f2ac364f7a4d9cc8c7f18588d5ba301 Mon Sep 17 00:00:00 2001
From: Laserlicht <13953785+Laserlicht@users.noreply.github.com>
Date: Sun, 10 Dec 2023 14:29:11 +0100
Subject: [PATCH 18/29] missed hover
---
config/widgets/settings/adventureOptionsTab.json | 3 +++
1 file changed, 3 insertions(+)
diff --git a/config/widgets/settings/adventureOptionsTab.json b/config/widgets/settings/adventureOptionsTab.json
index c2f742062..96731dd4c 100644
--- a/config/widgets/settings/adventureOptionsTab.json
+++ b/config/widgets/settings/adventureOptionsTab.json
@@ -347,6 +347,9 @@
{
"text": "vcmi.adventureOptions.leftButtonDrag.hover",
"created" : "desktop"
+ },
+ {
+ "text": "vcmi.adventureOptions.smoothDragging.hover"
}
]
},
From df2a5f05d865919d90fb39c889825ead5ec5c740 Mon Sep 17 00:00:00 2001
From: Laserlicht <13953785+Laserlicht@users.noreply.github.com>
Date: Sun, 10 Dec 2023 14:49:27 +0100
Subject: [PATCH 19/29] audio mute on focus lost setting
---
Mods/vcmi/config/vcmi/english.json | 4 +++-
Mods/vcmi/config/vcmi/german.json | 2 ++
client/eventsSDL/InputHandler.cpp | 4 ++--
client/windows/settings/GeneralOptionsTab.cpp | 9 ++++++++
config/schemas/settings.json | 7 +++++-
.../widgets/settings/generalOptionsTab.json | 22 +++++++++++++++++++
6 files changed, 44 insertions(+), 4 deletions(-)
diff --git a/Mods/vcmi/config/vcmi/english.json b/Mods/vcmi/config/vcmi/english.json
index 242099ee7..141973013 100644
--- a/Mods/vcmi/config/vcmi/english.json
+++ b/Mods/vcmi/config/vcmi/english.json
@@ -114,6 +114,8 @@
"vcmi.systemOptions.enableUiEnhancementsButton.help" : "{Interface Enhancements}\n\nToggle various quality of life interface improvements. Such as a backpack button etc. Disable to have a more classic experience.",
"vcmi.systemOptions.enableLargeSpellbookButton.hover" : "Large Spell Book",
"vcmi.systemOptions.enableLargeSpellbookButton.help" : "{Large Spell Book}\n\nEnables larger spell book that fits more spells per page. Spell book page change animation does not work with this setting enabled.",
+ "vcmi.systemOptions.audioMuteFocus.hover" : "Mute on inactivity",
+ "vcmi.systemOptions.audioMuteFocus.help" : "{Mute on inactivity}\n\nMute audio on inactive window focus. Exceptions are ingame messages and new turn sound.",
"vcmi.adventureOptions.infoBarPick.hover" : "Show Messages in Info Panel",
"vcmi.adventureOptions.infoBarPick.help" : "{Show Messages in Info Panel}\n\nWhenever possible, game messages from visiting map objects will be shown in the info panel, instead of popping up in a separate window.",
@@ -258,7 +260,7 @@
"vcmi.optionsTab.simturnsMin.help" : "Play simultaneously for specified number of days. Contacts between players during this period are blocked",
"vcmi.optionsTab.simturnsMax.help" : "Play simultaneously for specified number of days or until contact with another player",
"vcmi.optionsTab.simturnsAI.help" : "{Simultaneous AI Turns}\nExperimental option. Allows AI players to act at the same time as human player when simultaneous turns are enabled.",
-
+
"vcmi.optionsTab.turnTime.select" : "Select turn timer preset",
"vcmi.optionsTab.turnTime.unlimited" : "Unlimited turn time",
"vcmi.optionsTab.turnTime.classic.1" : "Classic timer: 1 minute",
diff --git a/Mods/vcmi/config/vcmi/german.json b/Mods/vcmi/config/vcmi/german.json
index 07d13f06d..ed1c11a51 100644
--- a/Mods/vcmi/config/vcmi/german.json
+++ b/Mods/vcmi/config/vcmi/german.json
@@ -114,6 +114,8 @@
"vcmi.systemOptions.enableUiEnhancementsButton.help" : "{Interface Verbesserungen}\n\nSchaltet verschiedene Interface Verbesserungen um. Wie z.B. ein Rucksack-Button, etc. Deaktivieren, um ein klassischeres Erlebnis zu haben.",
"vcmi.systemOptions.enableLargeSpellbookButton.hover" : "Großes Zauberbuch",
"vcmi.systemOptions.enableLargeSpellbookButton.help" : "{Großes Zauberbuch}\n\nErmöglicht ein größeres Zauberbuch, in das mehr Zaubersprüche pro Seite passen. Die Animation des Seitenwechsels im Zauberbuch funktioniert nicht, wenn diese Einstellung aktiviert ist.",
+ "vcmi.systemOptions.audioMuteFocus.hover" : "Stumm bei Inaktivität",
+ "vcmi.systemOptions.audioMuteFocus.help" : "{Stumm bei Inaktivität}\n\nSchaltet Audio bei inaktiven Fenster-Fokus stumm. Ausnahmen sind Ingame-Nachrichten und der Neuer-Zug-Sound.",
"vcmi.adventureOptions.infoBarPick.hover" : "Meldungen im Infobereich anzeigen",
"vcmi.adventureOptions.infoBarPick.help" : "{Meldungen im Infobereich anzeigen}\n\nWann immer möglich, werden Spielnachrichten von besuchten Kartenobjekten in der Infoleiste angezeigt, anstatt als Popup-Fenster zu erscheinen",
diff --git a/client/eventsSDL/InputHandler.cpp b/client/eventsSDL/InputHandler.cpp
index 2db1020a9..adfbbde07 100644
--- a/client/eventsSDL/InputHandler.cpp
+++ b/client/eventsSDL/InputHandler.cpp
@@ -170,7 +170,7 @@ void InputHandler::preprocessEvent(const SDL_Event & ev)
case SDL_WINDOWEVENT_FOCUS_GAINED:
{
boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
- if(settings["general"]["enableUiEnhancements"].Bool()) {
+ if(settings["general"]["audioMuteFocus"].Bool()) {
CCS->musich->setVolume(settings["general"]["music"].Integer());
CCS->soundh->setVolume(settings["general"]["sound"].Integer());
}
@@ -179,7 +179,7 @@ void InputHandler::preprocessEvent(const SDL_Event & ev)
case SDL_WINDOWEVENT_FOCUS_LOST:
{
boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
- if(settings["general"]["enableUiEnhancements"].Bool()) {
+ if(settings["general"]["audioMuteFocus"].Bool()) {
CCS->musich->setVolume(0);
CCS->soundh->setVolume(0);
}
diff --git a/client/windows/settings/GeneralOptionsTab.cpp b/client/windows/settings/GeneralOptionsTab.cpp
index c4a6ec84b..82d455c3d 100644
--- a/client/windows/settings/GeneralOptionsTab.cpp
+++ b/client/windows/settings/GeneralOptionsTab.cpp
@@ -167,6 +167,11 @@ GeneralOptionsTab::GeneralOptionsTab()
setBoolSetting("gameTweaks", "enableLargeSpellbook", value);
});
+ addCallback("audioMuteFocusChanged", [](bool value)
+ {
+ setBoolSetting("general", "audioMuteFocus", value);
+ });
+
//moved from "other" tab that is disabled for now to avoid excessible tabs with barely any content
addCallback("availableCreaturesAsDwellingChanged", [=](int value)
{
@@ -215,6 +220,10 @@ GeneralOptionsTab::GeneralOptionsTab()
if (enableLargeSpellbookCheckbox)
enableLargeSpellbookCheckbox->setSelected(settings["gameTweaks"]["enableLargeSpellbook"].Bool());
+ std::shared_ptr audioMuteFocusCheckbox = widget("audioMuteFocusCheckbox");
+ if (audioMuteFocusCheckbox)
+ audioMuteFocusCheckbox->setSelected(settings["general"]["audioMuteFocus"].Bool());
+
std::shared_ptr musicSlider = widget("musicSlider");
musicSlider->scrollTo(CCS->musich->getVolume());
diff --git a/config/schemas/settings.json b/config/schemas/settings.json
index c65cf374d..0ea20d327 100644
--- a/config/schemas/settings.json
+++ b/config/schemas/settings.json
@@ -39,7 +39,8 @@
"useSavePrefix",
"savePrefix",
"startTurnAutosave",
- "enableUiEnhancements"
+ "enableUiEnhancements",
+ "audioMuteFocus"
],
"properties" : {
"playerName" : {
@@ -131,6 +132,10 @@
"enableUiEnhancements" : {
"type": "boolean",
"default": true
+ },
+ "audioMuteFocus" : {
+ "type": "boolean",
+ "default": false
}
}
},
diff --git a/config/widgets/settings/generalOptionsTab.json b/config/widgets/settings/generalOptionsTab.json
index 41d3b57a8..42348177e 100644
--- a/config/widgets/settings/generalOptionsTab.json
+++ b/config/widgets/settings/generalOptionsTab.json
@@ -180,6 +180,28 @@
"type": "labelCentered",
"position": {"x": 565, "y": 158}
},
+ {
+ "type" : "verticalLayout",
+ "customType" : "labelDescription",
+ "position" : {"x": 415, "y": 202},
+ "items" : [
+ {
+ "text": "vcmi.systemOptions.audioMuteFocus.hover"
+ }
+ ]
+ },
+ {
+ "type" : "verticalLayout",
+ "customType" : "checkbox",
+ "position" : {"x": 380, "y": 200},
+ "items" : [
+ {
+ "name": "audioMuteFocusCheckbox",
+ "help": "vcmi.systemOptions.audioMuteFocus",
+ "callback": "audioMuteFocusChanged"
+ }
+ ]
+ },
/////////////////////////////////////// Bottom section - Towns Settings
{
"type" : "verticalLayout",
From ee7bd87b8d6512a7d63238f50ec4026e8dabbdab Mon Sep 17 00:00:00 2001
From: Ivan Savenko
Date: Sun, 10 Dec 2023 16:14:01 +0200
Subject: [PATCH 20/29] Fix crash on losing mission-critical hero in battle
---
lib/gameState/CGameState.cpp | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/lib/gameState/CGameState.cpp b/lib/gameState/CGameState.cpp
index 519b23e8f..5d49b350e 100644
--- a/lib/gameState/CGameState.cpp
+++ b/lib/gameState/CGameState.cpp
@@ -1444,18 +1444,22 @@ bool CGameState::checkForVictory(const PlayerColor & player, const EventConditio
{
// list of players that need to control object to fulfull condition
// NOTE: cgameinfocallback specified explicitly in order to get const version
- const auto & team = CGameInfoCallback::getPlayerTeam(player)->players;
+ const auto * team = CGameInfoCallback::getPlayerTeam(player);
if (condition.objectID != ObjectInstanceID::NONE) // mode A - flag one specific object, like town
{
- return team.count(getObjInstance(condition.objectID)->tempOwner) != 0;
+ const auto * object = getObjInstance(condition.objectID);
+
+ if (!object)
+ return false;
+ return team->players.count(object->getOwner()) != 0;
}
else
{
for(const auto & elem : map->objects) // mode B - flag all objects of this type
{
//check not flagged objs
- if ( elem && elem->ID == condition.objectType.as() && team.count(elem->tempOwner) == 0 )
+ if ( elem && elem->ID == condition.objectType.as() && team->players.count(elem->getOwner()) == 0 )
return false;
}
return true;
From a7c838036df5d4131e73807bd211416e3c53e9cc Mon Sep 17 00:00:00 2001
From: Ivan Savenko
Date: Sun, 10 Dec 2023 16:32:43 +0200
Subject: [PATCH 21/29] Workaround to avoid crash on invalid bonus
---
server/battles/BattleActionProcessor.cpp | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/server/battles/BattleActionProcessor.cpp b/server/battles/BattleActionProcessor.cpp
index 07180c913..f61d04548 100644
--- a/server/battles/BattleActionProcessor.cpp
+++ b/server/battles/BattleActionProcessor.cpp
@@ -1088,7 +1088,10 @@ void BattleActionProcessor::attackCasting(const CBattleInfoCallback & battle, bo
TConstBonusListPtr spells = attacker->getBonuses(Selector::type()(attackMode));
for(const auto & sf : *spells)
{
- spellsToCast.insert(sf->subtype.as());
+ if (sf->subtype.as() != SpellID())
+ spellsToCast.insert(sf->subtype.as());
+ else
+ logMod->error("Invalid spell to cast during attack!");
}
for(SpellID spellID : spellsToCast)
{
From 999db2ed78c339000ec340cc21401792958cca76 Mon Sep 17 00:00:00 2001
From: Ivan Savenko
Date: Sun, 10 Dec 2023 16:33:22 +0200
Subject: [PATCH 22/29] Avoid boost::format that throws exception on invalid
format string
---
lib/MetaString.cpp | 5 ++++-
lib/mapObjects/CGTownInstance.cpp | 13 +++++++++++--
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/lib/MetaString.cpp b/lib/MetaString.cpp
index 8fdb6d3a0..2845a6f38 100644
--- a/lib/MetaString.cpp
+++ b/lib/MetaString.cpp
@@ -168,7 +168,10 @@ DLL_LINKAGE std::string MetaString::toString() const
boost::replace_first(dst, "%d", std::to_string(numbers[nums++]));
break;
case EMessage::REPLACE_POSITIVE_NUMBER:
- boost::replace_first(dst, "%+d", '+' + std::to_string(numbers[nums++]));
+ if (dst.find("%+d") != std::string::npos)
+ boost::replace_first(dst, "%+d", '+' + std::to_string(numbers[nums++]));
+ else
+ boost::replace_first(dst, "%d", std::to_string(numbers[nums++]));
break;
default:
logGlobal->error("MetaString processing error! Received message of type %d", static_cast(elem));
diff --git a/lib/mapObjects/CGTownInstance.cpp b/lib/mapObjects/CGTownInstance.cpp
index ab3fe7cd7..0f7c49bcf 100644
--- a/lib/mapObjects/CGTownInstance.cpp
+++ b/lib/mapObjects/CGTownInstance.cpp
@@ -1224,12 +1224,21 @@ TerrainId CGTownInstance::getNativeTerrain() const
GrowthInfo::Entry::Entry(const std::string &format, int _count)
: count(_count)
{
- description = boost::str(boost::format(format) % count);
+ MetaString formatter;
+ formatter.appendRawString(format);
+ formatter.replacePositiveNumber(count);
+
+ description = formatter.toString();
}
GrowthInfo::Entry::Entry(int subID, const BuildingID & building, int _count): count(_count)
{
- description = boost::str(boost::format("%s %+d") % (*VLC->townh)[subID]->town->buildings.at(building)->getNameTranslated() % count);
+ MetaString formatter;
+ formatter.appendRawString("%s %+d");
+ formatter.replaceRawString((*VLC->townh)[subID]->town->buildings.at(building)->getNameTranslated());
+ formatter.replacePositiveNumber(count);
+
+ description = formatter.toString();
}
GrowthInfo::Entry::Entry(int _count, std::string fullDescription):
From 705718abc1cae4461018e35bab29ae97e0a4819e Mon Sep 17 00:00:00 2001
From: Ivan Savenko
Date: Sun, 10 Dec 2023 19:16:45 +0200
Subject: [PATCH 23/29] Do not alter case of mod description
---
launcher/modManager/cmodlistview_moc.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/launcher/modManager/cmodlistview_moc.cpp b/launcher/modManager/cmodlistview_moc.cpp
index 23789707d..9bfffda43 100644
--- a/launcher/modManager/cmodlistview_moc.cpp
+++ b/launcher/modManager/cmodlistview_moc.cpp
@@ -313,7 +313,7 @@ QString CModListView::genModInfoText(CModEntry & mod)
result += replaceIfNotEmpty(getModNames(mod.getDependencies()), lineTemplate.arg(tr("Required mods")));
result += replaceIfNotEmpty(getModNames(mod.getConflicts()), lineTemplate.arg(tr("Conflicting mods")));
- result += replaceIfNotEmpty(getModNames(mod.getValue("description").toStringList()), textTemplate.arg(tr("Description")));
+ result += replaceIfNotEmpty(mod.getValue("description"), textTemplate.arg(tr("Description")));
result += ""; // to get some empty space
From 3b6d3dee690b863a9c27a9f77d20510e26d2922e Mon Sep 17 00:00:00 2001
From: Ivan Savenko
Date: Sun, 10 Dec 2023 19:17:09 +0200
Subject: [PATCH 24/29] Slayer spell should only affect creatures with KING
bonus
---
lib/battle/DamageCalculator.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lib/battle/DamageCalculator.cpp b/lib/battle/DamageCalculator.cpp
index dfed47953..d735222f4 100644
--- a/lib/battle/DamageCalculator.cpp
+++ b/lib/battle/DamageCalculator.cpp
@@ -132,6 +132,9 @@ int DamageCalculator::getActorAttackSlayer() const
const std::string cachingStrSlayer = "type_SLAYER";
static const auto selectorSlayer = Selector::type()(BonusType::SLAYER);
+ if (!info.defender->hasBonusOfType(BonusType::KING))
+ return 0;
+
auto slayerEffects = info.attacker->getBonuses(selectorSlayer, cachingStrSlayer);
auto slayerAffected = info.defender->unitType()->valOfBonuses(Selector::type()(BonusType::KING));
From c0572b061a71c88a08fa12dc8b336add5f72ca78 Mon Sep 17 00:00:00 2001
From: Ivan Savenko
Date: Sun, 10 Dec 2023 19:17:24 +0200
Subject: [PATCH 25/29] Fix compile on FreeBSD
---
lib/modding/CModVersion.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/modding/CModVersion.h b/lib/modding/CModVersion.h
index e0ae7c8be..221decb88 100644
--- a/lib/modding/CModVersion.h
+++ b/lib/modding/CModVersion.h
@@ -10,7 +10,7 @@
#pragma once
-#ifdef __UCLIBC__
+#if defined(__UCLIBC__) || defined(__FreeBSD__)
#undef major
#undef minor
#undef patch
From 65721123a149205e774ade32bd67451a27e4213e Mon Sep 17 00:00:00 2001
From: Ivan Savenko
Date: Sun, 10 Dec 2023 19:17:58 +0200
Subject: [PATCH 26/29] Partial fix for Coronius specialty bug
---
lib/spells/CSpellHandler.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/spells/CSpellHandler.cpp b/lib/spells/CSpellHandler.cpp
index 1acb58c6b..aeceb6f7f 100644
--- a/lib/spells/CSpellHandler.cpp
+++ b/lib/spells/CSpellHandler.cpp
@@ -107,8 +107,8 @@ const CSpell::LevelInfo & CSpell::getLevelInfo(const int32_t level) const
{
if(level < 0 || level >= GameConstants::SPELL_SCHOOL_LEVELS)
{
- logGlobal->error("CSpell::getLevelInfo: invalid school level %d", level);
- return levels.at(0);
+ logGlobal->error("CSpell::getLevelInfo: invalid school mastery level %d", level);
+ return levels.at(MasteryLevel::EXPERT);
}
return levels.at(level);
From e23cddac8c9caa2a07537031a38ffa6a523c933d Mon Sep 17 00:00:00 2001
From: Ivan Savenko
Date: Sun, 10 Dec 2023 19:18:15 +0200
Subject: [PATCH 27/29] Fix AI movement
---
server/CGameHandler.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp
index 4d989108f..c46241587 100644
--- a/server/CGameHandler.cpp
+++ b/server/CGameHandler.cpp
@@ -1133,7 +1133,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
if (guardian && getVisitingHero(guardian) != nullptr)
return complainRet("Cannot move hero, destination monster is busy!");
- if (objectToVisit && getVisitingHero(objectToVisit) != nullptr)
+ if (objectToVisit && getVisitingHero(objectToVisit) != nullptr && getVisitingHero(objectToVisit) != h)
return complainRet("Cannot move hero, destination object is busy!");
if (objectToVisit &&
From b62e801530eab1d613ab082a05aafe983174ebcf Mon Sep 17 00:00:00 2001
From: Ivan Savenko
Date: Sun, 10 Dec 2023 19:48:27 +0200
Subject: [PATCH 28/29] Fix uninitialized variable in Seer Huts
---
lib/rewardable/Limiter.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lib/rewardable/Limiter.cpp b/lib/rewardable/Limiter.cpp
index e6fd3b361..f4a03edfd 100644
--- a/lib/rewardable/Limiter.cpp
+++ b/lib/rewardable/Limiter.cpp
@@ -30,6 +30,7 @@ Rewardable::Limiter::Limiter()
, heroLevel(-1)
, manaPercentage(0)
, manaPoints(0)
+ , canLearnSkills(false)
, primary(GameConstants::PRIMARY_SKILLS, 0)
{
}
@@ -45,6 +46,7 @@ bool operator==(const Rewardable::Limiter & l, const Rewardable::Limiter & r)
&& l.manaPoints == r.manaPoints
&& l.manaPercentage == r.manaPercentage
&& l.secondary == r.secondary
+ && l.canLearnSkills == r.canLearnSkills
&& l.creatures == r.creatures
&& l.spells == r.spells
&& l.artifacts == r.artifacts
From 7187ba2d7928ba8f065391b49997a9b36967ec47 Mon Sep 17 00:00:00 2001
From: Ivan Savenko
Date: Sun, 10 Dec 2023 19:48:44 +0200
Subject: [PATCH 29/29] Fix crash on visiting Seer Hut with no reward
---
lib/mapObjects/CRewardableObject.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/mapObjects/CRewardableObject.cpp b/lib/mapObjects/CRewardableObject.cpp
index c05fbd9aa..ce8399115 100644
--- a/lib/mapObjects/CRewardableObject.cpp
+++ b/lib/mapObjects/CRewardableObject.cpp
@@ -59,7 +59,7 @@ std::vector CRewardableObject::loadComponents(const CGHeroInstance *
if (rewardIndices.empty())
return result;
- if (configuration.selectMode != Rewardable::SELECT_FIRST)
+ if (configuration.selectMode != Rewardable::SELECT_FIRST && rewardIndices.size() > 1)
{
for (auto index : rewardIndices)
result.push_back(configuration.info.at(index).reward.getDisplayedComponent(contextHero));