diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index c1f2a808f..c51a418bf 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -300,6 +300,30 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con case SelectWrapper::Function_PcCrimeLevel: return MWWorld::Class::get (player).getNpcStats (player).getBounty(); + + case SelectWrapper::Function_RankRequirement: + { + if (MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().empty()) + return 0; + + std::string faction = + MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().begin()->first; + + int rank = getFactionRank (player, faction); + + if (rank>=9) + return 0; // max rank + + int result = 0; + + if (hasFactionRankSkillRequirements (player, faction, rank+1)) + result += 1; + + if (hasFactionRankReputationRequirements (player, faction, rank+1)) + result += 2; + + return result; + } default: @@ -382,6 +406,50 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co } } +int MWDialogue::Filter::getFactionRank (const MWWorld::Ptr& actor, const std::string& factionId) const +{ + MWMechanics::NpcStats& stats = MWWorld::Class::get (actor).getNpcStats (actor); + + std::map::const_iterator iter = stats.getFactionRanks().find (factionId); + + if (iter==stats.getFactionRanks().end()) + return -1; + + return iter->second; +} + +bool MWDialogue::Filter::hasFactionRankSkillRequirements (const MWWorld::Ptr& actor, + const std::string& factionId, int rank) const +{ + if (rank<0 || rank>=10) + throw std::runtime_error ("rank index out of range"); + + if (!MWWorld::Class::get (actor).getNpcStats (actor).hasSkillsForRank (factionId, rank)) + return false; + + const ESM::Faction& faction = + *MWBase::Environment::get().getWorld()->getStore().get().find (factionId); + + MWMechanics::CreatureStats& stats = MWWorld::Class::get (actor).getCreatureStats (actor); + + return stats.getAttribute (faction.mData.mAttribute1).getBase()>=faction.mData.mRankData[rank].mAttribute1 && + stats.getAttribute (faction.mData.mAttribute2).getBase()>=faction.mData.mRankData[rank].mAttribute2; +} + +bool MWDialogue::Filter::hasFactionRankReputationRequirements (const MWWorld::Ptr& actor, + const std::string& factionId, int rank) const +{ + if (rank<0 || rank>=10) + throw std::runtime_error ("rank index out of range"); + + MWMechanics::NpcStats& stats = MWWorld::Class::get (actor).getNpcStats (actor); + + const ESM::Faction& faction = + *MWBase::Environment::get().getWorld()->getStore().get().find (factionId); + + return stats.getFactionReputation (factionId)>=faction.mData.mRankData[rank].mFactReaction; +} + MWDialogue::Filter::Filter (const MWWorld::Ptr& actor, int choice, bool talkedToPlayer) : mActor (actor), mChoice (choice), mTalkedToPlayer (talkedToPlayer) {} diff --git a/apps/openmw/mwdialogue/filter.hpp b/apps/openmw/mwdialogue/filter.hpp index 2a252edc3..7c8f1116f 100644 --- a/apps/openmw/mwdialogue/filter.hpp +++ b/apps/openmw/mwdialogue/filter.hpp @@ -36,6 +36,14 @@ namespace MWDialogue bool getSelectStructBoolean (const SelectWrapper& select) const; + int getFactionRank (const MWWorld::Ptr& actor, const std::string& factionId) const; + + bool hasFactionRankSkillRequirements (const MWWorld::Ptr& actor, const std::string& factionId, + int rank) const; + + bool hasFactionRankReputationRequirements (const MWWorld::Ptr& actor, const std::string& factionId, + int rank) const; + public: Filter (const MWWorld::Ptr& actor, int choice, bool talkedToPlayer); diff --git a/apps/openmw/mwdialogue/selectwrapper.cpp b/apps/openmw/mwdialogue/selectwrapper.cpp index c143e9697..11f25741f 100644 --- a/apps/openmw/mwdialogue/selectwrapper.cpp +++ b/apps/openmw/mwdialogue/selectwrapper.cpp @@ -61,7 +61,9 @@ MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::decodeFunction() switch (index) { - // 0-5 + // 0, 1 + case 2: return Function_RankRequirement; + // 3-5 case 6: return Function_PcLevel; case 7: return Function_PcHealthPercent; case 8: case 9: return Function_PcDynamicStat; @@ -76,6 +78,7 @@ MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::decodeFunction() // 42 case 42: return Function_PcClothingModifier; case 43: return Function_PcCrimeLevel; + // 44-45 case 46: return Function_SameFaction; // 47-49 case 50: return Function_Choice; @@ -196,6 +199,7 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const Function_FriendlyHit, Function_PcLevel, Function_PcGender, Function_PcClothingModifier, Function_PcCrimeLevel, + Function_RankRequirement, Function_None // end marker }; @@ -250,7 +254,8 @@ bool MWDialogue::SelectWrapper::isNpcOnly() const Function_PcSkill, Function_PcExpelled, Function_PcVampire, - Function_PcCrimeLevel, + Function_PcCrimeLevel, + Function_RankRequirement, Function_None // end marker }; diff --git a/apps/openmw/mwdialogue/selectwrapper.hpp b/apps/openmw/mwdialogue/selectwrapper.hpp index fd51101d8..c12b39436 100644 --- a/apps/openmw/mwdialogue/selectwrapper.hpp +++ b/apps/openmw/mwdialogue/selectwrapper.hpp @@ -34,7 +34,8 @@ namespace MWDialogue Function_FriendlyHit, Function_TalkedToPc, Function_PcLevel, Function_PcHealthPercent, Function_PcDynamicStat, - Function_PcGender, Function_PcClothingModifier, Function_PcCrimeLevel + Function_PcGender, Function_PcClothingModifier, Function_PcCrimeLevel, + Function_RankRequirement }; enum Type diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 23e5cf54b..26415b631 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -3,12 +3,15 @@ #include #include +#include +#include #include #include #include #include +#include #include "../mwworld/esmstore.hpp" @@ -309,3 +312,28 @@ void MWMechanics::NpcStats::setReputation(int reputation) mReputation = reputation; } +bool MWMechanics::NpcStats::hasSkillsForRank (const std::string& factionId, int rank) const +{ + if (rank<0 || rank>=10) + throw std::runtime_error ("rank index out of range"); + + const ESM::Faction& faction = + *MWBase::Environment::get().getWorld()->getStore().get().find (factionId); + + std::vector skills; + + for (int i=0; i<6; ++i) + skills.push_back (static_cast (getSkill (faction.mData.mSkillID[i]).getModified())); + + std::sort (skills.begin(), skills.end()); + + std::vector::const_reverse_iterator iter = skills.rbegin(); + + const ESM::RankData& rankData = faction.mData.mRankData[rank]; + + if (*iter=rankData.mSkill2; +} + diff --git a/apps/openmw/mwmechanics/npcstats.hpp b/apps/openmw/mwmechanics/npcstats.hpp index 190c9a475..46af216d9 100644 --- a/apps/openmw/mwmechanics/npcstats.hpp +++ b/apps/openmw/mwmechanics/npcstats.hpp @@ -123,6 +123,8 @@ namespace MWMechanics bool isVampire() const; void setVampire (bool set); + + bool hasSkillsForRank (const std::string& factionId, int rank) const; }; }