From dd919b9f2cb2e1e546e0e0ef899f051782cfebb3 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 26 Jul 2017 14:42:01 +0400 Subject: [PATCH] Do not allow to loot fighting actors during death animation (bug #3528) --- apps/openmw/mwclass/creature.cpp | 30 +++++++++++++--- apps/openmw/mwclass/npc.cpp | 36 +++++++++++++------ .../reference/modding/settings/game.rst | 18 +++++++++- files/settings-default.cfg | 3 ++ 4 files changed, 72 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index ce03af7a1..65f8c80d8 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/magiceffects.hpp" @@ -448,10 +449,27 @@ namespace MWClass return action; } - if(getCreatureStats(ptr).isDead()) - return std::shared_ptr(new MWWorld::ActionOpen(ptr, true)); - if(ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat()) + const MWMechanics::CreatureStats& stats = getCreatureStats(ptr); + + if(stats.isDead()) + { + bool canLoot = Settings::Manager::getBool ("can loot during death animation", "Game"); + + // by default user can loot friendly actors during death animation + if (canLoot && !stats.getAiSequence().isInCombat()) + return std::shared_ptr(new MWWorld::ActionOpen(ptr, true)); + + // otherwise wait until death animation + if(stats.isDeathAnimationFinished()) + return std::shared_ptr(new MWWorld::ActionOpen(ptr, true)); + + // death animation is not finished, do nothing + return std::shared_ptr (new MWWorld::FailedAction("")); + } + + if(stats.getAiSequence().isInCombat()) return std::shared_ptr(new MWWorld::FailedAction("")); + return std::shared_ptr(new MWWorld::ActionTalk(ptr)); } @@ -558,7 +576,11 @@ namespace MWClass return true; const CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData(); - return !customData.mCreatureStats.getAiSequence().isInCombat() || customData.mCreatureStats.isDead(); + + if (customData.mCreatureStats.isDead() && customData.mCreatureStats.isDeathAnimationFinished()) + return true; + + return !customData.mCreatureStats.getAiSequence().isInCombat(); } MWGui::ToolTipInfo Creature::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index f8ff3da19..ed1f12b31 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -863,16 +864,27 @@ namespace MWClass return action; } - if(getCreatureStats(ptr).isDead()) - return std::shared_ptr(new MWWorld::ActionOpen(ptr, true)); - if(ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat()) - return std::shared_ptr(new MWWorld::FailedAction("#{sActorInCombat}")); - if(getCreatureStats(actor).getStance(MWMechanics::CreatureStats::Stance_Sneak) - || ptr.getClass().getCreatureStats(ptr).getKnockedDown()) - return std::shared_ptr(new MWWorld::ActionOpen(ptr)); // stealing - // Can't talk to werewolfs - if(ptr.getClass().isNpc() && ptr.getClass().getNpcStats(ptr).isWerewolf()) + const MWMechanics::CreatureStats& stats = getCreatureStats(ptr); + + if(stats.isDead()) + { + bool canLoot = Settings::Manager::getBool ("can loot during death animation", "Game"); + + // by default user can loot friendly actors during death animation + if (canLoot && !stats.getAiSequence().isInCombat()) + return std::shared_ptr(new MWWorld::ActionOpen(ptr, true)); + + // otherwise wait until death animation + if(stats.isDeathAnimationFinished()) + return std::shared_ptr(new MWWorld::ActionOpen(ptr, true)); + + // death animation is not finished, do nothing return std::shared_ptr (new MWWorld::FailedAction("")); + } + + if(stats.getAiSequence().isInCombat()) + return std::shared_ptr(new MWWorld::FailedAction("")); + return std::shared_ptr(new MWWorld::ActionTalk(ptr)); } @@ -1019,7 +1031,11 @@ namespace MWClass return true; const NpcCustomData& customData = ptr.getRefData().getCustomData()->asNpcCustomData(); - return !customData.mNpcStats.getAiSequence().isInCombat() || customData.mNpcStats.isDead(); + + if (customData.mNpcStats.isDead() && customData.mNpcStats.isDeathAnimationFinished()) + return true; + + return !customData.mNpcStats.getAiSequence().isInCombat(); } MWGui::ToolTipInfo Npc::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const diff --git a/docs/source/reference/modding/settings/game.rst b/docs/source/reference/modding/settings/game.rst index 62fe5a70e..e1d5d75f6 100644 --- a/docs/source/reference/modding/settings/game.rst +++ b/docs/source/reference/modding/settings/game.rst @@ -65,6 +65,22 @@ the type of attack is determined by the direction that the character is moving a The default value is false. This setting can be toggled with the Always Use Best Attack button in the Prefs panel of the Options menu. +can loot during death animation +------------------------------- + +:Type: boolean +:Range: True/False +:Default: True + +If this setting is true, the player is allowed to loot actors (e.g. summoned creatures) during death animation, if they are not in combat. +However disposing corpses during death animation is not recommended - death counter may not be incremented, and this behaviour can break quests. +This is how original Morrowind behaves. + +If this setting is false, player has to wait until end of death animation in all cases. +This case is more safe, but makes using of summoned creatures exploit (looting summoned Dremoras and Golden Saints for expensive weapons) a lot harder. + +The default value is true. This setting can only be configured by editing the settings configuration file. + difficulty ---------- @@ -110,4 +126,4 @@ followers attack on sight :Default: False Makes player followers and escorters start combat with enemies who have started combat with them or the player. -Otherwise they wait for the enemies or the player to do an attack first. \ No newline at end of file +Otherwise they wait for the enemies or the player to do an attack first. diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 40c1ed099..a0460326b 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -180,6 +180,9 @@ prevent merchant equipping = false # or the player. Otherwise they wait for the enemies or the player to do an attack first. followers attack on sight = false +# Can loot non-fighting actors during death animation +can loot during death animation = true + [General] # Anisotropy reduces distortion in textures at low angles (e.g. 0 to 16).