diff --git a/apps/mwinterpreter/context.cpp b/apps/mwinterpreter/context.cpp index e09626198..cbe379f0f 100644 --- a/apps/mwinterpreter/context.cpp +++ b/apps/mwinterpreter/context.cpp @@ -120,14 +120,14 @@ namespace SAInterpreter return 0; } - bool Context::isDisabled() const + bool Context::isDisabled (const std::string& id) const { return false; } - void Context::enable() {} + void Context::enable (const std::string& id) {} - void Context::disable() {} + void Context::disable (const std::string& id) {} void Context::report() { diff --git a/apps/mwinterpreter/context.hpp b/apps/mwinterpreter/context.hpp index d3e61df78..1ee3129f7 100644 --- a/apps/mwinterpreter/context.hpp +++ b/apps/mwinterpreter/context.hpp @@ -62,11 +62,11 @@ namespace SAInterpreter virtual float getSecondsPassed() const; - virtual bool isDisabled() const; + virtual bool isDisabled (const std::string& id = "") const; - virtual void enable(); + virtual void enable (const std::string& id = ""); - virtual void disable(); + virtual void disable (const std::string& id = ""); void report(); ///< Write state to std::cout diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 7e57e5aea..064ac583d 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,33 +202,21 @@ namespace MWScript return mEnvironment.mFrameDuration; } - bool InterpreterContext::isDisabled() const + bool InterpreterContext::isDisabled (const std::string& id) const { - if (mReference.isEmpty()) - throw std::runtime_error ("no implicit reference"); - - return !mReference.getRefData().isEnabled(); + CPtrWithCell ref = getReference (id, false); + return !ref.first.getRefData().isEnabled(); } - void InterpreterContext::enable() + void InterpreterContext::enable (const std::string& id) { - if (mReference.isEmpty()) - throw std::runtime_error ("no implicit reference"); - - std::pair ref - (mReference, mEnvironment.mWorld->find (mReference)); - + PtrWithCell ref = getReference (id, false); mEnvironment.mWorld->enable (ref); } - void InterpreterContext::disable() + void InterpreterContext::disable (const std::string& id) { - if (mReference.isEmpty()) - throw std::runtime_error ("no implicit reference"); - - std::pair ref - (mReference, mEnvironment.mWorld->find (mReference)); - + PtrWithCell ref = getReference (id, false); mEnvironment.mWorld->disable (ref); } diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 9d426aafc..bdc871a01 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,11 +76,11 @@ namespace MWScript virtual float getSecondsPassed() const; - virtual bool isDisabled() const; + virtual bool isDisabled (const std::string& id = "") const; - virtual void enable(); + virtual void enable (const std::string& id = ""); - virtual void disable(); + virtual void disable (const std::string& id = ""); MWWorld::World& getWorld(); diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index 8fae00adf..9ebd0c89a 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 (mOperands.empty() && mOperators.empty() && mExplicit.empty()) + { + 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) @@ -351,7 +386,7 @@ namespace Compiler { mTokenLoc = loc; - Generator::getDisabled (mCode); + Generator::getDisabled (mCode, mLiterals, ""); mOperands.push_back ('l'); mNextOperand = false; @@ -391,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; @@ -498,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 b8f295b5c..0dd8c871a 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/generator.cpp b/components/compiler/generator.cpp index 4b6014e55..ece1bebaf 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -300,6 +300,20 @@ namespace 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 @@ -702,19 +716,46 @@ namespace Compiler opGetSecondsPassed (code); } - void getDisabled (CodeContainer& code) + void getDisabled (CodeContainer& code, Literals& literals, const std::string id) { - opGetDisabled (code); + if (id.empty()) + { + opGetDisabled (code); + } + else + { + int index = literals.addString (id); + opPushInt (code, index); + opGetDisabledExplicit (code); + } } - void enable (CodeContainer& code) + void enable (CodeContainer& code, Literals& literals, const std::string id) { - opEnable (code); + if (id.empty()) + { + opEnable (code); + } + else + { + int index = literals.addString (id); + opPushInt (code, index); + opEnableExplicit (code); + } } - void disable (CodeContainer& code) + void disable (CodeContainer& code, Literals& literals, const std::string id) { - opDisable (code); + 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 4a043ecdb..9623b7226 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -111,11 +111,11 @@ namespace Compiler void getSecondsPassed (CodeContainer& code); - void getDisabled (CodeContainer& code); + void getDisabled (CodeContainer& code, Literals& literals, const std::string id); - void enable (CodeContainer& code); + void enable (CodeContainer& code, Literals& literals, const std::string id); - void disable (CodeContainer& code); + void disable (CodeContainer& code, Literals& literals, const std::string id); } } diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index b1acbec45..0b5f563d0 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -129,11 +129,36 @@ namespace Compiler return false; } + if (mState==BeginState) + { + 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) @@ -163,18 +188,6 @@ namespace Compiler Generator::stopScript (mCode); mState = EndState; return true; - - case Scanner::K_enable: - - Generator::enable (mCode); - mState = EndState; - return true; - - case Scanner::K_disable: - - Generator::disable (mCode); - mState = EndState; - return true; } // check for custom extensions @@ -233,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); } @@ -241,6 +260,7 @@ namespace Compiler { mState = BeginState; mName.clear(); + mExplicit.clear(); } } diff --git a/components/compiler/lineparser.hpp b/components/compiler/lineparser.hpp index 63efb60a4..717d73451 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/interpreter/context.hpp b/components/interpreter/context.hpp index 30eb56167..aae0051bd 100644 --- a/components/interpreter/context.hpp +++ b/components/interpreter/context.hpp @@ -57,11 +57,11 @@ namespace Interpreter virtual float getSecondsPassed() const = 0; - virtual bool isDisabled() const = 0; + virtual bool isDisabled (const std::string& id = "") const = 0; - virtual void enable() = 0; + virtual void enable (const std::string& id = "") = 0; - virtual void disable() = 0; + virtual void disable (const std::string& id = "") = 0; }; } diff --git a/components/interpreter/docs/vmformat.txt b/components/interpreter/docs/vmformat.txt index 2be1fcf0a..dcf204473 100644 --- a/components/interpreter/docs/vmformat.txt +++ b/components/interpreter/docs/vmformat.txt @@ -112,6 +112,9 @@ op 50: push frame duration (float) op 51: enable implicit reference op 52: disable implicit reference op 53: push 1, if implicit reference is disabled, 0 else -opcodes 54-33554431 unused +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 e991bf937..522f77b95 100644 --- a/components/interpreter/installopcodes.cpp +++ b/components/interpreter/installopcodes.cpp @@ -92,7 +92,10 @@ namespace Interpreter 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 ba090a488..852d2d154 100644 --- a/components/interpreter/miscopcodes.hpp +++ b/components/interpreter/miscopcodes.hpp @@ -161,6 +161,48 @@ namespace Interpreter } }; + 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