diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 4765ceadc5..bff952ab8c 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -60,7 +60,7 @@ void OMW::Engine::executeLocalScripts() MWScript::InterpreterContext interpreterContext (mEnvironment, &script.second.getRefData().getLocals(), script.second); - mScriptManager->run (script.first, interpreterContext); + mEnvironment.mScriptManager->run (script.first, interpreterContext); if (mEnvironment.mWorld->hasCellChanged()) break; @@ -183,7 +183,6 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager) , mCompileAll (false) , mReportFocus (false) , mFocusTDiff (0) - , mScriptManager (0) , mScriptContext (0) , mFSStrict (false) , mCfgMgr(configurationManager) @@ -200,7 +199,7 @@ OMW::Engine::~Engine() delete mEnvironment.mMechanicsManager; delete mEnvironment.mDialogueManager; delete mEnvironment.mJournal; - delete mScriptManager; + delete mEnvironment.mScriptManager; delete mScriptContext; delete mOgre; } @@ -350,11 +349,11 @@ void OMW::Engine::go() mEnvironment); mScriptContext->setExtensions (&mExtensions); - mScriptManager = new MWScript::ScriptManager (mEnvironment.mWorld->getStore(), mVerboseScripts, - *mScriptContext); + mEnvironment.mScriptManager = new MWScript::ScriptManager (mEnvironment.mWorld->getStore(), + mVerboseScripts, *mScriptContext); mEnvironment.mGlobalScripts = new MWScript::GlobalScripts (mEnvironment.mWorld->getStore(), - *mScriptManager); + *mEnvironment.mScriptManager); // Create game mechanics system mEnvironment.mMechanicsManager = new MWMechanics::MechanicsManager (mEnvironment); @@ -395,7 +394,7 @@ void OMW::Engine::go() // scripts if (mCompileAll) { - std::pair result = mScriptManager->compileAll(); + std::pair result = mEnvironment.mScriptManager->compileAll(); if (result.first) std::cout @@ -437,7 +436,7 @@ void OMW::Engine::activate() if (!script.empty()) { mEnvironment.mWorld->getLocalScripts().setIgnore (ptr); - mScriptManager->run (script, interpreterContext); + mEnvironment.mScriptManager->run (script, interpreterContext); } if (!interpreterContext.hasActivationBeenHandled()) diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 5c5cdc018f..690430784b 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -78,10 +78,9 @@ namespace OMW std::string mFocusName; MWWorld::Environment mEnvironment; - MWScript::ScriptManager *mScriptManager; Compiler::Extensions mExtensions; Compiler::Context *mScriptContext; - + Files::Collections mFileCollections; bool mFSStrict; diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index 9c099f7dbc..5bcf465990 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -25,6 +25,8 @@ #include #include "../mwscript/extensions.hpp" +#include "../mwscript/scriptmanager.hpp" + #include #include #include @@ -409,7 +411,7 @@ namespace MWDialogue return true; } - DialogueManager::DialogueManager (MWWorld::Environment& environment) : + DialogueManager::DialogueManager (MWWorld::Environment& environment) : mEnvironment (environment),mCompilerContext (MWScript::CompilerContext::Type_Dialgoue, environment), mErrorStream(std::cout.rdbuf()),mErrorHandler(mErrorStream) { @@ -524,11 +526,21 @@ namespace MWDialogue { mErrorHandler.reset(); - std::istringstream input (cmd); + std::istringstream input (cmd + "\n"); Compiler::Scanner scanner (mErrorHandler, input, mCompilerContext.getExtensions()); - Compiler::ScriptParser parser(mErrorHandler,mCompilerContext,Compiler::Locals());//??????&mActor.getRefData().getLocals()); + Compiler::Locals locals; + + std::string actorScript = MWWorld::Class::get (mActor).getScript (mActor); + + if (!actorScript.empty()) + { + // grab local variables from actor's script, if available. + locals = mEnvironment.mScriptManager->getLocals (actorScript); + } + + Compiler::ScriptParser parser(mErrorHandler,mCompilerContext, locals); scanner.scan (parser); diff --git a/apps/openmw/mwscript/scriptmanager.cpp b/apps/openmw/mwscript/scriptmanager.cpp index 5fcfcc6050..e93f2deeca 100644 --- a/apps/openmw/mwscript/scriptmanager.cpp +++ b/apps/openmw/mwscript/scriptmanager.cpp @@ -63,7 +63,7 @@ namespace MWScript { std::vector code; mParser.getCode (code); - mScripts.insert (std::make_pair (name, code)); + mScripts.insert (std::make_pair (name, std::make_pair (code, mParser.getLocals()))); // TODO sanity check on generated locals @@ -77,8 +77,7 @@ namespace MWScript void ScriptManager::run (const std::string& name, Interpreter::Context& interpreterContext) { // compile script - std::map >::iterator iter = - mScripts.find (name); + ScriptCollection::iterator iter = mScripts.find (name); if (iter==mScripts.end()) { @@ -86,7 +85,7 @@ namespace MWScript { // failed -> ignore script from now on. std::vector empty; - mScripts.insert (std::make_pair (name, empty)); + mScripts.insert (std::make_pair (name, std::make_pair (empty, Compiler::Locals()))); return; } @@ -95,7 +94,7 @@ namespace MWScript } // execute script - if (!iter->second.empty()) + if (!iter->second.first.empty()) try { if (!mOpcodesInstalled) @@ -104,7 +103,7 @@ namespace MWScript mOpcodesInstalled = true; } - mInterpreter.run (&iter->second[0], iter->second.size(), interpreterContext); + mInterpreter.run (&iter->second.first[0], iter->second.first.size(), interpreterContext); } catch (const std::exception& e) { @@ -113,7 +112,7 @@ namespace MWScript if (mVerbose) std::cerr << "(" << e.what() << ")" << std::endl; - iter->second.clear(); // don't execute again. + iter->second.first.clear(); // don't execute again. } } @@ -132,4 +131,24 @@ namespace MWScript return std::make_pair (count, success); } + + Compiler::Locals& ScriptManager::getLocals (const std::string& name) + { + ScriptCollection::iterator iter = mScripts.find (name); + + if (iter==mScripts.end()) + { + if (!compile (name)) + { + // failed -> ignore script from now on. + std::vector empty; + mScripts.insert (std::make_pair (name, std::make_pair (empty, Compiler::Locals()))); + throw std::runtime_error ("failed to compile script " + name); + } + + iter = mScripts.find (name); + } + + return iter->second.second; + } } diff --git a/apps/openmw/mwscript/scriptmanager.hpp b/apps/openmw/mwscript/scriptmanager.hpp index 74511f456e..35cbc0d1e8 100644 --- a/apps/openmw/mwscript/scriptmanager.hpp +++ b/apps/openmw/mwscript/scriptmanager.hpp @@ -39,7 +39,11 @@ namespace MWScript Interpreter::Interpreter mInterpreter; bool mOpcodesInstalled; - std::map > mScripts; + typedef std::pair, Compiler::Locals> CompiledScript; + typedef std::map ScriptCollection; + + + ScriptCollection mScripts; public: @@ -56,6 +60,9 @@ namespace MWScript std::pair compileAll(); ///< Compile all scripts /// \return count, success + + Compiler::Locals& getLocals (const std::string& name); + ///< Return locals for script \a name. }; }; diff --git a/apps/openmw/mwworld/environment.hpp b/apps/openmw/mwworld/environment.hpp index a403ee1657..3a83f886fd 100644 --- a/apps/openmw/mwworld/environment.hpp +++ b/apps/openmw/mwworld/environment.hpp @@ -9,6 +9,7 @@ namespace MWSound namespace MWScript { class GlobalScripts; + class ScriptManager; } namespace MWGui @@ -41,7 +42,7 @@ namespace MWWorld { public: Environment() - : mWorld (0), mSoundManager (0), mGlobalScripts (0), mWindowManager (0), + : mWorld (0), mSoundManager (0), mGlobalScripts (0), mScriptManager (0), mWindowManager (0), mMechanicsManager (0), mDialogueManager (0), mJournal (0), mFrameDuration (0), mInputManager (0) {} @@ -49,6 +50,7 @@ namespace MWWorld World *mWorld; MWSound::SoundManager *mSoundManager; MWScript::GlobalScripts *mGlobalScripts; + MWScript::ScriptManager *mScriptManager; MWGui::WindowManager *mWindowManager; MWMechanics::MechanicsManager *mMechanicsManager; MWDialogue::DialogueManager *mDialogueManager;