From 72fca4009057169a63b05da9ff86d5f75ec2f1b7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 7 Jun 2012 11:59:45 +0200 Subject: [PATCH 01/16] Issue #181: member variable access in interpreter context --- apps/openmw/mwscript/interpretercontext.cpp | 66 +++++++++++++++++++++ apps/openmw/mwscript/interpretercontext.hpp | 12 ++++ apps/openmw/mwscript/scriptmanager.cpp | 39 ++++++++++++ apps/openmw/mwscript/scriptmanager.hpp | 4 ++ components/interpreter/context.hpp | 13 ++++ 5 files changed, 134 insertions(+) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index a369486faf..55059b5224 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -270,6 +270,72 @@ namespace MWScript MWBase::Environment::get().getWorld()->disable (ref); } + int InterpreterContext::getMemberShort (const std::string& id, const std::string& name) const + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's'); + + return ptr.getRefData().getLocals().mShorts[index]; + } + + int InterpreterContext::getMemberLong (const std::string& id, const std::string& name) const + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l'); + + return ptr.getRefData().getLocals().mLongs[index]; + } + + float InterpreterContext::getMemberFloat (const std::string& id, const std::string& name) const + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f'); + + return ptr.getRefData().getLocals().mFloats[index]; + } + + void InterpreterContext::setMemberShort (const std::string& id, const std::string& name, int value) + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's'); + + ptr.getRefData().getLocals().mShorts[index] = value; + } + + void InterpreterContext::setMemberLong (const std::string& id, const std::string& name, int value) + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l'); + + ptr.getRefData().getLocals().mLongs[index] = value; + } + + void InterpreterContext::setMemberFloat (const std::string& id, const std::string& name, float value) + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f'); + + ptr.getRefData().getLocals().mFloats[index] = value; + } + MWWorld::Ptr InterpreterContext::getReference() { return getReference ("", true); diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 40f53337db..9fdc3c21a0 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -107,6 +107,18 @@ namespace MWScript virtual void disable (const std::string& id = ""); + virtual int getMemberShort (const std::string& id, const std::string& name) const; + + virtual int getMemberLong (const std::string& id, const std::string& name) const; + + virtual float getMemberFloat (const std::string& id, const std::string& name) const; + + virtual void setMemberShort (const std::string& id, const std::string& name, int value); + + virtual void setMemberLong (const std::string& id, const std::string& name, int value); + + virtual void setMemberFloat (const std::string& id, const std::string& name, float value); + MWWorld::Ptr getReference(); ///< Reference, that the script is running from (can be empty) }; diff --git a/apps/openmw/mwscript/scriptmanager.cpp b/apps/openmw/mwscript/scriptmanager.cpp index 506cf049c4..6ae5064832 100644 --- a/apps/openmw/mwscript/scriptmanager.cpp +++ b/apps/openmw/mwscript/scriptmanager.cpp @@ -156,4 +156,43 @@ namespace MWScript { return mGlobalScripts; } + + int ScriptManager::getLocalIndex (const std::string& scriptId, const std::string& variable, + char type) + { + const ESM::Script *script = mStore.scripts.find (scriptId); + + int offset = 0; + int size = 0; + + switch (type) + { + case 's': + + offset = 0; + size = script->data.numShorts; + break; + + case 'l': + + offset = script->data.numShorts; + size = script->data.numLongs; + break; + + case 'f': + + offset = script->data.numShorts+script->data.numLongs; + size = script->data.numFloats; + + default: + + throw std::runtime_error ("invalid variable type"); + } + + for (int i=0; ivarNames.at (i+offset)==variable) + return i; + + throw std::runtime_error ("unable to access local variable " + variable + " of " + scriptId); + } } diff --git a/apps/openmw/mwscript/scriptmanager.hpp b/apps/openmw/mwscript/scriptmanager.hpp index 35c1fadd9e..34cc0defec 100644 --- a/apps/openmw/mwscript/scriptmanager.hpp +++ b/apps/openmw/mwscript/scriptmanager.hpp @@ -67,6 +67,10 @@ namespace MWScript ///< Return locals for script \a name. GlobalScripts& getGlobalScripts(); + + int getLocalIndex (const std::string& scriptId, const std::string& variable, char type); + ///< Return index of the variable of the given name and type in the given script. Will + /// throw an exception, if there is no such script or variable or the type does not match. }; }; diff --git a/components/interpreter/context.hpp b/components/interpreter/context.hpp index 973b22d350..4221da36ed 100644 --- a/components/interpreter/context.hpp +++ b/components/interpreter/context.hpp @@ -65,6 +65,19 @@ namespace Interpreter virtual void enable (const std::string& id = "") = 0; virtual void disable (const std::string& id = "") = 0; + + virtual int getMemberShort (const std::string& id, const std::string& name) const = 0; + + virtual int getMemberLong (const std::string& id, const std::string& name) const = 0; + + virtual float getMemberFloat (const std::string& id, const std::string& name) const = 0; + + virtual void setMemberShort (const std::string& id, const std::string& name, int value) = 0; + + virtual void setMemberLong (const std::string& id, const std::string& name, int value) = 0; + + virtual void setMemberFloat (const std::string& id, const std::string& name, float value) + = 0; }; } From ce43ff8d0520729e4d36e7b3fd40e7460d3e2909 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 7 Jun 2012 13:56:49 +0200 Subject: [PATCH 02/16] Issue #181: added member variable access opcodes --- components/interpreter/docs/vmformat.txt | 8 +- components/interpreter/installopcodes.cpp | 6 + components/interpreter/localopcodes.hpp | 217 ++++++++++++++++------ 3 files changed, 178 insertions(+), 53 deletions(-) diff --git a/components/interpreter/docs/vmformat.txt b/components/interpreter/docs/vmformat.txt index 3e513aa44e..91e0c060e7 100644 --- a/components/interpreter/docs/vmformat.txt +++ b/components/interpreter/docs/vmformat.txt @@ -121,5 +121,11 @@ op 58: report string literal index in stack[0]; additional arguments (if any) in stack[n]..stack[1]; n is determined according to the message string all arguments are removed from stack -opcodes 59-33554431 unused +op 59: store stack[0] in member short stack[2] of object with ID stack[1] +op 60: store stack[0] in member long stack[2] of object with ID stack[1] +op 61: store stack[0] in member float stack[2] of object with ID stack[1] +op 62: replace stack[0] with member short stack[1] of object with ID stack[0] +op 63: replace stack[0] with member short stack[1] of object with ID stack[0] +op 64: replace stack[0] with member short stack[1] of object with ID stack[0] +opcodes 65-33554431 unused opcodes 33554432-67108863 reserved for extensions diff --git a/components/interpreter/installopcodes.cpp b/components/interpreter/installopcodes.cpp index 556477af25..05f71f1cca 100644 --- a/components/interpreter/installopcodes.cpp +++ b/components/interpreter/installopcodes.cpp @@ -40,6 +40,12 @@ namespace Interpreter interpreter.installSegment5 (42, new OpFetchGlobalShort); interpreter.installSegment5 (43, new OpFetchGlobalLong); interpreter.installSegment5 (44, new OpFetchGlobalFloat); + interpreter.installSegment5 (59, new OpStoreMemberShort); + interpreter.installSegment5 (60, new OpStoreMemberLong); + interpreter.installSegment5 (61, new OpStoreMemberFloat); + interpreter.installSegment5 (62, new OpFetchMemberShort); + interpreter.installSegment5 (63, new OpFetchMemberLong); + interpreter.installSegment5 (64, new OpFetchMemberFloat); // math interpreter.installSegment5 (9, new OpAddInt); diff --git a/components/interpreter/localopcodes.hpp b/components/interpreter/localopcodes.hpp index ea62b7ad89..852fa7099b 100644 --- a/components/interpreter/localopcodes.hpp +++ b/components/interpreter/localopcodes.hpp @@ -6,11 +6,11 @@ #include "context.hpp" namespace Interpreter -{ +{ class OpStoreLocalShort : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Integer data = runtime[0].mInteger; @@ -20,13 +20,13 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } + } }; - + class OpStoreLocalLong : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Integer data = runtime[0].mInteger; @@ -36,13 +36,13 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } - }; - + } + }; + class OpStoreLocalFloat : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Float data = runtime[0].mFloat; @@ -52,71 +52,71 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } + } }; - + class OpFetchIntLiteral : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Integer intValue = runtime.getIntegerLiteral (runtime[0].mInteger); runtime[0].mInteger = intValue; - } - }; - + } + }; + class OpFetchFloatLiteral : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Float floatValue = runtime.getFloatLiteral (runtime[0].mInteger); runtime[0].mFloat = floatValue; - } - }; - + } + }; + class OpFetchLocalShort : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { int index = runtime[0].mInteger; int value = runtime.getContext().getLocalShort (index); runtime[0].mInteger = value; - } - }; + } + }; class OpFetchLocalLong : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { - int index = runtime[0].mInteger; + int index = runtime[0].mInteger; int value = runtime.getContext().getLocalLong (index); runtime[0].mInteger = value; - } - }; + } + }; class OpFetchLocalFloat : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { int index = runtime[0].mInteger; float value = runtime.getContext().getLocalFloat (index); runtime[0].mFloat = value; - } - }; - + } + }; + class OpStoreGlobalShort : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Integer data = runtime[0].mInteger; @@ -128,13 +128,13 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } + } }; - + class OpStoreGlobalLong : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Integer data = runtime[0].mInteger; @@ -146,13 +146,13 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } - }; - + } + }; + class OpStoreGlobalFloat : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Float data = runtime[0].mFloat; @@ -164,48 +164,161 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } + } }; - + class OpFetchGlobalShort : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { - int index = runtime[0].mInteger; + int index = runtime[0].mInteger; std::string name = runtime.getStringLiteral (index); Type_Integer value = runtime.getContext().getGlobalShort (name); runtime[0].mInteger = value; - } - }; + } + }; class OpFetchGlobalLong : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { - int index = runtime[0].mInteger; + int index = runtime[0].mInteger; std::string name = runtime.getStringLiteral (index); Type_Integer value = runtime.getContext().getGlobalLong (name); runtime[0].mInteger = value; - } - }; + } + }; class OpFetchGlobalFloat : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { int index = runtime[0].mInteger; std::string name = runtime.getStringLiteral (index); Type_Float value = runtime.getContext().getGlobalFloat (name); runtime[0].mFloat = value; - } - }; + } + }; + + class OpStoreMemberShort : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer data = runtime[0].mInteger; + Type_Integer index = runtime[1].mInteger; + std::string id = runtime.getStringLiteral (index); + index = runtime[2].mInteger; + std::string variable = runtime.getStringLiteral (index); + + runtime.getContext().setMemberShort (id, variable, data); + + runtime.pop(); + runtime.pop(); + runtime.pop(); + } + }; + + class OpStoreMemberLong : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer data = runtime[0].mInteger; + Type_Integer index = runtime[1].mInteger; + std::string id = runtime.getStringLiteral (index); + index = runtime[2].mInteger; + std::string variable = runtime.getStringLiteral (index); + + runtime.getContext().setMemberLong (id, variable, data); + + runtime.pop(); + runtime.pop(); + runtime.pop(); + } + }; + + class OpStoreMemberFloat : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer index = runtime[0].mInteger; + std::string id = runtime.getStringLiteral (index); + Type_Float data = runtime[1].mFloat; + index = runtime[2].mInteger; + std::string variable = runtime.getStringLiteral (index); + + runtime.getContext().setMemberFloat (id, variable, data); + + runtime.pop(); + runtime.pop(); + runtime.pop(); + } + }; + + class OpFetchMemberShort : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer index = runtime[0].mInteger; + std::string id = runtime.getStringLiteral (index); + index = runtime[1].mInteger; + std::string variable = runtime.getStringLiteral (index); + runtime.pop(); + + index = runtime[0].mInteger; + int value = runtime.getContext().getMemberShort (id, variable); + runtime[0].mInteger = value; + } + }; + + class OpFetchMemberLong : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer index = runtime[0].mInteger; + std::string id = runtime.getStringLiteral (index); + index = runtime[1].mInteger; + std::string variable = runtime.getStringLiteral (index); + runtime.pop(); + + index = runtime[0].mInteger; + int value = runtime.getContext().getMemberLong (id, variable); + runtime[0].mInteger = value; + } + }; + + class OpFetchMemberFloat : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer index = runtime[0].mInteger; + std::string id = runtime.getStringLiteral (index); + index = runtime[1].mInteger; + std::string variable = runtime.getStringLiteral (index); + runtime.pop(); + + index = runtime[0].mInteger; + float value = runtime.getContext().getMemberFloat (id, variable); + runtime[0].mFloat = value; + } + }; } #endif - From 050559d2e2f20883faa15aa7426369d0189d8627 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 10:31:33 +0200 Subject: [PATCH 03/16] Issue #181: added member variable access token --- components/compiler/scanner.cpp | 2 ++ components/compiler/scanner.hpp | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index d0397e8cf1..962699dfa4 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -360,6 +360,8 @@ namespace Compiler special = S_open; else if (c==')') special = S_close; + else if (c=='.') + special = S_member; else if (c=='=') { if (get (c)) diff --git a/components/compiler/scanner.hpp b/components/compiler/scanner.hpp index 53cb92ef26..19f4ca96ad 100644 --- a/components/compiler/scanner.hpp +++ b/components/compiler/scanner.hpp @@ -65,7 +65,8 @@ namespace Compiler S_cmpEQ, S_cmpNE, S_cmpLT, S_cmpLE, S_cmpGT, S_cmpGE, S_plus, S_minus, S_mult, S_div, S_comma, - S_ref + S_ref, + S_member }; private: From d1441d79e7611f7a226a816b317bc005b217b048 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 10:49:34 +0200 Subject: [PATCH 04/16] Issue #181: added code generation for member variable access --- components/compiler/generator.cpp | 112 +++++++++++++++++++++++++++++- components/compiler/generator.hpp | 6 ++ 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index 26a80387b1..b619ad67a3 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -260,6 +260,36 @@ namespace code.push_back (Compiler::Generator::segment5 (44)); } + void opStoreMemberShort (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (59)); + } + + void opStoreMemberLong (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (60)); + } + + void opStoreMemberFloat (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (61)); + } + + void opFetchMemberShort (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (62)); + } + + void opFetchMemberLong (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (63)); + } + + void opFetchMemberFloat (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (64)); + } + void opRandom (Compiler::Generator::CodeContainer& code) { code.push_back (Compiler::Generator::segment5 (45)); @@ -644,7 +674,7 @@ namespace Compiler if (localType!=valueType) { - if (localType=='f' && valueType=='l') + if (localType=='f' && (valueType=='l' || valueType=='s')) { opIntToFloat (code); } @@ -707,6 +737,86 @@ namespace Compiler } } + void assignToMember (CodeContainer& code, Literals& literals, char localType, + const std::string& name, const std::string& id, const CodeContainer& value, char valueType) + { + int index = literals.addString (name); + + opPushInt (code, index); + + index = literals.addString (id); + + opPushInt (code, index); + + std::copy (value.begin(), value.end(), std::back_inserter (code)); + + if (localType!=valueType) + { + if (localType=='f' && (valueType=='l' || valueType=='s')) + { + opIntToFloat (code); + } + else if ((localType=='l' || localType=='s') && valueType=='f') + { + opFloatToInt (code); + } + } + + switch (localType) + { + case 'f': + + opStoreMemberFloat (code); + break; + + case 's': + + opStoreMemberShort (code); + break; + + case 'l': + + opStoreMemberLong (code); + break; + + default: + + assert (0); + } + } + + void fetchMember (CodeContainer& code, Literals& literals, char localType, + const std::string& name, const std::string& id) + { + int index = literals.addString (name); + + opPushInt (code, index); + + index = literals.addString (id); + + switch (localType) + { + case 'f': + + opFetchMemberFloat (code); + break; + + case 's': + + opFetchMemberShort (code); + break; + + case 'l': + + opFetchMemberLong (code); + break; + + default: + + assert (0); + } + } + void random (CodeContainer& code) { opRandom (code); diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp index 89e1984314..feab26c93d 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -101,6 +101,12 @@ namespace Compiler void fetchGlobal (CodeContainer& code, Literals& literals, char localType, const std::string& name); + void assignToMember (CodeContainer& code, Literals& literals, char memberType, + const std::string& name, const std::string& id, const CodeContainer& value, char valueType); + + void fetchMember (CodeContainer& code, Literals& literals, char memberType, + const std::string& name, const std::string& id); + void random (CodeContainer& code); void scriptRunning (CodeContainer& code); From 6a89d76321f415942872f9c4bbdbb4e7c43f49a7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 11:52:35 +0200 Subject: [PATCH 05/16] Issue #181: Improved script error reporting for local and global scripts --- apps/openmw/mwscript/scriptmanager.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/scriptmanager.cpp b/apps/openmw/mwscript/scriptmanager.cpp index 6ae5064832..67414a06fd 100644 --- a/apps/openmw/mwscript/scriptmanager.cpp +++ b/apps/openmw/mwscript/scriptmanager.cpp @@ -11,6 +11,7 @@ #include #include +#include #include "extensions.hpp" @@ -46,8 +47,13 @@ namespace MWScript if (!mErrorHandler.isGood()) Success = false; } - catch (...) + catch (const Compiler::SourceException&) { + // error has already been reported via error handler + } + catch (const std::exception& error) + { + std::cerr << "An exception has been thrown: " << error.what() << std::endl; Success = false; } From 6c5b21fa42dcd7e66ff8640e146cbb0fc86e3649 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 13:06:23 +0200 Subject: [PATCH 06/16] Issue #181: Member variable access in expressions; error reporting fix for the previous commit --- apps/openmw/mwscript/compilercontext.cpp | 14 +++++++++ apps/openmw/mwscript/compilercontext.hpp | 3 ++ apps/openmw/mwscript/scriptmanager.cpp | 4 +++ components/compiler/context.hpp | 20 +++++++------ components/compiler/exprparser.cpp | 37 ++++++++++++++++++++++-- components/compiler/exprparser.hpp | 3 ++ 6 files changed, 70 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwscript/compilercontext.cpp b/apps/openmw/mwscript/compilercontext.cpp index 078d0da5e7..0a6ffd0c7a 100644 --- a/apps/openmw/mwscript/compilercontext.cpp +++ b/apps/openmw/mwscript/compilercontext.cpp @@ -5,6 +5,8 @@ #include "../mwworld/world.hpp" +#include "scriptmanager.hpp" + namespace MWScript { CompilerContext::CompilerContext (Type type) @@ -21,6 +23,18 @@ namespace MWScript return MWBase::Environment::get().getWorld()->getGlobalVariableType (name); } + char CompilerContext::getMemberType (const std::string& name, const std::string& id) const + { + MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPtr (id, false); + + std::string script = MWWorld::Class::get (ptr).getScript (ptr); + + if (script.empty()) + return ' '; + + return MWBase::Environment::get().getScriptManager()->getLocals (script).getType (name); + } + bool CompilerContext::isId (const std::string& name) const { return diff --git a/apps/openmw/mwscript/compilercontext.hpp b/apps/openmw/mwscript/compilercontext.hpp index 32b2f1881c..5ec98e09a7 100644 --- a/apps/openmw/mwscript/compilercontext.hpp +++ b/apps/openmw/mwscript/compilercontext.hpp @@ -30,6 +30,9 @@ namespace MWScript /// 'l: long, 's': short, 'f': float, ' ': does not exist. virtual char getGlobalType (const std::string& name) const; + virtual char getMemberType (const std::string& name, const std::string& id) const; + ///< '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/openmw/mwscript/scriptmanager.cpp b/apps/openmw/mwscript/scriptmanager.cpp index 67414a06fd..d8bd269c69 100644 --- a/apps/openmw/mwscript/scriptmanager.cpp +++ b/apps/openmw/mwscript/scriptmanager.cpp @@ -50,6 +50,7 @@ namespace MWScript catch (const Compiler::SourceException&) { // error has already been reported via error handler + Success = false; } catch (const std::exception& error) { @@ -146,6 +147,9 @@ namespace MWScript { if (!compile (name)) { + /// \todo Handle case of cyclic member variable access. Currently this could look up + /// the whole application in an endless recursion. + // failed -> ignore script from now on. std::vector empty; mScripts.insert (std::make_pair (name, std::make_pair (empty, Compiler::Locals()))); diff --git a/components/compiler/context.hpp b/components/compiler/context.hpp index 929119cf40..1b02613c59 100644 --- a/components/compiler/context.hpp +++ b/components/compiler/context.hpp @@ -10,33 +10,35 @@ namespace Compiler class Context { const Extensions *mExtensions; - + public: - + Context() : mExtensions (0) {} - + virtual ~Context() {} - + virtual bool canDeclareLocals() const = 0; ///< Is the compiler allowed to declare local variables? - + void setExtensions (const Extensions *extensions = 0) { mExtensions = extensions; } - + const Extensions *getExtensions() const { return mExtensions; } - + virtual char getGlobalType (const std::string& name) const = 0; ///< 'l: long, 's': short, 'f': float, ' ': does not exist. - + + virtual char getMemberType (const std::string& name, const std::string& id) const = 0; + ///< '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? }; } #endif - diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index 95480c0239..8041a7c8af 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -195,10 +195,31 @@ namespace Compiler return parseArguments (arguments, scanner, mCode); } + bool ExprParser::handleMemberAccess (const std::string& name) + { + mMemberOp = false; + + std::string name2 = toLower (name); + std::string id = toLower (mExplicit); + + char type = getContext().getMemberType (name2, id); + + if (type!=' ') + { + Generator::fetchMember (mCode, mLiterals, type, name2, id); + mNextOperand = false; + mExplicit.clear(); + mOperands.push_back (type=='f' ? 'f' : 'l'); + return true; + } + + return false; + } + ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals, Literals& literals, bool argument) : Parser (errorHandler, context), mLocals (locals), mLiterals (literals), - mNextOperand (true), mFirst (true), mArgument (argument) + mNextOperand (true), mFirst (true), mArgument (argument), mRefOp (false), mMemberOp (false) {} bool ExprParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner) @@ -251,7 +272,12 @@ namespace Compiler Scanner& scanner) { if (!mExplicit.empty()) + { + if (mMemberOp && handleMemberAccess (name)) + return true; + return Parser::parseName (name, loc, scanner); + } mFirst = false; @@ -281,7 +307,7 @@ namespace Compiler return true; } - if (mExplicit.empty() && getContext().isId (name)) + if (mExplicit.empty() && getContext().isId (name2)) { mExplicit = name; return true; @@ -497,6 +523,12 @@ namespace Compiler return true; } + if (!mMemberOp && code==Scanner::S_member) + { + mMemberOp = true; + return true; + } + return Parser::parseSpecial (code, loc, scanner); } @@ -609,6 +641,7 @@ namespace Compiler mFirst = true; mExplicit.clear(); mRefOp = false; + mMemberOp = false; Parser::reset(); } diff --git a/components/compiler/exprparser.hpp b/components/compiler/exprparser.hpp index 87945c6280..8ce5409d23 100644 --- a/components/compiler/exprparser.hpp +++ b/components/compiler/exprparser.hpp @@ -26,6 +26,7 @@ namespace Compiler bool mArgument; std::string mExplicit; bool mRefOp; + bool mMemberOp; int getPriority (char op) const; @@ -53,6 +54,8 @@ namespace Compiler int parseArguments (const std::string& arguments, Scanner& scanner); + bool handleMemberAccess (const std::string& name); + public: ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals, From 8b19de17b6371d4cb2afa647c39dca69209b24eb Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 13:21:01 +0200 Subject: [PATCH 07/16] Iisue #181: enable member variable access from expressions in console --- components/compiler/lineparser.cpp | 17 ++++++++++++++++- components/compiler/lineparser.hpp | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 834cd27b48..db21cce9bb 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -18,7 +18,10 @@ namespace Compiler if (!mExplicit.empty()) { mExprParser.parseName (mExplicit, loc, scanner); - mExprParser.parseSpecial (Scanner::S_ref, loc, scanner); + if (mState==MemberState) + mExprParser.parseSpecial (Scanner::S_member, loc, scanner); + else + mExprParser.parseSpecial (Scanner::S_ref, loc, scanner); } scanner.scan (mExprParser); @@ -256,6 +259,7 @@ namespace Compiler { scanner.putbackKeyword (keyword, loc); parseExpression (scanner, loc); + mState = EndState; return true; } @@ -269,6 +273,7 @@ namespace Compiler { scanner.putbackKeyword (keyword, loc); parseExpression (scanner, loc); + mState = EndState; return true; } } @@ -342,6 +347,7 @@ namespace Compiler { scanner.putbackKeyword (keyword, loc); parseExpression (scanner, loc); + mState = EndState; return true; } } @@ -366,6 +372,14 @@ namespace Compiler return true; } + if (code==Scanner::S_member && mState==PotentialExplicitState) + { + mState = MemberState; + parseExpression (scanner, loc); + mState = EndState; + return true; + } + if (code==Scanner::S_newline && mState==MessageButtonState) { Generator::message (mCode, mLiterals, mName, mButtons); @@ -383,6 +397,7 @@ namespace Compiler { scanner.putbackSpecial (code, loc); parseExpression (scanner, loc); + mState = EndState; return true; } diff --git a/components/compiler/lineparser.hpp b/components/compiler/lineparser.hpp index 531b7762f0..6f331b7bf2 100644 --- a/components/compiler/lineparser.hpp +++ b/components/compiler/lineparser.hpp @@ -24,7 +24,7 @@ namespace Compiler SetState, SetLocalVarState, SetGlobalVarState, MessageState, MessageCommaState, MessageButtonState, MessageButtonCommaState, EndState, - PotentialExplicitState, ExplicitState + PotentialExplicitState, ExplicitState, MemberState }; Locals& mLocals; From 10b27e582b5e0959db0219e91aa82aa7a9d5f567 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 13:51:13 +0200 Subject: [PATCH 08/16] Issue #181: various fixed to member variable access --- apps/openmw/mwscript/interpretercontext.cpp | 12 ++++++++++++ components/compiler/generator.cpp | 2 ++ components/interpreter/localopcodes.hpp | 3 --- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 55059b5224..152fcf85cb 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -278,6 +278,8 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's'); + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); return ptr.getRefData().getLocals().mShorts[index]; } @@ -289,6 +291,8 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l'); + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); return ptr.getRefData().getLocals().mLongs[index]; } @@ -300,6 +304,8 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f'); + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); return ptr.getRefData().getLocals().mFloats[index]; } @@ -311,6 +317,8 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's'); + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); ptr.getRefData().getLocals().mShorts[index] = value; } @@ -322,6 +330,8 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l'); + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); ptr.getRefData().getLocals().mLongs[index] = value; } @@ -333,6 +343,8 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f'); + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); ptr.getRefData().getLocals().mFloats[index] = value; } diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index b619ad67a3..9b02e4273f 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -794,6 +794,8 @@ namespace Compiler index = literals.addString (id); + opPushInt (code, index); + switch (localType) { case 'f': diff --git a/components/interpreter/localopcodes.hpp b/components/interpreter/localopcodes.hpp index 852fa7099b..4b0edff9cb 100644 --- a/components/interpreter/localopcodes.hpp +++ b/components/interpreter/localopcodes.hpp @@ -278,7 +278,6 @@ namespace Interpreter std::string variable = runtime.getStringLiteral (index); runtime.pop(); - index = runtime[0].mInteger; int value = runtime.getContext().getMemberShort (id, variable); runtime[0].mInteger = value; } @@ -296,7 +295,6 @@ namespace Interpreter std::string variable = runtime.getStringLiteral (index); runtime.pop(); - index = runtime[0].mInteger; int value = runtime.getContext().getMemberLong (id, variable); runtime[0].mInteger = value; } @@ -314,7 +312,6 @@ namespace Interpreter std::string variable = runtime.getStringLiteral (index); runtime.pop(); - index = runtime[0].mInteger; float value = runtime.getContext().getMemberFloat (id, variable); runtime[0].mFloat = value; } From fe85de5ea7d7cebf0d09ffccfc7a5f9e76a34caf Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 14:29:55 +0200 Subject: [PATCH 09/16] Issue #181: assignment to member variables --- components/compiler/lineparser.cpp | 39 +++++++++++++++++++++++-- components/compiler/lineparser.hpp | 4 ++- components/interpreter/localopcodes.hpp | 4 +-- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index db21cce9bb..a4cbc1ffeb 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -113,12 +113,13 @@ namespace Compiler if (mState==SetState) { std::string name2 = toLower (name); + mName = name2; // local variable? char type = mLocals.getType (name2); if (type!=' ') { - mName = name2; + mType = type; mState = SetLocalVarState; return true; } @@ -126,12 +127,27 @@ namespace Compiler type = getContext().getGlobalType (name2); if (type!=' ') { - mName = name2; mType = type; mState = SetGlobalVarState; return true; } + mState = SetPotentialMemberVarState; + return true; + } + + if (mState==SetMemberVarState) + { + mMemberName = toLower (name); + char type = getContext().getMemberType (mMemberName, mName); + + if (type!=' ') + { + mState = SetMemberVarState2; + mType = type; + return true; + } + getErrorHandler().error ("unknown variable", loc); SkipParser skip (getErrorHandler(), getContext()); scanner.scan (skip); @@ -338,6 +354,19 @@ namespace Compiler mState = EndState; return true; } + else if (mState==SetMemberVarState2 && keyword==Scanner::K_to) + { + mExprParser.reset(); + scanner.scan (mExprParser); + + std::vector code; + char type = mExprParser.append (code); + + Generator::assignToMember (mCode, mLiterals, mType, mMemberName, mName, code, type); + + mState = EndState; + return true; + } if (mAllowExpression) { @@ -392,6 +421,12 @@ namespace Compiler return true; } + if (code==Scanner::S_member && mState==SetPotentialMemberVarState) + { + mState = SetMemberVarState; + return true; + } + if (mAllowExpression && mState==BeginState && (code==Scanner::S_open || code==Scanner::S_minus)) { diff --git a/components/compiler/lineparser.hpp b/components/compiler/lineparser.hpp index 6f331b7bf2..aa74cd232f 100644 --- a/components/compiler/lineparser.hpp +++ b/components/compiler/lineparser.hpp @@ -21,7 +21,8 @@ namespace Compiler { BeginState, ShortState, LongState, FloatState, - SetState, SetLocalVarState, SetGlobalVarState, + SetState, SetLocalVarState, SetGlobalVarState, SetPotentialMemberVarState, + SetMemberVarState, SetMemberVarState2, MessageState, MessageCommaState, MessageButtonState, MessageButtonCommaState, EndState, PotentialExplicitState, ExplicitState, MemberState @@ -32,6 +33,7 @@ namespace Compiler std::vector& mCode; State mState; std::string mName; + std::string mMemberName; int mButtons; std::string mExplicit; char mType; diff --git a/components/interpreter/localopcodes.hpp b/components/interpreter/localopcodes.hpp index 4b0edff9cb..731c16276d 100644 --- a/components/interpreter/localopcodes.hpp +++ b/components/interpreter/localopcodes.hpp @@ -252,9 +252,9 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - Type_Integer index = runtime[0].mInteger; + Type_Float data = runtime[0].mFloat; + Type_Integer index = runtime[1].mInteger; std::string id = runtime.getStringLiteral (index); - Type_Float data = runtime[1].mFloat; index = runtime[2].mInteger; std::string variable = runtime.getStringLiteral (index); From 3167ae9473e49ad1720fd398329077db7d02ca54 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 15:49:03 +0200 Subject: [PATCH 10/16] added force/clearforce instructions for run and sneak --- apps/openmw/mwscript/controlextensions.cpp | 87 ++++++++++++++++++++++ apps/openmw/mwscript/docs/vmformat.txt | 10 ++- 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/controlextensions.cpp b/apps/openmw/mwscript/controlextensions.cpp index 363a09b6bd..1a7b452465 100644 --- a/apps/openmw/mwscript/controlextensions.cpp +++ b/apps/openmw/mwscript/controlextensions.cpp @@ -11,7 +11,10 @@ #include "../mwworld/player.hpp" +#include "../mwmechanics/npcstats.hpp" + #include "interpretercontext.hpp" +#include "ref.hpp" #include @@ -54,11 +57,71 @@ namespace MWScript } }; + template + class OpClearForceRun : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + MWWorld::Class::get (ptr).getNpcStats (ptr).mForceRun = false; + } + }; + + template + class OpForceRun : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + MWWorld::Class::get (ptr).getNpcStats (ptr).mForceRun = true; + } + }; + + template + class OpClearForceSneak : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + MWWorld::Class::get (ptr).getNpcStats (ptr).mForceSneak = false; + } + }; + + template + class OpForceSneak : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + MWWorld::Class::get (ptr).getNpcStats (ptr).mForceSneak = true; + } + }; + const int numberOfControls = 7; const int opcodeEnable = 0x200007e; const int opcodeDisable = 0x2000085; const int opcodeToggleCollision = 0x2000130; + const int opcodeClearForceRun = 0x2000154; + const int opcodeClearForceRunExplicit = 0x2000155; + const int opcodeForceRun = 0x2000156; + const int opcodeForceRunExplicit = 0x2000157; + const int opcodeClearForceSneak = 0x2000158; + const int opcodeClearForceSneakExplicit = 0x2000159; + const int opcodeForceSneak = 0x200015a; + const int opcodeForceSneakExplicit = 0x200015b; const char *controls[numberOfControls] = { @@ -79,6 +142,16 @@ namespace MWScript extensions.registerInstruction ("togglecollision", "", opcodeToggleCollision); extensions.registerInstruction ("tcl", "", opcodeToggleCollision); + + extensions.registerInstruction ("clearforcerun", "", opcodeClearForceRun, + opcodeClearForceRunExplicit); + extensions.registerInstruction ("forcerun", "", opcodeForceRun, + opcodeForceRunExplicit); + + extensions.registerInstruction ("clearforcesneak", "", opcodeClearForceSneak, + opcodeClearForceSneakExplicit); + extensions.registerInstruction ("forcesneak", "", opcodeForceSneak, + opcodeForceSneakExplicit); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -90,6 +163,20 @@ namespace MWScript } interpreter.installSegment5 (opcodeToggleCollision, new OpToggleCollision); + + interpreter.installSegment5 (opcodeClearForceRun, new OpClearForceRun); + interpreter.installSegment5 (opcodeForceRun, new OpForceRun); + interpreter.installSegment5 (opcodeClearForceSneak, new OpClearForceSneak); + interpreter.installSegment5 (opcodeForceSneak, new OpForceSneak); + + interpreter.installSegment5 (opcodeClearForceRunExplicit, + new OpClearForceRun); + interpreter.installSegment5 (opcodeForceRunExplicit, + new OpForceRun); + interpreter.installSegment5 (opcodeClearForceSneakExplicit, + new OpClearForceSneak); + interpreter.installSegment5 (opcodeForceSneakExplicit, + new OpForceSneak); } } } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 4423f17cfb..eb13a87224 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -147,4 +147,12 @@ op 0x2000150: ForceGreeting, explicit reference op 0x2000151: ToggleFullHelp op 0x2000152: Goodbye op 0x2000153: DontSaveObject (left unimplemented) -opcodes 0x2000154-0x3ffffff unused +op 0x2000154: ClearForceRun +op 0x2000155: ClearForceRun, explicit reference +op 0x2000156: ForceRun +op 0x2000156: ForceRun, explicit reference +op 0x2000157: ClearForceSneak +op 0x2000158: ClearForceSneak, explicit reference +op 0x2000159: ForceSneak +op 0x200015a: ForceSneak, explicit reference +opcodes 0x200015b-0x3ffffff unused From b16157a618115214b3b5f19e1a49287470a5765c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 15:49:39 +0200 Subject: [PATCH 11/16] documentation fix --- apps/openmw/mwscript/docs/vmformat.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index eb13a87224..219af9a0b4 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -150,9 +150,9 @@ op 0x2000153: DontSaveObject (left unimplemented) op 0x2000154: ClearForceRun op 0x2000155: ClearForceRun, explicit reference op 0x2000156: ForceRun -op 0x2000156: ForceRun, explicit reference -op 0x2000157: ClearForceSneak -op 0x2000158: ClearForceSneak, explicit reference -op 0x2000159: ForceSneak -op 0x200015a: ForceSneak, explicit reference +op 0x2000157: ForceRun, explicit reference +op 0x2000158: ClearForceSneak +op 0x2000159: ClearForceSneak, explicit reference +op 0x200015a: ForceSneak +op 0x200015b: ForceSneak, explicit reference opcodes 0x200015b-0x3ffffff unused From 7454713a9be6fdfc4ede96f52b787423e941d4a0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 16:06:15 +0200 Subject: [PATCH 12/16] addet provisional implementation of AiWander (doesn't do anything yet) --- apps/openmw/mwscript/aiextensions.cpp | 30 ++++++++++++++++++++++++++ apps/openmw/mwscript/docs/vmformat.txt | 4 +++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index aa541e55d3..54a67a8cd3 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -88,7 +88,31 @@ namespace MWScript } }; + template + class OpAiWander : public Interpreter::Opcode1 + { + public: + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + MWWorld::Ptr ptr = R()(runtime); + +// Interpreter::Type_Float range = runtime[0].mFloat; + runtime.pop(); + +// Interpreter::Type_Float duration = runtime[0].mFloat; + runtime.pop(); + +// Interpreter::Type_Float time = runtime[0].mFloat; + runtime.pop(); + + // discard additional idle arguments for now + // discard additional arguments (reset), because we have no idea what they mean. + for (unsigned int i=0; i); interpreter.installSegment3 (opcodeAiEscort, new OpAiEscort); interpreter.installSegment3 (opcodeAiEscortExplicit, new OpAiEscort); + interpreter.installSegment3 (opcodeAiWander, new OpAiWander); + interpreter.installSegment3 (opcodeAiWanderExplicit, new OpAiWander); interpreter.installSegment5 (opcodeGetAiPackageDone, new OpGetAiPackageDone); interpreter.installSegment5 (opcodeGetAiPackageDoneExplicit, new OpGetAiPackageDone); diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 219af9a0b4..7faba7f415 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -29,7 +29,9 @@ op 0x2000c: PCLowerRank op 0x2000d: PCJoinFaction op 0x2000e: PCGetRank implicit op 0x2000f: PCGetRank explicit -opcodes 0x20010-0x3ffff unused +op 0x20010: AiWander +op 0x20011: AiWander, explicit reference +opcodes 0x20012-0x3ffff unused Segment 4: (not implemented yet) From ea29b74bb439a9ea5a73210c60a2fe30705e0bb6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 16:17:42 +0200 Subject: [PATCH 13/16] added per NPC/creature basic AI-settings (hello, fight, flee, alarm) --- apps/openmw/mwclass/creature.cpp | 5 +++++ apps/openmw/mwclass/npc.cpp | 7 ++++++- apps/openmw/mwmechanics/creaturestats.hpp | 4 ++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index e33fd322a7..c9b43896b2 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -57,6 +57,11 @@ namespace MWClass data->mCreatureStats.mLevel = ref->base->data.level; + data->mCreatureStats.mHello = ref->base->AI.hello; + data->mCreatureStats.mFight = ref->base->AI.fight; + data->mCreatureStats.mFlee = ref->base->AI.flee; + data->mCreatureStats.mAlarm = ref->base->AI.alarm; + // store ptr.getRefData().setCustomData (data.release()); } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 4c964c7007..f30e164f96 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -70,12 +70,12 @@ namespace MWClass } } + // creature stats if(ref->base->npdt52.gold != -10) { for (int i=0; i<27; ++i) data->mNpcStats.mSkill[i].setBase (ref->base->npdt52.skills[i]); - // creature stats data->mCreatureStats.mAttributes[0].set (ref->base->npdt52.strength); data->mCreatureStats.mAttributes[1].set (ref->base->npdt52.intelligence); data->mCreatureStats.mAttributes[2].set (ref->base->npdt52.willpower); @@ -95,6 +95,11 @@ namespace MWClass /// \todo do something with npdt12 maybe:p } + data->mCreatureStats.mHello = ref->base->AI.hello; + data->mCreatureStats.mFight = ref->base->AI.fight; + data->mCreatureStats.mFlee = ref->base->AI.flee; + data->mCreatureStats.mAlarm = ref->base->AI.alarm; + // store ptr.getRefData().setCustomData (data.release()); } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index cc3c409da2..8d40e19423 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -19,6 +19,10 @@ namespace MWMechanics Spells mSpells; ActiveSpells mActiveSpells; MagicEffects mMagicEffects; + int mHello; + int mFight; + int mFlee; + int mAlarm; }; } From 8283f5f13597420ab83417951c89498ffa2043ef Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 16:31:32 +0200 Subject: [PATCH 14/16] added setHello/Fight/Flee/Alarm instructions --- apps/openmw/mwscript/aiextensions.cpp | 88 ++++++++++++++++++++++++++ apps/openmw/mwscript/docs/vmformat.txt | 10 ++- 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index 54a67a8cd3..08b1f6f8cf 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -7,6 +7,8 @@ #include #include +#include "../mwmechanics/creaturestats.hpp" + #include "interpretercontext.hpp" #include "ref.hpp" @@ -114,6 +116,71 @@ namespace MWScript } }; + template + class OpSetHello : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + MWWorld::Class::get (ptr).getCreatureStats (ptr).mHello = value; + } + }; + + template + class OpSetFight : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + MWWorld::Class::get (ptr).getCreatureStats (ptr).mFight = value; + } + }; + + template + class OpSetFlee : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + MWWorld::Class::get (ptr).getCreatureStats (ptr).mFlee = value; + } + }; + + template + class OpSetAlarm : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + MWWorld::Class::get (ptr).getCreatureStats (ptr).mAlarm = value; + } + }; + + const int opcodeAiTravel = 0x20000; const int opcodeAiTravelExplicit = 0x20001; const int opcodeAiEscort = 0x20002; @@ -122,6 +189,14 @@ namespace MWScript const int opcodeGetAiPackageDoneExplicit = 0x200007d; const int opcodeAiWander = 0x20010; const int opcodeAiWanderExplicit = 0x20011; + const int opcodeSetHello = 0x200015e; + const int opcodeSetHelloExplicit = 0x200015d; + const int opcodeSetFight = 0x200015e; + const int opcodeSetFightExplicit = 0x200015f; + const int opcodeSetFlee = 0x2000160; + const int opcodeSetFleeExplicit = 0x2000161; + const int opcodeSetAlarm = 0x2000162; + const int opcodeSetAlarmExplicit = 0x2000163; void registerExtensions (Compiler::Extensions& extensions) { @@ -134,6 +209,11 @@ namespace MWScript extensions.registerFunction ("getaipackagedone", 'l', "", opcodeGetAiPackageDone, opcodeGetAiPackageDoneExplicit); + + extensions.registerInstruction ("sethello", "l", opcodeSetHello, opcodeSetHelloExplicit); + extensions.registerInstruction ("setfight", "l", opcodeSetFight, opcodeSetFightExplicit); + extensions.registerInstruction ("setflee", "l", opcodeSetFlee, opcodeSetFleeExplicit); + extensions.registerInstruction ("setalarm", "l", opcodeSetAlarm, opcodeSetAlarmExplicit); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -147,6 +227,14 @@ namespace MWScript interpreter.installSegment5 (opcodeGetAiPackageDone, new OpGetAiPackageDone); interpreter.installSegment5 (opcodeGetAiPackageDoneExplicit, new OpGetAiPackageDone); + interpreter.installSegment5 (opcodeSetHello, new OpSetHello); + interpreter.installSegment5 (opcodeSetHelloExplicit, new OpSetHello); + interpreter.installSegment5 (opcodeSetFight, new OpSetFight); + interpreter.installSegment5 (opcodeSetFightExplicit, new OpSetFight); + interpreter.installSegment5 (opcodeSetFlee, new OpSetFlee); + interpreter.installSegment5 (opcodeSetFleeExplicit, new OpSetFlee); + interpreter.installSegment5 (opcodeSetAlarm, new OpSetAlarm); + interpreter.installSegment5 (opcodeSetAlarmExplicit, new OpSetAlarm); } } } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 7faba7f415..8a166eff3a 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -157,4 +157,12 @@ op 0x2000158: ClearForceSneak op 0x2000159: ClearForceSneak, explicit reference op 0x200015a: ForceSneak op 0x200015b: ForceSneak, explicit reference -opcodes 0x200015b-0x3ffffff unused +op 0x200015c: SetHello +op 0x200015d: SetHello, explicit reference +op 0x200015e: SetFight +op 0x200015f: SetFight, explicit reference +op 0x2000160: SetFlee +op 0x2000161: SetFlee, explicit reference +op 0x2000162: SetAlarm +op 0x2000163: SetAlarm, explicit reference +opcodes 0x2000164-0x3ffffff unused From e2a77037ebf88bd014df905bbf8515291ce59d8e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 16:38:54 +0200 Subject: [PATCH 15/16] fixed a type in a script instruction --- apps/openmw/mwscript/guiextensions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/guiextensions.cpp b/apps/openmw/mwscript/guiextensions.cpp index b267cc6e49..8e5897298b 100644 --- a/apps/openmw/mwscript/guiextensions.cpp +++ b/apps/openmw/mwscript/guiextensions.cpp @@ -104,7 +104,7 @@ namespace MWScript extensions.registerInstruction ("enableclassmenu", "", opcodeEnableClassMenu); extensions.registerInstruction ("enablenamemenu", "", opcodeEnableNameMenu); extensions.registerInstruction ("enableracemenu", "", opcodeEnableRaceMenu); - extensions.registerInstruction ("enablestatsreviewmenu", "", + extensions.registerInstruction ("enablestatreviewmenu", "", opcodeEnableStatsReviewMenu); extensions.registerInstruction ("enableinventorymenu", "", opcodeEnableInventoryMenu); From 3c42a71dae5e766d79a7e7b65b321804ce4db022 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 16:42:35 +0200 Subject: [PATCH 16/16] removed some cout spam --- apps/openmw/mwgui/messagebox.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 0bb7d3c1cf..27e14ba82b 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -86,13 +86,12 @@ void MessageBoxManager::createMessageBox (const std::string& message) bool MessageBoxManager::createInteractiveMessageBox (const std::string& message, const std::vector& buttons) { + /// \todo Don't write this kind of error message to cout. Either discard the old message box + /// silently or throw an exception. if(mInterMessageBoxe != NULL) { std::cout << "there is a MessageBox already" << std::endl; return false; } - std::cout << "interactive MessageBox: " << message << " - "; - std::copy (buttons.begin(), buttons.end(), std::ostream_iterator (std::cout, ", ")); - std::cout << std::endl; mInterMessageBoxe = new InteractiveMessageBox(*this, message, buttons);