From 4614d2bc8ed0d804db910b1545901810be94f0c5 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 8 Nov 2012 16:49:38 +0100 Subject: [PATCH] Issue #219: added basic select struct analysis and type checking --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 5 -- apps/openmw/mwdialogue/filter.cpp | 46 +++++++++++++- apps/openmw/mwdialogue/filter.hpp | 11 ++++ apps/openmw/mwdialogue/selectwrapper.cpp | 62 +++++++++++++++++++ apps/openmw/mwdialogue/selectwrapper.hpp | 40 ++++++++++++ 6 files changed, 159 insertions(+), 7 deletions(-) create mode 100644 apps/openmw/mwdialogue/selectwrapper.cpp create mode 100644 apps/openmw/mwdialogue/selectwrapper.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 29f5f2ccc..57a417722 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -34,7 +34,7 @@ add_openmw_dir (mwgui ) add_openmw_dir (mwdialogue - dialoguemanagerimp journalimp journalentry quest topic filter + dialoguemanagerimp journalimp journalentry quest topic filter selectwrapper ) add_openmw_dir (mwscript diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 37f3260c6..37de30c96 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -469,11 +469,6 @@ namespace MWDialogue throw std::runtime_error ( "unsupported variable type in dialogue info select"); return true; - - - default: - - std::cout << "unchecked select: " << type << " " << comp << " " << name << std::endl; } } diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index b69a6d727..5161ea5ed 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -9,6 +9,8 @@ #include "../mwmechanics/npcstats.hpp" +#include "selectwrapper.hpp" + namespace { std::string toLower (const std::string& name) @@ -109,9 +111,51 @@ bool MWDialogue::Filter::testPlayer (const ESM::DialInfo& info) const return true; } +bool MWDialogue::Filter::testSelectStructs (const ESM::DialInfo& info) const +{ + for (std::vector::const_iterator iter (info.mSelects.begin()); + iter != info.mSelects.end(); ++iter) + if (!testSelectStruct (*iter)) + return false; + + return true; +} + +bool MWDialogue::Filter::testSelectStruct (const SelectWrapper& select) const +{ + switch (select.getType()) + { + case SelectWrapper::Type_None: return true; + case SelectWrapper::Type_Integer: return select.selectCompare (getSelectStructInteger (select)); + case SelectWrapper::Type_Numeric: return testSelectStructNumeric (select); + } + + return true; +} + +bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) const +{ + switch (select.getFunction()) + { + default: + + throw std::runtime_error ("unknown numeric select function"); + } +} + +int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) const +{ + switch (select.getFunction()) + { + default: + + throw std::runtime_error ("unknown integer select function"); + } +} + MWDialogue::Filter::Filter (const MWWorld::Ptr& actor) : mActor (actor) {} bool MWDialogue::Filter::operator() (const ESM::DialInfo& info) const { - return testActor (info) && testPlayer (info); + return testActor (info) && testPlayer (info) && testSelectStructs (info); } diff --git a/apps/openmw/mwdialogue/filter.hpp b/apps/openmw/mwdialogue/filter.hpp index 3ca4153b3..2b8410941 100644 --- a/apps/openmw/mwdialogue/filter.hpp +++ b/apps/openmw/mwdialogue/filter.hpp @@ -10,6 +10,8 @@ namespace ESM namespace MWDialogue { + class SelectWrapper; + class Filter { MWWorld::Ptr mActor; @@ -20,6 +22,15 @@ namespace MWDialogue bool testPlayer (const ESM::DialInfo& info) const; ///< Do the player and the cell the player is currently in match \a info? + bool testSelectStructs (const ESM::DialInfo& info) const; + ///< Are all select structs matching? + + bool testSelectStruct (const SelectWrapper& select) const; + + bool testSelectStructNumeric (const SelectWrapper& select) const; + + int getSelectStructInteger (const SelectWrapper& select) const; + public: Filter (const MWWorld::Ptr& actor); diff --git a/apps/openmw/mwdialogue/selectwrapper.cpp b/apps/openmw/mwdialogue/selectwrapper.cpp new file mode 100644 index 000000000..a45c0adc0 --- /dev/null +++ b/apps/openmw/mwdialogue/selectwrapper.cpp @@ -0,0 +1,62 @@ + +#include "selectwrapper.hpp" + +#include + +namespace +{ + template + bool selectCompareImp (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 selectCompareImp (const ESM::DialInfo::SelectStruct& select, T value1) + { + if (select.mType==ESM::VT_Short || select.mType==ESM::VT_Int || + select.mType==ESM::VT_Long) + { + return selectCompareImp (select.mSelectRule[4], value1, select.mI); + } + else if (select.mType==ESM::VT_Float) + { + return selectCompareImp (select.mSelectRule[4], value1, select.mF); + } + else + throw std::runtime_error ( + "unsupported variable type in dialogue info select"); + } +} + +MWDialogue::SelectWrapper::SelectWrapper (const ESM::DialInfo::SelectStruct& select) : mSelect (select) {} + +MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::getFunction() const +{ + return Function_None; +} + +MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const +{ + return Type_None; +} + +bool MWDialogue::SelectWrapper::selectCompare (int value) const +{ + return selectCompareImp (mSelect, value); +} + +bool MWDialogue::SelectWrapper::selectCompare (float value) const +{ + return selectCompareImp (mSelect, value); +} diff --git a/apps/openmw/mwdialogue/selectwrapper.hpp b/apps/openmw/mwdialogue/selectwrapper.hpp new file mode 100644 index 000000000..acc3e9cc4 --- /dev/null +++ b/apps/openmw/mwdialogue/selectwrapper.hpp @@ -0,0 +1,40 @@ +#ifndef GAME_MWDIALOGUE_SELECTWRAPPER_H +#define GAME_MWDIALOGUE_SELECTWRAPPER_H + +#include + +namespace MWDialogue +{ + class SelectWrapper + { + const ESM::DialInfo::SelectStruct& mSelect; + + public: + + enum Function + { + Function_None + }; + + enum Type + { + Type_None, + Type_Integer, + Type_Numeric + }; + + public: + + SelectWrapper (const ESM::DialInfo::SelectStruct& select); + + Function getFunction() const; + + Type getType() const; + + bool selectCompare (int value) const; + + bool selectCompare (float value) const; + }; +} + +#endif