Commit f775f797 authored by Andrei Kortunov's avatar Andrei Kortunov

Fix RaiseRank/LowerRank script functions (feature #4316)

parent 5ccf7da1
......@@ -98,6 +98,7 @@
Feature #3999: Shift + Double Click should maximize/restore menu size
Feature #4001: Toggle sneak controller shortcut
Feature #4209: Editor: Faction rank sub-table
Feature #4316: Implement RaiseRank/LowerRank functions properly
Feature #4360: Improve default controller bindings
Feature #4673: Weapon sheathing
Feature #4675: Support for NiRollController
......
......@@ -1416,6 +1416,19 @@ namespace MWClass
int Npc::getPrimaryFactionRank (const MWWorld::ConstPtr& ptr) const
{
std::string factionID = ptr.getClass().getPrimaryFaction(ptr);
if(factionID.empty())
return -1;
// Search in the NPC data first
if (const MWWorld::CustomData* data = ptr.getRefData().getCustomData())
{
int rank = data->asNpcCustomData().mNpcStats.getFactionRank(factionID);
if (rank >= 0)
return rank;
}
// Use base NPC record as a fallback
const MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
return ref->mBase->getFactionRank();
}
......
......@@ -66,6 +66,16 @@ const std::map<std::string, int>& MWMechanics::NpcStats::getFactionRanks() const
return mFactionRank;
}
int MWMechanics::NpcStats::getFactionRank(const std::string &faction) const
{
const std::string lower = Misc::StringUtils::lowerCase(faction);
std::map<std::string, int>::const_iterator it = mFactionRank.find(lower);
if (it != mFactionRank.end())
return it->second;
return -1;
}
void MWMechanics::NpcStats::raiseRank(const std::string &faction)
{
const std::string lower = Misc::StringUtils::lowerCase(faction);
......
......@@ -29,7 +29,7 @@ namespace MWMechanics
// ----- used by the player only, maybe should be moved at some point -------
int mBounty;
int mWerewolfKills;
/// Used for the player only; NPCs have maximum one faction defined in their NPC record
/// Used only for the player and for NPC's with ranks, modified by scripts; other NPCs have maximum one faction defined in their NPC record
std::map<std::string, int> mFactionRank;
std::set<std::string> mExpelled;
std::map<std::string, int> mFactionReputation;
......@@ -61,7 +61,9 @@ namespace MWMechanics
SkillValue& getSkill (int index);
void setSkill(int index, const SkillValue& value);
int getFactionRank(const std::string &faction) const;
const std::map<std::string, int>& getFactionRanks() const;
/// Increase the rank in this faction by 1, if such a rank exists.
void raiseRank(const std::string& faction);
/// Lower the rank in this faction by 1, if such a rank exists.
......
......@@ -1019,7 +1019,19 @@ namespace MWScript
if (ptr == player)
return;
ptr.getClass().getNpcStats(ptr).raiseRank(factionID);
// If we already changed rank for this NPC, modify current rank in the NPC stats.
// Otherwise take rank from base NPC record, increase it and put it to NPC data.
int currentRank = ptr.getClass().getNpcStats(ptr).getFactionRank(factionID);
if (currentRank >= 0)
ptr.getClass().getNpcStats(ptr).raiseRank(factionID);
else
{
int rank = ptr.getClass().getPrimaryFactionRank(ptr);
rank++;
ptr.getClass().getNpcStats(ptr).joinFaction(factionID);
for (int i=0; i<rank; i++)
ptr.getClass().getNpcStats(ptr).raiseRank(factionID);
}
}
};
......@@ -1042,7 +1054,21 @@ namespace MWScript
if (ptr == player)
return;
ptr.getClass().getNpcStats(ptr).lowerRank(factionID);
// If we already changed rank for this NPC, modify current rank in the NPC stats.
// Otherwise take rank from base NPC record, decrease it and put it to NPC data.
int currentRank = ptr.getClass().getNpcStats(ptr).getFactionRank(factionID);
if (currentRank == 0)
return;
else if (currentRank > 0)
ptr.getClass().getNpcStats(ptr).lowerRank(factionID);
else
{
int rank = ptr.getClass().getPrimaryFactionRank(ptr);
rank--;
ptr.getClass().getNpcStats(ptr).joinFaction(factionID);
for (int i=0; i<rank; i++)
ptr.getClass().getNpcStats(ptr).raiseRank(factionID);
}
}
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment