Increase death count immediately on death (Bug #1588)

This is required for scripts using getDeadCount as reaction to onDeath that rely on the increased value.
deque
scrawl 11 years ago
parent d43c21a9fc
commit c0645d4978

@ -196,6 +196,10 @@ namespace MWBase
/// @param bias Can be used to add an additional aggression bias towards the target,
/// 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;
};
}

@ -1029,10 +1029,6 @@ namespace MWMechanics
iter->second->update(duration);
}
// Kill dead actors, update some variables
int hostilesCount = 0; // need to know this to play Battle music
for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{
const MWWorld::Class &cls = iter->first.getClass();
@ -1048,68 +1044,23 @@ namespace MWMechanics
stats.setKnockedDownOneFrame(false);
stats.setKnockedDownOverOneFrame(true);
}
}
if(!stats.isDead())
{
if (stats.isHostile()) hostilesCount++;
if(iter->second->isDead())
{
// Actor has been resurrected. Notify the CharacterController and re-enable collision.
MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, true);
iter->second->resurrect();
}
if(!stats.isDead())
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());
int hostilesCount = 0; // need to know this to play Battle music
if (stat.getModified()<1)
{
stat.setModified(1, 0);
stats.setHealth(stat);
}
stats.resurrect();
continue;
}
for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{
const MWWorld::Class &cls = iter->first.getClass();
CreatureStats &stats = cls.getCreatureStats(iter->first);
if (iter->second->kill())
if(!stats.isDead())
{
++mDeathCount[cls.getId(iter->first)];
// Make sure spell effects with CasterLinked flag are removed
for (PtrControllerMap::iterator iter2(mActors.begin());iter2 != mActors.end();++iter2)
{
MWMechanics::ActiveSpells& spells = iter2->first.getClass().getCreatureStats(iter2->first).getActiveSpells();
spells.purge(stats.getActorId());
}
// Apply soultrap
if (iter->first.getTypeName() == typeid(ESM::Creature).name())
{
SoulTrap soulTrap (iter->first);
stats.getActiveSpells().visitEffectSources(soulTrap);
}
// Reset magic effects and recalculate derived effects
// One case where we need this is to make sure bound items are removed upon death
stats.setMagicEffects(MWMechanics::MagicEffects());
stats.getActiveSpells().clear();
calculateCreatureStatModifiers(iter->first, 0);
MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false);
if (cls.isEssential(iter->first))
MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}");
if (stats.isHostile()) hostilesCount++;
}
}
killDeadActors();
// check if we still have any player enemies to switch music
static bool isBattleMusic = false;
@ -1184,6 +1135,74 @@ namespace MWMechanics
}
}
}
void Actors::killDeadActors()
{
for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{
const MWWorld::Class &cls = iter->first.getClass();
CreatureStats &stats = cls.getCreatureStats(iter->first);
if(!stats.isDead())
{
if(iter->second->isDead())
{
// Actor has been resurrected. Notify the CharacterController and re-enable collision.
MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, true);
iter->second->resurrect();
}
if(!stats.isDead())
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())
{
++mDeathCount[Misc::StringUtils::lowerCase(iter->first.getCellRef().getRefId())];
// Make sure spell effects with CasterLinked flag are removed
for (PtrControllerMap::iterator iter2(mActors.begin());iter2 != mActors.end();++iter2)
{
MWMechanics::ActiveSpells& spells = iter2->first.getClass().getCreatureStats(iter2->first).getActiveSpells();
spells.purge(stats.getActorId());
}
// Apply soultrap
if (iter->first.getTypeName() == typeid(ESM::Creature).name())
{
SoulTrap soulTrap (iter->first);
stats.getActiveSpells().visitEffectSources(soulTrap);
}
// Reset magic effects and recalculate derived effects
// One case where we need this is to make sure bound items are removed upon death
stats.setMagicEffects(MWMechanics::MagicEffects());
stats.getActiveSpells().clear();
calculateCreatureStatModifiers(iter->first, 0);
MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false);
if (cls.isEssential(iter->first))
MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}");
}
}
}
void Actors::restoreDynamicStats(bool sleep)
{
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)

@ -96,6 +96,9 @@ 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);

@ -8,6 +8,7 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/mechanicsmanager.hpp"
namespace MWMechanics
{
@ -191,6 +192,12 @@ namespace MWMechanics
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();
}
}

@ -653,6 +653,10 @@ 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)

@ -160,6 +160,10 @@ namespace MWMechanics
/// @param bias Can be used to add an additional aggression bias towards the target,
/// 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();
};
}

Loading…
Cancel
Save