mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-08 22:26:51 +02:00
Merge pull request #5363 from IvanSavenko/crashfixes
[1.6.5] Crashfixes for reported crashes from 1.6.4
This commit is contained in:
@@ -62,6 +62,7 @@
|
||||
#include "windows/CTutorialWindow.h"
|
||||
#include "windows/GUIClasses.h"
|
||||
#include "windows/InfoWindows.h"
|
||||
#include "windows/settings/SettingsMainWindow.h"
|
||||
|
||||
#include "../CCallback.h"
|
||||
|
||||
@@ -187,6 +188,7 @@ void CPlayerInterface::closeAllDialogs()
|
||||
while(true)
|
||||
{
|
||||
auto adventureWindow = GH.windows().topWindow<AdventureMapInterface>();
|
||||
auto settingsWindow = GH.windows().topWindow<SettingsMainWindow>();
|
||||
auto infoWindow = GH.windows().topWindow<CInfoWindow>();
|
||||
auto topWindow = GH.windows().topWindow<WindowBase>();
|
||||
|
||||
@@ -196,10 +198,16 @@ void CPlayerInterface::closeAllDialogs()
|
||||
if(infoWindow && infoWindow->ID != QueryID::NONE)
|
||||
break;
|
||||
|
||||
if (topWindow == nullptr)
|
||||
throw std::runtime_error("Invalid or non-existing top window! Total windows: " + std::to_string(GH.windows().count()));
|
||||
if (settingsWindow)
|
||||
{
|
||||
settingsWindow->close();
|
||||
continue;
|
||||
}
|
||||
|
||||
topWindow->close();
|
||||
if (topWindow)
|
||||
topWindow->close();
|
||||
else
|
||||
GH.windows().popWindows(1); // does not inherits from WindowBase, e.g. settings dialog
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -683,18 +683,24 @@ BattleHex::EDir BattleFieldController::selectAttackDirection(const BattleHex & m
|
||||
// | - - | - - | - - | - o o | o o - | - - | - - | o o
|
||||
|
||||
for (size_t i : { 1, 2, 3})
|
||||
attackAvailability[i] = occupiableHexes.contains(neighbours[i]) && occupiableHexes.contains(neighbours[i].cloneInDirection(BattleHex::RIGHT, false));
|
||||
{
|
||||
BattleHex target = neighbours[i].cloneInDirection(BattleHex::RIGHT, false);
|
||||
attackAvailability[i] = neighbours[i].isValid() && occupiableHexes.contains(neighbours[i]) && target.isValid() && occupiableHexes.contains(target);
|
||||
}
|
||||
|
||||
for (size_t i : { 4, 5, 0})
|
||||
attackAvailability[i] = occupiableHexes.contains(neighbours[i]) && occupiableHexes.contains(neighbours[i].cloneInDirection(BattleHex::LEFT, false));
|
||||
{
|
||||
BattleHex target = neighbours[i].cloneInDirection(BattleHex::LEFT, false);
|
||||
attackAvailability[i] = neighbours[i].isValid() && occupiableHexes.contains(neighbours[i]) && target.isValid() && occupiableHexes.contains(target);
|
||||
}
|
||||
|
||||
attackAvailability[6] = occupiableHexes.contains(neighbours[0]) && occupiableHexes.contains(neighbours[1]);
|
||||
attackAvailability[7] = occupiableHexes.contains(neighbours[3]) && occupiableHexes.contains(neighbours[4]);
|
||||
attackAvailability[6] = neighbours[0].isValid() && neighbours[1].isValid() && occupiableHexes.contains(neighbours[0]) && occupiableHexes.contains(neighbours[1]);
|
||||
attackAvailability[7] = neighbours[3].isValid() && neighbours[4].isValid() && occupiableHexes.contains(neighbours[3]) && occupiableHexes.contains(neighbours[4]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < 6; ++i)
|
||||
attackAvailability[i] = occupiableHexes.contains(neighbours[i]);
|
||||
attackAvailability[i] = neighbours[i].isValid() && occupiableHexes.contains(neighbours[i]);
|
||||
|
||||
attackAvailability[6] = false;
|
||||
attackAvailability[7] = false;
|
||||
@@ -739,7 +745,7 @@ BattleHex::EDir BattleFieldController::selectAttackDirection(const BattleHex & m
|
||||
|
||||
BattleHex BattleFieldController::fromWhichHexAttack(const BattleHex & attackTarget)
|
||||
{
|
||||
BattleHex::EDir direction = selectAttackDirection(getHoveredHex());
|
||||
BattleHex::EDir direction = selectAttackDirection(attackTarget);
|
||||
|
||||
const CStack * attacker = owner.stacksController->getActiveStack();
|
||||
|
||||
|
@@ -686,7 +686,12 @@ void StackInfoBasicPanel::initializeData(const CStack * stack)
|
||||
if (hasGraphics)
|
||||
{
|
||||
//FIXME: support permanent duration
|
||||
int duration = stack->getFirstBonus(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(effect)))->turnsRemain;
|
||||
auto spellBonuses = stack->getBonuses(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(effect)));
|
||||
|
||||
if (spellBonuses->empty())
|
||||
throw std::runtime_error("Failed to find effects for spell " + effect.toSpell()->getJsonKey());
|
||||
|
||||
int duration = spellBonuses->front()->duration;
|
||||
|
||||
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())
|
||||
|
@@ -116,6 +116,7 @@ void GlobalLobbyLoginWindow::onLogin()
|
||||
onConnectionSuccess();
|
||||
|
||||
buttonClose->block(true);
|
||||
buttonLogin->block(true);
|
||||
}
|
||||
|
||||
void GlobalLobbyLoginWindow::onConnectionSuccess()
|
||||
@@ -142,4 +143,5 @@ void GlobalLobbyLoginWindow::onConnectionFailed(const std::string & reason)
|
||||
|
||||
labelStatus->setText(formatter.toString());
|
||||
buttonClose->block(false);
|
||||
buttonLogin->block(false);
|
||||
}
|
||||
|
@@ -134,6 +134,7 @@ CGuiHandler::~CGuiHandler()
|
||||
// enforce deletion order on shutdown
|
||||
// all UI elements including adventure map must be destroyed before Gui Handler
|
||||
// proper solution would be removal of adventureInt global
|
||||
windowHandlerInstance->clear();
|
||||
adventureInt.reset();
|
||||
}
|
||||
|
||||
|
@@ -345,7 +345,7 @@ void WindowBase::close()
|
||||
if(!GH.windows().isTopWindow(this))
|
||||
{
|
||||
auto topWindow = GH.windows().topWindow<IShowActivatable>().get();
|
||||
throw std::runtime_error(std::string("Only top interface can be closed! Top window is ") + typeid(*this).name() + " but attempted to close " + typeid(*topWindow).name());
|
||||
throw std::runtime_error(std::string("Only top interface can be closed! Top window is ") + typeid(*topWindow).name() + " but attempted to close " + typeid(*this).name());
|
||||
}
|
||||
GH.windows().popWindows(1);
|
||||
}
|
||||
|
@@ -68,6 +68,9 @@ void OptionsTab::recreate()
|
||||
entries.clear();
|
||||
humanPlayers = 0;
|
||||
|
||||
for (auto heroOverview : GH.windows().findWindows<CHeroOverview>())
|
||||
heroOverview->close();
|
||||
|
||||
for (auto selectionWindow : GH.windows().findWindows<SelectionWindow>())
|
||||
{
|
||||
selectionWindow->reopen();
|
||||
|
@@ -120,6 +120,9 @@ const Rect & SDLImageOptimizer::getResultDimensions() const
|
||||
|
||||
void SDLImageScaler::scaleSurface(Point targetDimensions, EScalingAlgorithm algorithm)
|
||||
{
|
||||
if (!intermediate)
|
||||
return; // may happen on scaling of empty images
|
||||
|
||||
if(!targetDimensions.x || !targetDimensions.y)
|
||||
throw std::runtime_error("invalid scaling dimensions!");
|
||||
|
||||
@@ -144,6 +147,9 @@ void SDLImageScaler::scaleSurface(Point targetDimensions, EScalingAlgorithm algo
|
||||
|
||||
void SDLImageScaler::scaleSurfaceIntegerFactor(int factor, EScalingAlgorithm algorithm)
|
||||
{
|
||||
if (!intermediate)
|
||||
return; // may happen on scaling of empty images
|
||||
|
||||
if(factor == 0)
|
||||
throw std::runtime_error("invalid scaling factor!");
|
||||
|
||||
|
@@ -234,7 +234,11 @@ CStackWindow::ActiveSpellsSection::ActiveSpellsSection(CStackWindow * owner, int
|
||||
spellText = CGI->generaltexth->allTexts[610]; //"%s, duration: %d rounds."
|
||||
boost::replace_first(spellText, "%s", spell->getNameTranslated());
|
||||
//FIXME: support permanent duration
|
||||
int duration = battleStack->getFirstBonus(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(effect)))->turnsRemain;
|
||||
auto spellBonuses = battleStack->getBonuses(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(effect)));
|
||||
if (spellBonuses->empty())
|
||||
throw std::runtime_error("Failed to find effects for spell " + effect.toSpell()->getJsonKey());
|
||||
|
||||
int duration = spellBonuses->front()->duration;
|
||||
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));
|
||||
|
@@ -29,7 +29,6 @@ private:
|
||||
std::shared_ptr<CIntObject> createTab(size_t index);
|
||||
void openTab(size_t index);
|
||||
|
||||
void close(); //TODO: copypaste of WindowBase::close(), consider changing Windowbase to IWindowbase with default close() implementation and changing WindowBase inheritance to CIntObject + IWindowBase
|
||||
|
||||
void loadGameButtonCallback();
|
||||
void saveGameButtonCallback();
|
||||
@@ -40,6 +39,7 @@ private:
|
||||
public:
|
||||
SettingsMainWindow(BattleInterface * parentBattleInterface = nullptr);
|
||||
|
||||
void close(); //TODO: copypaste of WindowBase::close(), consider changing Windowbase to IWindowbase with default close() implementation and changing WindowBase inheritance to CIntObject + IWindowBase
|
||||
void showAll(Canvas & to) override;
|
||||
void onScreenResize() override;
|
||||
};
|
||||
|
@@ -161,12 +161,24 @@ uint32_t TextOperations::getUnicodeCodepoint(char data, const std::string & enco
|
||||
|
||||
std::string TextOperations::toUnicode(const std::string &text, const std::string &encoding)
|
||||
{
|
||||
return boost::locale::conv::to_utf<char>(text, encoding);
|
||||
try {
|
||||
return boost::locale::conv::to_utf<char>(text, encoding);
|
||||
}
|
||||
catch (const boost::locale::conv::conversion_error &)
|
||||
{
|
||||
throw std::runtime_error("Failed to convert text '" + text + "' from encoding " + encoding );
|
||||
}
|
||||
}
|
||||
|
||||
std::string TextOperations::fromUnicode(const std::string &text, const std::string &encoding)
|
||||
{
|
||||
return boost::locale::conv::from_utf<char>(text, encoding);
|
||||
try {
|
||||
return boost::locale::conv::from_utf<char>(text, encoding);
|
||||
}
|
||||
catch (const boost::locale::conv::conversion_error &)
|
||||
{
|
||||
throw std::runtime_error("Failed to convert text '" + text + "' to encoding " + encoding );
|
||||
}
|
||||
}
|
||||
|
||||
void TextOperations::trimRightUnicode(std::string & text, const size_t amount)
|
||||
|
Reference in New Issue
Block a user