1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-30 21:32:42 +00:00
OpenMW/apps/openmw/mwmechanics/creaturestats.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

719 lines
19 KiB
C++
Raw Normal View History

2012-07-22 18:29:54 +04:00
#include "creaturestats.hpp"
#include <algorithm>
#include <type_traits>
#include <components/esm3/creaturestats.hpp>
#include <components/esm3/esmreader.hpp>
#include <components/esm3/esmwriter.hpp>
#include <components/esm3/loadmgef.hpp>
#include "../mwworld/class.hpp"
2012-10-01 19:17:04 +04:00
#include "../mwworld/esmstore.hpp"
#include "../mwworld/player.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
2012-07-22 18:29:54 +04:00
namespace MWMechanics
{
2014-04-29 15:27:49 +02:00
int CreatureStats::sActorId = 0;
2012-09-15 17:12:42 +02:00
CreatureStats::CreatureStats()
: mDrawState(DrawState::Nothing)
, mDead(false)
, mDeathAnimationFinished(false)
, mDied(false)
, mMurdered(false)
, mFriendlyHits(0)
, mTalkedTo(false)
, mAlarmed(false)
, mAttacked(false)
, mKnockdown(false)
, mKnockdownOneFrame(false)
, mKnockdownOverOneFrame(false)
, mHitRecovery(false)
, mBlock(false)
, mMovementFlags(0)
, mFallHeight(0)
, mLastRestock(0, 0)
, mGoldPool(0)
, mActorId(-1)
, mHitAttemptActorId(-1)
2020-06-22 02:03:38 +02:00
, mDeathAnimation(-1)
, mTimeOfDeath()
, mSideMovementAngle(0)
, mLevel(0)
, mAttackingOrSpell(false)
2012-09-15 17:12:42 +02:00
{
}
const AiSequence& CreatureStats::getAiSequence() const
{
return mAiSequence;
}
AiSequence& CreatureStats::getAiSequence()
{
return mAiSequence;
}
float CreatureStats::getFatigueTerm() const
{
float max = getFatigue().getModified();
float current = getFatigue().getCurrent();
float normalised = std::floor(max) == 0 ? 1 : std::max(0.0f, current / max);
const MWWorld::Store<ESM::GameSetting>& gmst
= MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
2018-08-29 18:38:12 +03:00
static const float fFatigueBase = gmst.find("fFatigueBase")->mValue.getFloat();
static const float fFatigueMult = gmst.find("fFatigueMult")->mValue.getFloat();
return fFatigueBase - fFatigueMult * (1 - normalised);
}
const AttributeValue& CreatureStats::getAttribute(int index) const
2012-09-13 10:52:34 +02:00
{
if (index < 0 || index > 7)
{
throw std::runtime_error("attribute index is out of range");
}
return mAttributes[index];
2012-09-13 10:52:34 +02:00
}
2012-09-15 17:12:42 +02:00
const DynamicStat<float>& CreatureStats::getHealth() const
2012-09-13 10:52:34 +02:00
{
return mDynamic[0];
}
2012-09-15 17:12:42 +02:00
const DynamicStat<float>& CreatureStats::getMagicka() const
2012-09-13 10:52:34 +02:00
{
return mDynamic[1];
}
2012-09-15 17:12:42 +02:00
const DynamicStat<float>& CreatureStats::getFatigue() const
2012-09-13 10:52:34 +02:00
{
return mDynamic[2];
}
const Spells& CreatureStats::getSpells() const
{
return mSpells;
}
const ActiveSpells& CreatureStats::getActiveSpells() const
{
return mActiveSpells;
}
const MagicEffects& CreatureStats::getMagicEffects() const
{
return mMagicEffects;
}
int CreatureStats::getLevel() const
{
return mLevel;
}
Stat<int> CreatureStats::getAiSetting(AiSetting index) const
2012-09-13 10:52:34 +02:00
{
return mAiSettings[static_cast<std::underlying_type_t<AiSetting>>(index)];
2012-09-13 10:52:34 +02:00
}
const DynamicStat<float>& CreatureStats::getDynamic(int index) const
2012-09-13 10:52:34 +02:00
{
if (index < 0 || index > 2)
{
throw std::runtime_error("dynamic stat index is out of range");
}
return mDynamic[index];
}
Spells& CreatureStats::getSpells()
{
return mSpells;
}
ActiveSpells& CreatureStats::getActiveSpells()
{
return mActiveSpells;
}
MagicEffects& CreatureStats::getMagicEffects()
{
return mMagicEffects;
}
void CreatureStats::setAttribute(int index, float base)
{
AttributeValue current = getAttribute(index);
current.setBase(base);
setAttribute(index, current);
}
void CreatureStats::setAttribute(int index, const AttributeValue& value)
2012-09-13 10:52:34 +02:00
{
if (index < 0 || index > 7)
{
throw std::runtime_error("attribute index is out of range");
}
const AttributeValue& currentValue = mAttributes[index];
if (value != currentValue)
{
mAttributes[index] = value;
if (index == ESM::Attribute::Intelligence)
recalculateMagicka();
else if (index == ESM::Attribute::Strength || index == ESM::Attribute::Willpower
|| index == ESM::Attribute::Agility || index == ESM::Attribute::Endurance)
{
float strength = getAttribute(ESM::Attribute::Strength).getModified();
float willpower = getAttribute(ESM::Attribute::Willpower).getModified();
float agility = getAttribute(ESM::Attribute::Agility).getModified();
float endurance = getAttribute(ESM::Attribute::Endurance).getModified();
DynamicStat<float> fatigue = getFatigue();
float currentToBaseRatio = fatigue.getBase() > 0 ? (fatigue.getCurrent() / fatigue.getBase()) : 0;
fatigue.setBase(std::max(0.f, strength + willpower + agility + endurance));
fatigue.setCurrent(fatigue.getBase() * currentToBaseRatio, false, true);
setFatigue(fatigue);
}
}
2012-09-13 10:52:34 +02:00
}
2012-09-15 17:12:42 +02:00
void CreatureStats::setHealth(const DynamicStat<float>& value)
2012-09-13 10:52:34 +02:00
{
setDynamic(0, value);
2012-09-13 10:52:34 +02:00
}
2012-09-15 17:12:42 +02:00
void CreatureStats::setMagicka(const DynamicStat<float>& value)
2012-09-13 10:52:34 +02:00
{
setDynamic(1, value);
2012-09-13 10:52:34 +02:00
}
2012-09-15 17:12:42 +02:00
void CreatureStats::setFatigue(const DynamicStat<float>& value)
2012-09-13 10:52:34 +02:00
{
setDynamic(2, value);
2012-09-13 10:52:34 +02:00
}
void CreatureStats::setDynamic(int index, const DynamicStat<float>& value)
{
if (index < 0 || index > 2)
throw std::runtime_error("dynamic stat index is out of range");
mDynamic[index] = value;
2012-10-25 12:22:48 +02:00
if (index == 0 && mDynamic[index].getCurrent() < 1)
2013-03-18 10:46:45 +01:00
{
if (!mDead)
mTimeOfDeath = MWBase::Environment::get().getWorld()->getTimeStamp();
mDead = true;
mDynamic[index].setCurrent(0);
2013-03-18 10:46:45 +01:00
}
}
2012-09-13 10:52:34 +02:00
void CreatureStats::setLevel(int level)
{
mLevel = level;
}
void CreatureStats::modifyMagicEffects(const MagicEffects& effects)
2012-09-13 10:52:34 +02:00
{
bool recalc = effects.get(ESM::MagicEffect::FortifyMaximumMagicka).getModifier()
!= mMagicEffects.get(ESM::MagicEffect::FortifyMaximumMagicka).getModifier();
mMagicEffects.setModifiers(effects);
if (recalc)
recalculateMagicka();
2012-09-13 10:52:34 +02:00
}
void CreatureStats::setAiSetting(AiSetting index, Stat<int> value)
2012-09-13 10:52:34 +02:00
{
mAiSettings[static_cast<std::underlying_type_t<AiSetting>>(index)] = value;
2012-09-13 10:52:34 +02:00
}
void CreatureStats::setAiSetting(AiSetting index, int base)
{
Stat<int> stat = getAiSetting(index);
stat.setBase(base);
setAiSetting(index, stat);
}
bool CreatureStats::isParalyzed() const
{
return mMagicEffects.get(ESM::MagicEffect::Paralyze).getMagnitude() > 0;
}
bool CreatureStats::isDead() const
{
return mDead;
}
bool CreatureStats::isDeathAnimationFinished() const
{
return mDeathAnimationFinished;
}
void CreatureStats::setDeathAnimationFinished(bool finished)
{
mDeathAnimationFinished = finished;
}
void CreatureStats::notifyDied()
{
mDied = true;
}
2013-03-18 10:46:45 +01:00
bool CreatureStats::hasDied() const
{
return mDied;
}
void CreatureStats::clearHasDied()
{
mDied = false;
}
bool CreatureStats::hasBeenMurdered() const
{
return mMurdered;
}
void CreatureStats::notifyMurder()
{
mMurdered = true;
}
void CreatureStats::clearHasBeenMurdered()
{
mMurdered = false;
}
void CreatureStats::resurrect()
{
if (mDead)
{
mDynamic[0].setCurrent(mDynamic[0].getBase());
mDead = false;
mDeathAnimationFinished = false;
}
}
2012-11-09 18:16:29 +01:00
bool CreatureStats::hasCommonDisease() const
{
return mSpells.hasCommonDisease();
}
bool CreatureStats::hasBlightDisease() const
{
return mSpells.hasBlightDisease();
}
int CreatureStats::getFriendlyHits() const
{
return mFriendlyHits;
}
void CreatureStats::friendlyHit()
{
++mFriendlyHits;
}
bool CreatureStats::hasTalkedToPlayer() const
{
return mTalkedTo;
}
void CreatureStats::talkedToPlayer()
{
mTalkedTo = true;
}
bool CreatureStats::isAlarmed() const
{
return mAlarmed;
}
void CreatureStats::setAlarmed(bool alarmed)
{
mAlarmed = alarmed;
}
bool CreatureStats::getAttacked() const
{
return mAttacked;
}
void CreatureStats::setAttacked(bool attacked)
{
mAttacked = attacked;
}
2013-07-31 12:25:14 -07:00
float CreatureStats::getEvasion() const
{
float evasion = (getAttribute(ESM::Attribute::Agility).getModified() / 5.0f)
+ (getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
evasion *= getFatigueTerm();
evasion += std::min(100.f, mMagicEffects.get(ESM::MagicEffect::Sanctuary).getMagnitude());
2013-07-31 12:25:14 -07:00
return evasion;
}
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID Slowly going through all the changes to make, still hundreds of errors a lot of functions/structures use std::string or stringview to designate an ID. So it takes time Continues slowly replacing ids. There are technically more and more compilation errors I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type Continue moving forward, changes to the stores slowly moving along Starting to see the fruit of those changes. still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type. More replacements. Things are starting to get easier I can see more and more often the issue is that the function is awaiting a RefId, but is given a string there is less need to go down functions and to fix a long list of them. Still moving forward, and for the first time error count is going down! Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably Cells are back to using string for the name, haven't fixed everything yet. Many other changes Under the bar of 400 compilation errors. more good progress <100 compile errors! More progress Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string some more progress on other fronts Mostly game settings clean one error opened a lot of other errors. Down to 18, but more will prbably appear only link errors left?? Fixed link errors OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
void CreatureStats::setLastHitObject(const ESM::RefId& objectid)
2013-07-26 08:08:52 -07:00
{
mLastHitObject = objectid;
}
void CreatureStats::clearLastHitObject()
{
mLastHitObject = ESM::RefId::sEmpty;
}
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID Slowly going through all the changes to make, still hundreds of errors a lot of functions/structures use std::string or stringview to designate an ID. So it takes time Continues slowly replacing ids. There are technically more and more compilation errors I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type Continue moving forward, changes to the stores slowly moving along Starting to see the fruit of those changes. still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type. More replacements. Things are starting to get easier I can see more and more often the issue is that the function is awaiting a RefId, but is given a string there is less need to go down functions and to fix a long list of them. Still moving forward, and for the first time error count is going down! Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably Cells are back to using string for the name, haven't fixed everything yet. Many other changes Under the bar of 400 compilation errors. more good progress <100 compile errors! More progress Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string some more progress on other fronts Mostly game settings clean one error opened a lot of other errors. Down to 18, but more will prbably appear only link errors left?? Fixed link errors OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
const ESM::RefId& CreatureStats::getLastHitObject() const
2013-07-26 08:08:52 -07:00
{
return mLastHitObject;
}
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID Slowly going through all the changes to make, still hundreds of errors a lot of functions/structures use std::string or stringview to designate an ID. So it takes time Continues slowly replacing ids. There are technically more and more compilation errors I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type Continue moving forward, changes to the stores slowly moving along Starting to see the fruit of those changes. still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type. More replacements. Things are starting to get easier I can see more and more often the issue is that the function is awaiting a RefId, but is given a string there is less need to go down functions and to fix a long list of them. Still moving forward, and for the first time error count is going down! Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably Cells are back to using string for the name, haven't fixed everything yet. Many other changes Under the bar of 400 compilation errors. more good progress <100 compile errors! More progress Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string some more progress on other fronts Mostly game settings clean one error opened a lot of other errors. Down to 18, but more will prbably appear only link errors left?? Fixed link errors OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
void CreatureStats::setLastHitAttemptObject(const ESM::RefId& objectid)
{
mLastHitAttemptObject = objectid;
}
void CreatureStats::clearLastHitAttemptObject()
{
mLastHitAttemptObject = ESM::RefId::sEmpty;
}
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID Slowly going through all the changes to make, still hundreds of errors a lot of functions/structures use std::string or stringview to designate an ID. So it takes time Continues slowly replacing ids. There are technically more and more compilation errors I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type Continue moving forward, changes to the stores slowly moving along Starting to see the fruit of those changes. still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type. More replacements. Things are starting to get easier I can see more and more often the issue is that the function is awaiting a RefId, but is given a string there is less need to go down functions and to fix a long list of them. Still moving forward, and for the first time error count is going down! Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably Cells are back to using string for the name, haven't fixed everything yet. Many other changes Under the bar of 400 compilation errors. more good progress <100 compile errors! More progress Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string some more progress on other fronts Mostly game settings clean one error opened a lot of other errors. Down to 18, but more will prbably appear only link errors left?? Fixed link errors OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
const ESM::RefId& CreatureStats::getLastHitAttemptObject() const
{
return mLastHitAttemptObject;
}
2017-02-06 21:32:36 +09:00
void CreatureStats::setHitAttemptActorId(int actorId)
{
2017-02-06 21:32:36 +09:00
mHitAttemptActorId = actorId;
}
2017-02-06 21:32:36 +09:00
int CreatureStats::getHitAttemptActorId() const
{
2017-02-06 21:32:36 +09:00
return mHitAttemptActorId;
}
void CreatureStats::addToFallHeight(float height)
{
mFallHeight += height;
}
float CreatureStats::getFallHeight() const
{
return mFallHeight;
}
float CreatureStats::land(bool isPlayer)
{
if (isPlayer)
MWBase::Environment::get().getWorld()->getPlayer().setJumping(false);
float height = mFallHeight;
mFallHeight = 0;
return height;
}
void CreatureStats::recalculateMagicka()
{
auto world = MWBase::Environment::get().getWorld();
float intelligence = getAttribute(ESM::Attribute::Intelligence).getModified();
float base = 1.f;
const auto& player = world->getPlayerPtr();
if (this == &player.getClass().getCreatureStats(player))
base = world->getStore().get<ESM::GameSetting>().find("fPCbaseMagickaMult")->mValue.getFloat();
else
base = world->getStore().get<ESM::GameSetting>().find("fNPCbaseMagickaMult")->mValue.getFloat();
double magickaFactor
= base + mMagicEffects.get(EffectKey(ESM::MagicEffect::FortifyMaximumMagicka)).getMagnitude() * 0.1;
DynamicStat<float> magicka = getMagicka();
float currentToBaseRatio = magicka.getBase() > 0 ? magicka.getCurrent() / magicka.getBase() : 0;
magicka.setBase(magickaFactor * intelligence);
magicka.setCurrent(magicka.getBase() * currentToBaseRatio, false, true);
setMagicka(magicka);
}
void CreatureStats::setKnockedDown(bool value)
{
mKnockdown = value;
2014-04-27 20:54:22 -04:00
if (!value) // Resets the "OverOneFrame" flag
setKnockedDownOverOneFrame(false);
}
bool CreatureStats::getKnockedDown() const
{
return mKnockdown;
}
2014-04-27 20:54:22 -04:00
void CreatureStats::setKnockedDownOneFrame(bool value)
{
mKnockdownOneFrame = value;
}
bool CreatureStats::getKnockedDownOneFrame() const
{
return mKnockdownOneFrame;
}
void CreatureStats::setKnockedDownOverOneFrame(bool value)
{
mKnockdownOverOneFrame = value;
}
bool CreatureStats::getKnockedDownOverOneFrame() const
{
return mKnockdownOverOneFrame;
}
void CreatureStats::setHitRecovery(bool value)
{
mHitRecovery = value;
}
bool CreatureStats::getHitRecovery() const
{
return mHitRecovery;
}
void CreatureStats::setBlock(bool value)
{
mBlock = value;
}
bool CreatureStats::getBlock() const
{
return mBlock;
}
bool CreatureStats::getMovementFlag(Flag flag) const
{
return (mMovementFlags & flag) != 0;
}
void CreatureStats::setMovementFlag(Flag flag, bool state)
{
if (state)
mMovementFlags |= flag;
else
mMovementFlags &= ~flag;
}
bool CreatureStats::getStance(Stance flag) const
{
switch (flag)
{
case Stance_Run:
return getMovementFlag(Flag_Run) || getMovementFlag(Flag_ForceRun);
case Stance_Sneak:
return getMovementFlag(Flag_Sneak) || getMovementFlag(Flag_ForceSneak);
2014-04-04 08:10:35 -04:00
default:
return false;
}
}
DrawState CreatureStats::getDrawState() const
{
return mDrawState;
}
void CreatureStats::setDrawState(DrawState state)
{
mDrawState = state;
}
void CreatureStats::writeState(ESM::CreatureStats& state) const
{
2014-05-12 21:04:02 +02:00
for (int i = 0; i < ESM::Attribute::Length; ++i)
mAttributes[i].writeState(state.mAttributes[i]);
for (int i = 0; i < 3; ++i)
mDynamic[i].writeState(state.mDynamic[i]);
2014-05-12 21:04:02 +02:00
state.mTradeTime = mLastRestock.toEsm();
2014-05-12 21:04:02 +02:00
state.mGoldPool = mGoldPool;
state.mDead = mDead;
state.mDeathAnimationFinished = mDeathAnimationFinished;
2014-05-12 21:04:02 +02:00
state.mDied = mDied;
state.mMurdered = mMurdered;
// The vanilla engine does not store friendly hits in the save file. Since there's no other mechanism
// that ever resets the friendly hits (at least not to my knowledge) this should be regarded a feature
// rather than a bug.
// state.mFriendlyHits = mFriendlyHits;
2014-05-12 21:04:02 +02:00
state.mTalkedTo = mTalkedTo;
state.mAlarmed = mAlarmed;
state.mAttacked = mAttacked;
// TODO: rewrite. does this really need 3 separate bools?
state.mKnockdown = mKnockdown;
state.mKnockdownOneFrame = mKnockdownOneFrame;
state.mKnockdownOverOneFrame = mKnockdownOverOneFrame;
state.mHitRecovery = mHitRecovery;
state.mBlock = mBlock;
state.mMovementFlags = mMovementFlags;
2014-05-14 22:16:39 +02:00
state.mFallHeight = mFallHeight; // TODO: vertical velocity (move from PhysicActor to CreatureStats?)
2014-05-12 21:04:02 +02:00
state.mLastHitObject = mLastHitObject;
state.mLastHitAttemptObject = mLastHitAttemptObject;
2021-10-31 11:57:33 +01:00
state.mRecalcDynamicStats = false;
state.mDrawState = static_cast<int>(mDrawState);
2014-05-12 21:04:02 +02:00
state.mLevel = mLevel;
2014-05-14 09:47:49 +02:00
state.mActorId = mActorId;
state.mDeathAnimation = mDeathAnimation;
state.mTimeOfDeath = mTimeOfDeath.toEsm();
// state.mHitAttemptActorId = mHitAttemptActorId;
2014-05-12 21:04:02 +02:00
mSpells.writeState(state.mSpells);
2014-05-14 22:16:39 +02:00
mActiveSpells.writeState(state.mActiveSpells);
2014-06-12 23:27:04 +02:00
mAiSequence.writeState(state.mAiSequence);
mMagicEffects.writeState(state.mMagicEffects);
state.mSummonedCreatures = mSummonedCreatures;
state.mSummonGraveyard = mSummonGraveyard;
state.mHasAiSettings = true;
for (int i = 0; i < 4; ++i)
mAiSettings[i].writeState(state.mAiSettings[i]);
state.mMissingACDT = false;
}
void CreatureStats::readState(const ESM::CreatureStats& state)
{
if (!state.mMissingACDT)
{
for (int i = 0; i < ESM::Attribute::Length; ++i)
mAttributes[i].readState(state.mAttributes[i]);
for (int i = 0; i < 3; ++i)
mDynamic[i].readState(state.mDynamic[i]);
mGoldPool = state.mGoldPool;
mTalkedTo = state.mTalkedTo;
mAttacked = state.mAttacked;
}
2014-05-12 21:04:02 +02:00
mLastRestock = MWWorld::TimeStamp(state.mTradeTime);
2014-05-12 21:04:02 +02:00
mDead = state.mDead;
mDeathAnimationFinished = state.mDeathAnimationFinished;
2014-05-12 21:04:02 +02:00
mDied = state.mDied;
mMurdered = state.mMurdered;
2014-05-12 21:04:02 +02:00
mAlarmed = state.mAlarmed;
// TODO: rewrite. does this really need 3 separate bools?
mKnockdown = state.mKnockdown;
mKnockdownOneFrame = state.mKnockdownOneFrame;
mKnockdownOverOneFrame = state.mKnockdownOverOneFrame;
mHitRecovery = state.mHitRecovery;
mBlock = state.mBlock;
mMovementFlags = state.mMovementFlags;
mFallHeight = state.mFallHeight;
mLastHitObject = state.mLastHitObject;
mLastHitAttemptObject = state.mLastHitAttemptObject;
mDrawState = DrawState(state.mDrawState);
2014-05-12 21:04:02 +02:00
mLevel = state.mLevel;
2014-05-14 09:47:49 +02:00
mActorId = state.mActorId;
mDeathAnimation = state.mDeathAnimation;
mTimeOfDeath = MWWorld::TimeStamp(state.mTimeOfDeath);
// mHitAttemptActorId = state.mHitAttemptActorId;
2014-05-12 21:04:02 +02:00
mSpells.readState(state.mSpells, this);
2014-05-14 22:16:39 +02:00
mActiveSpells.readState(state.mActiveSpells);
2014-06-12 23:27:04 +02:00
mAiSequence.readState(state.mAiSequence);
mMagicEffects.readState(state.mMagicEffects);
mSummonedCreatures = state.mSummonedCreatures;
mSummonGraveyard = state.mSummonGraveyard;
if (state.mHasAiSettings)
for (int i = 0; i < 4; ++i)
mAiSettings[i].readState(state.mAiSettings[i]);
if (state.mRecalcDynamicStats)
recalculateMagicka();
}
void CreatureStats::setLastRestockTime(MWWorld::TimeStamp tradeTime)
{
mLastRestock = tradeTime;
}
MWWorld::TimeStamp CreatureStats::getLastRestockTime() const
{
return mLastRestock;
}
2014-04-27 20:54:22 -04:00
void CreatureStats::setGoldPool(int pool)
{
mGoldPool = pool;
}
2014-04-27 20:54:22 -04:00
int CreatureStats::getGoldPool() const
{
return mGoldPool;
}
2014-04-29 15:27:49 +02:00
int CreatureStats::getActorId()
{
if (mActorId == -1)
mActorId = sActorId++;
return mActorId;
}
bool CreatureStats::matchesActorId(int id) const
{
return mActorId != -1 && id == mActorId;
}
2014-04-29 19:56:33 +02:00
void CreatureStats::cleanup()
{
sActorId = 0;
}
2014-05-14 09:47:49 +02:00
void CreatureStats::writeActorIdCounter(ESM::ESMWriter& esm)
{
esm.startRecord(ESM::REC_ACTC);
esm.writeHNT("COUN", sActorId);
esm.endRecord(ESM::REC_ACTC);
}
void CreatureStats::readActorIdCounter(ESM::ESMReader& esm)
{
esm.getHNT(sActorId, "COUN");
}
signed char CreatureStats::getDeathAnimation() const
{
return mDeathAnimation;
}
void CreatureStats::setDeathAnimation(signed char index)
{
mDeathAnimation = index;
}
MWWorld::TimeStamp CreatureStats::getTimeOfDeath() const
{
return mTimeOfDeath;
}
std::multimap<int, int>& CreatureStats::getSummonedCreatureMap()
{
return mSummonedCreatures;
}
std::vector<int>& CreatureStats::getSummonedCreatureGraveyard()
{
return mSummonGraveyard;
}
2012-07-22 18:29:54 +04:00
}