mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-09 09:39:53 +00:00
Handle death event manually before disposing a corpse if a death animation was not finished yet (feature #5146)
This commit is contained in:
parent
84b3aaedaa
commit
b6044d231a
@ -176,6 +176,7 @@
|
||||
Feature #5122: Use magic glow for enchanted arrows
|
||||
Feature #5131: Custom skeleton bones
|
||||
Feature #5132: Unique animations for different weapon types
|
||||
Feature #5146: Safe Dispose corpse
|
||||
Task #4686: Upgrade media decoder to a more current FFmpeg API
|
||||
Task #4695: Optimize Distant Terrain memory consumption
|
||||
Task #4789: Optimize cell transitions
|
||||
|
@ -237,6 +237,8 @@ namespace MWBase
|
||||
|
||||
virtual float getActorsProcessingRange() const = 0;
|
||||
|
||||
virtual void notifyDied(const MWWorld::Ptr& actor) = 0;
|
||||
|
||||
virtual bool onOpen(const MWWorld::Ptr& ptr) = 0;
|
||||
virtual void onClose(const MWWorld::Ptr& ptr) = 0;
|
||||
|
||||
|
@ -7,12 +7,15 @@
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/scriptmanager.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
|
||||
#include "../mwscript/interpretercontext.hpp"
|
||||
|
||||
#include "countdialog.hpp"
|
||||
#include "inventorywindow.hpp"
|
||||
|
||||
@ -229,7 +232,26 @@ namespace MWGui
|
||||
if (mPtr.getClass().isPersistent(mPtr))
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sDisposeCorpseFail}");
|
||||
else
|
||||
{
|
||||
MWMechanics::CreatureStats& creatureStats = mPtr.getClass().getCreatureStats(mPtr);
|
||||
|
||||
// If we dispose corpse before end of death animation, we should update death counter counter manually.
|
||||
// Also we should run actor's script - it may react on actor's death.
|
||||
if (creatureStats.isDead() && !creatureStats.isDeathAnimationFinished())
|
||||
{
|
||||
creatureStats.setDeathAnimationFinished(true);
|
||||
MWBase::Environment::get().getMechanicsManager()->notifyDied(mPtr);
|
||||
|
||||
const std::string script = mPtr.getClass().getScript(mPtr);
|
||||
if (!script.empty() && MWBase::Environment::get().getWorld()->getScriptsEnabled())
|
||||
{
|
||||
MWScript::InterpreterContext interpreterContext (&mPtr.getRefData().getLocals(), mPtr);
|
||||
MWBase::Environment::get().getScriptManager()->run (script, interpreterContext);
|
||||
}
|
||||
}
|
||||
|
||||
MWBase::Environment::get().getWorld()->deleteObject(mPtr);
|
||||
}
|
||||
|
||||
mPtr = MWWorld::Ptr();
|
||||
}
|
||||
|
@ -1630,6 +1630,13 @@ namespace MWMechanics
|
||||
updateCombatMusic();
|
||||
}
|
||||
|
||||
void Actors::notifyDied(const MWWorld::Ptr &actor)
|
||||
{
|
||||
actor.getClass().getCreatureStats(actor).notifyDied();
|
||||
|
||||
++mDeathCount[Misc::StringUtils::lowerCase(actor.getCellRef().getRefId())];
|
||||
}
|
||||
|
||||
void Actors::killDeadActors()
|
||||
{
|
||||
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
|
||||
@ -1673,9 +1680,7 @@ namespace MWMechanics
|
||||
}
|
||||
else if (killResult == CharacterController::Result_DeathAnimJustFinished)
|
||||
{
|
||||
iter->first.getClass().getCreatureStats(iter->first).notifyDied();
|
||||
|
||||
++mDeathCount[Misc::StringUtils::lowerCase(iter->first.getCellRef().getRefId())];
|
||||
notifyDied(iter->first);
|
||||
|
||||
// Reset magic effects and recalculate derived effects
|
||||
// One case where we need this is to make sure bound items are removed upon death
|
||||
|
@ -71,6 +71,8 @@ namespace MWMechanics
|
||||
PtrActorMap::const_iterator begin() { return mActors.begin(); }
|
||||
PtrActorMap::const_iterator end() { return mActors.end(); }
|
||||
|
||||
void notifyDied(const MWWorld::Ptr &actor);
|
||||
|
||||
/// Check if the target actor was detected by an observer
|
||||
/// If the observer is a non-NPC, check all actors in AI processing distance as observers
|
||||
bool isActorDetected(const MWWorld::Ptr& actor, const MWWorld::Ptr& observer);
|
||||
|
@ -455,6 +455,11 @@ namespace MWMechanics
|
||||
}
|
||||
}
|
||||
|
||||
void MechanicsManager::notifyDied(const MWWorld::Ptr& actor)
|
||||
{
|
||||
mActors.notifyDied(actor);
|
||||
}
|
||||
|
||||
float MechanicsManager::getActorsProcessingRange() const
|
||||
{
|
||||
return mActors.getProcessingRange();
|
||||
|
@ -211,6 +211,8 @@ namespace MWMechanics
|
||||
|
||||
virtual float getActorsProcessingRange() const override;
|
||||
|
||||
virtual void notifyDied(const MWWorld::Ptr& actor) override;
|
||||
|
||||
/// Check if the target actor was detected by an observer
|
||||
/// If the observer is a non-NPC, check all actors in AI processing distance as observers
|
||||
virtual bool isActorDetected(const MWWorld::Ptr& actor, const MWWorld::Ptr& observer) override;
|
||||
|
@ -72,13 +72,10 @@ can loot during death animation
|
||||
: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 Morrowind behaves.
|
||||
if they are not in combat. In this case we have to increment death counter and run disposed actor's script instantly.
|
||||
|
||||
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.
|
||||
Makes using of summoned creatures exploit (looting summoned Dremoras and Golden Saints for expensive weapons) a lot harder.
|
||||
Conflicts with mannequin mods, which use SkipAnim to prevent end of death animation.
|
||||
|
||||
This setting can be toggled in Advanced tab of the launcher.
|
||||
|
@ -19,7 +19,7 @@
|
||||
<item>
|
||||
<widget class="QCheckBox" name="canLootDuringDeathAnimationCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>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.</p><p>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.</p></body></html></string>
|
||||
<string><html><head/><body><p>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. In this case we have to increment death counter and run disposed actor's script instantly.</p><p>If this setting is false, player has to wait until end of death animation in all cases. Makes using of summoned creatures exploit (looting summoned Dremoras and Golden Saints for expensive weapons) a lot harder. Conflicts with mannequin mods, which use SkipAnim to prevent end of death animation.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Can loot during death animation</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user