Issue #219: implemented rank requirement filter

This commit is contained in:
Marc Zinnschlag 2012-11-12 13:23:25 +01:00
parent 75f64aa38b
commit 77ba8c5117
6 changed files with 115 additions and 3 deletions

View file

@ -300,6 +300,30 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
case SelectWrapper::Function_PcCrimeLevel: case SelectWrapper::Function_PcCrimeLevel:
return MWWorld::Class::get (player).getNpcStats (player).getBounty(); 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: 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<std::string, int>::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<ESM::Faction>().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<ESM::Faction>().find (factionId);
return stats.getFactionReputation (factionId)>=faction.mData.mRankData[rank].mFactReaction;
}
MWDialogue::Filter::Filter (const MWWorld::Ptr& actor, int choice, bool talkedToPlayer) MWDialogue::Filter::Filter (const MWWorld::Ptr& actor, int choice, bool talkedToPlayer)
: mActor (actor), mChoice (choice), mTalkedToPlayer (talkedToPlayer) : mActor (actor), mChoice (choice), mTalkedToPlayer (talkedToPlayer)
{} {}

View file

@ -36,6 +36,14 @@ namespace MWDialogue
bool getSelectStructBoolean (const SelectWrapper& select) const; 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: public:
Filter (const MWWorld::Ptr& actor, int choice, bool talkedToPlayer); Filter (const MWWorld::Ptr& actor, int choice, bool talkedToPlayer);

View file

@ -61,7 +61,9 @@ MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::decodeFunction()
switch (index) switch (index)
{ {
// 0-5 // 0, 1
case 2: return Function_RankRequirement;
// 3-5
case 6: return Function_PcLevel; case 6: return Function_PcLevel;
case 7: return Function_PcHealthPercent; case 7: return Function_PcHealthPercent;
case 8: case 9: return Function_PcDynamicStat; case 8: case 9: return Function_PcDynamicStat;
@ -76,6 +78,7 @@ MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::decodeFunction()
// 42 // 42
case 42: return Function_PcClothingModifier; case 42: return Function_PcClothingModifier;
case 43: return Function_PcCrimeLevel; case 43: return Function_PcCrimeLevel;
// 44-45
case 46: return Function_SameFaction; case 46: return Function_SameFaction;
// 47-49 // 47-49
case 50: return Function_Choice; case 50: return Function_Choice;
@ -196,6 +199,7 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const
Function_FriendlyHit, Function_FriendlyHit,
Function_PcLevel, Function_PcGender, Function_PcClothingModifier, Function_PcLevel, Function_PcGender, Function_PcClothingModifier,
Function_PcCrimeLevel, Function_PcCrimeLevel,
Function_RankRequirement,
Function_None // end marker Function_None // end marker
}; };
@ -250,7 +254,8 @@ bool MWDialogue::SelectWrapper::isNpcOnly() const
Function_PcSkill, Function_PcSkill,
Function_PcExpelled, Function_PcExpelled,
Function_PcVampire, Function_PcVampire,
Function_PcCrimeLevel, Function_PcCrimeLevel,
Function_RankRequirement,
Function_None // end marker Function_None // end marker
}; };

View file

@ -34,7 +34,8 @@ namespace MWDialogue
Function_FriendlyHit, Function_FriendlyHit,
Function_TalkedToPc, Function_TalkedToPc,
Function_PcLevel, Function_PcHealthPercent, Function_PcDynamicStat, Function_PcLevel, Function_PcHealthPercent, Function_PcDynamicStat,
Function_PcGender, Function_PcClothingModifier, Function_PcCrimeLevel Function_PcGender, Function_PcClothingModifier, Function_PcCrimeLevel,
Function_RankRequirement
}; };
enum Type enum Type

View file

@ -3,12 +3,15 @@
#include <cmath> #include <cmath>
#include <stdexcept> #include <stdexcept>
#include <vector>
#include <algorithm>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <components/esm/loadskil.hpp> #include <components/esm/loadskil.hpp>
#include <components/esm/loadclas.hpp> #include <components/esm/loadclas.hpp>
#include <components/esm/loadgmst.hpp> #include <components/esm/loadgmst.hpp>
#include <components/esm/loadfact.hpp>
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
@ -309,3 +312,28 @@ void MWMechanics::NpcStats::setReputation(int reputation)
mReputation = 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<ESM::Faction>().find (factionId);
std::vector<int> skills;
for (int i=0; i<6; ++i)
skills.push_back (static_cast<int> (getSkill (faction.mData.mSkillID[i]).getModified()));
std::sort (skills.begin(), skills.end());
std::vector<int>::const_reverse_iterator iter = skills.rbegin();
const ESM::RankData& rankData = faction.mData.mRankData[rank];
if (*iter<rankData.mSkill1)
return false;
return *++iter>=rankData.mSkill2;
}

View file

@ -123,6 +123,8 @@ namespace MWMechanics
bool isVampire() const; bool isVampire() const;
void setVampire (bool set); void setVampire (bool set);
bool hasSkillsForRank (const std::string& factionId, int rank) const;
}; };
} }