From 7ba6bdb56c01a67fdef62c00cfaeb8c1c79e2eaf Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 3 Aug 2010 22:43:53 +0200 Subject: [PATCH] prepared InterpreterContext for activation implementation --- apps/openmw/mwscript/interpretercontext.cpp | 117 +++++++++++++------- apps/openmw/mwscript/interpretercontext.hpp | 72 +++++++----- apps/openmw/mwscript/miscextensions.cpp | 30 ++--- 3 files changed, 138 insertions(+), 81 deletions(-) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index f2dc57dd0e..404aa69a68 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -27,9 +27,9 @@ namespace MWScript { if (mReference.isEmpty()) throw std::runtime_error ("no implicit reference"); - + return mReference; - } + } } const MWWorld::Ptr InterpreterContext::getReference ( @@ -43,21 +43,22 @@ namespace MWScript { if (mReference.isEmpty()) throw std::runtime_error ("no implicit reference"); - + return mReference; - } + } } - + InterpreterContext::InterpreterContext (MWWorld::Environment& environment, MWScript::Locals *locals, MWWorld::Ptr reference) - : mEnvironment (environment), mLocals (locals), mReference (reference) + : mEnvironment (environment), mLocals (locals), mReference (reference), + mActivationHandled (false) {} int InterpreterContext::getLocalShort (int index) const { if (!mLocals) throw std::runtime_error ("local variables not available in this context"); - + return mLocals->mShorts.at (index); } @@ -65,7 +66,7 @@ namespace MWScript { if (!mLocals) throw std::runtime_error ("local variables not available in this context"); - + return mLocals->mLongs.at (index); } @@ -73,7 +74,7 @@ namespace MWScript { if (!mLocals) throw std::runtime_error ("local variables not available in this context"); - + return mLocals->mFloats.at (index); } @@ -90,45 +91,45 @@ namespace MWScript if (!mLocals) throw std::runtime_error ("local variables not available in this context"); - mLocals->mLongs.at (index) = value; + mLocals->mLongs.at (index) = value; } void InterpreterContext::setLocalFloat (int index, float value) { if (!mLocals) throw std::runtime_error ("local variables not available in this context"); - - mLocals->mFloats.at (index) = value; + + mLocals->mFloats.at (index) = value; } - + void InterpreterContext::messageBox (const std::string& message, const std::vector& buttons) { std::cout << "message box: " << message << std::endl; - - if (!buttons.empty()) + + if (!buttons.empty()) std::cerr << "error: message box buttons not supported" << std::endl; } - + bool InterpreterContext::menuMode() { return mEnvironment.mWindowManager->isGuiMode(); } - + int InterpreterContext::getGlobalShort (const std::string& name) const { - return mEnvironment.mWorld->getGlobalVariable (name).mShort; + return mEnvironment.mWorld->getGlobalVariable (name).mShort; } int InterpreterContext::getGlobalLong (const std::string& name) const { // a global long is internally a float. - return mEnvironment.mWorld->getGlobalVariable (name).mLong; + return mEnvironment.mWorld->getGlobalVariable (name).mLong; } float InterpreterContext::getGlobalFloat (const std::string& name) const { - return mEnvironment.mWorld->getGlobalVariable (name).mFloat; + return mEnvironment.mWorld->getGlobalVariable (name).mFloat; } void InterpreterContext::setGlobalShort (const std::string& name, int value) @@ -166,83 +167,117 @@ namespace MWScript else mEnvironment.mWorld->getGlobalVariable (name).mFloat = value; } - + bool InterpreterContext::isScriptRunning (const std::string& name) const { return mEnvironment.mGlobalScripts->isRunning (name); } - + void InterpreterContext::startScript (const std::string& name) { mEnvironment.mGlobalScripts->addScript (name); } - + void InterpreterContext::stopScript (const std::string& name) { mEnvironment.mGlobalScripts->removeScript (name); } - + float InterpreterContext::getDistance (const std::string& name, const std::string& id) const { // TODO handle exterior cells (when ref and ref2 are located in different cells) const MWWorld::Ptr ref2 = getReference (id, false); - + const MWWorld::Ptr ref = mEnvironment.mWorld->getPtr (name, true); - + double diff[3]; - - for (int i=0; i<3; ++i) + + for (int i=0; i<3; ++i) diff[i] = ref.getCellRef().pos.pos[i] - ref2.getCellRef().pos.pos[i]; - + return std::sqrt (diff[0]*diff[0] + diff[1]*diff[1] + diff[2]*diff[2]); } - - bool InterpreterContext::hasBeenActivated() const + + bool InterpreterContext::hasBeenActivated (const MWWorld::Ptr& ptr) { + if (!mActivated.isEmpty() && mActivated==ptr) + { + mActivationHandled = true; + return true; + } + return false; } - + + bool InterpreterContext::hasActivationBeenHandled() const + { + return mActivationHandled; + } + + void InterpreterContext::activate (const MWWorld::Ptr& ptr, + boost::shared_ptr action) + { + mActivated = ptr; + mActivationHandled = false; + mAction = action; + } + + void InterpreterContext::executeActivation() + { + if (!mAction.get()) + throw std::runtime_error ("activation failed, because no action to perform"); + + mAction->execute (mEnvironment); + mActivationHandled = true; + } + + void InterpreterContext::clearActivation() + { + mActivated = MWWorld::Ptr(); + mActivationHandled = false; + mAction.reset(); + } + float InterpreterContext::getSecondsPassed() const { return mEnvironment.mFrameDuration; } - + bool InterpreterContext::isDisabled (const std::string& id) const { const MWWorld::Ptr ref = getReference (id, false); return !ref.getRefData().isEnabled(); } - + void InterpreterContext::enable (const std::string& id) { MWWorld::Ptr ref = getReference (id, false); mEnvironment.mWorld->enable (ref); } - + void InterpreterContext::disable (const std::string& id) { - MWWorld::Ptr ref = getReference (id, false); + MWWorld::Ptr ref = getReference (id, false); mEnvironment.mWorld->disable (ref); } - + MWGui::WindowManager& InterpreterContext::getWindowManager() { return *mEnvironment.mWindowManager; } - + MWWorld::World& InterpreterContext::getWorld() { return *mEnvironment.mWorld; } - + MWSound::SoundManager& InterpreterContext::getSoundManager() { return *mEnvironment.mSoundManager; } - + MWWorld::Ptr InterpreterContext::getReference() { return getReference ("", true); } } - diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index ee35964b80..e63c4838c3 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -1,11 +1,14 @@ #ifndef GAME_SCRIPT_INTERPRETERCONTEXT_H #define GAME_SCRIPT_INTERPRETERCONTEXT_H +#include + #include #include "../mwworld/ptr.hpp" #include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" +#include "../mwworld/action.hpp" namespace MWSound { @@ -17,80 +20,95 @@ namespace MWScript struct Locals; class InterpreterContext : public Interpreter::Context - { + { MWWorld::Environment& mEnvironment; Locals *mLocals; MWWorld::Ptr mReference; - - + + MWWorld::Ptr mActivated; + bool mActivationHandled; + boost::shared_ptr mAction; + MWWorld::Ptr getReference (const std::string& id, bool activeOnly); const MWWorld::Ptr getReference (const std::string& id, bool activeOnly) const; public: - - InterpreterContext (MWWorld::Environment& environment, + + InterpreterContext (MWWorld::Environment& environment, MWScript::Locals *locals, MWWorld::Ptr reference); ///< The ownership of \a locals is not transferred. 0-pointer allowed. - + virtual int getLocalShort (int index) const; virtual int getLocalLong (int index) const; virtual float getLocalFloat (int index) const; - virtual void setLocalShort (int index, int value); + virtual void setLocalShort (int index, int value); virtual void setLocalLong (int index, int value); virtual void setLocalFloat (int index, float value); - + virtual void messageBox (const std::string& message, - const std::vector& buttons); + const std::vector& buttons); virtual bool menuMode(); - + virtual int getGlobalShort (const std::string& name) const; virtual int getGlobalLong (const std::string& name) const; virtual float getGlobalFloat (const std::string& name) const; - virtual void setGlobalShort (const std::string& name, int value); + virtual void setGlobalShort (const std::string& name, int value); - virtual void setGlobalLong (const std::string& name, int value); + virtual void setGlobalLong (const std::string& name, int value); virtual void setGlobalFloat (const std::string& name, float value); - + virtual bool isScriptRunning (const std::string& name) const; - + virtual void startScript (const std::string& name); - + virtual void stopScript (const std::string& name); - + virtual float getDistance (const std::string& name, const std::string& id = "") const; - - virtual bool hasBeenActivated() const; - + + bool hasBeenActivated (const MWWorld::Ptr& ptr); + ///< \attention Calling this function for the right reference will mark the action as + /// been handled. + + bool hasActivationBeenHandled() const; + + void activate (const MWWorld::Ptr& ptr, boost::shared_ptr action); + ///< Store reference acted upon and action. The actual execution of the action does not + /// take place here. + + void executeActivation(); + ///< Execute the action defined by the last activate call. + + void clearActivation(); + ///< Discard the action defined by the last activate call. + virtual float getSecondsPassed() const; - + virtual bool isDisabled (const std::string& id = "") const; - + virtual void enable (const std::string& id = ""); - + virtual void disable (const std::string& id = ""); - + MWWorld::World& getWorld(); - + MWSound::SoundManager& getSoundManager(); MWGui::WindowManager& getWindowManager(); - + MWWorld::Ptr getReference(); ///< Reference, that the script is running from (can be empty) }; } #endif - - diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 3d865d56fa..6abd224544 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -16,37 +16,41 @@ namespace MWScript class OpXBox : public Interpreter::Opcode0 { public: - + virtual void execute (Interpreter::Runtime& runtime) { runtime.push (0); - } + } }; - + class OpOnActivate : public Interpreter::Opcode0 { public: - + virtual void execute (Interpreter::Runtime& runtime) { - runtime.push (static_cast ( - runtime.getContext()).hasBeenActivated()); - } + InterpreterContext& context = + static_cast (runtime.getContext()); + + MWWorld::Ptr ptr = context.getReference(); + + runtime.push (context.hasBeenActivated (ptr)); + } }; - + const int opcodeXBox = 0x200000c; - const int opcodeOnActivate = 0x200000d; - + const int opcodeOnActivate = 0x200000d; + void registerExtensions (Compiler::Extensions& extensions) { extensions.registerFunction ("xbox", 'l', "", opcodeXBox); extensions.registerFunction ("onactivate", 'l', "", opcodeOnActivate); } - + void installOpcodes (Interpreter::Interpreter& interpreter) { interpreter.installSegment5 (opcodeXBox, new OpXBox); interpreter.installSegment5 (opcodeOnActivate, new OpOnActivate); - } - } + } + } }