diff --git a/apps/mwinterpreter/context.cpp b/apps/mwinterpreter/context.cpp index cbe379f0f..7924f1dc7 100644 --- a/apps/mwinterpreter/context.cpp +++ b/apps/mwinterpreter/context.cpp @@ -110,7 +110,7 @@ namespace SAInterpreter void Context::stopScript (const std::string& name) {} - float Context::getDistance (const std::string& name) const + float Context::getDistance (const std::string& name, const std::string& id) const { return 0; } diff --git a/apps/mwinterpreter/context.hpp b/apps/mwinterpreter/context.hpp index 1ee3129f7..6cf4f8cd7 100644 --- a/apps/mwinterpreter/context.hpp +++ b/apps/mwinterpreter/context.hpp @@ -58,7 +58,7 @@ namespace SAInterpreter virtual void stopScript (const std::string& name); - virtual float getDistance (const std::string& name) const; + virtual float getDistance (const std::string& name, const std::string& id = "") const; virtual float getSecondsPassed() const; diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 064ac583d..a0f1d9d95 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -176,18 +176,18 @@ namespace MWScript mEnvironment.mGlobalScripts->removeScript (name); } - float InterpreterContext::getDistance (const std::string& name) const + float InterpreterContext::getDistance (const std::string& name, const std::string& id) const { - if (mReference.isEmpty()) - throw std::runtime_error ("no implicit reference"); - + // TODO handle exterior cells (when ref and ref2 are located in different cells) + CPtrWithCell ref2 = getReference (id, false); + std::pair ref = mEnvironment.mWorld->getPtr (name, true); double diff[3]; for (int i=0; i<3; ++i) - diff[i] = ref.first.getCellRef().pos.pos[i] - mReference.getCellRef().pos.pos[i]; + diff[i] = ref.first.getCellRef().pos.pos[i] - ref2.first.getCellRef().pos.pos[i]; return std::sqrt (diff[0]*diff[0] + diff[1]*diff[1] + diff[2]*diff[2]); } diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index bdc871a01..14c0a9e85 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -70,7 +70,7 @@ namespace MWScript virtual void stopScript (const std::string& name); - virtual float getDistance (const std::string& name) const; + virtual float getDistance (const std::string& name, const std::string& id = "") const; virtual bool hasBeenActivated() const; diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index e11dde521..2938bbae3 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -311,6 +311,19 @@ namespace Compiler mNextOperand = false; return true; } + else if (keyword==Scanner::K_getdistance) + { + mTokenLoc = loc; + parseArguments ("c", scanner); + + Generator::getDistance (mCode, mLiterals, mExplicit); + mOperands.push_back ('f'); + mExplicit.clear(); + mRefOp = false; + + mNextOperand = false; + return true; + } } return Parser::parseKeyword (keyword, loc, scanner); @@ -360,18 +373,18 @@ namespace Compiler mNextOperand = false; return true; - } + } else if (keyword==Scanner::K_getdistance) { mTokenLoc = loc; parseArguments ("c", scanner); - Generator::getDistance (mCode); + Generator::getDistance (mCode, mLiterals, ""); mOperands.push_back ('f'); mNextOperand = false; return true; - } + } else if (keyword==Scanner::K_getsecondspassed) { mTokenLoc = loc; diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index ece1bebaf..0be2c4151 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -314,6 +314,11 @@ namespace { code.push_back (Compiler::Generator::segment5 (56)); } + + void opGetDistanceExplicit (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (57)); + } } namespace Compiler @@ -706,9 +711,18 @@ namespace Compiler opStopScript (code); } - void getDistance (CodeContainer& code) + void getDistance (CodeContainer& code, Literals& literals, const std::string id) { - opGetDistance (code); + if (id.empty()) + { + opGetDistance (code); + } + else + { + int index = literals.addString (id); + opPushInt (code, index); + opGetDistanceExplicit (code); + } } void getSecondsPassed (CodeContainer& code) diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp index 9623b7226..a7559f7e9 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -107,7 +107,7 @@ namespace Compiler void stopScript (CodeContainer& code); - void getDistance (CodeContainer& code); + void getDistance (CodeContainer& code, Literals& literals, const std::string id); void getSecondsPassed (CodeContainer& code); diff --git a/components/interpreter/context.hpp b/components/interpreter/context.hpp index aae0051bd..0d77903f4 100644 --- a/components/interpreter/context.hpp +++ b/components/interpreter/context.hpp @@ -53,7 +53,8 @@ namespace Interpreter virtual void stopScript (const std::string& name) = 0; - virtual float getDistance (const std::string& name) const = 0; + virtual float getDistance (const std::string& name, const std::string& id = "") const + = 0; virtual float getSecondsPassed() const = 0; diff --git a/components/interpreter/docs/vmformat.txt b/components/interpreter/docs/vmformat.txt index dcf204473..40ce3535b 100644 --- a/components/interpreter/docs/vmformat.txt +++ b/components/interpreter/docs/vmformat.txt @@ -115,6 +115,8 @@ 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 +op 57: explicit reference = stack[0]; pop; + replace stack[0] with distance between explicit reference and a reference of ID stack[0] +opcodes 58-33554431 unused opcodes 33554432-67108863 reserved for extensions diff --git a/components/interpreter/installopcodes.cpp b/components/interpreter/installopcodes.cpp index 522f77b95..2e22d10e5 100644 --- a/components/interpreter/installopcodes.cpp +++ b/components/interpreter/installopcodes.cpp @@ -103,6 +103,7 @@ namespace Interpreter // spacial interpreter.installSegment5 (49, new OpGetDistance); + interpreter.installSegment5 (57, new OpGetDistanceExplicit); } } diff --git a/components/interpreter/spatialopcodes.hpp b/components/interpreter/spatialopcodes.hpp index 2a401ae8a..d897ff69d 100644 --- a/components/interpreter/spatialopcodes.hpp +++ b/components/interpreter/spatialopcodes.hpp @@ -19,6 +19,24 @@ namespace Interpreter runtime[0] = *reinterpret_cast (&distance); } }; + + class OpGetDistanceExplicit : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + int index = runtime[0]; + runtime.pop(); + std::string id = runtime.getStringLiteral (index); + + std::string name = runtime.getStringLiteral (runtime[0]); + + float distance = runtime.getContext().getDistance (name, id); + + runtime[0] = *reinterpret_cast (&distance); + } + }; } #endif