1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-06 00:55:50 +00:00

Handle death in actor update rather than instantly (Fixes #1866)

This commit is contained in:
scrawl 2014-09-05 17:17:45 +02:00
parent 1c178768f5
commit 282c93ccc5
7 changed files with 33 additions and 37 deletions

View File

@ -198,9 +198,8 @@ namespace MWBase
/// making it more likely for the function to return true.
virtual bool isAggressive (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, int bias=0, bool ignoreDistance=false) = 0;
/// Usually done once a frame, but can be invoked manually in time-critical situations.
/// This will increase the death count for any actors that were killed.
virtual void killDeadActors() = 0;
/// Resurrects the player if necessary
virtual void keepPlayerAlive() = 0;
};
}

View File

@ -1292,23 +1292,10 @@ namespace MWMechanics
continue;
}
// If it's the player and God Mode is turned on, keep it alive
if (iter->first.getRefData().getHandle()=="player" &&
MWBase::Environment::get().getWorld()->getGodModeState())
{
MWMechanics::DynamicStat<float> stat (stats.getHealth());
if (stat.getModified()<1)
{
stat.setModified(1, 0);
stats.setHealth(stat);
}
stats.resurrect();
continue;
}
if (iter->second->kill())
{
iter->first.getClass().getCreatureStats(iter->first).notifyDied();
++mDeathCount[Misc::StringUtils::lowerCase(iter->first.getCellRef().getRefId())];
// Make sure spell effects with CasterLinked flag are removed

View File

@ -44,6 +44,8 @@ namespace MWMechanics
void updateCrimePersuit (const MWWorld::Ptr& ptr, float duration);
void killDeadActors ();
public:
Actors();
@ -98,9 +100,6 @@ namespace MWMechanics
int countDeaths (const std::string& id) const;
///< Return the number of deaths for actors with the given ID.
///@see MechanicsManager::killDeadActors
void killDeadActors ();
void forceStateUpdate(const MWWorld::Ptr &ptr);
void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number);

View File

@ -188,16 +188,10 @@ namespace MWMechanics
if (index==0 && mDynamic[index].getCurrent()<1)
{
if (!mDead)
mDied = true;
mDead = true;
if (mDied)
// Must increase death count immediately. There are scripts that use getDeadCount as reaction to onDeath
// and rely on the increased value.
// Would be more appropriate to use a killActor(actor) function, but we don't have access to the Ptr in CreatureStats.
MWBase::Environment::get().getMechanicsManager()->killDeadActors();
if (MWBase::Environment::get().getWorld()->getGodModeState())
MWBase::Environment::get().getMechanicsManager()->keepPlayerAlive();
}
}
@ -242,6 +236,11 @@ namespace MWMechanics
return mDead;
}
void CreatureStats::notifyDied()
{
mDied = true;
}
bool CreatureStats::hasDied() const
{
return mDied;

View File

@ -168,6 +168,8 @@ namespace MWMechanics
bool isDead() const;
void notifyDied();
bool hasDied() const;
void clearHasDied();

View File

@ -664,11 +664,6 @@ namespace MWMechanics
return mActors.countDeaths (id);
}
void MechanicsManager::killDeadActors()
{
mActors.killDeadActors();
}
void MechanicsManager::getPersuasionDispositionChange (const MWWorld::Ptr& npc, PersuasionType type,
float currentTemporaryDispositionDelta, bool& success, float& tempChange, float& permChange)
{
@ -1303,4 +1298,21 @@ namespace MWMechanics
return (fight >= 100);
}
void MechanicsManager::keepPlayerAlive()
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
CreatureStats& stats = player.getClass().getCreatureStats(player);
if (stats.isDead())
{
MWMechanics::DynamicStat<float> stat (stats.getHealth());
if (stat.getModified()<1)
{
stat.setModified(1, 0);
stats.setHealth(stat);
}
stats.resurrect();
}
}
}

View File

@ -162,9 +162,7 @@ namespace MWMechanics
/// making it more likely for the function to return true.
virtual bool isAggressive (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, int bias=0, bool ignoreDistance=false);
/// Usually done once a frame, but can be invoked manually in time-critical situations.
/// This will increase the death count for any actors that were killed.
virtual void killDeadActors();
virtual void keepPlayerAlive();
};
}