From a204b4da9648d41264f4526dab0f09f13347f7aa Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Tue, 14 Dec 2021 21:06:40 +0100 Subject: [PATCH] Change the legalities of opening unlocked objects --- CHANGELOG.md | 1 + .../mwmechanics/mechanicsmanagerimp.cpp | 70 +++++++++++-------- 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bc340bef0..b61cf944b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -89,6 +89,7 @@ Bug #6433: Items bound to Quick Keys sometimes do not appear until the Quick Key menu is opened Bug #6451: Weapon summoned from Cast When Used item will have the name "None" Bug #6473: Strings from NIF should be parsed only to first null terminator + Bug #6493: Unlocking owned but not locked or unlocked containers is considered a crime Feature #890: OpenMW-CS: Column filtering Feature #1465: "Reset" argument for AI functions Feature #2554: Modifying an object triggers the instances table to scroll to the corresponding record diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 9974cb44cd..fa5aaa82ef 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -66,6 +66,35 @@ namespace } } + bool isOwned(const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, MWWorld::Ptr& victim) + { + const MWWorld::CellRef& cellref = target.getCellRef(); + + const std::string& owner = cellref.getOwner(); + bool isOwned = !owner.empty() && owner != "player"; + + const std::string& faction = cellref.getFaction(); + bool isFactionOwned = false; + if (!faction.empty() && ptr.getClass().isNpc()) + { + const std::map& factions = ptr.getClass().getNpcStats(ptr).getFactionRanks(); + auto found = factions.find(Misc::StringUtils::lowerCase(faction)); + if (found == factions.end() || found->second < cellref.getFactionRank()) + isFactionOwned = true; + } + + const std::string& globalVariable = cellref.getGlobalVariable(); + if (!globalVariable.empty() && MWBase::Environment::get().getWorld()->getGlobalInt(globalVariable)) + { + isOwned = false; + isFactionOwned = false; + } + + if (!cellref.getOwner().empty()) + victim = MWBase::Environment::get().getWorld()->searchPtr(cellref.getOwner(), true, false); + + return isOwned || isFactionOwned; + } } namespace MWMechanics @@ -881,35 +910,11 @@ namespace MWMechanics return true; } - const std::string& owner = cellref.getOwner(); - bool isOwned = !owner.empty() && owner != "player"; - - const std::string& faction = cellref.getFaction(); - bool isFactionOwned = false; - if (!faction.empty() && ptr.getClass().isNpc()) - { - const std::map& factions = ptr.getClass().getNpcStats(ptr).getFactionRanks(); - std::map::const_iterator found = factions.find(Misc::StringUtils::lowerCase(faction)); - if (found == factions.end() - || found->second < cellref.getFactionRank()) - isFactionOwned = true; - } - - const std::string& globalVariable = cellref.getGlobalVariable(); - if (!globalVariable.empty() && MWBase::Environment::get().getWorld()->getGlobalInt(Misc::StringUtils::lowerCase(globalVariable)) == 1) - { - isOwned = false; - isFactionOwned = false; - } - - if (!cellref.getOwner().empty()) - victim = MWBase::Environment::get().getWorld()->searchPtr(cellref.getOwner(), true, false); - - // A special case for evidence chest - we should not allow to take items even if it is technically permitted - if (Misc::StringUtils::ciEqual(cellref.getRefId(), "stolen_goods")) + if (isOwned(ptr, target, victim)) return false; - return (!isOwned && !isFactionOwned); + // A special case for evidence chest - we should not allow to take items even if it is technically permitted + return !Misc::StringUtils::ciEqual(cellref.getRefId(), "stolen_goods"); } bool MechanicsManager::sleepInBed(const MWWorld::Ptr &ptr, const MWWorld::Ptr &bed) @@ -941,9 +946,14 @@ namespace MWMechanics void MechanicsManager::unlockAttempted(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item) { MWWorld::Ptr victim; - if (isAllowedToUse(ptr, item, victim)) - return; - commitCrime(ptr, victim, OT_Trespassing, item.getCellRef().getFaction()); + if (isOwned(ptr, item, victim)) + { + // Note that attempting to unlock something that has ever been locked (even ESM::UnbreakableLock) is a crime even if it's already unlocked. + // Likewise, it's illegal to unlock something that has a trap but isn't otherwise locked. + const auto& cellref = item.getCellRef(); + if(cellref.getLockLevel() || !cellref.getTrap().empty()) + commitCrime(ptr, victim, OT_Trespassing, item.getCellRef().getFaction()); + } } std::vector > MechanicsManager::getStolenItemOwners(const std::string& itemid)