diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index 24e955cdf..85fcfc75b 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -112,6 +112,8 @@ namespace MWBase OffenseType type, int arg=0) = 0; /// Utility to check if taking this item is illegal and calling commitCrime if so virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count) = 0; + /// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so + virtual void objectOpened (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item) = 0; /// Attempt sleeping in a bed. If this is illegal, call commitCrime. /// @return was it illegal, and someone saw you doing it? virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed) = 0; diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 511fe6544..002cd561d 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -19,7 +19,7 @@ namespace { /// @return is \a ptr allowed to take/use \a item or is it a crime? - bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item) + bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, MWWorld::Ptr& victim) { const std::string& owner = item.getCellRef().mOwner; bool isOwned = !owner.empty(); @@ -33,6 +33,9 @@ namespace isFactionOwned = true; } + if (!item.getCellRef().mOwner.empty()) + victim = MWBase::Environment::get().getWorld()->getPtr(item.getCellRef().mOwner, true); + return (!isOwned && !isFactionOwned); } } @@ -752,11 +755,9 @@ namespace MWMechanics bool MechanicsManager::sleepInBed(const MWWorld::Ptr &ptr, const MWWorld::Ptr &bed) { - if (isAllowedToUse(ptr, bed)) - return false; MWWorld::Ptr victim; - if (!bed.getCellRef().mOwner.empty()) - victim = MWBase::Environment::get().getWorld()->getPtr(bed.getCellRef().mOwner, true); + if (isAllowedToUse(ptr, bed, victim)) + return false; if(commitCrime(ptr, victim, OT_SleepingInOwnedBed)) { @@ -767,14 +768,19 @@ namespace MWMechanics return false; } + void MechanicsManager::objectOpened(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item) + { + MWWorld::Ptr victim; + if (isAllowedToUse(ptr, item, victim)) + return; + commitCrime(ptr, victim, OT_Trespassing); + } + void MechanicsManager::itemTaken(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item, int count) { - if (isAllowedToUse(ptr, item)) - return; MWWorld::Ptr victim; - if (!item.getCellRef().mOwner.empty()) - victim = MWBase::Environment::get().getWorld()->getPtr(item.getCellRef().mOwner, true); - + if (isAllowedToUse(ptr, item, victim)) + return; commitCrime(ptr, victim, OT_Theft, item.getClass().getValue(item) * count); } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index cec08fa92..569cd2fca 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -113,6 +113,8 @@ namespace MWMechanics OffenseType type, int arg=0); /// Utility to check if taking this item is illegal and calling commitCrime if so virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count); + /// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so + virtual void objectOpened (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item); /// Attempt sleeping in a bed. If this is illegal, call commitCrime. /// @return was it illegal, and someone saw you doing it? virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed); diff --git a/apps/openmw/mwmechanics/security.cpp b/apps/openmw/mwmechanics/security.cpp index 0769e13df..2e5eaecfd 100644 --- a/apps/openmw/mwmechanics/security.cpp +++ b/apps/openmw/mwmechanics/security.cpp @@ -6,6 +6,7 @@ #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/mechanicsmanager.hpp" #include "npcstats.hpp" #include "creaturestats.hpp" @@ -45,6 +46,7 @@ namespace MWMechanics resultMessage = "#{sLockImpossible}"; else { + MWBase::Environment::get().getMechanicsManager()->objectOpened(mActor, lock); int roll = static_cast (std::rand()) / RAND_MAX * 100; if (roll <= x) { @@ -86,6 +88,7 @@ namespace MWMechanics resultMessage = "#{sTrapImpossible}"; else { + MWBase::Environment::get().getMechanicsManager()->objectOpened(mActor, trap); int roll = static_cast (std::rand()) / RAND_MAX * 100; if (roll <= x) { diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index a1cdb8b61..8c4c4d292 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -4,7 +4,7 @@ #include "../mwbase/windowmanager.hpp" #include "../mwbase/soundmanager.hpp" - +#include "../mwbase/mechanicsmanager.hpp" #include "../mwworld/containerstore.hpp" #include "../mwworld/actionteleport.hpp" @@ -167,7 +167,7 @@ namespace MWMechanics } } else - applyInstantEffect(target, EffectKey(*effectIt), magnitude); + applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude); // HACK: Damage attribute/skill actually has a duration, even though the actual effect is instant and permanent. // This was probably just done to have the effect visible in the magic menu for a while @@ -177,7 +177,7 @@ namespace MWMechanics || effectIt->mEffectID == ESM::MagicEffect::RestoreAttribute || effectIt->mEffectID == ESM::MagicEffect::RestoreSkill ) - applyInstantEffect(target, EffectKey(*effectIt), magnitude); + applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude); if (target.getClass().isActor() || magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration) { @@ -220,7 +220,7 @@ namespace MWMechanics mSourceName, caster.getRefData().getHandle()); } - void CastSpell::applyInstantEffect(const MWWorld::Ptr &target, MWMechanics::EffectKey effect, float magnitude) + void CastSpell::applyInstantEffect(const MWWorld::Ptr &target, const MWWorld::Ptr &caster, MWMechanics::EffectKey effect, float magnitude) { short effectId = effect.mId; if (!target.getClass().isActor()) @@ -232,11 +232,13 @@ namespace MWMechanics } else if (effectId == ESM::MagicEffect::Open) { - // TODO: This is a crime if (target.getCellRef().mLockLevel <= magnitude) { if (target.getCellRef().mLockLevel > 0) + { MWBase::Environment::get().getSoundManager()->playSound3D(target, "Open Lock", 1.f, 1.f); + MWBase::Environment::get().getMechanicsManager()->objectOpened(caster, target); + } target.getCellRef().mLockLevel = 0; } else diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp index a55c45fd1..438b65575 100644 --- a/apps/openmw/mwmechanics/spellcasting.hpp +++ b/apps/openmw/mwmechanics/spellcasting.hpp @@ -203,7 +203,7 @@ namespace MWMechanics void inflict (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const ESM::EffectList& effects, ESM::RangeType range, bool reflected=false); - void applyInstantEffect (const MWWorld::Ptr& target, MWMechanics::EffectKey effect, float magnitude); + void applyInstantEffect (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, MWMechanics::EffectKey effect, float magnitude); }; } diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 2aee74eee..b11c22c72 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -392,7 +392,7 @@ void MWWorld::InventoryStore::updateMagicEffects(const Ptr& actor) // Apply instant effects MWMechanics::CastSpell cast(actor, actor); if (magnitude) - cast.applyInstantEffect(actor, effectIt->mEffectID, magnitude); + cast.applyInstantEffect(actor, actor, effectIt->mEffectID, magnitude); } if (magnitude)