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

Merge pull request #4095 from vcmi/master

Merge master -> beta
Ivan Savenko 1 жил өмнө
parent
commit
861ed7667d

+ 1 - 1
android/vcmi-app/build.gradle

@@ -10,7 +10,7 @@ android {
 		applicationId "is.xyz.vcmi"
 		minSdk 19
 		targetSdk 33
-		versionCode 1520
+		versionCode 1521
 		versionName "1.5.2"
 		setProperty("archivesBaseName", "vcmi")
 	}

+ 1 - 1
client/CPlayerInterface.cpp

@@ -244,7 +244,7 @@ void CPlayerInterface::performAutosave()
 				int txtlen = TextOperations::getUnicodeCharactersCount(name);
 
 				TextOperations::trimRightUnicode(name, std::max(0, txtlen - 15));
-				std::string forbiddenChars("\\/:?\"<>| ");
+				std::string forbiddenChars("\\/:*?\"<>| ");
 				std::replace_if(name.begin(), name.end(), [&](char c) { return std::string::npos != forbiddenChars.find(c); }, '_' );
 
 				prefix = name + "_" + cb->getStartInfo()->startTimeIso8601 + "/";

+ 4 - 0
client/adventureMap/AdventureMapInterface.cpp

@@ -643,11 +643,15 @@ void AdventureMapInterface::onTileHovered(const int3 &targetPosition)
 		objRelations = LOCPLINT->cb->getPlayerRelations(LOCPLINT->playerID, objAtTile->tempOwner);
 		std::string text = LOCPLINT->localState->getCurrentHero() ? objAtTile->getHoverText(LOCPLINT->localState->getCurrentHero()) : objAtTile->getHoverText(LOCPLINT->playerID);
 		boost::replace_all(text,"\n"," ");
+		if (GH.isKeyboardShiftDown())
+			text.append(" (" + std::to_string(targetPosition.x) + ", " + std::to_string(targetPosition.y) + ")");
 		GH.statusbar()->write(text);
 	}
 	else if(isTargetPositionVisible)
 	{
 		std::string tileTooltipText = CGI->mh->getTerrainDescr(targetPosition, false);
+		if (GH.isKeyboardShiftDown())
+			tileTooltipText.append(" (" + std::to_string(targetPosition.x) + ", " + std::to_string(targetPosition.y) + ")");
 		GH.statusbar()->write(tileTooltipText);
 	}
 

+ 8 - 16
client/widgets/CGarrisonInt.cpp

@@ -542,42 +542,34 @@ void CGarrisonInt::addSplitBtn(std::shared_ptr<CButton> button)
 
 void CGarrisonInt::createSlots()
 {
+	availableSlots.clear();
+
 	int distance = interx + (smallIcons ? 32 : 58);
 	for(auto i : { EGarrisonType::UPPER, EGarrisonType::LOWER })
 	{
 		Point offset = garOffset * static_cast<int>(i);
-
-		std::vector<std::shared_ptr<CGarrisonSlot>> garrisonSlots;
-		garrisonSlots.resize(7);
-		if(army(i))
-		{
-			for(auto & elem : army(i)->Slots())
-			{
-				garrisonSlots[elem.first.getNum()] = std::make_shared<CGarrisonSlot>(this, offset.x + (elem.first.getNum()*distance), offset.y, elem.first, i, elem.second);
-			}
-		}
 		for(int j = 0; j < 7; j++)
 		{
-			if(!garrisonSlots[j])
-				garrisonSlots[j] = std::make_shared<CGarrisonSlot>(this, offset.x + (j*distance), offset.y, SlotID(j), i, nullptr);
+			Point position(offset.x + (j*distance), offset.y);
 
 			if(layout == ESlotsLayout::TWO_ROWS && j >= 4)
 			{
-				garrisonSlots[j]->moveBy(Point(-126, 37));
+				position += Point(-126, 37);
 			}
 			else if(layout == ESlotsLayout::REVERSED_TWO_ROWS)
 			{
 				if(j >= 3)
 				{
-					garrisonSlots[j]->moveBy(Point(-90, 49));
+					position += Point(-90, 49);
 				}
 				else
 				{
-					garrisonSlots[j]->moveBy(Point(36, 0));
+					position += Point(36, 0);
 				}
 			}
+			SlotID slot(j);
+			availableSlots.push_back(std::make_shared<CGarrisonSlot>(this, position.x, position.y, slot, i, army(i) ? army(i)->getStackPtr(slot) : nullptr));
 		}
-		vstd::concatenate(availableSlots, garrisonSlots);
 	}
 }
 

+ 3 - 2
client/windows/GUIClasses.cpp

@@ -434,14 +434,15 @@ CLevelWindow::CLevelWindow(const CGHeroInstance * hero, PrimarySkill pskill, std
 	skillValue = std::make_shared<CLabel>(192, 253, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->primarySkillNames[static_cast<int>(pskill)] + " +1");
 }
 
-
-CLevelWindow::~CLevelWindow()
+void CLevelWindow::close()
 {
 	//FIXME: call callback if there was nothing to select?
 	if (box && box->selectedIndex() != -1)
 		cb(box->selectedIndex());
 
 	LOCPLINT->showingDialog->setFree();
+
+	CWindowObject::close();
 }
 
 CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj, const std::function<void()> & onWindowClosed)

+ 2 - 1
client/windows/GUIClasses.h

@@ -150,7 +150,8 @@ class CLevelWindow : public CWindowObject
 
 public:
 	CLevelWindow(const CGHeroInstance *hero, PrimarySkill pskill, std::vector<SecondarySkill> &skills, std::function<void(ui32)> callback);
-	~CLevelWindow();
+
+	void close() override;
 };
 
 /// Town portal, castle gate window

+ 5 - 1
server/CGameHandler.cpp

@@ -1104,7 +1104,11 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
 		objectToVisit = t.visitableObjects.back();
 
 	if (isInTheMap(guardPos))
-		guardian = getTile(guardPos)->visitableObjects.back();
+	{
+		for (auto const & object : getTile(guardPos)->visitableObjects)
+			if (object->ID == MapObjectID::MONSTER) // exclude other objects, such as hero flying above monster
+				guardian = object;
+	}
 
 	const bool embarking = !h->boat && objectToVisit && objectToVisit->ID == Obj::BOAT;
 	const bool disembarking = h->boat

+ 7 - 1
server/CVCMIServer.cpp

@@ -165,6 +165,9 @@ void CVCMIServer::onNewConnection(const std::shared_ptr<INetworkConnection> & co
 void CVCMIServer::onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<std::byte> & message)
 {
 	std::shared_ptr<CConnection> c = findConnection(connection);
+	if (c == nullptr)
+		throw std::out_of_range("Unknown connection received in CVCMIServer::findConnection");
+
 	auto pack = c->retrievePack(message);
 	pack->c = c;
 	CVCMIServerPackVisitor visitor(*this, this->gh);
@@ -197,7 +200,7 @@ std::shared_ptr<CConnection> CVCMIServer::findConnection(const std::shared_ptr<I
 			return gameConnection;
 	}
 
-	throw std::runtime_error("Unknown connection received in CVCMIServer::findConnection");
+	return nullptr;
 }
 
 bool CVCMIServer::wasStartedByClient() const
@@ -342,6 +345,9 @@ void CVCMIServer::onDisconnected(const std::shared_ptr<INetworkConnection> & con
 	logNetwork->error("Network error receiving a pack. Connection has been closed");
 
 	std::shared_ptr<CConnection> c = findConnection(connection);
+	if (!c)
+		return; // player have already disconnected via clientDisconnected call
+
 	vstd::erase(activeConnections, c);
 
 	if(activeConnections.empty() || hostClientId == c->connectionID)