diff --git a/apps/mwcompiler/context.cpp b/apps/mwcompiler/context.cpp index 895e2c62ae..ff84494af9 100644 --- a/apps/mwcompiler/context.cpp +++ b/apps/mwcompiler/context.cpp @@ -12,5 +12,10 @@ namespace SACompiler { return ' '; } + + bool Context::isId (const std::string& name) const + { + return false; + } } diff --git a/apps/mwcompiler/context.hpp b/apps/mwcompiler/context.hpp index be06bbca84..ebf84166c5 100644 --- a/apps/mwcompiler/context.hpp +++ b/apps/mwcompiler/context.hpp @@ -13,7 +13,10 @@ namespace SACompiler ///< Is the compiler allowed to declare local variables? virtual char getGlobalType (const std::string& name) const; - ///< 'l: long, 's': short, 'f': float, ' ': does not exist. + ///< 'l: long, 's': short, 'f': float, ' ': does not exist. + + virtual bool isId (const std::string& name) const; + ///< Does \a name match an ID, that can be referenced? }; } diff --git a/apps/mwinterpreter/context.cpp b/apps/mwinterpreter/context.cpp index ecf4bd8290..cbe379f0f3 100644 --- a/apps/mwinterpreter/context.cpp +++ b/apps/mwinterpreter/context.cpp @@ -120,6 +120,15 @@ namespace SAInterpreter return 0; } + bool Context::isDisabled (const std::string& id) const + { + return false; + } + + void Context::enable (const std::string& id) {} + + void Context::disable (const std::string& id) {} + void Context::report() { std::size_t i = 0; diff --git a/apps/mwinterpreter/context.hpp b/apps/mwinterpreter/context.hpp index 48ba40ca30..1ee3129f7c 100644 --- a/apps/mwinterpreter/context.hpp +++ b/apps/mwinterpreter/context.hpp @@ -62,6 +62,12 @@ namespace SAInterpreter 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 = ""); + void report(); ///< Write state to std::cout }; diff --git a/apps/openmw/mwrender/cell.hpp b/apps/openmw/mwrender/cell.hpp index 756ec1cdae..9e214209ab 100644 --- a/apps/openmw/mwrender/cell.hpp +++ b/apps/openmw/mwrender/cell.hpp @@ -1,6 +1,8 @@ #ifndef GAME_RENDER_CELL_H #define GAME_RENDER_CELL_H +#include + namespace MWRender { class CellRender @@ -15,6 +17,12 @@ namespace MWRender /// Remove the cell from rendering, but don't remove it from /// memory. virtual void hide() = 0; + + /// Make the reference with the given handle visible. + virtual void enable (const std::string& handle) = 0; + + /// Make the reference with the given handle invisible. + virtual void disable (const std::string& handle) = 0; }; } diff --git a/apps/openmw/mwrender/cellimp.cpp b/apps/openmw/mwrender/cellimp.cpp index 7a8de957e3..86bddb3a93 100644 --- a/apps/openmw/mwrender/cellimp.cpp +++ b/apps/openmw/mwrender/cellimp.cpp @@ -13,7 +13,7 @@ void insertObj(CellRenderImp& cellRender, T& liveRef) { cellRender.insertBegin (liveRef.ref); cellRender.insertMesh ("meshes\\" + model); - liveRef.mData.setHandle (cellRender.insertEnd()); + liveRef.mData.setHandle (cellRender.insertEnd (liveRef.mData.isEnabled())); } } @@ -36,7 +36,7 @@ void insertObj(CellRenderImp& cellRender, ESMS::LiveCellRefdata.radius); cellRender.insertLight(r, g, b, radius); - liveRef.mData.setHandle (cellRender.insertEnd()); + liveRef.mData.setHandle (cellRender.insertEnd (liveRef.mData.isEnabled())); } } diff --git a/apps/openmw/mwrender/cellimp.hpp b/apps/openmw/mwrender/cellimp.hpp index 88406bb4f6..f93bbbbf3a 100644 --- a/apps/openmw/mwrender/cellimp.hpp +++ b/apps/openmw/mwrender/cellimp.hpp @@ -33,7 +33,7 @@ namespace MWRender virtual void insertLight(float r, float g, float b, float radius) = 0; /// finish inserting a new reference and return a handle to it. - virtual std::string insertEnd() = 0; + virtual std::string insertEnd (bool Enable) = 0; void insertCell(ESMS::CellStore &cell); diff --git a/apps/openmw/mwrender/interior.cpp b/apps/openmw/mwrender/interior.cpp index 5cf38a5a1b..a2f55880ba 100644 --- a/apps/openmw/mwrender/interior.cpp +++ b/apps/openmw/mwrender/interior.cpp @@ -103,12 +103,15 @@ void InteriorCellRender::insertLight(float r, float g, float b, float radius) // finish inserting a new reference and return a handle to it. -std::string InteriorCellRender::insertEnd() +std::string InteriorCellRender::insertEnd (bool enable) { assert (insert); std::string handle = insert->getName(); + if (!enable) + insert->setVisible (false); + insert = 0; return handle; @@ -219,6 +222,18 @@ void InteriorCellRender::toggleLight() setAmbientMode(); } +void InteriorCellRender::enable (const std::string& handle) +{ + if (!handle.empty()) + scene.getMgr()->getSceneNode (handle)->setVisible (true); +} + +void InteriorCellRender::disable (const std::string& handle) +{ + if (!handle.empty()) + scene.getMgr()->getSceneNode (handle)->setVisible (false); +} + // Magic function from the internets. Might need this later. /* void Scene::DestroyAllAttachedMovableObjects( SceneNode* i_pSceneNode ) diff --git a/apps/openmw/mwrender/interior.hpp b/apps/openmw/mwrender/interior.hpp index 5eda4eccd0..cd6834999c 100644 --- a/apps/openmw/mwrender/interior.hpp +++ b/apps/openmw/mwrender/interior.hpp @@ -66,7 +66,7 @@ namespace MWRender virtual void insertLight(float r, float g, float b, float radius); /// finish inserting a new reference and return a handle to it. - virtual std::string insertEnd(); + virtual std::string insertEnd (bool Enable); /// configure lighting according to cell void configureAmbient(); @@ -88,13 +88,19 @@ namespace MWRender /// Remove the cell from rendering, but don't remove it from /// memory. - void hide(); + virtual void hide(); /// Destroy all rendering objects connected with this cell. void destroy(); // comment by Zini: shouldn't this go into the destructor? /// Switch through lighting modes. void toggleLight(); + + /// Make the reference with the given handle visible. + virtual void enable (const std::string& handle); + + /// Make the reference with the given handle invisible. + virtual void disable (const std::string& handle); }; } diff --git a/apps/openmw/mwscript/compilercontext.cpp b/apps/openmw/mwscript/compilercontext.cpp index 1e5cdaf4ac..5e4882f259 100644 --- a/apps/openmw/mwscript/compilercontext.cpp +++ b/apps/openmw/mwscript/compilercontext.cpp @@ -31,5 +31,30 @@ namespace MWScript return ' '; } + + bool CompilerContext::isId (const std::string& name) const + { + return + mEnvironment.mWorld->getStore().activators.find (name) || + mEnvironment.mWorld->getStore().potions.find (name) || + mEnvironment.mWorld->getStore().appas.find (name) || + mEnvironment.mWorld->getStore().armors.find (name) || + mEnvironment.mWorld->getStore().books.find (name) || + mEnvironment.mWorld->getStore().clothes.find (name) || + mEnvironment.mWorld->getStore().containers.find (name) || + mEnvironment.mWorld->getStore().creatures.find (name) || + mEnvironment.mWorld->getStore().doors.find (name) || + mEnvironment.mWorld->getStore().ingreds.find (name) || + mEnvironment.mWorld->getStore().creatureLists.find (name) || + mEnvironment.mWorld->getStore().itemLists.find (name) || + mEnvironment.mWorld->getStore().lights.find (name) || + mEnvironment.mWorld->getStore().lockpicks.find (name) || + mEnvironment.mWorld->getStore().miscItems.find (name) || + mEnvironment.mWorld->getStore().npcs.find (name) || + mEnvironment.mWorld->getStore().probes.find (name) || + mEnvironment.mWorld->getStore().repairs.find (name) || + mEnvironment.mWorld->getStore().statics.find (name) || + mEnvironment.mWorld->getStore().weapons.find (name); + } } diff --git a/apps/openmw/mwscript/compilercontext.hpp b/apps/openmw/mwscript/compilercontext.hpp index 41d5f314e4..7a3411bba7 100644 --- a/apps/openmw/mwscript/compilercontext.hpp +++ b/apps/openmw/mwscript/compilercontext.hpp @@ -35,6 +35,9 @@ namespace MWScript /// 'l: long, 's': short, 'f': float, ' ': does not exist. virtual char getGlobalType (const std::string& name) const; + + virtual bool isId (const std::string& name) const; + ///< Does \a name match an ID, that can be referenced? }; } diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 0b1610f4f6..064ac583dd 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -16,6 +16,42 @@ namespace MWScript { + InterpreterContext::PtrWithCell InterpreterContext::getReference ( + const std::string& id, bool activeOnly) + { + PtrWithCell ref; + + if (!id.empty()) + { + return mEnvironment.mWorld->getPtr (id, activeOnly); + } + else + { + if (mReference.isEmpty()) + throw std::runtime_error ("no implicit reference"); + + return PtrWithCell (mReference, mEnvironment.mWorld->find (mReference)); + } + } + + InterpreterContext::CPtrWithCell InterpreterContext::getReference ( + const std::string& id, bool activeOnly) const + { + CPtrWithCell ref; + + if (!id.empty()) + { + return mEnvironment.mWorld->getPtr (id, activeOnly); + } + else + { + if (mReference.isEmpty()) + throw std::runtime_error ("no implicit reference"); + + return CPtrWithCell (mReference, mEnvironment.mWorld->find (mReference)); + } + } + InterpreterContext::InterpreterContext (MWWorld::Environment& environment, MWScript::Locals *locals, MWWorld::Ptr reference) : mEnvironment (environment), mLocals (locals), mReference (reference) @@ -166,6 +202,24 @@ namespace MWScript return mEnvironment.mFrameDuration; } + bool InterpreterContext::isDisabled (const std::string& id) const + { + CPtrWithCell ref = getReference (id, false); + return !ref.first.getRefData().isEnabled(); + } + + void InterpreterContext::enable (const std::string& id) + { + PtrWithCell ref = getReference (id, false); + mEnvironment.mWorld->enable (ref); + } + + void InterpreterContext::disable (const std::string& id) + { + PtrWithCell ref = getReference (id, false); + mEnvironment.mWorld->disable (ref); + } + MWGui::GuiManager& InterpreterContext::getGuiManager() { return *mEnvironment.mGuiManager; diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 9477562620..bdc871a019 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -5,11 +5,7 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/environment.hpp" - -namespace MWWorld -{ - class World; -} +#include "../mwworld/world.hpp" namespace MWSound { @@ -26,6 +22,13 @@ namespace MWScript Locals *mLocals; MWWorld::Ptr mReference; + typedef std::pair PtrWithCell; + typedef std::pair CPtrWithCell; + + PtrWithCell getReference (const std::string& id, bool activeOnly); + + CPtrWithCell getReference (const std::string& id, bool activeOnly) const; + public: InterpreterContext (MWWorld::Environment& environment, @@ -73,6 +76,12 @@ namespace MWScript 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(); diff --git a/apps/openmw/mwworld/refdata.hpp b/apps/openmw/mwworld/refdata.hpp index a7e137b9dd..58c169c0e5 100644 --- a/apps/openmw/mwworld/refdata.hpp +++ b/apps/openmw/mwworld/refdata.hpp @@ -20,10 +20,11 @@ namespace MWWorld // object in the refdata of refs without a script, // we can make this a pointer later. bool mHasLocals; + bool mEnabled; public: - RefData() : mHasLocals (false) {} + RefData() : mHasLocals (false), mEnabled (true) {} std::string getHandle() { @@ -48,6 +49,21 @@ namespace MWWorld { return mLocals; } + + bool isEnabled() const + { + return mEnabled; + } + + void enable() + { + mEnabled = true; + } + + void disable() + { + mEnabled = true; + } }; } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 01f03b6410..8fb635ef30 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -9,6 +9,8 @@ #include "apps/openmw/mwrender/sky.hpp" #include "apps/openmw/mwrender/interior.hpp" +#include "ptr.hpp" + namespace { template @@ -31,6 +33,20 @@ namespace } } } + + template + bool hasReference (ESMS::CellRefList& cellRefList, const MWWorld::Ptr& ptr) + { + for (typename ESMS::CellRefList::List::iterator iter ( + cellRefList.list.begin()); + iter!=cellRefList.list.end(); ++iter) + { + if (&iter->mData==&ptr.getRefData()) + return true; + } + + return false; + } } namespace MWWorld @@ -121,6 +137,24 @@ namespace MWWorld return Ptr(); } + MWRender::CellRender *World::searchRender (CellStore *store) + { + CellRenderCollection::iterator iter = mActiveCells.find (store); + + if (iter!=mActiveCells.end()) + { + return iter->second; + } + else + { + iter = mBufferedCells.find (store); + if (iter!=mBufferedCells.end()) + return iter->second; + } + + return 0; + } + World::World (Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir, const std::string& master, const std::string& startCell, bool newGame) : mSkyManager (0), mScene (renderer), mPlayerPos (0) @@ -245,4 +279,59 @@ namespace MWWorld throw std::runtime_error ("unknown ID: " + name); } + + void World::enable (std::pair& reference) + { + if (!reference.first.getRefData().isEnabled()) + { + reference.first.getRefData().enable(); + + if (MWRender::CellRender *render = searchRender (reference.second)) + { + render->enable (reference.first.getRefData().getHandle()); + } + } + } + + void World::disable (std::pair& reference) + { + if (!reference.first.getRefData().isEnabled()) + { + reference.first.getRefData().enable(); + + if (MWRender::CellRender *render = searchRender (reference.second)) + { + render->disable (reference.first.getRefData().getHandle()); + } + } + } + + World::CellStore *World::find (const Ptr& ptr) + { + for (CellRenderCollection::iterator iter (mActiveCells.begin()); iter!=mActiveCells.end(); + ++iter) + { + if ( + hasReference (iter->first->activators, ptr) || + hasReference (iter->first->potions, ptr) || + hasReference (iter->first->appas, ptr) || + hasReference (iter->first->armors, ptr) || + hasReference (iter->first->books, ptr) || + hasReference (iter->first->clothes, ptr) || + hasReference (iter->first->containers, ptr) || + hasReference (iter->first->creatures, ptr) || + hasReference (iter->first->doors, ptr) || + hasReference (iter->first->ingreds, ptr) || + hasReference (iter->first->lights, ptr) || + hasReference (iter->first->lockpicks, ptr) || + hasReference (iter->first->miscItems, ptr) || + hasReference (iter->first->npcs, ptr) || + hasReference (iter->first->probes, ptr) || + hasReference (iter->first->repairs, ptr) || + hasReference (iter->first->weapons, ptr)) + return iter->first; + } + + throw std::runtime_error ("failed to locate reference in active cell"); + } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 74a1ee159e..0c299b9f94 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -61,6 +61,8 @@ namespace MWWorld Ptr getPtr (const std::string& name, CellStore& cellStore); + MWRender::CellRender *searchRender (CellStore *store); + public: World (Render::OgreRenderer& renderer, const boost::filesystem::path& master, @@ -83,6 +85,13 @@ namespace MWWorld std::pair getPtr (const std::string& name, bool activeOnly); ///< Return a pointer to a liveCellRef with the given name. /// \param activeOnly do non search inactive cells. + + void enable (std::pair& reference); + + void disable (std::pair& reference); + + CellStore *find (const Ptr& ptr); + ///< Only active cells are searched. }; } diff --git a/components/compiler/context.hpp b/components/compiler/context.hpp index b34297cce0..929119cf40 100644 --- a/components/compiler/context.hpp +++ b/components/compiler/context.hpp @@ -31,7 +31,10 @@ namespace Compiler } virtual char getGlobalType (const std::string& name) const = 0; - ///< 'l: long, 's': short, 'f': float, ' ': does not exist. + ///< 'l: long, 's': short, 'f': float, ' ': does not exist. + + virtual bool isId (const std::string& name) const = 0; + ///< Does \a name match an ID, that can be referenced? }; } diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index fdf8feedf5..e11dde5215 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -203,6 +203,9 @@ namespace Compiler bool ExprParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner) { + if (!mExplicit.empty()) + return Parser::parseInt (value, loc, scanner); + mFirst = false; if (mNextOperand) @@ -221,6 +224,9 @@ namespace Compiler bool ExprParser::parseFloat (float value, const TokenLoc& loc, Scanner& scanner) { + if (!mExplicit.empty()) + return Parser::parseFloat (value, loc, scanner); + mFirst = false; if (mNextOperand) @@ -240,6 +246,9 @@ namespace Compiler bool ExprParser::parseName (const std::string& name, const TokenLoc& loc, Scanner& scanner) { + if (!mExplicit.empty()) + return Parser::parseName (name, loc, scanner); + mFirst = false; if (mNextOperand) @@ -255,7 +264,6 @@ namespace Compiler mOperands.push_back (type=='f' ? 'f' : 'l'); return true; } - type = getContext().getGlobalType (name2); @@ -266,6 +274,12 @@ namespace Compiler mOperands.push_back (type=='f' ? 'f' : 'l'); return true; } + + if (mExplicit.empty() && getContext().isId (name)) + { + mExplicit = name; + return true; + } } else { @@ -280,7 +294,28 @@ namespace Compiler bool ExprParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner) { mFirst = false; + + if (!mExplicit.empty()) + { + if (mRefOp && mNextOperand) + { + if (keyword==Scanner::K_getdisabled) + { + mTokenLoc = loc; + Generator::getDisabled (mCode, mLiterals, mExplicit); + mOperands.push_back ('l'); + mExplicit.clear(); + mRefOp = false; + + mNextOperand = false; + return true; + } + } + + return Parser::parseKeyword (keyword, loc, scanner); + } + if (mNextOperand) { if (keyword==Scanner::K_getsquareroot) @@ -346,7 +381,17 @@ namespace Compiler mNextOperand = false; return true; - } + } + else if (keyword==Scanner::K_getdisabled) + { + mTokenLoc = loc; + + Generator::getDisabled (mCode, mLiterals, ""); + mOperands.push_back ('l'); + + mNextOperand = false; + return true; + } else { // check for custom extensions @@ -381,6 +426,17 @@ namespace Compiler bool ExprParser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner) { + if (!mExplicit.empty()) + { + if (!mRefOp && code==Scanner::S_ref) + { + mRefOp = true; + return true; + } + + return Parser::parseSpecial (code, loc, scanner); + } + if (code==Scanner::S_comma) { mTokenLoc = loc; @@ -488,6 +544,8 @@ namespace Compiler mNextOperand = true; mCode.clear(); mFirst = true; + mExplicit.clear(); + mRefOp = false; } char ExprParser::append (std::vector& code) diff --git a/components/compiler/exprparser.hpp b/components/compiler/exprparser.hpp index b8f295b5c1..0dd8c871ac 100644 --- a/components/compiler/exprparser.hpp +++ b/components/compiler/exprparser.hpp @@ -24,6 +24,8 @@ namespace Compiler std::vector mCode; bool mFirst; bool mArgument; + std::string mExplicit; + bool mRefOp; int getPriority (char op) const; diff --git a/components/compiler/fileparser.cpp b/components/compiler/fileparser.cpp index 6e3e1de69e..6e26f48d60 100644 --- a/components/compiler/fileparser.cpp +++ b/components/compiler/fileparser.cpp @@ -75,6 +75,12 @@ namespace Compiler { if (code==Scanner::S_newline) { + if (mState==BeginState) + { + // ignore empty lines + return true; + } + if (mState==BeginCompleteState) { // parse the script body diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index 27448e37d6..ece1bebaf9 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -284,6 +284,36 @@ namespace { code.push_back (Compiler::Generator::segment5 (50)); } + + void opEnable (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (51)); + } + + void opDisable (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (52)); + } + + void opGetDisabled (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (53)); + } + + void opEnableExplicit (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (54)); + } + + void opDisableExplicit (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (55)); + } + + void opGetDisabledExplicit (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (56)); + } } namespace Compiler @@ -685,6 +715,48 @@ namespace Compiler { opGetSecondsPassed (code); } + + void getDisabled (CodeContainer& code, Literals& literals, const std::string id) + { + if (id.empty()) + { + opGetDisabled (code); + } + else + { + int index = literals.addString (id); + opPushInt (code, index); + opGetDisabledExplicit (code); + } + } + + void enable (CodeContainer& code, Literals& literals, const std::string id) + { + if (id.empty()) + { + opEnable (code); + } + else + { + int index = literals.addString (id); + opPushInt (code, index); + opEnableExplicit (code); + } + } + + void disable (CodeContainer& code, Literals& literals, const std::string id) + { + if (id.empty()) + { + opDisable (code); + } + else + { + int index = literals.addString (id); + opPushInt (code, index); + opDisableExplicit (code); + } + } } } diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp index 3df789f617..9623b7226b 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -110,6 +110,12 @@ namespace Compiler void getDistance (CodeContainer& code); void getSecondsPassed (CodeContainer& code); + + void getDisabled (CodeContainer& code, Literals& literals, const std::string id); + + void enable (CodeContainer& code, Literals& literals, const std::string id); + + void disable (CodeContainer& code, Literals& literals, const std::string id); } } diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 5a254a8043..d46d5f0937 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -129,11 +129,36 @@ namespace Compiler return false; } + if (mState==BeginState && getContext().isId (name)) + { + mState = PotentialExplicitState; + mExplicit = toLower (name); + return true; + } + return Parser::parseName (name, loc, scanner); } bool LineParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner) { + if (mState==BeginState || mState==ExplicitState) + { + switch (keyword) + { + case Scanner::K_enable: + + Generator::enable (mCode, mLiterals, mExplicit); + mState = EndState; + return true; + + case Scanner::K_disable: + + Generator::disable (mCode, mLiterals, mExplicit); + mState = EndState; + return true; + } + } + if (mState==BeginState) { switch (keyword) @@ -162,7 +187,7 @@ namespace Compiler mExprParser.parseArguments ("c", scanner, mCode, true); Generator::stopScript (mCode); mState = EndState; - return true; + return true; } // check for custom extensions @@ -221,6 +246,12 @@ namespace Compiler mState = MessageCommaState; return true; } + + if (code==Scanner::S_ref && mState==PotentialExplicitState) + { + mState = ExplicitState; + return true; + } return Parser::parseSpecial (code, loc, scanner); } @@ -229,6 +260,7 @@ namespace Compiler { mState = BeginState; mName.clear(); + mExplicit.clear(); } } diff --git a/components/compiler/lineparser.hpp b/components/compiler/lineparser.hpp index 63efb60a47..717d734510 100644 --- a/components/compiler/lineparser.hpp +++ b/components/compiler/lineparser.hpp @@ -23,7 +23,8 @@ namespace Compiler ShortState, LongState, FloatState, SetState, SetLocalVarState, SetGlobalVarState, MessageState, MessageCommaState, - EndState + EndState, + PotentialExplicitState, ExplicitState }; Locals& mLocals; @@ -31,6 +32,7 @@ namespace Compiler std::vector& mCode; State mState; std::string mName; + std::string mExplicit; char mType; ExprParser mExprParser; diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index 8899d561cc..6f43f9fde9 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -247,6 +247,7 @@ namespace Compiler "startscript", "stopscript", "scriptrunning", "getdistance", "getsecondspassed", + "enable", "disable", "getdisabled", 0 }; diff --git a/components/compiler/scanner.hpp b/components/compiler/scanner.hpp index 9e6e6a7d18..99fca52292 100644 --- a/components/compiler/scanner.hpp +++ b/components/compiler/scanner.hpp @@ -53,7 +53,8 @@ namespace Compiler K_random, K_startscript, K_stopscript, K_scriptrunning, K_getdistance, - K_getsecondspassed + K_getsecondspassed, + K_enable, K_disable, K_getdisabled }; enum special diff --git a/components/esm_store/cell_store.hpp b/components/esm_store/cell_store.hpp index 444c3e1afb..941dba6fe2 100644 --- a/components/esm_store/cell_store.hpp +++ b/components/esm_store/cell_store.hpp @@ -175,8 +175,6 @@ namespace ESMS std::cout << "WARNING: Ignoring reference '" << ref.refID << "' of unhandled type\n"; } } - - std::cout << "Statics in cell: " << statics.list.size() << std::endl; } }; diff --git a/components/interpreter/context.hpp b/components/interpreter/context.hpp index 34b78d580f..aae0051bdf 100644 --- a/components/interpreter/context.hpp +++ b/components/interpreter/context.hpp @@ -55,7 +55,13 @@ namespace Interpreter virtual float getDistance (const std::string& name) const = 0; - virtual float getSecondsPassed() const = 0; + virtual float getSecondsPassed() const = 0; + + virtual bool isDisabled (const std::string& id = "") const = 0; + + virtual void enable (const std::string& id = "") = 0; + + virtual void disable (const std::string& id = "") = 0; }; } diff --git a/components/interpreter/docs/vmformat.txt b/components/interpreter/docs/vmformat.txt index 12225e865a..dcf204473b 100644 --- a/components/interpreter/docs/vmformat.txt +++ b/components/interpreter/docs/vmformat.txt @@ -109,6 +109,12 @@ op 47: start script stack[0] and pop op 48: stop script stack[0] and pop op 49: replace stack[0] with distance between implicit reference and a reference of ID stack[0] op 50: push frame duration (float) -opcodes 51-33554431 unused +op 51: enable implicit reference +op 52: disable implicit reference +op 53: push 1, if implicit reference is disabled, 0 else +op 54: explicit reference = stack[0]; pop; enable explicit reference +op 55: explicit reference = stack[0]; pop; disable explicit reference +op 56: explicit reference = stack[0]; pop; push 1, if explicit reference is disabled, 0 else +opcodes 57-33554431 unused opcodes 33554432-67108863 reserved for extensions diff --git a/components/interpreter/installopcodes.cpp b/components/interpreter/installopcodes.cpp index 302812ad69..522f77b953 100644 --- a/components/interpreter/installopcodes.cpp +++ b/components/interpreter/installopcodes.cpp @@ -89,7 +89,13 @@ namespace Interpreter interpreter.installSegment5 (38, new OpMenuMode); interpreter.installSegment5 (45, new OpRandom); interpreter.installSegment5 (50, new OpGetSecondsPassed); - + interpreter.installSegment5 (51, new OpEnable); + interpreter.installSegment5 (52, new OpDisable); + interpreter.installSegment5 (53, new OpGetDisabled); + interpreter.installSegment5 (54, new OpEnableExplicit); + interpreter.installSegment5 (55, new OpDisableExplicit); + interpreter.installSegment5 (56, new OpGetDisabledExplicit); + // script control interpreter.installSegment5 (46, new OpScriptRunning); interpreter.installSegment5 (47, new OpStartScript); diff --git a/components/interpreter/miscopcodes.hpp b/components/interpreter/miscopcodes.hpp index 17acb72db3..852d2d154d 100644 --- a/components/interpreter/miscopcodes.hpp +++ b/components/interpreter/miscopcodes.hpp @@ -130,6 +130,79 @@ namespace Interpreter runtime.push (*reinterpret_cast (&duration)); } }; + + class OpEnable : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + runtime.getContext().enable(); + } + }; + + class OpDisable : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + runtime.getContext().disable(); + } + }; + + class OpGetDisabled : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + runtime.push (runtime.getContext().isDisabled()); + } + }; + + class OpEnableExplicit : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + int index = runtime[0]; + runtime.pop(); + std::string id = runtime.getStringLiteral (index); + + runtime.getContext().enable (id); + } + }; + + class OpDisableExplicit : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + int index = runtime[0]; + runtime.pop(); + std::string id = runtime.getStringLiteral (index); + + runtime.getContext().disable (id); + } + }; + + class OpGetDisabledExplicit : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + int index = runtime[0]; + runtime.pop(); + std::string id = runtime.getStringLiteral (index); + + runtime.push (runtime.getContext().isDisabled (id)); + } + }; + } #endif