diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 5fd328022..62457cae6 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -76,8 +76,6 @@ void OMW::Engine::executeLocalScripts() &script.second.getRefData().getLocals(), script.second); mEnvironment.getScriptManager()->run (script.first, interpreterContext); } - - localScripts.setIgnore (MWWorld::Ptr()); } void OMW::Engine::frame(float frametime) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 7a6afe2e0..79f856398 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -138,8 +138,7 @@ namespace MWScript InterpreterContext::InterpreterContext ( MWScript::Locals *locals, MWWorld::Ptr reference, const std::string& targetId) - : mLocals (locals), mReference (reference), - mActivationHandled (false), mTargetId (targetId) + : mLocals (locals), mReference (reference), mTargetId (targetId) { // If we run on a reference (local script, dialogue script or console with object // selected), store the ID of that reference store it so it can be inherited by @@ -477,37 +476,10 @@ namespace MWScript return static_cast(std::sqrt(diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2])); } - 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) - { - mActivated = ptr; - mActivationHandled = false; - } - void InterpreterContext::executeActivation(MWWorld::Ptr ptr, MWWorld::Ptr actor) { boost::shared_ptr action = (ptr.getClass().activate(ptr, actor)); action->execute (actor); - if (mActivated == ptr) - { - mActivationHandled = true; - mActivated = MWWorld::Ptr(); - } } float InterpreterContext::getSecondsPassed() const diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 3c43444cc..fdd5aa55f 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -27,9 +27,6 @@ namespace MWScript Locals *mLocals; mutable MWWorld::Ptr mReference; - MWWorld::Ptr mActivated; - bool mActivationHandled; - std::string mTargetId; /// If \a id is empty, a reference the script is run from is returned or in case @@ -131,16 +128,6 @@ namespace MWScript virtual float getDistance (const std::string& name, const std::string& id = "") const; ///< @note if \a id is empty, assumes an implicit reference - 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); - ///< Store reference acted upon. The actual execution of the action does not - /// take place here. - void executeActivation(MWWorld::Ptr ptr, MWWorld::Ptr actor); ///< Execute the activation action for this ptr. If ptr is mActivated, mark activation as handled. diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 51f0c6c55..9e415faaa 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -142,7 +142,7 @@ namespace MWScript MWWorld::Ptr ptr = context.getReference(); - runtime.push (context.hasBeenActivated (ptr)); + runtime.push (ptr.getRefData().onActivate()); } }; @@ -158,7 +158,8 @@ namespace MWScript MWWorld::Ptr ptr = R()(runtime); - context.executeActivation(ptr, MWMechanics::getPlayer()); + if (ptr.getRefData().activateByScript()) + context.executeActivation(ptr, MWMechanics::getPlayer()); } }; diff --git a/apps/openmw/mwworld/localscripts.cpp b/apps/openmw/mwworld/localscripts.cpp index f0174ac52..5f6d10b31 100644 --- a/apps/openmw/mwworld/localscripts.cpp +++ b/apps/openmw/mwworld/localscripts.cpp @@ -66,11 +66,6 @@ MWWorld::LocalScripts::LocalScripts (const MWWorld::ESMStore& store) : mStore (s mIter = mScripts.end(); } -void MWWorld::LocalScripts::setIgnore (const ConstPtr& ptr) -{ - mIgnore = ptr; -} - void MWWorld::LocalScripts::startIteration() { mIter = mScripts.begin(); @@ -81,11 +76,8 @@ bool MWWorld::LocalScripts::getNext(std::pair& script) while (mIter!=mScripts.end()) { std::list >::iterator iter = mIter++; - if (mIgnore.isEmpty() || iter->second!=mIgnore) - { - script = *iter; - return true; - } + script = *iter; + return true; } return false; } diff --git a/apps/openmw/mwworld/localscripts.hpp b/apps/openmw/mwworld/localscripts.hpp index 6c2118ea8..c698daf04 100644 --- a/apps/openmw/mwworld/localscripts.hpp +++ b/apps/openmw/mwworld/localscripts.hpp @@ -17,17 +17,12 @@ namespace MWWorld { std::list > mScripts; std::list >::iterator mIter; - MWWorld::ConstPtr mIgnore; const MWWorld::ESMStore& mStore; public: LocalScripts (const MWWorld::ESMStore& store); - void setIgnore (const ConstPtr& ptr); - ///< Mark a single reference for ignoring during iteration over local scripts (will revoke - /// previous ignores). - void startIteration(); ///< Set the iterator to the begin of the script list. diff --git a/apps/openmw/mwworld/refdata.cpp b/apps/openmw/mwworld/refdata.cpp index 1da6b53fa..f85abcc32 100644 --- a/apps/openmw/mwworld/refdata.cpp +++ b/apps/openmw/mwworld/refdata.cpp @@ -8,8 +8,18 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +namespace +{ +enum RefDataFlags +{ + Flag_SuppressActivate = 1, // If set, activation will be suppressed and redirected to the OnActivate flag, which can then be handled by a script. + Flag_OnActivate = 2 +}; +} + namespace MWWorld { + void RefData::copy (const RefData& refData) { mBaseNode = refData.mBaseNode; @@ -19,6 +29,7 @@ namespace MWWorld mPosition = refData.mPosition; mChanged = refData.mChanged; mDeletedByContentFile = refData.mDeletedByContentFile; + mFlags = refData.mFlags; mCustomData = refData.mCustomData ? refData.mCustomData->clone() : 0; } @@ -32,7 +43,7 @@ namespace MWWorld } RefData::RefData() - : mBaseNode(0), mDeletedByContentFile(false), mEnabled (true), mCount (1), mCustomData (0), mChanged(false) + : mBaseNode(0), mDeletedByContentFile(false), mEnabled (true), mCount (1), mCustomData (0), mChanged(false), mFlags(0) { for (int i=0; i<3; ++i) { @@ -45,7 +56,7 @@ namespace MWWorld : mBaseNode(0), mDeletedByContentFile(false), mEnabled (true), mCount (1), mPosition (cellRef.mPos), mCustomData (0), - mChanged(false) // Loading from ESM/ESP files -> assume unchanged + mChanged(false), mFlags(0) // Loading from ESM/ESP files -> assume unchanged { } @@ -55,8 +66,12 @@ namespace MWWorld mCount (objectState.mCount), mPosition (objectState.mPosition), mCustomData (0), - mChanged(true) // Loading from a savegame -> assume changed + mChanged(true), mFlags(objectState.mFlags) // Loading from a savegame -> assume changed { + // "Note that the ActivationFlag_UseEnabled is saved to the reference, + // which will result in permanently suppressed activation if the reference script is removed. + // This occurred when removing the animated containers mod, and the fix in MCP is to reset UseEnabled to true on loading a game." + mFlags &= (~Flag_SuppressActivate); } RefData::RefData (const RefData& refData) @@ -80,6 +95,7 @@ namespace MWWorld objectState.mEnabled = mEnabled; objectState.mCount = mCount; objectState.mPosition = mPosition; + objectState.mFlags = mFlags; } RefData& RefData::operator= (const RefData& refData) @@ -219,4 +235,38 @@ namespace MWWorld { return mChanged; } + + bool RefData::activate() + { + if (!(mFlags & Flag_SuppressActivate)) + return true; + else + { + mFlags |= Flag_OnActivate; + return false; + } + } + + bool RefData::onActivate() + { + mFlags |= Flag_SuppressActivate; + + if (mFlags & Flag_OnActivate) + { + mFlags &= (~Flag_OnActivate); + return true; + } + return false; + } + + bool RefData::activateByScript() + { + if (mFlags & Flag_SuppressActivate) + { + mFlags &= (~Flag_SuppressActivate); + return true; + } + else + return false; + } } diff --git a/apps/openmw/mwworld/refdata.hpp b/apps/openmw/mwworld/refdata.hpp index d87ffdb70..9e662e430 100644 --- a/apps/openmw/mwworld/refdata.hpp +++ b/apps/openmw/mwworld/refdata.hpp @@ -50,6 +50,8 @@ namespace MWWorld bool mChanged; + unsigned int mFlags; + public: RefData(); @@ -122,6 +124,12 @@ namespace MWWorld const CustomData *getCustomData() const; + bool activate(); + + bool onActivate(); + + bool activateByScript(); + bool hasChanged() const; ///< Has this RefData changed since it was originally loaded? }; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f3d80ee67..ea2069bd2 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -3148,25 +3148,16 @@ namespace MWWorld void World::activate(const Ptr &object, const Ptr &actor) { - MWScript::InterpreterContext interpreterContext (&object.getRefData().getLocals(), object); - interpreterContext.activate (object); - - std::string script = object.getClass().getScript (object); - breakInvisibility(actor); if (mScriptsEnabled) { - if (!script.empty()) + if (object.getRefData().activate()) { - getLocalScripts().setIgnore (object); - MWBase::Environment::get().getScriptManager()->run (script, interpreterContext); + boost::shared_ptr action = (object.getClass().activate(object, actor)); + action->execute (actor); } - if (!interpreterContext.hasActivationBeenHandled()) - interpreterContext.executeActivation(object, actor); } - else - interpreterContext.executeActivation(object, actor); } struct ResetActorsVisitor diff --git a/components/esm/objectstate.cpp b/components/esm/objectstate.cpp index d736bab66..b80c72ffe 100644 --- a/components/esm/objectstate.cpp +++ b/components/esm/objectstate.cpp @@ -27,6 +27,9 @@ void ESM::ObjectState::load (ESMReader &esm) if (esm.isNextSub("LROT")) esm.skipHSub(); // local rotation, no longer used + mFlags = 0; + esm.getHNOT (mFlags, "FLAG"); + // obsolete int unused; esm.getHNOT(unused, "LTIM"); @@ -55,6 +58,9 @@ void ESM::ObjectState::save (ESMWriter &esm, bool inInventory) const if (!inInventory) esm.writeHNT ("POS_", mPosition, 24); + if (mFlags != 0) + esm.writeHNT ("FLAG", mFlags); + if (!mHasCustomState) esm.writeHNT ("HCUS", false); } @@ -70,6 +76,7 @@ void ESM::ObjectState::blank() mPosition.pos[i] = 0; mPosition.rot[i] = 0; } + mFlags = 0; mHasCustomState = true; } diff --git a/components/esm/objectstate.hpp b/components/esm/objectstate.hpp index 215cb74ba..5b78074af 100644 --- a/components/esm/objectstate.hpp +++ b/components/esm/objectstate.hpp @@ -24,6 +24,7 @@ namespace ESM unsigned char mEnabled; int mCount; ESM::Position mPosition; + unsigned int mFlags; // Is there any class-specific state following the ObjectState bool mHasCustomState;