From f775f7977b1c318fd6cdb8c8f741182a70be86a9 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Tue, 14 May 2019 10:12:40 +0400 Subject: [PATCH] Fix RaiseRank/LowerRank script functions (feature #4316) --- CHANGELOG.md | 1 + apps/openmw/mwclass/npc.cpp | 13 ++++++++++ apps/openmw/mwmechanics/npcstats.cpp | 10 ++++++++ apps/openmw/mwmechanics/npcstats.hpp | 4 +++- apps/openmw/mwscript/statsextensions.cpp | 30 ++++++++++++++++++++++-- 5 files changed, 55 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5be672229..43e4fe4ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 5f9640653..f22ac06b9 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -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 *ref = ptr.get(); return ref->mBase->getFactionRank(); } diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 0d16e3a85..ed4a7a4ad 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -66,6 +66,16 @@ const std::map& 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::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); diff --git a/apps/openmw/mwmechanics/npcstats.hpp b/apps/openmw/mwmechanics/npcstats.hpp index d2e42e994..47784ac1d 100644 --- a/apps/openmw/mwmechanics/npcstats.hpp +++ b/apps/openmw/mwmechanics/npcstats.hpp @@ -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 mFactionRank; std::set mExpelled; std::map 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& 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. diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 4499f1b5a..aa1da8b47 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -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 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