From f9227beedd787e2386ce85310b11c663b07c6770 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Sat, 10 Jan 2015 23:58:55 +0100
Subject: [PATCH] Add warning when loading a savegame that depends on
 non-existing content files (Fixes #2261)

---
 apps/openmw/mwgui/messagebox.cpp              |  5 +--
 apps/openmw/mwgui/messagebox.hpp              |  3 +-
 apps/openmw/mwgui/windowmanagerimp.cpp        |  5 +--
 apps/openmw/mwstate/statemanagerimp.cpp       | 33 +++++++++++++++++++
 apps/openmw/mwstate/statemanagerimp.hpp       |  2 ++
 .../openmw_interactive_messagebox.layout      |  2 +-
 files/mygui/openmw_layers.xml                 |  1 +
 7 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp
index c45136eb38..9cb778ea2d 100644
--- a/apps/openmw/mwgui/messagebox.cpp
+++ b/apps/openmw/mwgui/messagebox.cpp
@@ -146,10 +146,11 @@ namespace MWGui
         return false;
     }
 
-    int MessageBoxManager::readPressedButton ()
+    int MessageBoxManager::readPressedButton (bool reset)
     {
         int pressed = mLastButtonPressed;
-        mLastButtonPressed = -1;
+        if (reset)
+            mLastButtonPressed = -1;
         return pressed;
     }
 
diff --git a/apps/openmw/mwgui/messagebox.hpp b/apps/openmw/mwgui/messagebox.hpp
index 59804e097c..48a92c844b 100644
--- a/apps/openmw/mwgui/messagebox.hpp
+++ b/apps/openmw/mwgui/messagebox.hpp
@@ -33,7 +33,8 @@ namespace MWGui
 
             bool removeMessageBox (MessageBox *msgbox);
 
-            int readPressedButton ();
+            /// @param reset Reset the pressed button to -1 after reading it.
+            int readPressedButton (bool reset=true);
 
             typedef MyGUI::delegates::CMultiDelegate1<int> EventHandle_Int;
 
diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp
index 7d9e10d8fd..077ca4fe33 100644
--- a/apps/openmw/mwgui/windowmanagerimp.cpp
+++ b/apps/openmw/mwgui/windowmanagerimp.cpp
@@ -607,7 +607,7 @@ namespace MWGui
                     // GM_Loading uses a texture of the last rendered frame so everything previously visible will be rendered.
                     mHud->setVisible(false);
                     mToolTips->setVisible(false);
-                    setCursorVisible(false);
+                    setCursorVisible(mMessageBoxManager && mMessageBoxManager->isInteractiveMessageBox());
                     break;
                 default:
                     // Unsupported mode, switch back to game
@@ -813,9 +813,10 @@ namespace MWGui
 
         if (block)
         {
-            while (mMessageBoxManager->readPressedButton() == -1
+            while (mMessageBoxManager->readPressedButton(false) == -1
                    && !MWBase::Environment::get().getStateManager()->hasQuitRequest())
             {
+                mMessageBoxManager->onFrame(0.f);
                 MWBase::Environment::get().getInputManager()->update(0, true, false);
 
                 mRendering->getWindow()->update();
diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp
index 8ae7fb3554..f756ee42ae 100644
--- a/apps/openmw/mwstate/statemanagerimp.cpp
+++ b/apps/openmw/mwstate/statemanagerimp.cpp
@@ -353,6 +353,12 @@ void MWState::StateManager::loadGame (const Character *character, const std::str
                     {
                         ESM::SavedGame profile;
                         profile.load(reader);
+                        if (!verifyProfile(profile))
+                        {
+                            cleanup (true);
+                            MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
+                            return;
+                        }
                         mTimePlayed = profile.mTimePlayed;
                     }
                     break;
@@ -517,3 +523,30 @@ void MWState::StateManager::update (float duration)
         }
     }
 }
+
+bool MWState::StateManager::verifyProfile(const ESM::SavedGame& profile) const
+{
+    const std::vector<std::string>& selectedContentFiles = MWBase::Environment::get().getWorld()->getContentFiles();
+    bool notFound = false;
+    for (std::vector<std::string>::const_iterator it = profile.mContentFiles.begin();
+         it != profile.mContentFiles.end(); ++it)
+    {
+        if (std::find(selectedContentFiles.begin(), selectedContentFiles.end(), *it)
+                == selectedContentFiles.end())
+        {
+            notFound = true;
+            break;
+        }
+    }
+    if (notFound)
+    {
+        std::vector<std::string> buttons;
+        buttons.push_back("#{sYes}");
+        buttons.push_back("#{sNo}");
+        MWBase::Environment::get().getWindowManager()->interactiveMessageBox("#{sMissingMastersMsg}", buttons, true);
+        int selectedButton = MWBase::Environment::get().getWindowManager()->readPressedButton();
+        if (selectedButton == 1 || selectedButton == -1)
+            return false;
+    }
+    return true;
+}
diff --git a/apps/openmw/mwstate/statemanagerimp.hpp b/apps/openmw/mwstate/statemanagerimp.hpp
index 956a2d73c4..37f38f8df7 100644
--- a/apps/openmw/mwstate/statemanagerimp.hpp
+++ b/apps/openmw/mwstate/statemanagerimp.hpp
@@ -23,6 +23,8 @@ namespace MWState
 
             void cleanup (bool force = false);
 
+            bool verifyProfile (const ESM::SavedGame& profile) const;
+
             std::map<int, int> buildContentFileIndexMap (const ESM::ESMReader& reader) const;
 
         public:
diff --git a/files/mygui/openmw_interactive_messagebox.layout b/files/mygui/openmw_interactive_messagebox.layout
index a1dbc5aa83..a72bebf3a9 100644
--- a/files/mygui/openmw_interactive_messagebox.layout
+++ b/files/mygui/openmw_interactive_messagebox.layout
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <MyGUI type="Layout">
-    <Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 500 400" name="_Main">
+    <Widget type="Window" skin="MW_Dialog" layer="MessageBox" position="0 0 500 400" name="_Main">
         <Widget type="EditBox" skin="MW_TextEditClient" position="10 10 490 20" align="Left Top Stretch" name="message">
             <Property key="FontName" value="Default"/>
             <Property key="TextAlign" value="Center"/>
diff --git a/files/mygui/openmw_layers.xml b/files/mygui/openmw_layers.xml
index 38a98d133f..50f83aaa2c 100644
--- a/files/mygui/openmw_layers.xml
+++ b/files/mygui/openmw_layers.xml
@@ -11,6 +11,7 @@
     <Layer name="Popup" overlapped="true" peek="true"/>
     <Layer name="DragAndDrop" overlapped="false" peek="false"/>
     <Layer name="LoadingScreen" overlapped="false" peek="true"/>
+    <Layer name="MessageBox" overlapped="false" peek="true"/>
     <Layer name="Overlay" overlapped="false" peek="true"/>
     <Layer name="Pointer" overlapped="false" peek="false"/>
 </MyGUI>