diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index 941c760e7..4f9cf602f 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -1,7 +1,6 @@ #include "dialoguemanager.hpp" -#include #include #include @@ -9,11 +8,110 @@ #include "../mwworld/class.hpp" #include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" +#include "../mwworld/refdata.hpp" #include +namespace +{ + template + bool selectCompare (char comp, T1 value1, T2 value2) + { + switch (comp) + { + case '0': return value1==value2; + case '1': return value1!=value2; + case '2': return value1>value2; + case '3': return value1>=value2; + case '4': return value1 + bool checkLocal (char comp, const std::string& name, T value, const MWWorld::Ptr& actor, + const ESMS::ESMStore& store) + { + std::string scriptName = MWWorld::Class::get (actor).getScript (actor); + + if (scriptName.empty()) + return false; // no script + + const ESM::Script *script = store.scripts.find (scriptName); + + int i = 0; + + for (; i (script->varNames.size()); ++i) + if (script->varNames[i]==name) + break; + + if (i>=static_cast (script->varNames.size())) + return false; // script does not have a variable of this name + + const MWScript::Locals& locals = actor.getRefData().getLocals(); + + if (idata.numShorts) + return selectCompare (comp, locals.mShorts[i], value); + else + i -= script->data.numShorts; + + if (idata.numLongs) + return selectCompare (comp, locals.mLongs[i], value); + else + i -= script->data.numShorts; + + return selectCompare (comp, locals.mFloats.at (i), value); + } +} + namespace MWDialogue { + bool DialogueManager::isMatching (const MWWorld::Ptr& actor, + const ESM::DialInfo::SelectStruct& select) const + { + char type = select.selectRule[1]; + + if (type!='0') + { + char comp = select.selectRule[4]; + std::string name = select.selectRule.substr (5); + + // TODO types 1, 2, 4, 5, 6, 7, 8, 9, A, B, C + + switch (type) + { + case '3': // local + + if (select.type==ESM::VT_Short || select.type==ESM::VT_Int || + select.type==ESM::VT_Long) + { + if (!checkLocal (comp, name, select.i, actor, + mEnvironment.mWorld->getStore())) + return false; + } + else if (select.type==ESM::VT_Float) + { + if (!checkLocal (comp, name, select.f, actor, + mEnvironment.mWorld->getStore())) + return false; + } + else + throw std::runtime_error ( + "unsupported variable type in dialogue info select"); + + return true; + + default: + + std::cout << "unchecked select: " << type << " " << comp << " " << name << std::endl; + } + } + + return true; + } + bool DialogueManager::isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const { // TODO check actor id @@ -28,7 +126,11 @@ namespace MWDialogue return false; // TODO check DATAstruct - // TODO check select structures + + for (std::vector::const_iterator iter (info.selects.begin()); + iter != info.selects.end(); ++iter) + if (!isMatching (actor, *iter)) + return false; std::cout << "unchecked entries:" << std::endl @@ -39,10 +141,6 @@ namespace MWDialogue << " player faction: " << info.pcFaction << std::endl << " DATAstruct" << std::endl; - for (std::vector::const_iterator iter (info.selects.begin()); - iter != info.selects.end(); ++iter) - std::cout << " select: " << iter->selectRule << std::endl; - return true; } diff --git a/apps/openmw/mwdialogue/dialoguemanager.hpp b/apps/openmw/mwdialogue/dialoguemanager.hpp index d51570b11..5b6b26240 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.hpp +++ b/apps/openmw/mwdialogue/dialoguemanager.hpp @@ -1,12 +1,9 @@ #ifndef GAME_MMDIALOG_DIALOGUEMANAGER_H #define GAME_MWDIALOG_DIALOGUEMANAGER_H -#include "../mwworld/ptr.hpp" +#include -namespace ESM -{ - struct DialInfo; -} +#include "../mwworld/ptr.hpp" namespace MWWorld { @@ -19,6 +16,8 @@ namespace MWDialogue { MWWorld::Environment& mEnvironment; + bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo::SelectStruct& select) const; + bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const; public: