diff --git a/CHANGELOG.md b/CHANGELOG.md index 25ed287ee..e6ec9cf57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ Feature #5445: Handle NiLines Feature #5457: Realistic diagonal movement Feature #5486: Fixes trainers to choose their training skills based on their base skill points + Feature #5524: Resume failed script execution after reload Task #5480: Drop Qt4 support 0.46.0 diff --git a/apps/openmw/mwbase/scriptmanager.hpp b/apps/openmw/mwbase/scriptmanager.hpp index da3454d34..ac8333ed1 100644 --- a/apps/openmw/mwbase/scriptmanager.hpp +++ b/apps/openmw/mwbase/scriptmanager.hpp @@ -35,6 +35,8 @@ namespace MWBase virtual ~ScriptManager() {} + virtual void clear() = 0; + virtual bool run (const std::string& name, Interpreter::Context& interpreterContext) = 0; ///< Run the script with the given name (compile first, if not compiled yet) diff --git a/apps/openmw/mwscript/scriptmanagerimp.cpp b/apps/openmw/mwscript/scriptmanagerimp.cpp index b69eb7f60..0077b7cd0 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.cpp +++ b/apps/openmw/mwscript/scriptmanagerimp.cpp @@ -79,8 +79,8 @@ namespace MWScript if (Success) { std::vector code; - mParser.getCode (code); - mScripts.insert (std::make_pair (name, std::make_pair (code, mParser.getLocals()))); + mParser.getCode(code); + mScripts.emplace(name, CompiledScript(code, mParser.getLocals())); return true; } @@ -100,7 +100,7 @@ namespace MWScript { // failed -> ignore script from now on. std::vector empty; - mScripts.insert (std::make_pair (name, std::make_pair (empty, Compiler::Locals()))); + mScripts.emplace(name, CompiledScript(empty, Compiler::Locals())); return false; } @@ -109,7 +109,7 @@ namespace MWScript } // execute script - if (!iter->second.first.empty()) + if (!iter->second.mByteCode.empty() && iter->second.mActive) try { if (!mOpcodesInstalled) @@ -118,7 +118,7 @@ namespace MWScript mOpcodesInstalled = true; } - mInterpreter.run (&iter->second.first[0], iter->second.first.size(), interpreterContext); + mInterpreter.run (&iter->second.mByteCode[0], iter->second.mByteCode.size(), interpreterContext); return true; } catch (const MissingImplicitRefError& e) @@ -129,11 +129,21 @@ namespace MWScript { Log(Debug::Error) << "Execution of script " << name << " failed: " << e.what(); - iter->second.first.clear(); // don't execute again. + iter->second.mActive = false; // don't execute again. } return false; } + void ScriptManager::clear() + { + for (auto& script : mScripts) + { + script.second.mActive = true; + } + + mGlobalScripts.clear(); + } + std::pair ScriptManager::compileAll() { int count = 0; @@ -163,7 +173,7 @@ namespace MWScript ScriptCollection::iterator iter = mScripts.find (name2); if (iter!=mScripts.end()) - return iter->second.second; + return iter->second.mLocals; } { diff --git a/apps/openmw/mwscript/scriptmanagerimp.hpp b/apps/openmw/mwscript/scriptmanagerimp.hpp index 27567a191..50cc7afa8 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.hpp +++ b/apps/openmw/mwscript/scriptmanagerimp.hpp @@ -41,7 +41,20 @@ namespace MWScript Interpreter::Interpreter mInterpreter; bool mOpcodesInstalled; - typedef std::pair, Compiler::Locals> CompiledScript; + struct CompiledScript + { + std::vector mByteCode; + Compiler::Locals mLocals; + bool mActive; + + CompiledScript(const std::vector& code, const Compiler::Locals& locals) + { + mByteCode = code; + mLocals = locals; + mActive = true; + } + }; + typedef std::map ScriptCollection; ScriptCollection mScripts; @@ -55,6 +68,8 @@ namespace MWScript Compiler::Context& compilerContext, int warningsMode, const std::vector& scriptBlacklist); + virtual void clear(); + virtual bool run (const std::string& name, Interpreter::Context& interpreterContext); ///< Run the script with the given name (compile first, if not compiled yet) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 9974b8f16..d59704bf1 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -47,7 +47,7 @@ void MWState::StateManager::cleanup (bool force) MWBase::Environment::get().getSoundManager()->clear(); MWBase::Environment::get().getDialogueManager()->clear(); MWBase::Environment::get().getJournal()->clear(); - MWBase::Environment::get().getScriptManager()->getGlobalScripts().clear(); + MWBase::Environment::get().getScriptManager()->clear(); MWBase::Environment::get().getWorld()->clear(); MWBase::Environment::get().getWindowManager()->clear(); MWBase::Environment::get().getInputManager()->clear();