From 5fd3ec103545cd9efb6150c2f06062fbc5c546c8 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Tue, 19 Jun 2018 14:17:33 +0400 Subject: [PATCH] Implement unlockable locks with 'lock 0' console command --- CHANGELOG.md | 1 + apps/openmw/mwclass/container.cpp | 12 +++++++----- apps/openmw/mwclass/door.cpp | 14 ++++++++------ apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 7 ++++++- apps/openmw/mwmechanics/security.cpp | 4 +++- components/esm/cellref.cpp | 3 +++ components/esm/cellref.hpp | 2 ++ 7 files changed, 30 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2033d3f08..af8c813db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ Bug #4419: MRK NiStringExtraData is handled incorrectly Bug #4426: RotateWorld behavior is incorrect Bug #4429: [Windows] Error on build INSTALL.vcxproj project (debug) with cmake 3.7.2 + Bug #4431: "Lock 0" console command is a no-op Bug #4432: Guards behaviour is incorrect if they do not have AI packages Bug #4433: Guard behaviour is incorrect with Alarm = 0 Bug #4451: Script fails to compile when using "Begin, [ScriptName]" syntax diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 1d51a7830..efe460b00 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -239,7 +239,8 @@ namespace MWClass info.caption = ref->mBase->mName; std::string text; - if (ptr.getCellRef().getLockLevel() > 0) + int lockLevel = ptr.getCellRef().getLockLevel(); + if (lockLevel > 0 && lockLevel != ESM::UnbreakableLock) text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ptr.getCellRef().getLockLevel()); else if (ptr.getCellRef().getLockLevel() < 0) text += "\n#{sUnlocked}"; @@ -271,15 +272,16 @@ namespace MWClass void Container::lock (const MWWorld::Ptr& ptr, int lockLevel) const { - if(lockLevel!=0) - ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, in positive + if(lockLevel != 0) + ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, if positive else - ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the original one + ptr.getCellRef().setLockLevel(ESM::UnbreakableLock); // If zero, set to max lock level } void Container::unlock (const MWWorld::Ptr& ptr) const { - ptr.getCellRef().setLockLevel(-abs(ptr.getCellRef().getLockLevel())); //Makes lockLevel negative + int lockLevel = ptr.getCellRef().getLockLevel(); + ptr.getCellRef().setLockLevel(-abs(lockLevel)); //Makes lockLevel negative } bool Container::canLock(const MWWorld::ConstPtr &ptr) const diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index a6aacfa12..d738974dd 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -193,7 +193,7 @@ namespace MWClass std::shared_ptr action(new MWWorld::ActionTeleport (ptr.getCellRef().getDestCell(), ptr.getCellRef().getDoorDest(), true)); action->setSound(openSound); return action; - } + } } else { @@ -240,15 +240,16 @@ namespace MWClass void Door::lock (const MWWorld::Ptr& ptr, int lockLevel) const { - if(lockLevel!=0) - ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, in positive + if(lockLevel != 0) + ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, if positive else - ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the original one + ptr.getCellRef().setLockLevel(ESM::UnbreakableLock); // If zero, set to max lock level } void Door::unlock (const MWWorld::Ptr& ptr) const { - ptr.getCellRef().setLockLevel(-abs(ptr.getCellRef().getLockLevel())); //Makes lockLevel negative + int lockLevel = ptr.getCellRef().getLockLevel(); + ptr.getCellRef().setLockLevel(-abs(lockLevel)); //Makes lockLevel negative } bool Door::canLock(const MWWorld::ConstPtr &ptr) const @@ -300,7 +301,8 @@ namespace MWClass text += "\n" + getDestination(*ref); } - if (ptr.getCellRef().getLockLevel() > 0) + int lockLevel = ptr.getCellRef().getLockLevel(); + if (lockLevel > 0 && lockLevel != ESM::UnbreakableLock) text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ptr.getCellRef().getLockLevel()); else if (ptr.getCellRef().getLockLevel() < 0) text += "\n#{sUnlocked}"; diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 1fc98a327..c2f7a664c 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -884,8 +884,13 @@ namespace MWMechanics const MWWorld::CellRef& cellref = target.getCellRef(); // there is no harm to use unlocked doors - if (target.getClass().isDoor() && cellref.getLockLevel() <= 0 && ptr.getCellRef().getTrap().empty()) + int lockLevel = cellref.getLockLevel(); + if (target.getClass().isDoor() && + (lockLevel <= 0 || lockLevel == ESM::UnbreakableLock) && + ptr.getCellRef().getTrap().empty()) + { return true; + } // TODO: implement a better check to check if target is owned bed if (target.getClass().isActivator() && target.getClass().getScript(target).compare(0, 3, "Bed") != 0) diff --git a/apps/openmw/mwmechanics/security.cpp b/apps/openmw/mwmechanics/security.cpp index 97878db87..3e38bc521 100644 --- a/apps/openmw/mwmechanics/security.cpp +++ b/apps/openmw/mwmechanics/security.cpp @@ -31,7 +31,9 @@ namespace MWMechanics void Security::pickLock(const MWWorld::Ptr &lock, const MWWorld::Ptr &lockpick, std::string& resultMessage, std::string& resultSound) { - if (!(lock.getCellRef().getLockLevel() > 0) || !lock.getClass().canLock(lock)) //If it's unlocked back out immediately + if (lock.getCellRef().getLockLevel() <= 0 || + lock.getCellRef().getLockLevel() == ESM::UnbreakableLock || + !lock.getClass().canLock(lock)) //If it's unlocked or can not be unlocked back out immediately return; int lockStrength = lock.getCellRef().getLockLevel(); diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index f35149586..1f7c2b964 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -126,6 +126,9 @@ void ESM::CellRef::loadData(ESMReader &esm, bool &isDeleted) break; } } + + if (mLockLevel == 0 && !mKey.empty()) + mLockLevel = UnbreakableLock; } void ESM::CellRef::save (ESMWriter &esm, bool wideRefNum, bool inInventory, bool isDeleted) const diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp index f14617531..a0b9fdd58 100644 --- a/components/esm/cellref.hpp +++ b/components/esm/cellref.hpp @@ -1,6 +1,7 @@ #ifndef OPENMW_ESM_CELLREF_H #define OPENMW_ESM_CELLREF_H +#include #include #include "defs.hpp" @@ -10,6 +11,7 @@ namespace ESM class ESMWriter; class ESMReader; + const int UnbreakableLock = std::numeric_limits::max(); struct RefNum {