From 662054acf4a2ee13542a4dde9208be2da4597fc8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 8 Nov 2012 14:55:31 +0100 Subject: [PATCH] Issue #219: moved checks for various dialogue info fields from DialogueManager to Filter --- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 96 +-------------- apps/openmw/mwdialogue/filter.cpp | 111 +++++++++++++++++- apps/openmw/mwdialogue/filter.hpp | 8 +- components/esm/loadinfo.hpp | 8 +- 4 files changed, 121 insertions(+), 102 deletions(-) diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 5838b8c0dd..37f3260c63 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -482,101 +482,7 @@ namespace MWDialogue bool DialogueManager::isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const { - bool isCreature = (actor.getTypeName() != typeid(ESM::NPC).name()); - - // actor id - if (!info.mActor.empty()) - if (toLower (info.mActor)!=MWWorld::Class::get (actor).getId (actor)) - return false; - - //NPC race - if (!info.mRace.empty()) - { - if (isCreature) - return false; - - MWWorld::LiveCellRef *cellRef = actor.get(); - - if (!cellRef) - return false; - - if (toLower (info.mRace)!=toLower (cellRef->mBase->mRace)) - return false; - } - - //NPC class - if (!info.mClass.empty()) - { - if (isCreature) - return false; - - MWWorld::LiveCellRef *cellRef = actor.get(); - - if (!cellRef) - return false; - - if (toLower (info.mClass)!=toLower (cellRef->mBase->mClass)) - return false; - } - - //NPC faction - if (!info.mNpcFaction.empty()) - { - if (isCreature) - return false; - - //MWWorld::Class npcClass = MWWorld::Class::get(actor); - MWMechanics::NpcStats stats = MWWorld::Class::get(actor).getNpcStats(actor); - std::map::iterator it = stats.getFactionRanks().find(toLower(info.mNpcFaction)); - if(it!=stats.getFactionRanks().end()) - { - //check rank - if(it->second < (int)info.mData.mRank) return false; - } - else - { - //not in the faction - return false; - } - } - - // TODO check player faction - if(!info.mPcFaction.empty()) - { - MWMechanics::NpcStats stats = MWWorld::Class::get(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()).getNpcStats(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); - std::map::iterator it = stats.getFactionRanks().find(toLower(info.mPcFaction)); - if(it!=stats.getFactionRanks().end()) - { - //check rank - if(it->second < (int)info.mData.mPCrank) return false; - } - else - { - //not in the faction - return false; - } - } - - //check gender - if (!isCreature) - { - MWWorld::LiveCellRef* npc = actor.get(); - if(npc->mBase->mFlags & npc->mBase->Female) - { - if(static_cast (info.mData.mGender)==0) return false; - } - else - { - if(static_cast (info.mData.mGender)==1) return false; - } - } - - // check cell - if (!info.mCell.empty()) - if (MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->mCell->mName != info.mCell) - return false; - - // TODO check DATAstruct + // check DATAstruct for (std::vector::const_iterator iter (info.mSelects.begin()); iter != info.mSelects.end(); ++iter) if (!isMatching (actor, *iter)) diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index 982062e5bf..b69a6d7279 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -1,10 +1,117 @@ #include "filter.hpp" -MWDialogue::Filter::Filter (const MWWorld::Ptr& actor) : mActor (actor) {} +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" -bool MWDialogue::Filter::operator() (const ESM::DialInfo& dialogue) +#include "../mwworld/class.hpp" +#include "../mwworld/player.hpp" + +#include "../mwmechanics/npcstats.hpp" + +namespace { + std::string toLower (const std::string& name) + { + std::string lowerCase; + + std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), + (int(*)(int)) std::tolower); + + return lowerCase; + } +} + +bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const +{ + // actor id + if (!info.mActor.empty()) + if (toLower (info.mActor)!=MWWorld::Class::get (mActor).getId (mActor)) + return false; + + bool isCreature = (mActor.getTypeName() != typeid (ESM::NPC).name()); + + // NPC race + if (!info.mRace.empty()) + { + if (isCreature) + return false; + + MWWorld::LiveCellRef *cellRef = mActor.get(); + + if (toLower (info.mRace)!=toLower (cellRef->mBase->mRace)) + return false; + } + + // NPC class + if (!info.mClass.empty()) + { + if (isCreature) + return false; + + MWWorld::LiveCellRef *cellRef = mActor.get(); + + if (toLower (info.mClass)!=toLower (cellRef->mBase->mClass)) + return false; + } + + // NPC faction + if (!info.mNpcFaction.empty()) + { + if (isCreature) + return false; + + MWMechanics::NpcStats& stats = MWWorld::Class::get (mActor).getNpcStats (mActor); + std::map::iterator iter = stats.getFactionRanks().find (toLower (info.mNpcFaction)); + + if (iter==stats.getFactionRanks().end()) + return false; + + // check rank + if (iter->second < info.mData.mRank) + return false; + } + + // Gender + if (!isCreature) + { + MWWorld::LiveCellRef* npc = mActor.get(); + if (info.mData.mGender==(npc->mBase->mFlags & npc->mBase->Female ? 0 : 1)) + return false; + } + + return true; +} + +bool MWDialogue::Filter::testPlayer (const ESM::DialInfo& info) const +{ + const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + + // check player faction + if (!info.mPcFaction.empty()) + { + MWMechanics::NpcStats& stats = MWWorld::Class::get (player).getNpcStats (player); + std::map::iterator iter = stats.getFactionRanks().find (toLower (info.mPcFaction)); + + if(iter==stats.getFactionRanks().end()) + return false; + + // check rank + if (iter->second < info.mData.mPCrank) + return false; + } + + // check cell + if (!info.mCell.empty()) + if (toLower (player.getCell()->mCell->mName) != toLower (info.mCell)) + return false; return true; } + +MWDialogue::Filter::Filter (const MWWorld::Ptr& actor) : mActor (actor) {} + +bool MWDialogue::Filter::operator() (const ESM::DialInfo& info) const +{ + return testActor (info) && testPlayer (info); +} diff --git a/apps/openmw/mwdialogue/filter.hpp b/apps/openmw/mwdialogue/filter.hpp index 5193937820..3ca4153b3e 100644 --- a/apps/openmw/mwdialogue/filter.hpp +++ b/apps/openmw/mwdialogue/filter.hpp @@ -14,11 +14,17 @@ namespace MWDialogue { MWWorld::Ptr mActor; + bool testActor (const ESM::DialInfo& info) const; + ///< Is this the right actor for this \a info? + + bool testPlayer (const ESM::DialInfo& info) const; + ///< Do the player and the cell the player is currently in match \a info? + public: Filter (const MWWorld::Ptr& actor); - bool operator() (const ESM::DialInfo& dialogue); + bool operator() (const ESM::DialInfo& info) const; ///< \return does the dialogue match? }; } diff --git a/components/esm/loadinfo.hpp b/components/esm/loadinfo.hpp index f04fe862e2..f1decb9c63 100644 --- a/components/esm/loadinfo.hpp +++ b/components/esm/loadinfo.hpp @@ -32,10 +32,10 @@ struct DialInfo { int mUnknown1; int mDisposition; - char mRank; // Rank of NPC - char mGender; // See Gender enum - char mPCrank; // Player rank - char mUnknown2; + signed char mRank; // Rank of NPC + signed char mGender; // See Gender enum + signed char mPCrank; // Player rank + signed char mUnknown2; }; // 12 bytes DATAstruct mData;