Răsfoiți Sursa

Merge pull request #4247 from IvanSavenko/release_154

Preparations for release 1.5.4
Ivan Savenko 1 an în urmă
părinte
comite
006fadb82c

+ 3 - 0
AI/BattleAI/BattleEvaluator.cpp

@@ -623,6 +623,9 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
 
 				for(const auto & unit : allUnits)
 				{
+					if (!unit->isValidTarget())
+						continue;
+					
 					auto newHealth = unit->getAvailableHealth();
 					auto oldHealth = vstd::find_or(healthOfStack, unit->unitId(), 0); // old health value may not exist for newly summoned units
 

+ 3 - 2
ChangeLog.md

@@ -24,8 +24,9 @@
 
 ### AI
 * Improved performance of Nullkiller AI
-* AI no longer overestimates damage when killing entire unit
-* Fixed an unsigned integer overflow that caused the AI to overestimate the total army strength after merging two armies.
+* Stupid AI no longer overestimates damage when killing entire unit
+* Fixed a bug leading to Battle AI not using spells when sieging town with Citadel or Castle built
+* Fixed an unsigned integer overflow that caused the Nullkiller AI to overestimate the total army strength after merging two armies.
 
 ### Launcher
 * Added button to reset touchscreen tutorial on mobile systems

+ 8 - 1
client/widgets/MiscWidgets.cpp

@@ -15,6 +15,7 @@
 #include "../gui/CGuiHandler.h"
 #include "../gui/CursorHandler.h"
 
+#include "../CMT.h"
 #include "../CPlayerInterface.h"
 #include "../CGameInfo.h"
 #include "../PlayerLocalState.h"
@@ -638,7 +639,13 @@ CCreaturePic::CCreaturePic(int x, int y, const CCreature * cre, bool Big, bool A
 	assert(CGI->townh->size() > faction);
 
 	if (cre->animDefName.empty())
-		throw std::runtime_error("Creature " + cre->getJsonKey() + " has no valid combat animation!");
+	{
+		GH.dispatchMainThread([cre]()
+		{
+			handleFatalError("Creature " + cre->getJsonKey() + " has no valid combat animation!", false);
+		});
+		return;
+	}
 
 	if(Big)
 		bg = std::make_shared<CPicture>((*CGI->townh)[faction]->creatureBg130);

+ 1 - 2
docs/Readme.md

@@ -1,8 +1,7 @@
 [![VCMI](https://github.com/vcmi/vcmi/actions/workflows/github.yml/badge.svg?branch=develop&event=push)](https://github.com/vcmi/vcmi/actions/workflows/github.yml?query=branch%3Adevelop+event%3Apush)
 [![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/1.5.0/total)](https://github.com/vcmi/vcmi/releases/tag/1.5.0)
-[![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/1.5.1/total)](https://github.com/vcmi/vcmi/releases/tag/1.5.1)
-[![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/1.5.2/total)](https://github.com/vcmi/vcmi/releases/tag/1.5.2)
 [![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/1.5.3/total)](https://github.com/vcmi/vcmi/releases/tag/1.5.3)
+[![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/1.5.4/total)](https://github.com/vcmi/vcmi/releases/tag/1.5.4)
 [![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/total)](https://github.com/vcmi/vcmi/releases)
 
 # VCMI Project

+ 9 - 8
launcher/translation/ukrainian.ts

@@ -461,7 +461,7 @@
     <message>
         <location filename="../modManager/cmodlistview_moc.cpp" line="701"/>
         <source>Downloading %1. %p% (%v MB out of %m MB) finished</source>
-        <translation type="unfinished"></translation>
+        <translation>Завантажується %1. %p% (%v MB з %m MB) завершено</translation>
     </message>
     <message>
         <source>Downloading %s%. %p% (%v MB out of %m MB) finished</source>
@@ -733,12 +733,12 @@ Install successfully downloaded?</source>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="1152"/>
         <source>Show Tutorial again</source>
-        <translation type="unfinished"></translation>
+        <translation>Повторно показати навчання</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="1159"/>
         <source>Reset</source>
-        <translation type="unfinished"></translation>
+        <translation>Скинути</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="860"/>
@@ -1268,7 +1268,7 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b
     <message>
         <location filename="../firstLaunch/firstlaunch_moc.cpp" line="330"/>
         <source>File cannot opened</source>
-        <translation type="unfinished"></translation>
+        <translation>Не вдається відкрити файл</translation>
     </message>
     <message>
         <location filename="../firstLaunch/firstlaunch_moc.cpp" line="336"/>
@@ -1317,23 +1317,24 @@ Please select directory with installed Heroes III data.</source>
     <message>
         <location filename="../firstLaunch/firstlaunch_moc.cpp" line="387"/>
         <source>You&apos;ve provided GOG Galaxy installer! This file doesn&apos;t contain the game. Please download the offline backup game installer!</source>
-        <translation type="unfinished"></translation>
+        <translation>Ви надали інсталятор GOG Galaxy! Цей файл не містить гри. Будь ласка, завантажте резервну копію інсталятора гри!</translation>
     </message>
     <message>
         <location filename="../firstLaunch/firstlaunch_moc.cpp" line="412"/>
         <source>Stream error while extracting files!
 error reason: </source>
-        <translation type="unfinished"></translation>
+        <translation>Помилка потоку під час розпакування файлів!
+причина помилки: </translation>
     </message>
     <message>
         <location filename="../firstLaunch/firstlaunch_moc.cpp" line="425"/>
         <source>Not a supported Inno Setup installer!</source>
-        <translation type="unfinished"></translation>
+        <translation>Не підтримуваний інсталятор Inno Setup!</translation>
     </message>
     <message>
         <location filename="../firstLaunch/firstlaunch_moc.cpp" line="436"/>
         <source>Extracting error!</source>
-        <translation type="unfinished"></translation>
+        <translation>Помилка видобування!</translation>
     </message>
     <message>
         <location filename="../firstLaunch/firstlaunch_moc.cpp" line="506"/>

+ 3 - 1
lib/gameState/CGameState.cpp

@@ -44,6 +44,7 @@
 #include "../mapping/CMapEditManager.h"
 #include "../mapping/CMapService.h"
 #include "../modding/IdentifierStorage.h"
+#include "../modding/ModScope.h"
 #include "../pathfinder/CPathfinder.h"
 #include "../pathfinder/PathfinderOptions.h"
 #include "../registerTypes/RegisterTypesClientPacks.h"
@@ -413,7 +414,8 @@ void CGameState::initGlobalBonuses()
 void CGameState::initDifficulty()
 {
 	logGlobal->debug("\tLoading difficulty settings");
-	const JsonNode config = JsonUtils::assembleFromFiles("config/difficulty.json");
+	JsonNode config = JsonUtils::assembleFromFiles("config/difficulty.json");
+	config.setModScope(ModScope::scopeGame()); // FIXME: should be set to actual mod
 	
 	const JsonNode & difficultyAI(config["ai"][GameConstants::DIFFICULTY_NAMES[scenarioOps->difficulty]]);
 	const JsonNode & difficultyHuman(config["human"][GameConstants::DIFFICULTY_NAMES[scenarioOps->difficulty]]);

+ 6 - 1
lib/mapObjects/CRewardableObject.cpp

@@ -348,7 +348,12 @@ std::vector<Component> CRewardableObject::getPopupComponentsImpl(PlayerColor pla
 
 	auto rewardIndices = getAvailableRewards(hero, Rewardable::EEventType::EVENT_FIRST_VISIT);
 	if (rewardIndices.empty() && !configuration.info.empty())
-		rewardIndices.push_back(0);
+	{
+		// Object has valid config, but current hero has no rewards that he can receive.
+		// Usually this happens if hero has already visited this object -> show reward using context without any hero
+		// since reward may be context-sensitive - e.g. Witch Hut that gives 1 skill, but always at basic level
+		return loadComponents(nullptr, {0});
+	}
 
 	if (rewardIndices.empty())
 		return {};

+ 1 - 1
lib/rewardable/Reward.cpp

@@ -106,7 +106,7 @@ void Rewardable::Reward::loadComponents(std::vector<Component> & comps, const CG
 	{
 		auto skillID = entry.first;
 		int levelsGained = entry.second;
-		int currentLevel = h->getSecSkillLevel(skillID);
+		int currentLevel = h ? h->getSecSkillLevel(skillID) : 0;
 		int finalLevel = std::min(static_cast<int>(MasteryLevel::EXPERT), currentLevel + levelsGained);
 		comps.emplace_back(ComponentType::SEC_SKILL, entry.first, finalLevel);
 	}