Przeglądaj źródła

Merge pull request #4655 from IvanSavenko/bugfixing

Bugfixing
Ivan Savenko 1 rok temu
rodzic
commit
92c5fd4156

+ 3 - 2
AI/BattleAI/AttackPossibility.cpp

@@ -45,11 +45,12 @@ void DamageCache::buildObstacleDamageCache(std::shared_ptr<HypotheticBattle> hb,
 			continue;
 
 		std::unique_ptr<spells::BattleCast> cast = nullptr;
+		std::unique_ptr<spells::ObstacleCasterProxy> caster = nullptr;
 		if(spellObstacle->obstacleType == SpellCreatedObstacle::EObstacleType::SPELL_CREATED)
 		{
 			const auto * hero = hb->battleGetFightingHero(spellObstacle->casterSide);
-			auto caster = spells::ObstacleCasterProxy(hb->getSidePlayer(spellObstacle->casterSide), hero, *spellObstacle);
-			cast = std::make_unique<spells::BattleCast>(spells::BattleCast(hb.get(), &caster, spells::Mode::PASSIVE, obst->getTrigger().toSpell()));
+			caster = std::make_unique<spells::ObstacleCasterProxy>(hb->getSidePlayer(spellObstacle->casterSide), hero, *spellObstacle);
+			cast = std::make_unique<spells::BattleCast>(spells::BattleCast(hb.get(), caster.get(), spells::Mode::PASSIVE, obst->getTrigger().toSpell()));
 		}
 
 		auto affectedHexes = obst->getAffectedTiles();

+ 3 - 1
client/eventsSDL/InputSourceMouse.cpp

@@ -72,7 +72,9 @@ void InputSourceMouse::handleEventMouseButtonDown(const SDL_MouseButtonEvent & b
 
 void InputSourceMouse::handleEventMouseWheel(const SDL_MouseWheelEvent & wheel)
 {
-#if SDL_VERSION_ATLEAST(2,26,0)
+	//NOTE: while mouseX / mouseY properties are available since 2.26.0, they are not converted into logical coordinates so don't account for resolution scaling
+	// This SDL bug was fixed in 2.30.1: https://github.com/libsdl-org/SDL/issues/9097
+#if SDL_VERSION_ATLEAST(2,30,1)
 	GH.events().dispatchMouseScrolled(Point(wheel.x, wheel.y), Point(wheel.mouseX, wheel.mouseY) / GH.screenHandler().getScalingFactor());
 #else
 	GH.events().dispatchMouseScrolled(Point(wheel.x, wheel.y), GH.getCursorPosition());

+ 5 - 10
client/windows/CMessage.cpp

@@ -83,7 +83,7 @@ std::vector<std::string> CMessage::breakText(std::string text, size_t maxLineWid
 		std::string printableString;
 
 		// loops till line is full or end of text reached
-		while(currPos < text.length() && text[currPos] != 0x0a)
+		while(currPos < text.length() && text[currPos] != 0x0a && graphics->fonts[font]->getStringWidth(printableString) <= maxLineWidth)
 		{
 			symbolSize = TextOperations::getUnicodeCharacterSize(text[currPos]);
 
@@ -115,18 +115,13 @@ std::vector<std::string> CMessage::breakText(std::string text, size_t maxLineWid
 				color = "";
 			}
 			else
-			{
-				std::string newPrintableString = printableString;
-				newPrintableString.append(text.data() + currPos, symbolSize);
-				if (graphics->fonts[font]->getStringWidth(newPrintableString) < maxLineWidth)
-					printableString.append(text.data() + currPos, symbolSize);
-				else
-					break;
-			}
+				printableString.append(text.data() + currPos, symbolSize);
+
 			currPos += symbolSize;
 		}
 
-		// long line, create line break
+		// not all line has been processed - it turned out to be too long, so erase everything after last word break
+		// if string consists from a single word (or this is Chinese/Korean) - erase only last symbol to bring line back to allowed length
 		if(currPos < text.length() && (text[currPos] != 0x0a))
 		{
 			if(wordBreak != ui32(-1))

+ 9 - 3
lib/gameState/CGameStateCampaign.cpp

@@ -139,10 +139,14 @@ void CGameStateCampaign::trimCrossoverHeroesParameters(const CampaignTravel & tr
 				bool locked = hero.hero->getSlot(al.slot)->locked;
 
 				if (!locked && takeable)
+				{
+					logGlobal->debug("Artifact %s from slot %d of hero %s will be transferred to next scenario", art->artType->getJsonKey(), al.slot.getNum(), hero.hero->getHeroTypeName());
 					hero.transferrableArtifacts.push_back(artifactPosition);
+				}
 
 				if (!locked && !takeable)
 				{
+					logGlobal->debug("Removing artifact %s from slot %d of hero %s", art->artType->getJsonKey(), al.slot.getNum(), hero.hero->getHeroTypeName());
 					hero.hero->getArt(al.slot)->removeFrom(*hero.hero, al.slot);
 					return true;
 				}
@@ -413,16 +417,18 @@ void CGameStateCampaign::transferMissingArtifacts(const CampaignTravel & travelO
 		if (!donorHero)
 			throw std::runtime_error("Failed to find hero to take artifacts from! Scenario: " + gameState->map->name.toString());
 
-		for (auto const & artLocation : campaignHeroReplacement.transferrableArtifacts)
+		// process in reverse - 2nd artifact from a backpack must be processed before 1st one to avoid invalidation of artifact positions
+		for (auto const & artLocation : boost::adaptors::reverse(campaignHeroReplacement.transferrableArtifacts))
 		{
 			auto * artifact = donorHero->getArt(artLocation);
-			if (!donorHero)
-				throw std::runtime_error("Failed to find artifacts to transfer to travelling hero! Scenario: " + gameState->map->name.toString());
 
+			logGlobal->debug("Removing artifact %s from slot %d of hero %s for transfer", artifact->artType->getJsonKey(), artLocation.getNum(), donorHero->getHeroTypeName());
 			artifact->removeFrom(*donorHero, artLocation);
 
 			if (receiver)
 			{
+				logGlobal->debug("Granting artifact %s to hero %s for transfer", artifact->artType->getJsonKey(), receiver->getHeroTypeName());
+
 				const auto slot = ArtifactUtils::getArtAnyPosition(receiver, artifact->getTypeId());
 				if(ArtifactUtils::isSlotEquipment(slot) || ArtifactUtils::isSlotBackpack(slot))
 					artifact->putAt(*receiver, slot);

+ 1 - 0
lib/rewardable/Info.cpp

@@ -105,6 +105,7 @@ void Rewardable::Info::init(const JsonNode & objectConfig, const std::string & o
 	loadString(parameters["visitedTooltip"], TextIdentifier(objectName, "visitedTooltip"));
 	loadString(parameters["onVisitedMessage"], TextIdentifier(objectName, "onVisited"));
 	loadString(parameters["onEmptyMessage"], TextIdentifier(objectName, "onEmpty"));
+	loadString(parameters["onGuardedMessage"], TextIdentifier(objectName, "onGuarded"));
 }
 
 Rewardable::LimitersList Rewardable::Info::configureSublimiters(Rewardable::Configuration & object, vstd::RNG & rng, IGameCallback * cb, const JsonNode & source) const

+ 2 - 0
server/queries/VisitQueries.cpp

@@ -68,6 +68,8 @@ TownBuildingVisitQuery::TownBuildingVisitQuery(CGameHandler * owner, const CGTow
 
 void TownBuildingVisitQuery::onExposure(QueryPtr topQuery)
 {
+	topQuery->notifyObjectAboutRemoval(visitedObject, visitingHero);
+
 	onAdded(players.front());
 }