diff --git a/android/vcmi-app/build.gradle b/android/vcmi-app/build.gradle index bbee1bd48..833805888 100644 --- a/android/vcmi-app/build.gradle +++ b/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") } diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 3cd1cc8f0..a1e192649 100644 --- a/client/CPlayerInterface.cpp +++ b/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 + "/"; diff --git a/client/adventureMap/AdventureMapInterface.cpp b/client/adventureMap/AdventureMapInterface.cpp index 981b3da7c..145d84bf0 100644 --- a/client/adventureMap/AdventureMapInterface.cpp +++ b/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); } diff --git a/client/widgets/CGarrisonInt.cpp b/client/widgets/CGarrisonInt.cpp index 1cbf9e4fa..6acf43b61 100644 --- a/client/widgets/CGarrisonInt.cpp +++ b/client/widgets/CGarrisonInt.cpp @@ -542,42 +542,34 @@ void CGarrisonInt::addSplitBtn(std::shared_ptr button) void CGarrisonInt::createSlots() { + availableSlots.clear(); + int distance = interx + (smallIcons ? 32 : 58); for(auto i : { EGarrisonType::UPPER, EGarrisonType::LOWER }) { Point offset = garOffset * static_cast(i); - - std::vector> garrisonSlots; - garrisonSlots.resize(7); - if(army(i)) - { - for(auto & elem : army(i)->Slots()) - { - garrisonSlots[elem.first.getNum()] = std::make_shared(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(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(this, position.x, position.y, slot, i, army(i) ? army(i)->getStackPtr(slot) : nullptr)); } - vstd::concatenate(availableSlots, garrisonSlots); } } diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index b3d72c7d0..60b4caef7 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -434,14 +434,15 @@ CLevelWindow::CLevelWindow(const CGHeroInstance * hero, PrimarySkill pskill, std skillValue = std::make_shared(192, 253, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->primarySkillNames[static_cast(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 & onWindowClosed) diff --git a/client/windows/GUIClasses.h b/client/windows/GUIClasses.h index bd086c25e..bcf8b6794 100644 --- a/client/windows/GUIClasses.h +++ b/client/windows/GUIClasses.h @@ -150,7 +150,8 @@ class CLevelWindow : public CWindowObject public: CLevelWindow(const CGHeroInstance *hero, PrimarySkill pskill, std::vector &skills, std::function callback); - ~CLevelWindow(); + + void close() override; }; /// Town portal, castle gate window diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 538da0405..065b2a4b3 100644 --- a/server/CGameHandler.cpp +++ b/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 diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index 4744e1cfe..4800fa5ab 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -165,6 +165,9 @@ void CVCMIServer::onNewConnection(const std::shared_ptr & co void CVCMIServer::onPacketReceived(const std::shared_ptr & connection, const std::vector & message) { std::shared_ptr 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 CVCMIServer::findConnection(const std::shared_ptr & con logNetwork->error("Network error receiving a pack. Connection has been closed"); std::shared_ptr c = findConnection(connection); + if (!c) + return; // player have already disconnected via clientDisconnected call + vstd::erase(activeConnections, c); if(activeConnections.empty() || hostClientId == c->connectionID)