2010-07-26 10:52:32 +00:00
|
|
|
#ifndef GAME_MWMECHANICS_STAT_H
|
|
|
|
#define GAME_MWMECHANICS_STAT_H
|
|
|
|
|
2011-02-19 18:18:03 +00:00
|
|
|
#undef min
|
|
|
|
#undef max
|
|
|
|
|
2010-07-26 21:09:37 +00:00
|
|
|
#include <limits>
|
|
|
|
|
2014-02-16 14:06:34 +00:00
|
|
|
#include <components/esm/statstate.hpp>
|
|
|
|
|
2010-07-26 10:52:32 +00:00
|
|
|
namespace MWMechanics
|
|
|
|
{
|
|
|
|
template<typename T>
|
|
|
|
class Stat
|
|
|
|
{
|
|
|
|
T mBase;
|
|
|
|
T mModified;
|
2010-07-28 16:27:46 +00:00
|
|
|
|
2010-07-26 10:52:32 +00:00
|
|
|
public:
|
2010-09-20 11:10:15 +00:00
|
|
|
typedef T Type;
|
2010-07-28 16:27:46 +00:00
|
|
|
|
2010-07-26 10:52:32 +00:00
|
|
|
Stat() : mBase (0), mModified (0) {}
|
2010-09-20 11:10:15 +00:00
|
|
|
Stat(T base) : mBase (base), mModified (base) {}
|
|
|
|
Stat(T base, T modified) : mBase (base), mModified (modified) {}
|
2010-07-28 16:27:46 +00:00
|
|
|
|
2010-07-26 10:52:32 +00:00
|
|
|
const T& getBase() const
|
|
|
|
{
|
|
|
|
return mBase;
|
|
|
|
}
|
2010-07-28 16:27:46 +00:00
|
|
|
|
2013-03-06 20:26:41 +00:00
|
|
|
T getModified() const
|
2010-07-26 10:52:32 +00:00
|
|
|
{
|
2013-03-06 19:45:11 +00:00
|
|
|
return std::max(static_cast<T>(0), mModified);
|
2010-07-26 10:52:32 +00:00
|
|
|
}
|
2010-07-28 16:27:46 +00:00
|
|
|
|
2012-07-09 16:26:00 +00:00
|
|
|
T getModifier() const
|
|
|
|
{
|
|
|
|
return mModified-mBase;
|
|
|
|
}
|
|
|
|
|
2010-07-26 10:52:32 +00:00
|
|
|
/// Set base and modified to \a value.
|
|
|
|
void set (const T& value)
|
|
|
|
{
|
|
|
|
mBase = mModified = value;
|
|
|
|
}
|
2010-07-28 16:27:46 +00:00
|
|
|
|
2013-08-28 05:44:52 +00:00
|
|
|
void modify(const T& diff)
|
|
|
|
{
|
|
|
|
mBase += diff;
|
|
|
|
if(mBase >= static_cast<T>(0))
|
|
|
|
mModified += diff;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mModified += diff - mBase;
|
|
|
|
mBase = static_cast<T>(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-26 10:52:32 +00:00
|
|
|
/// Set base and adjust modified accordingly.
|
|
|
|
void setBase (const T& value)
|
|
|
|
{
|
|
|
|
T diff = value - mBase;
|
|
|
|
mBase = value;
|
|
|
|
mModified += diff;
|
|
|
|
}
|
2010-07-28 16:27:46 +00:00
|
|
|
|
2010-07-26 21:09:37 +00:00
|
|
|
/// Set modified value an adjust base accordingly.
|
|
|
|
void setModified (T value, const T& min, const T& max = std::numeric_limits<T>::max())
|
|
|
|
{
|
|
|
|
T diff = value - mModified;
|
2010-07-28 16:27:46 +00:00
|
|
|
|
2010-07-26 21:09:37 +00:00
|
|
|
if (mBase+diff<min)
|
|
|
|
{
|
|
|
|
value = min + (mModified - mBase);
|
|
|
|
diff = value - mModified;
|
|
|
|
}
|
2010-08-05 14:40:21 +00:00
|
|
|
else if (mBase+diff>max)
|
2010-07-26 21:09:37 +00:00
|
|
|
{
|
|
|
|
value = max + (mModified - mBase);
|
|
|
|
diff = value - mModified;
|
|
|
|
}
|
2010-07-28 16:27:46 +00:00
|
|
|
|
2010-07-26 21:09:37 +00:00
|
|
|
mModified = value;
|
|
|
|
mBase += diff;
|
|
|
|
}
|
2010-07-28 16:27:46 +00:00
|
|
|
|
2012-07-09 16:26:00 +00:00
|
|
|
void setModifier (const T& modifier)
|
2010-07-26 10:52:32 +00:00
|
|
|
{
|
2012-07-09 16:26:00 +00:00
|
|
|
mModified = mBase + modifier;
|
2010-07-26 10:52:32 +00:00
|
|
|
}
|
2014-02-16 14:56:36 +00:00
|
|
|
|
|
|
|
void writeState (ESM::StatState<T>& state) const
|
|
|
|
{
|
|
|
|
state.mBase = mBase;
|
|
|
|
state.mMod = mModified;
|
|
|
|
}
|
|
|
|
|
|
|
|
void readState (const ESM::StatState<T>& state)
|
|
|
|
{
|
|
|
|
mBase = state.mBase;
|
|
|
|
mModified = state.mMod;
|
|
|
|
}
|
2010-07-26 10:52:32 +00:00
|
|
|
};
|
2010-07-28 16:27:46 +00:00
|
|
|
|
2010-07-27 13:59:41 +00:00
|
|
|
template<typename T>
|
|
|
|
inline bool operator== (const Stat<T>& left, const Stat<T>& right)
|
|
|
|
{
|
|
|
|
return left.getBase()==right.getBase() &&
|
2010-07-28 16:27:46 +00:00
|
|
|
left.getModified()==right.getModified();
|
2010-07-27 13:59:41 +00:00
|
|
|
}
|
2010-07-28 16:27:46 +00:00
|
|
|
|
2010-07-27 13:59:41 +00:00
|
|
|
template<typename T>
|
|
|
|
inline bool operator!= (const Stat<T>& left, const Stat<T>& right)
|
|
|
|
{
|
|
|
|
return !(left==right);
|
|
|
|
}
|
2010-07-28 16:27:46 +00:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
class DynamicStat
|
|
|
|
{
|
|
|
|
Stat<T> mStatic;
|
|
|
|
T mCurrent;
|
|
|
|
|
|
|
|
public:
|
2010-09-20 11:10:15 +00:00
|
|
|
typedef T Type;
|
2010-07-28 16:27:46 +00:00
|
|
|
|
2013-07-20 12:52:17 +00:00
|
|
|
DynamicStat() : mStatic (0), mCurrent (0) {}
|
|
|
|
DynamicStat(T base) : mStatic (base), mCurrent (base) {}
|
2010-09-20 11:10:15 +00:00
|
|
|
DynamicStat(T base, T modified, T current) : mStatic(base, modified), mCurrent (current) {}
|
|
|
|
DynamicStat(const Stat<T> &stat, T current) : mStatic(stat), mCurrent (current) {}
|
2010-07-28 16:48:01 +00:00
|
|
|
|
2010-07-28 16:27:46 +00:00
|
|
|
const T& getBase() const
|
|
|
|
{
|
|
|
|
return mStatic.getBase();
|
|
|
|
}
|
|
|
|
|
2013-03-06 20:26:41 +00:00
|
|
|
T getModified() const
|
2010-07-28 16:27:46 +00:00
|
|
|
{
|
|
|
|
return mStatic.getModified();
|
|
|
|
}
|
|
|
|
|
|
|
|
const T& getCurrent() const
|
|
|
|
{
|
|
|
|
return mCurrent;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set base, modified and current to \a value.
|
|
|
|
void set (const T& value)
|
|
|
|
{
|
|
|
|
mStatic.set (value);
|
|
|
|
mCurrent = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set base and adjust modified accordingly.
|
|
|
|
void setBase (const T& value)
|
|
|
|
{
|
|
|
|
mStatic.setBase (value);
|
|
|
|
|
|
|
|
if (mCurrent>getModified())
|
|
|
|
mCurrent = getModified();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set modified value an adjust base accordingly.
|
|
|
|
void setModified (T value, const T& min, const T& max = std::numeric_limits<T>::max())
|
|
|
|
{
|
|
|
|
mStatic.setModified (value, min, max);
|
|
|
|
|
|
|
|
if (mCurrent>getModified())
|
|
|
|
mCurrent = getModified();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Change modified relatively.
|
|
|
|
void modify (const T& diff)
|
|
|
|
{
|
|
|
|
mStatic.modify (diff);
|
2012-07-17 13:49:37 +00:00
|
|
|
setCurrent (getCurrent()+diff);
|
2010-07-28 16:27:46 +00:00
|
|
|
}
|
|
|
|
|
2013-12-09 20:13:06 +00:00
|
|
|
void setCurrent (const T& value, bool allowDecreaseBelowZero = false)
|
2010-07-28 16:27:46 +00:00
|
|
|
{
|
2013-12-09 20:13:06 +00:00
|
|
|
if (value > mCurrent)
|
|
|
|
{
|
|
|
|
// increase
|
|
|
|
mCurrent = value;
|
2010-07-28 16:27:46 +00:00
|
|
|
|
2013-12-09 20:13:06 +00:00
|
|
|
if (mCurrent > getModified())
|
|
|
|
mCurrent = getModified();
|
|
|
|
}
|
|
|
|
else if (value > 0 || allowDecreaseBelowZero)
|
|
|
|
{
|
|
|
|
// allowed decrease
|
|
|
|
mCurrent = value;
|
|
|
|
}
|
|
|
|
else if (mCurrent > 0)
|
|
|
|
{
|
|
|
|
// capped decrease
|
2010-07-28 16:27:46 +00:00
|
|
|
mCurrent = 0;
|
2013-12-09 20:13:06 +00:00
|
|
|
}
|
2010-07-28 16:27:46 +00:00
|
|
|
}
|
2012-07-17 13:49:37 +00:00
|
|
|
|
|
|
|
void setModifier (const T& modifier)
|
|
|
|
{
|
|
|
|
T diff = modifier - mStatic.getModifier();
|
|
|
|
mStatic.setModifier (modifier);
|
|
|
|
setCurrent (getCurrent()+diff);
|
|
|
|
}
|
2014-02-16 14:56:36 +00:00
|
|
|
|
|
|
|
void writeState (ESM::StatState<T>& state) const
|
|
|
|
{
|
|
|
|
mStatic.writeState (state);
|
|
|
|
state.mCurrent = mCurrent;
|
|
|
|
}
|
|
|
|
|
|
|
|
void readState (const ESM::StatState<T>& state)
|
|
|
|
{
|
|
|
|
mStatic.readState (state);
|
|
|
|
mCurrent = state.mCurrent;
|
|
|
|
}
|
2010-07-28 16:27:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline bool operator== (const DynamicStat<T>& left, const DynamicStat<T>& right)
|
|
|
|
{
|
|
|
|
return left.getBase()==right.getBase() &&
|
|
|
|
left.getModified()==right.getModified() &&
|
|
|
|
left.getCurrent()==right.getCurrent();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline bool operator!= (const DynamicStat<T>& left, const DynamicStat<T>& right)
|
|
|
|
{
|
|
|
|
return !(left==right);
|
|
|
|
}
|
2014-01-03 00:59:15 +00:00
|
|
|
|
2014-01-03 02:46:30 +00:00
|
|
|
class AttributeValue
|
|
|
|
{
|
|
|
|
int mBase;
|
2015-02-28 21:27:51 +00:00
|
|
|
int mFortified;
|
|
|
|
int mModifier; // net effect of Fortified, Drain & Absorb
|
2014-11-02 17:01:12 +00:00
|
|
|
float mDamage; // needs to be float to allow continuous damage
|
2014-01-03 02:46:30 +00:00
|
|
|
|
|
|
|
public:
|
2015-02-28 21:27:51 +00:00
|
|
|
AttributeValue() : mBase(0), mFortified(0), mModifier(0), mDamage(0) {}
|
2014-01-03 02:46:30 +00:00
|
|
|
|
2014-11-02 17:01:12 +00:00
|
|
|
int getModified() const { return std::max(0, mBase - (int) mDamage + mModifier); }
|
2014-01-03 02:46:30 +00:00
|
|
|
int getBase() const { return mBase; }
|
|
|
|
int getModifier() const { return mModifier; }
|
|
|
|
|
|
|
|
void setBase(int base) { mBase = std::max(0, base); }
|
2015-03-08 04:42:07 +00:00
|
|
|
void setModifiers(float fortify, float drain, float absorb);
|
2014-01-03 02:46:30 +00:00
|
|
|
|
2015-02-28 21:27:51 +00:00
|
|
|
void damage(float damage) { mDamage = std::min(mDamage + damage, (float)(mBase + mFortified)); }
|
2014-11-02 17:01:12 +00:00
|
|
|
void restore(float amount) { mDamage -= std::min(mDamage, amount); }
|
2014-02-16 14:06:34 +00:00
|
|
|
|
|
|
|
void writeState (ESM::StatState<int>& state) const;
|
|
|
|
|
|
|
|
void readState (const ESM::StatState<int>& state);
|
2015-02-28 21:27:51 +00:00
|
|
|
|
|
|
|
friend bool operator== (const AttributeValue& left, const AttributeValue& right);
|
2014-01-03 02:46:30 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class SkillValue : public AttributeValue
|
|
|
|
{
|
|
|
|
float mProgress;
|
|
|
|
public:
|
2014-01-06 23:37:52 +00:00
|
|
|
SkillValue() : mProgress(0) {}
|
2014-01-03 02:46:30 +00:00
|
|
|
float getProgress() const { return mProgress; }
|
|
|
|
void setProgress(float progress) { mProgress = progress; }
|
2014-02-16 14:06:34 +00:00
|
|
|
|
|
|
|
void writeState (ESM::StatState<int>& state) const;
|
|
|
|
|
|
|
|
void readState (const ESM::StatState<int>& state);
|
2015-02-28 21:27:51 +00:00
|
|
|
|
|
|
|
friend bool operator== (const SkillValue& left, const SkillValue& right);
|
2014-01-03 02:46:30 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
inline bool operator== (const AttributeValue& left, const AttributeValue& right)
|
|
|
|
{
|
|
|
|
return left.getBase() == right.getBase()
|
2015-02-28 21:27:51 +00:00
|
|
|
&& left.mFortified == right.mFortified
|
2014-01-03 02:46:30 +00:00
|
|
|
&& left.getModifier() == right.getModifier()
|
2015-02-28 21:27:51 +00:00
|
|
|
&& left.mDamage == right.mDamage;
|
2014-01-03 02:46:30 +00:00
|
|
|
}
|
|
|
|
inline bool operator!= (const AttributeValue& left, const AttributeValue& right)
|
|
|
|
{
|
|
|
|
return !(left == right);
|
|
|
|
}
|
2014-01-13 06:05:52 +00:00
|
|
|
|
|
|
|
inline bool operator== (const SkillValue& left, const SkillValue& right)
|
|
|
|
{
|
2015-02-28 21:27:51 +00:00
|
|
|
// delegate to base class for most of the work
|
|
|
|
return (static_cast<const AttributeValue&>(left) == right)
|
2014-01-13 06:05:52 +00:00
|
|
|
&& left.getProgress() == right.getProgress();
|
|
|
|
}
|
|
|
|
inline bool operator!= (const SkillValue& left, const SkillValue& right)
|
|
|
|
{
|
|
|
|
return !(left == right);
|
|
|
|
}
|
2010-07-26 10:52:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|