From 04452b094963d8cbe1e453d9344d8407c4cf11f8 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sat, 30 Sep 2017 20:11:53 +0400 Subject: [PATCH 1/6] Use a pickpocket crime instead of theft when pickpocketing was failed --- apps/openmw/mwgui/container.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 57c756762..a70d833c7 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -136,7 +136,7 @@ namespace MWGui bool loot = mPtr.getClass().isActor() && mPtr.getClass().getCreatureStats(mPtr).isDead(); - if (mPtr.getTypeName() == typeid(ESM::NPC).name() && !loot) + if (mPtr.getClass().isNpc() && !loot) { // we are stealing stuff MWWorld::Ptr player = MWMechanics::getPlayer(); @@ -271,9 +271,8 @@ namespace MWGui MWMechanics::Pickpocket pickpocket(player, mPtr); if (pickpocket.pick(item.mBase, count)) { - int value = item.mBase.getClass().getValue(item.mBase) * count; MWBase::Environment::get().getMechanicsManager()->commitCrime( - player, mPtr, MWBase::MechanicsManager::OT_Theft, value, true); + player, mPtr, MWBase::MechanicsManager::OT_Pickpocket, 0, true); MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container); mPickpocketDetected = true; return false; From 34895157f91e25f2990afa59e2d4572ff837db37 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sat, 30 Sep 2017 20:22:26 +0400 Subject: [PATCH 2/6] Consider taking items from unconscious NPC as a theft --- apps/openmw/mwbase/mechanicsmanager.hpp | 2 +- apps/openmw/mwgui/tooltips.cpp | 2 +- apps/openmw/mwgui/tooltips.hpp | 4 ++-- apps/openmw/mwgui/windowmanagerimp.cpp | 2 +- .../mwmechanics/mechanicsmanagerimp.cpp | 23 +++++++++++++++---- .../mwmechanics/mechanicsmanagerimp.hpp | 4 ++-- 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index d9068b285..398439ad8 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -238,7 +238,7 @@ namespace MWBase /// Has the player stolen this item from the given owner? virtual bool isItemStolenFrom(const std::string& itemid, const std::string& ownerid) = 0; - virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::ConstPtr& item, MWWorld::Ptr& victim) = 0; + virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, MWWorld::Ptr& victim) = 0; /// Turn actor into werewolf or normal form. virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf) = 0; diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index e6de9c42c..a9930db4f 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -325,7 +325,7 @@ namespace MWGui } } - void ToolTips::setFocusObject(const MWWorld::ConstPtr& focus) + void ToolTips::setFocusObject(const MWWorld::Ptr& focus) { mFocusObject = focus; diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index bb2affc63..2793e6544 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -59,7 +59,7 @@ namespace MWGui void setDelay(float delay); - void setFocusObject(const MWWorld::ConstPtr& focus); + void setFocusObject(const MWWorld::Ptr& focus); void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y); ///< set the screen-space position of the tooltip for focused object @@ -96,7 +96,7 @@ namespace MWGui private: MyGUI::Widget* mDynamicToolTipBox; - MWWorld::ConstPtr mFocusObject; + MWWorld::Ptr mFocusObject; MyGUI::IntSize getToolTipViaPtr (int count, bool image=true); ///< @return requested tooltip size diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index fbee52c82..e96743b91 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1573,7 +1573,7 @@ namespace MWGui mMessageBoxManager->clear(); - mToolTips->setFocusObject(MWWorld::ConstPtr()); + mToolTips->setFocusObject(MWWorld::Ptr()); mSelectedSpell.clear(); mCustomMarkers.clear(); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 574444a8f..950cf8a01 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -840,17 +840,30 @@ namespace MWMechanics mAI = true; } - bool MechanicsManager::isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::ConstPtr& item, MWWorld::Ptr& victim) + bool MechanicsManager::isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, MWWorld::Ptr& victim) { - const MWWorld::CellRef& cellref = item.getCellRef(); + const MWWorld::CellRef& cellref = target.getCellRef(); // there is no harm to use unlocked doors - if (item.getClass().isDoor() && cellref.getLockLevel() <= 0 && ptr.getCellRef().getTrap().empty()) + if (target.getClass().isDoor() && cellref.getLockLevel() <= 0 && ptr.getCellRef().getTrap().empty()) return true; - // TODO: implement a better check to check if item is owned bed - if (item.getClass().isActivator() && item.getClass().getScript(item).compare(0, 3, "Bed") != 0) + // 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) return true; + if (target.getClass().isNpc()) + { + if (target.getClass().getCreatureStats(target).isDead()) + return true; + + // check if a player tries to pickpocket a target NPC + if(ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Sneak) + || target.getClass().getCreatureStats(target).getKnockedDown()) + return false; + + return true; + } + const std::string& owner = cellref.getOwner(); bool isOwned = !owner.empty() && owner != "player"; diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 1bf3a8d22..ee4cf28af 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -204,8 +204,8 @@ namespace MWMechanics /// Has the player stolen this item from the given owner? virtual bool isItemStolenFrom(const std::string& itemid, const std::string& ownerid); - /// @return is \a ptr allowed to take/use \a cellref or is it a crime? - virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::ConstPtr& item, MWWorld::Ptr& victim); + /// @return is \a ptr allowed to take/use \a target or is it a crime? + virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, MWWorld::Ptr& victim); virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf); virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor); From 3ebb18ce18b89407464f388c00fb36455500be36 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sat, 30 Sep 2017 20:31:06 +0400 Subject: [PATCH 3/6] Make unconscious actors do not report about crimes --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 950cf8a01..525749c38 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1097,6 +1097,10 @@ namespace MWMechanics if (it->getClass().getCreatureStats(*it).isDead()) continue; + // Unconsious actor can not report about crime + if (it->getClass().getCreatureStats(*it).getKnockedDown()) + continue; + if ((*it == victim && victimAware) || (MWBase::Environment::get().getWorld()->getLOS(player, *it) && awarenessCheck(player, *it) ) // Murder crime can be reported even if no one saw it (hearing is enough, I guess). @@ -1208,12 +1212,16 @@ namespace MWMechanics // Tell everyone (including the original reporter) in alarm range for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) { - if ( *it == player + if (*it == player || !it->getClass().isNpc() || it->getClass().getCreatureStats(*it).isDead()) continue; if (it->getClass().getCreatureStats(*it).getAiSequence().isInCombat(victim)) continue; + // Unconsious actor can not report about crime and should not become hostile + if (it->getClass().getCreatureStats(*it).getKnockedDown()) + continue; + // Player's followers should not attack player, or try to arrest him if (it->getClass().getCreatureStats(*it).getAiSequence().hasPackage(AiPackage::TypeIdFollow)) { From f26206b63026253e91993003a69bc29dbb9acb19 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sat, 30 Sep 2017 20:55:42 +0400 Subject: [PATCH 4/6] Make unconscious actors do not speak and do not track targets --- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 6 ++++++ apps/openmw/mwmechanics/actors.cpp | 14 +++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 4ed3b82a9..6fac03e92 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -567,6 +567,12 @@ namespace MWDialogue return; } + if (actor.getClass().getCreatureStats(actor).getKnockedDown()) + { + // Unconscious actors can not speak + return; + } + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Dialogue *dial = store.get().find(topic); diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index cef429504..d0fe5a755 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1232,13 +1232,17 @@ namespace MWMechanics float sqrHeadTrackDistance = std::numeric_limits::max(); MWWorld::Ptr headTrackTarget; - for(PtrActorMap::iterator it(mActors.begin()); it != mActors.end(); ++it) + // Unconsious actor can not track target + if (!iter->first.getClass().getCreatureStats(iter->first).getKnockedDown()) { - if (it->first == iter->first) - continue; - updateHeadTracking(iter->first, it->first, headTrackTarget, sqrHeadTrackDistance); + for(PtrActorMap::iterator it(mActors.begin()); it != mActors.end(); ++it) + { + if (it->first == iter->first) + continue; + updateHeadTracking(iter->first, it->first, headTrackTarget, sqrHeadTrackDistance); + } + iter->second->getCharacterController()->setHeadTrackTarget(headTrackTarget); } - iter->second->getCharacterController()->setHeadTrackTarget(headTrackTarget); } if (iter->first.getClass().isNpc() && iter->first != player) From b8fd530ee1111372f34f6e084fd0b966eb7c9dd0 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sat, 30 Sep 2017 21:20:38 +0400 Subject: [PATCH 5/6] Do not speak with unconscious creatures --- apps/openmw/mwclass/creature.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index d6926f11d..2e16b13aa 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -470,6 +470,9 @@ namespace MWClass if(stats.getAiSequence().isInCombat()) return std::shared_ptr(new MWWorld::FailedAction("")); + if(stats.getKnockedDown()) + return std::shared_ptr(new MWWorld::FailedAction("")); + return std::shared_ptr(new MWWorld::ActionTalk(ptr)); } From c5fcb9684efe3c0b41a0d7901af4887d7b9ca003 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sat, 30 Sep 2017 21:29:02 +0400 Subject: [PATCH 6/6] Improve owned crosshair feature behaviour --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 525749c38..da98e7f5f 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -856,6 +856,9 @@ namespace MWMechanics if (target.getClass().getCreatureStats(target).isDead()) return true; + if (target.getClass().getCreatureStats(target).getAiSequence().isInCombat()) + return true; + // check if a player tries to pickpocket a target NPC if(ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Sneak) || target.getClass().getCreatureStats(target).getKnockedDown())