2
0
Эх сурвалжийг харах

Merge pull request #5383 from IvanSavenko/bugfixing

[1.6.6] Fixes for issues in 1.6.5
Ivan Savenko 8 сар өмнө
parent
commit
c13edc8af3

+ 1 - 1
client/battle/BattleFieldController.cpp

@@ -533,7 +533,7 @@ void BattleFieldController::showHighlightedHexes(Canvas & canvas)
 	BattleHexArray hoveredMoveHexes  = getHighlightedHexesForMovementTarget();
 
 	BattleHex hoveredHex = getHoveredHex();
-	BattleHexArray hoveredMouseHex = hoveredHex.isValid() ? BattleHexArray({ hoveredHex }) : BattleHexArray();
+	BattleHexArray hoveredMouseHex = hoveredHex.isAvailable() ? BattleHexArray({ hoveredHex }) : BattleHexArray();
 
 	const CStack * hoveredStack = getHoveredStack();
 	if(!hoveredStack && hoveredHex == BattleHex::INVALID)

+ 1 - 1
client/battle/BattleInterfaceClasses.cpp

@@ -691,7 +691,7 @@ void StackInfoBasicPanel::initializeData(const CStack * stack)
 			if (spellBonuses->empty())
 				throw std::runtime_error("Failed to find effects for spell " + effect.toSpell()->getJsonKey());
 
-			int duration = spellBonuses->front()->duration;
+			int duration = spellBonuses->front()->turnsRemain;
 
 			icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("SpellInt"), effect + 1, 0, firstPos.x + offset.x * printed, firstPos.y + offset.y * printed));
 			if(settings["general"]["enableUiEnhancements"].Bool())

+ 10 - 0
client/globalLobby/GlobalLobbyWidget.cpp

@@ -28,6 +28,7 @@
 #include "../widgets/Images.h"
 #include "../widgets/MiscWidgets.h"
 #include "../widgets/ObjectLists.h"
+#include "../widgets/Slider.h"
 #include "../widgets/TextControls.h"
 
 #include "../../lib/CConfigHandler.h"
@@ -126,6 +127,15 @@ std::shared_ptr<CIntObject> GlobalLobbyWidget::buildItemList(const JsonNode & co
 
 	auto result = std::make_shared<CListBox>(callback, position, itemOffset, visibleAmount, totalAmount, initialPos, sliderMode, Rect(sliderPosition, sliderSize));
 
+	if (result->getSlider())
+	{
+		Point scrollBoundsDimensions(sliderPosition.x + result->getSlider()->pos.w, result->getSlider()->pos.h);
+		Point scrollBoundsOffset = -sliderPosition;
+
+		result->getSlider()->setScrollBounds(Rect(scrollBoundsOffset, scrollBoundsDimensions));
+		result->getSlider()->setPanningStep(itemOffset.length());
+	}
+
 	result->setRedrawParent(true);
 	return result;
 }

+ 1 - 1
client/render/AssetGenerator.cpp

@@ -247,7 +247,7 @@ AssetGenerator::CanvasPtr AssetGenerator::createCampaignBackground()
 
 AssetGenerator::CanvasPtr AssetGenerator::createChroniclesCampaignImages(int chronicle)
 {
-	auto imgPathBg = ImagePath::builtin("data/chronicles_" + std::to_string(chronicle) + "/GamSelBk");
+	auto imgPathBg = ImagePath::builtin("chronicles_" + std::to_string(chronicle) + "/GamSelBk");
 	auto locator = ImageLocator(imgPathBg, EImageBlitMode::OPAQUE);
 
 	std::shared_ptr<IImage> img = GH.renderHandler().loadImage(locator);

+ 5 - 0
client/render/CanvasImage.cpp

@@ -25,6 +25,11 @@ CanvasImage::CanvasImage(const Point & size, CanvasScalingPolicy scalingPolicy)
 {
 }
 
+CanvasImage::~CanvasImage()
+{
+	SDL_FreeSurface(surface);
+}
+
 void CanvasImage::draw(SDL_Surface * where, const Point & pos, const Rect * src, int scalingFactor) const
 {
 	if(src)

+ 1 - 0
client/render/CanvasImage.h

@@ -16,6 +16,7 @@ class CanvasImage : public IImage
 {
 public:
 	CanvasImage(const Point & size, CanvasScalingPolicy scalingPolicy);
+	~CanvasImage();
 
 	Canvas getCanvas();
 

+ 3 - 3
client/renderSDL/RenderHandler.cpp

@@ -379,7 +379,7 @@ void RenderHandler::addImageListEntries(const EntityService * service)
 			if (imageName.empty())
 				return;
 
-			auto & layout = getAnimationLayout(AnimationPath::builtin("SPRITES/" + listName), 1, EImageBlitMode::SIMPLE);
+			auto & layout = getAnimationLayout(AnimationPath::builtin("SPRITES/" + listName), 1, EImageBlitMode::COLORKEY);
 
 			JsonNode entry;
 			entry["file"].String() = imageName;
@@ -417,8 +417,8 @@ static void detectOverlappingBuildings(RenderHandler * renderHandler, const Fact
 			if (left->pos.z != right->pos.z)
 				continue; // buildings already have different z-index and have well-defined overlap logic
 
-			auto leftImage = renderHandler->loadImage(left->defName, 0, 0, EImageBlitMode::SIMPLE);
-			auto rightImage = renderHandler->loadImage(right->defName, 0, 0, EImageBlitMode::SIMPLE);
+			auto leftImage = renderHandler->loadImage(left->defName, 0, 0, EImageBlitMode::COLORKEY);
+			auto rightImage = renderHandler->loadImage(right->defName, 0, 0, EImageBlitMode::COLORKEY);
 
 			Rect leftRect( left->pos.x, left->pos.y, leftImage->width(), leftImage->height());
 			Rect rightRect( right->pos.x, right->pos.y, rightImage->width(), rightImage->height());

+ 5 - 0
client/widgets/ObjectLists.cpp

@@ -168,6 +168,11 @@ std::shared_ptr<CIntObject> CListBox::getItem(size_t which)
 	return std::shared_ptr<CIntObject>();
 }
 
+std::shared_ptr<CSlider> CListBox::getSlider()
+{
+	return slider;
+}
+
 size_t CListBox::getIndexOf(std::shared_ptr<CIntObject> item)
 {
 	size_t i=first;

+ 2 - 0
client/widgets/ObjectLists.h

@@ -91,6 +91,8 @@ public:
 	//return item with index which or null if not present
 	std::shared_ptr<CIntObject> getItem(size_t which);
 
+	std::shared_ptr<CSlider> getSlider();
+
 	//return currently active items
 	const std::list<std::shared_ptr<CIntObject>> & getItems();
 

+ 1 - 1
client/windows/CCreatureWindow.cpp

@@ -238,7 +238,7 @@ CStackWindow::ActiveSpellsSection::ActiveSpellsSection(CStackWindow * owner, int
 			if (spellBonuses->empty())
 				throw std::runtime_error("Failed to find effects for spell " + effect.toSpell()->getJsonKey());
 
-			int duration = spellBonuses->front()->duration;
+			int duration = spellBonuses->front()->turnsRemain;
 			boost::replace_first(spellText, "%d", std::to_string(duration));
 
 			spellIcons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("SpellInt"), effect + 1, 0, firstPos.x + offset.x * printed, firstPos.y + offset.y * printed));

+ 1 - 1
config/campaignSets.json

@@ -50,7 +50,7 @@
 	},
 	"chr":
 	{
-		"images" : [ {"x": 0, "y": 0, "name":"data/CampaignBackground8"} ],
+		"images" : [ {"x": 0, "y": 0, "name":"CampaignBackground8"} ],
 		"exitbutton" : {"x": 658, "y": 482, "name":"CMPSCAN" },
 		"items":
 		[

+ 115 - 0
config/mapOverrides.json

@@ -2370,5 +2370,120 @@
 		},
 		"victoryIconIndex" : 11,
 		"victoryString" : "core.vcdesc.0"
+	},
+	
+	"data/gelu:1" : { // Cutthroats
+		"defeatIconIndex" : 1,
+		"defeatString" : "core.lcdesc.2",
+		"triggeredEvents" : {
+			"heroesMustSurvive" : {
+				"condition" : [
+					"allOf",
+					[ "isHuman", { "value" : 1 } ],
+					[ "noneOf",
+						[ "control", { "position" : [ 11, 8, 0 ], "type" : "hero" } ] // Gelu
+					]
+				],
+				"effect" : {
+					"messageToSend" : "core.genrltxt.5",
+					"type" : "defeat"
+				},
+				"message" : "core.genrltxt.253"
+			},
+			"specialVictory" : {
+				"condition" : [ "haveArtifact", { "type" : "artifact.ringOfVitality" } ],
+				"effect" : {
+					"messageToSend" : "core.genrltxt.281",
+					"type" : "victory"
+				},
+				"message" : "core.genrltxt.280"
+			},
+			"standardDefeat" : {
+				"condition" : [ "daysWithoutTown", { "value" : 7 } ],
+				"effect" : {
+					"messageToSend" : "core.genrltxt.8",
+					"type" : "defeat"
+				},
+				"message" : "core.genrltxt.7"
+			}
+		},
+		"victoryIconIndex" : 0,
+		"victoryString" : "core.vcdesc.1"
+	},
+	"data/gelu:2" : { // Valley of the Dragon Lords
+		"defeatIconIndex" : 1,
+		"defeatString" : "core.lcdesc.2",
+		"triggeredEvents" : {
+			"heroesMustSurvive" : {
+				"condition" : [
+					"allOf",
+					[ "isHuman", { "value" : 1 } ],
+					[ "noneOf",
+						[ "control", { "position" : [ 62, 12, 0 ], "type" : "hero" } ] // Gelu
+					]
+				],
+				"effect" : {
+					"messageToSend" : "core.genrltxt.5",
+					"type" : "defeat"
+				},
+				"message" : "core.genrltxt.253"
+			},
+			"specialVictory" : {
+				"condition" : [ "haveArtifact", { "type" : "artifact.ringOfLife" } ],
+				"effect" : {
+					"messageToSend" : "core.genrltxt.281",
+					"type" : "victory"
+				},
+				"message" : "core.genrltxt.280"
+			},
+			"standardDefeat" : {
+				"condition" : [ "daysWithoutTown", { "value" : 7 } ],
+				"effect" : {
+					"messageToSend" : "core.genrltxt.8",
+					"type" : "defeat"
+				},
+				"message" : "core.genrltxt.7"
+			}
+		},
+		"victoryIconIndex" : 0,
+		"victoryString" : "core.vcdesc.1"
+	},
+	"data/gelu:3" : { // A Thief in the Night
+		"defeatIconIndex" : 1,
+		"defeatString" : "core.lcdesc.2",
+		"triggeredEvents" : {
+			"heroesMustSurvive" : {
+				"condition" : [
+					"allOf",
+					[ "isHuman", { "value" : 1 } ],
+					[ "noneOf",
+						[ "control", { "position" : [ 50, 9, 0 ], "type" : "hero" } ] // Gelu
+					]
+				],
+				"effect" : {
+					"messageToSend" : "core.genrltxt.5",
+					"type" : "defeat"
+				},
+				"message" : "core.genrltxt.253"
+			},
+			"specialVictory" : {
+				"condition" : [ "haveArtifact", { "type" : "artifact.vialOfLifeblood" } ],
+				"effect" : {
+					"messageToSend" : "core.genrltxt.281",
+					"type" : "victory"
+				},
+				"message" : "core.genrltxt.280"
+			},
+			"standardDefeat" : {
+				"condition" : [ "daysWithoutTown", { "value" : 7 } ],
+				"effect" : {
+					"messageToSend" : "core.genrltxt.8",
+					"type" : "defeat"
+				},
+				"message" : "core.genrltxt.7"
+			}
+		},
+		"victoryIconIndex" : 0,
+		"victoryString" : "core.vcdesc.1"
 	}
 }

+ 2 - 0
lib/bonuses/CBonusSystemNode.cpp

@@ -188,6 +188,7 @@ std::shared_ptr<Bonus> CBonusSystemNode::getUpdatedBonus(const std::shared_ptr<B
 CBonusSystemNode::CBonusSystemNode(bool isHypotetic):
 	nodeType(UNKNOWN),
 	cachedLast(0),
+	nodeChanged(0),
 	isHypotheticNode(isHypotetic)
 {
 }
@@ -195,6 +196,7 @@ CBonusSystemNode::CBonusSystemNode(bool isHypotetic):
 CBonusSystemNode::CBonusSystemNode(ENodeTypes NodeType):
 	nodeType(NodeType),
 	cachedLast(0),
+	nodeChanged(0),
 	isHypotheticNode(false)
 {
 }

+ 0 - 5
lib/filesystem/Filesystem.cpp

@@ -183,14 +183,9 @@ void CResourceHandler::initialize()
 	knownLoaders["saves"] = new CFilesystemLoader("SAVES/", VCMIDirs::get().userSavePath());
 	knownLoaders["config"] = new CFilesystemLoader("CONFIG/", VCMIDirs::get().userConfigPath());
 
-	knownLoaders["gen_data"] = new CFilesystemLoader("DATA/", VCMIDirs::get().userDataPath() / "Generated" / "Data");
-	knownLoaders["gen_sprites"] = new CFilesystemLoader("SPRITES/", VCMIDirs::get().userDataPath() / "Generated" / "Sprites");
-
 	auto * localFS = new CFilesystemList();
 	localFS->addLoader(knownLoaders["saves"], true);
 	localFS->addLoader(knownLoaders["config"], true);
-	localFS->addLoader(knownLoaders["gen_data"], true);
-	localFS->addLoader(knownLoaders["gen_sprites"], true);
 
 	addFilesystem("root", "initial", createInitial());
 	addFilesystem("root", "data", new CFilesystemList());

+ 11 - 2
lib/mapping/CMapHeader.cpp

@@ -117,8 +117,17 @@ void CMapHeader::setupEvents()
 	defeatMessage.appendTextID("core.lcdesc.0");
 }
 
-CMapHeader::CMapHeader() : version(EMapFormat::VCMI), height(72), width(72),
-	twoLevel(true), difficulty(EMapDifficulty::NORMAL), levelLimit(0), howManyTeams(0), areAnyPlayers(false)
+CMapHeader::CMapHeader()
+	: version(EMapFormat::VCMI)
+	, height(72)
+	, width(72)
+	, twoLevel(true)
+	, difficulty(EMapDifficulty::NORMAL)
+	, levelLimit(0)
+	, howManyTeams(0)
+	, areAnyPlayers(false)
+	, victoryIconIndex(0)
+	, defeatIconIndex(0)
 {
 	setupEvents();
 	allowedHeroes = VLC->heroh->getDefaultAllowed();

+ 7 - 5
lib/network/NetworkConnection.cpp

@@ -216,22 +216,25 @@ InternalConnection::InternalConnection(INetworkConnectionListener & listener, co
 
 void InternalConnection::receivePacket(const std::vector<std::byte> & message)
 {
-	io->post([self = shared_from_this(), message](){
-		self->listener.onPacketReceived(self, message);
+	io->post([self = std::static_pointer_cast<InternalConnection>(shared_from_this()), message](){
+		if (self->connectionActive)
+			self->listener.onPacketReceived(self, message);
 	});
 }
 
 void InternalConnection::disconnect()
 {
-	io->post([self = shared_from_this()](){
+	io->post([self = std::static_pointer_cast<InternalConnection>(shared_from_this())](){
 		self->listener.onDisconnected(self, "Internal connection has been terminated");
 		self->otherSideWeak.reset();
+		self->connectionActive = false;
 	});
 }
 
 void InternalConnection::connectTo(std::shared_ptr<IInternalConnection> connection)
 {
 	otherSideWeak = connection;
+	connectionActive = true;
 }
 
 void InternalConnection::sendPacket(const std::vector<std::byte> & message)
@@ -240,8 +243,6 @@ void InternalConnection::sendPacket(const std::vector<std::byte> & message)
 
 	if (otherSide)
 		otherSide->receivePacket(message);
-	else
-		throw std::runtime_error("Failed to send packet! Connection has been deleted!");
 }
 
 void InternalConnection::setAsyncWritesEnabled(bool on)
@@ -257,6 +258,7 @@ void InternalConnection::close()
 		otherSide->disconnect();
 
 	otherSideWeak.reset();
+	connectionActive = false;
 }
 
 VCMI_LIB_NAMESPACE_END

+ 1 - 0
lib/network/NetworkConnection.h

@@ -51,6 +51,7 @@ class InternalConnection final : public IInternalConnection, public std::enable_
 	std::weak_ptr<IInternalConnection> otherSideWeak;
 	std::shared_ptr<NetworkContext> io;
 	INetworkConnectionListener & listener;
+	bool connectionActive = false;
 public:
 	InternalConnection(INetworkConnectionListener & listener, const std::shared_ptr<NetworkContext> & context);
 

+ 13 - 5
lib/pathfinder/PathfinderUtil.h

@@ -40,15 +40,23 @@ namespace PathfinderUtil
 				}
 				else
 				{
+					bool hasBlockedVisitable = false;
+					bool hasVisitable = false;
+
 					for(const CGObjectInstance * obj : tinfo.visitableObjects)
 					{
 						if(obj->isBlockedVisitable())
-							return EPathAccessibility::BLOCKVIS;
-						else if(obj->passableFor(player))
-							return EPathAccessibility::ACCESSIBLE;
-						else if(obj->ID != Obj::EVENT)
-							return EPathAccessibility::VISITABLE;
+							hasBlockedVisitable = true;
+						else if(!obj->passableFor(player) && obj->ID != Obj::EVENT)
+							hasVisitable = true;
 					}
+
+					if(hasBlockedVisitable)
+						return EPathAccessibility::BLOCKVIS;
+					if(hasVisitable)
+						return EPathAccessibility::VISITABLE;
+
+					return EPathAccessibility::ACCESSIBLE;
 				}
 			}
 			else if(tinfo.blocked())

+ 2 - 1
lib/serializer/Connection.cpp

@@ -102,7 +102,8 @@ std::unique_ptr<CPack> CConnection::retrievePack(const std::vector<std::byte> &
 	if (packReader->position != data.size())
 		throw std::runtime_error("Failed to retrieve pack! Not all data has been read!");
 
-	logNetwork->trace("Received CPack of type %s", typeid(result.get()).name());
+	auto packRawPtr = result.get();
+	logNetwork->trace("Received CPack of type %s", typeid(*packRawPtr).name());
 	deserializer->loadedPointers.clear();
 	deserializer->loadedSharedPointers.clear();
 	return result;

+ 2 - 1
server/processors/TurnOrderProcessor.cpp

@@ -249,6 +249,8 @@ void TurnOrderProcessor::doStartNewDay()
 	assert(awaitingPlayers.empty());
 	assert(actingPlayers.empty());
 
+	gameHandler->onNewTurn();
+
 	bool activePlayer = false;
 	for (auto player : actedPlayers)
 	{
@@ -264,7 +266,6 @@ void TurnOrderProcessor::doStartNewDay()
 
 	std::swap(actedPlayers, awaitingPlayers);
 
-	gameHandler->onNewTurn();
 	updateAndNotifyContactStatus();
 	tryStartTurnsForPlayers();
 }