From 8aa1fd921ba450258ad4c08bda5221454c0d4b9f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 13 Nov 2012 14:19:43 +0100 Subject: [PATCH 1/4] fixed some stats related script instructions --- apps/openmw/mwscript/statsextensions.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 4fbb81b37..83c25bc19 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -565,7 +565,7 @@ namespace MWScript { if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty()) { - //throw exception? + factionID = -1; } else { @@ -601,10 +601,11 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); -// Interpreter::Type_Integer value = runtime[0].mInteger; + Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); - /// \todo modify disposition towards the player + MWWorld::Class::get (ptr).getNpcStats (ptr).setBaseDisposition + (MWWorld::Class::get (ptr).getNpcStats (ptr).getBaseDisposition() + value); } }; From c621a9f7e48ab8b06c74ed3bcf6a5cd55fdd557a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 13 Nov 2012 14:29:00 +0100 Subject: [PATCH 2/4] added missing disposition script instructions --- apps/openmw/mwscript/docs/vmformat.txt | 6 ++- apps/openmw/mwscript/statsextensions.cpp | 48 ++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index cb984e257..1ea467e3b 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -207,5 +207,9 @@ op 0x20001a0: ShowMap op 0x20001a1: FillMap op 0x20001a2: WakeUpPc op 0x20001a3: GetDeadCount -opcodes 0x20001a4-0x3ffffff unused +op 0x20001a4: SetDisposition +op 0x20001a5: SetDisposition, Explicit +op 0x20001a6: GetDisposition +op 0x20001a7: GetDisposition, Explicit +opcodes 0x20001a8-0x3ffffff unused diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 83c25bc19..bdac4748c 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -608,6 +608,35 @@ namespace MWScript (MWWorld::Class::get (ptr).getNpcStats (ptr).getBaseDisposition() + value); } }; + + template + class OpSetDisposition : 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).getNpcStats (ptr).setBaseDisposition (value); + } + }; + + template + class OpGetDisposition : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + runtime.push (MWWorld::Class::get (ptr).getNpcStats (ptr).getBaseDisposition()); + } + }; class OpGetDeadCount : public Interpreter::Opcode0 { @@ -666,6 +695,10 @@ namespace MWScript const int opcodeGetPCRankExplicit = 0x2000f; const int opcodeModDisposition = 0x200014d; const int opcodeModDispositionExplicit = 0x200014e; + const int opcodeSetDisposition = 0x20001a4; + const int opcodeSetDispositionExplicit = 0x20001a5; + const int opcodeGetDisposition = 0x20001a6; + const int opcodeGetDispositionExplicit = 0x20001a7; const int opcodeGetLevel = 0x200018c; const int opcodeGetLevelExplicit = 0x200018d; @@ -753,8 +786,12 @@ namespace MWScript extensions.registerInstruction("pcraiserank","/S",opcodePCRaiseRank); extensions.registerInstruction("pclowerrank","/S",opcodePCLowerRank); extensions.registerInstruction("pcjoinfaction","/S",opcodePCJoinFaction); - extensions.registerInstruction("moddisposition","l",opcodeModDisposition, + extensions.registerInstruction ("moddisposition","l",opcodeModDisposition, opcodeModDispositionExplicit); + extensions.registerInstruction ("setdisposition","l",opcodeSetDisposition, + opcodeSetDispositionExplicit); + extensions.registerFunction ("getdisposition",'l', "",opcodeGetDisposition, + opcodeGetDispositionExplicit); extensions.registerFunction("getpcrank",'l',"/S",opcodeGetPCRank,opcodeGetPCRankExplicit); extensions.registerInstruction("setlevel", "l", opcodeSetLevel, opcodeSetLevelExplicit); @@ -828,11 +865,16 @@ namespace MWScript interpreter.installSegment3(opcodePCRaiseRank,new OpPCRaiseRank); interpreter.installSegment3(opcodePCLowerRank,new OpPCLowerRank); interpreter.installSegment3(opcodePCJoinFaction,new OpPCJoinFaction); - interpreter.installSegment5(opcodeModDisposition,new OpModDisposition); - interpreter.installSegment5(opcodeModDispositionExplicit,new OpModDisposition); interpreter.installSegment3(opcodeGetPCRank,new OpGetPCRank); interpreter.installSegment3(opcodeGetPCRankExplicit,new OpGetPCRank); + interpreter.installSegment5(opcodeModDisposition,new OpModDisposition); + interpreter.installSegment5(opcodeModDispositionExplicit,new OpModDisposition); + interpreter.installSegment5(opcodeSetDisposition,new OpSetDisposition); + interpreter.installSegment5(opcodeSetDispositionExplicit,new OpSetDisposition); + interpreter.installSegment5(opcodeGetDisposition,new OpGetDisposition); + interpreter.installSegment5(opcodeGetDispositionExplicit,new OpGetDisposition); + interpreter.installSegment5 (opcodeGetLevel, new OpGetLevel); interpreter.installSegment5 (opcodeGetLevelExplicit, new OpGetLevel); interpreter.installSegment5 (opcodeSetLevel, new OpSetLevel); From 2a1727d4c584d28cbace5e1738216cebb97a433f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 13 Nov 2012 15:35:46 +0100 Subject: [PATCH 3/4] improved error reporting for dialogue scripts (enabled via --script-verbose) --- apps/openmw/engine.cpp | 2 +- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 30 +++++++++++++------ apps/openmw/mwdialogue/dialoguemanagerimp.hpp | 3 +- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index d646d5aca..2299053cd 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -356,7 +356,7 @@ void OMW::Engine::go() // Create dialog system mEnvironment.setJournal (new MWDialogue::Journal); - mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions)); + mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts)); // Sets up the input system mEnvironment.setInputManager (new MWInput::InputManager (*mOgre, diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 881a02d00..6a0f9d71f 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -75,11 +75,11 @@ namespace namespace MWDialogue { - DialogueManager::DialogueManager (const Compiler::Extensions& extensions) : + DialogueManager::DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose) : mCompilerContext (MWScript::CompilerContext::Type_Dialgoue), mErrorStream(std::cout.rdbuf()),mErrorHandler(mErrorStream) , mTemporaryDispositionChange(0.f) - , mPermanentDispositionChange(0.f) + , mPermanentDispositionChange(0.f), mScriptVerbose (scriptVerbose) { mChoice = -1; mIsInChoice = false; @@ -174,6 +174,8 @@ namespace MWDialogue bool DialogueManager::compile (const std::string& cmd,std::vector& code) { + bool success = true; + try { mErrorHandler.reset(); @@ -195,23 +197,33 @@ namespace MWDialogue Compiler::ScriptParser parser(mErrorHandler,mCompilerContext, locals, false); scanner.scan (parser); - if(mErrorHandler.isGood()) - { - parser.getCode(code); - return true; - } - return false; + + if (!mErrorHandler.isGood()) + success = false; + + if (success) + parser.getCode (code); } catch (const Compiler::SourceException& /* error */) { // error has already been reported via error handler + success = false; } catch (const std::exception& error) { printError (std::string ("An exception has been thrown: ") + error.what()); + success = false; } - return false; + if (!success && mScriptVerbose) + { + std::cerr + << "compiling failed (dialogue script)" << std::endl + << cmd + << std::endl << std::endl; + } + + return success; } void DialogueManager::executeScript (const std::string& script) diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp index 8e862f932..9e1971b0f 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp @@ -35,6 +35,7 @@ namespace MWDialogue float mTemporaryDispositionChange; float mPermanentDispositionChange; + bool mScriptVerbose; void parseText (const std::string& text); @@ -47,7 +48,7 @@ namespace MWDialogue public: - DialogueManager (const Compiler::Extensions& extensions); + DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose); virtual void startDialogue (const MWWorld::Ptr& actor); From b046687f467452dfc85673ff7815bf3ed4790411 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 13 Nov 2012 16:11:03 +0100 Subject: [PATCH 4/4] added PCFacRep script instructions --- apps/openmw/mwscript/docs/vmformat.txt | 8 +- apps/openmw/mwscript/statsextensions.cpp | 148 +++++++++++++++++++++-- 2 files changed, 143 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 1ea467e3b..4ec9cfb99 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -31,7 +31,13 @@ op 0x2000e: PCGetRank implicit op 0x2000f: PCGetRank explicit op 0x20010: AiWander op 0x20011: AiWander, explicit reference -op s 0x20012-0x3ffff unused +op 0x20012: GetPCFacRep +op 0x20013: GetPCFacRep, explicit reference +op 0x20014: SetPCFacRep +op 0x20015: SetPCFacRep, explicit reference +op 0x20016: ModPCFacRep +op 0x20017: ModPCFacRep, explicit reference +op s 0x20018-0x3ffff unused Segment 4: (not implemented yet) diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index bdac4748c..124eaf4c3 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -33,13 +33,13 @@ namespace std::string getDialogueActorFaction() { MWWorld::Ptr actor = MWBase::Environment::get().getDialogueManager()->getActor(); - + MWMechanics::NpcStats stats = MWWorld::Class::get (actor).getNpcStats (actor); - + if (stats.getFactionRanks().empty()) throw std::runtime_error ( "failed to determine dialogue actors faction (because actor is factionless)"); - + return stats.getFactionRanks().begin()->first; } } @@ -208,7 +208,7 @@ namespace MWScript .getDynamic (mIndex)); stat.setModified (value, 0); - + MWWorld::Class::get (ptr).getCreatureStats (ptr).setDynamic (mIndex, stat); } }; @@ -565,7 +565,7 @@ namespace MWScript { if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty()) { - factionID = -1; + factionID = ""; } else { @@ -623,7 +623,7 @@ namespace MWScript MWWorld::Class::get (ptr).getNpcStats (ptr).setBaseDisposition (value); } - }; + }; template class OpGetDisposition : public Interpreter::Opcode0 @@ -636,8 +636,8 @@ namespace MWScript runtime.push (MWWorld::Class::get (ptr).getNpcStats (ptr).getBaseDisposition()); } - }; - + }; + class OpGetDeadCount : public Interpreter::Opcode0 { public: @@ -647,7 +647,112 @@ namespace MWScript std::string id = runtime.getStringLiteral (runtime[0].mInteger); runtime[0].mInteger = MWBase::Environment::get().getMechanicsManager()->countDeaths (id); } - }; + }; + + template + class OpGetPCFacRep : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + std::string factionId; + + if (arg0==1) + { + factionId = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + } + else + { + MWWorld::Ptr ptr = R()(runtime); + + if (!MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().empty()) + factionId = MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().begin()->first; + } + + if (factionId.empty()) + throw std::runtime_error ("failed to determine faction"); + + boost::algorithm::to_lower (factionId); + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + runtime.push ( + MWWorld::Class::get (player).getNpcStats (player).getFactionReputation (factionId)); + } + }; + + template + class OpSetPCFacRep : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + std::string factionId; + + if (arg0==1) + { + factionId = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + } + else + { + MWWorld::Ptr ptr = R()(runtime); + + if (!MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().empty()) + factionId = MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().begin()->first; + } + + if (factionId.empty()) + throw std::runtime_error ("failed to determine faction"); + + boost::algorithm::to_lower (factionId); + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::Class::get (player).getNpcStats (player).setFactionReputation (factionId, value); + } + }; + + template + class OpModPCFacRep : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + std::string factionId; + + if (arg0==1) + { + factionId = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + } + else + { + MWWorld::Ptr ptr = R()(runtime); + + if (!MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().empty()) + factionId = MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().begin()->first; + } + + if (factionId.empty()) + throw std::runtime_error ("failed to determine faction"); + + boost::algorithm::to_lower (factionId); + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::Class::get (player).getNpcStats (player).setFactionReputation (factionId, + MWWorld::Class::get (player).getNpcStats (player).getFactionReputation (factionId)+ + value); + } + }; const int numberOfAttributes = 8; @@ -704,9 +809,17 @@ namespace MWScript const int opcodeGetLevelExplicit = 0x200018d; const int opcodeSetLevel = 0x200018e; const int opcodeSetLevelExplicit = 0x200018f; - + const int opcodeGetDeadCount = 0x20001a3; + const int opcodeGetPCFacRep = 0x20012; + const int opcodeGetPCFacRepExplicit = 0x20013; + const int opcodeSetPCFacRep = 0x20014; + const int opcodeSetPCFacRepExplicit = 0x20015; + const int opcodeModPCFacRep = 0x20016; + const int opcodeModPCFacRepExplicit = 0x20017; + + void registerExtensions (Compiler::Extensions& extensions) { static const char *attributes[numberOfAttributes] = @@ -797,7 +910,11 @@ namespace MWScript extensions.registerInstruction("setlevel", "l", opcodeSetLevel, opcodeSetLevelExplicit); extensions.registerFunction("getlevel", 'l', "", opcodeGetLevel, opcodeGetLevelExplicit); - extensions.registerFunction("getdeadcount", 'l', "c", opcodeGetDeadCount); + extensions.registerFunction ("getdeadcount", 'l', "c", opcodeGetDeadCount); + + extensions.registerFunction ("getpcfacrep", 'l', "/c", opcodeGetPCFacRep, opcodeGetPCFacRepExplicit); + extensions.registerInstruction ("setpcfacrep", "/lc", opcodeSetPCFacRep, opcodeSetPCFacRepExplicit); + extensions.registerInstruction ("modpcfacrep", "/lc", opcodeModPCFacRep, opcodeModPCFacRepExplicit); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -874,13 +991,20 @@ namespace MWScript interpreter.installSegment5(opcodeSetDispositionExplicit,new OpSetDisposition); interpreter.installSegment5(opcodeGetDisposition,new OpGetDisposition); interpreter.installSegment5(opcodeGetDispositionExplicit,new OpGetDisposition); - + interpreter.installSegment5 (opcodeGetLevel, new OpGetLevel); interpreter.installSegment5 (opcodeGetLevelExplicit, new OpGetLevel); interpreter.installSegment5 (opcodeSetLevel, new OpSetLevel); interpreter.installSegment5 (opcodeSetLevelExplicit, new OpSetLevel); interpreter.installSegment5 (opcodeGetDeadCount, new OpGetDeadCount); + + interpreter.installSegment3 (opcodeGetPCFacRep, new OpGetPCFacRep); + interpreter.installSegment3 (opcodeGetPCFacRepExplicit, new OpGetPCFacRep); + interpreter.installSegment3 (opcodeSetPCFacRep, new OpSetPCFacRep); + interpreter.installSegment3 (opcodeSetPCFacRepExplicit, new OpSetPCFacRep); + interpreter.installSegment3 (opcodeModPCFacRep, new OpModPCFacRep); + interpreter.installSegment3 (opcodeModPCFacRepExplicit, new OpModPCFacRep); } } }