mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-23 21:39:42 +00:00
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.
This commit is contained in:
parent
d43c21a9fc
commit
c0645d4978
6 changed files with 100 additions and 59 deletions
|
@ -196,6 +196,10 @@ namespace MWBase
|
||||||
/// @param bias Can be used to add an additional aggression bias towards the target,
|
/// @param bias Can be used to add an additional aggression bias towards the target,
|
||||||
/// making it more likely for the function to return true.
|
/// 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;
|
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);
|
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)
|
for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
|
||||||
{
|
{
|
||||||
const MWWorld::Class &cls = iter->first.getClass();
|
const MWWorld::Class &cls = iter->first.getClass();
|
||||||
|
@ -1048,68 +1044,23 @@ namespace MWMechanics
|
||||||
stats.setKnockedDownOneFrame(false);
|
stats.setKnockedDownOneFrame(false);
|
||||||
stats.setKnockedDownOverOneFrame(true);
|
stats.setKnockedDownOverOneFrame(true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
CreatureStats &stats = cls.getCreatureStats(iter->first);
|
||||||
|
|
||||||
if(!stats.isDead())
|
if(!stats.isDead())
|
||||||
{
|
{
|
||||||
if (stats.isHostile()) hostilesCount++;
|
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());
|
|
||||||
|
|
||||||
if (stat.getModified()<1)
|
|
||||||
{
|
|
||||||
stat.setModified(1, 0);
|
|
||||||
stats.setHealth(stat);
|
|
||||||
}
|
|
||||||
stats.resurrect();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iter->second->kill())
|
|
||||||
{
|
|
||||||
++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}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
killDeadActors();
|
||||||
|
|
||||||
// check if we still have any player enemies to switch music
|
// check if we still have any player enemies to switch music
|
||||||
static bool isBattleMusic = false;
|
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)
|
void Actors::restoreDynamicStats(bool sleep)
|
||||||
{
|
{
|
||||||
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
||||||
|
|
|
@ -96,6 +96,9 @@ namespace MWMechanics
|
||||||
int countDeaths (const std::string& id) const;
|
int countDeaths (const std::string& id) const;
|
||||||
///< Return the number of deaths for actors with the given ID.
|
///< Return the number of deaths for actors with the given ID.
|
||||||
|
|
||||||
|
///@see MechanicsManager::killDeadActors
|
||||||
|
void killDeadActors ();
|
||||||
|
|
||||||
void forceStateUpdate(const MWWorld::Ptr &ptr);
|
void forceStateUpdate(const MWWorld::Ptr &ptr);
|
||||||
|
|
||||||
void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number);
|
void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number);
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
|
@ -191,6 +192,12 @@ namespace MWMechanics
|
||||||
mDied = true;
|
mDied = true;
|
||||||
|
|
||||||
mDead = 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);
|
return mActors.countDeaths (id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MechanicsManager::killDeadActors()
|
||||||
|
{
|
||||||
|
mActors.killDeadActors();
|
||||||
|
}
|
||||||
|
|
||||||
void MechanicsManager::getPersuasionDispositionChange (const MWWorld::Ptr& npc, PersuasionType type,
|
void MechanicsManager::getPersuasionDispositionChange (const MWWorld::Ptr& npc, PersuasionType type,
|
||||||
float currentTemporaryDispositionDelta, bool& success, float& tempChange, float& permChange)
|
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,
|
/// @param bias Can be used to add an additional aggression bias towards the target,
|
||||||
/// making it more likely for the function to return true.
|
/// 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);
|
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…
Reference in a new issue