2010-07-26 12:52:32 +02:00
|
|
|
#ifndef GAME_MWMECHANICS_STAT_H
|
|
|
|
#define GAME_MWMECHANICS_STAT_H
|
|
|
|
|
2015-07-07 19:16:32 +02:00
|
|
|
#include <algorithm>
|
2010-07-26 23:09:37 +02:00
|
|
|
#include <limits>
|
|
|
|
|
2015-07-09 14:41:37 +02:00
|
|
|
namespace ESM
|
|
|
|
{
|
|
|
|
template <typename T>
|
|
|
|
struct StatState;
|
|
|
|
}
|
2014-02-16 15:06:34 +01:00
|
|
|
|
2010-07-26 12:52:32 +02:00
|
|
|
namespace MWMechanics
|
|
|
|
{
|
|
|
|
template <typename T>
|
|
|
|
class Stat
|
|
|
|
{
|
|
|
|
T mBase;
|
2022-02-10 20:32:59 +01:00
|
|
|
T mModifier;
|
2010-07-28 18:27:46 +02:00
|
|
|
|
2010-07-26 12:52:32 +02:00
|
|
|
public:
|
2010-09-20 13:10:15 +02:00
|
|
|
typedef T Type;
|
2010-07-28 18:27:46 +02:00
|
|
|
|
2015-07-09 14:41:37 +02:00
|
|
|
Stat();
|
|
|
|
Stat(T base, T modified);
|
2010-07-28 18:27:46 +02:00
|
|
|
|
2022-10-05 23:45:17 +02:00
|
|
|
const T& getBase() const { return mBase; }
|
2010-07-28 18:27:46 +02:00
|
|
|
|
2021-02-04 21:25:38 +01:00
|
|
|
T getModified(bool capped = true) const;
|
2022-10-05 23:45:17 +02:00
|
|
|
T getModifier() const { return mModifier; }
|
2012-07-09 18:26:00 +02:00
|
|
|
|
2022-10-05 23:45:17 +02:00
|
|
|
void setBase(const T& value) { mBase = value; }
|
2013-08-27 22:44:52 -07:00
|
|
|
|
2022-10-05 23:45:17 +02:00
|
|
|
void setModifier(const T& modifier) { mModifier = modifier; }
|
2015-07-09 14:41:37 +02:00
|
|
|
|
|
|
|
void writeState(ESM::StatState<T>& state) const;
|
|
|
|
void readState(const ESM::StatState<T>& state);
|
2010-07-26 12:52:32 +02:00
|
|
|
};
|
2010-07-28 18:27:46 +02:00
|
|
|
|
2010-07-27 15:59:41 +02:00
|
|
|
template <typename T>
|
|
|
|
inline bool operator==(const Stat<T>& left, const Stat<T>& right)
|
|
|
|
{
|
|
|
|
return left.getBase() == right.getBase() && left.getModifier() == right.getModifier();
|
|
|
|
}
|
2010-07-28 18:27:46 +02:00
|
|
|
|
2010-07-27 15:59:41 +02:00
|
|
|
template <typename T>
|
|
|
|
inline bool operator!=(const Stat<T>& left, const Stat<T>& right)
|
|
|
|
{
|
|
|
|
return !(left == right);
|
|
|
|
}
|
2010-07-28 18:27:46 +02:00
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
class DynamicStat
|
|
|
|
{
|
|
|
|
Stat<T> mStatic;
|
|
|
|
T mCurrent;
|
|
|
|
|
|
|
|
public:
|
2010-09-20 13:10:15 +02:00
|
|
|
typedef T Type;
|
2010-07-28 18:27:46 +02:00
|
|
|
|
2015-07-09 14:41:37 +02:00
|
|
|
DynamicStat();
|
|
|
|
DynamicStat(T base);
|
|
|
|
DynamicStat(T base, T modified, T current);
|
|
|
|
DynamicStat(const Stat<T>& stat, T current);
|
2010-07-28 18:27:46 +02:00
|
|
|
|
2022-10-05 23:45:17 +02:00
|
|
|
const T& getBase() const { return mStatic.getBase(); }
|
|
|
|
T getModified(bool capped = true) const { return mStatic.getModified(capped); }
|
|
|
|
const T& getCurrent() const { return mCurrent; }
|
2022-02-10 22:10:46 +01:00
|
|
|
T getRatio(bool nanIsZero = true) const;
|
2010-07-28 18:27:46 +02:00
|
|
|
|
2022-02-10 20:32:59 +01:00
|
|
|
/// Set base and adjust current accordingly.
|
2022-10-05 23:45:17 +02:00
|
|
|
void setBase(const T& value) { mStatic.setBase(value); }
|
2016-11-24 00:58:30 +09:00
|
|
|
|
|
|
|
void setCurrent(const T& value, bool allowDecreaseBelowZero = false, bool allowIncreaseAboveModified = false);
|
2022-02-10 20:32:59 +01:00
|
|
|
|
|
|
|
T getModifier() const { return mStatic.getModifier(); }
|
|
|
|
void setModifier(T value) { mStatic.setModifier(value); }
|
2015-07-09 14:41:37 +02:00
|
|
|
|
|
|
|
void writeState(ESM::StatState<T>& state) const;
|
|
|
|
void readState(const ESM::StatState<T>& state);
|
2010-07-28 18:27:46 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
inline bool operator==(const DynamicStat<T>& left, const DynamicStat<T>& right)
|
|
|
|
{
|
2022-02-10 20:32:59 +01:00
|
|
|
return left.getBase() == right.getBase() && left.getModifier() == right.getModifier()
|
2010-07-28 18:27:46 +02:00
|
|
|
&& left.getCurrent() == right.getCurrent();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
inline bool operator!=(const DynamicStat<T>& left, const DynamicStat<T>& right)
|
|
|
|
{
|
|
|
|
return !(left == right);
|
|
|
|
}
|
2014-01-03 01:59:15 +01:00
|
|
|
|
2014-01-03 03:46:30 +01:00
|
|
|
class AttributeValue
|
|
|
|
{
|
2018-12-23 15:18:33 +04:00
|
|
|
float mBase;
|
|
|
|
float mModifier;
|
2014-11-02 18:01:12 +01:00
|
|
|
float mDamage; // needs to be float to allow continuous damage
|
2014-01-03 03:46:30 +01:00
|
|
|
|
|
|
|
public:
|
2015-07-09 14:41:37 +02:00
|
|
|
AttributeValue();
|
2014-01-03 03:46:30 +01:00
|
|
|
|
2018-12-23 15:18:33 +04:00
|
|
|
float getModified() const;
|
|
|
|
float getBase() const;
|
|
|
|
float getModifier() const;
|
2014-01-03 03:46:30 +01:00
|
|
|
|
2021-11-20 00:15:18 +01:00
|
|
|
void setBase(float base, bool clearModifier = false);
|
2014-01-03 03:46:30 +01:00
|
|
|
|
2018-12-23 15:18:33 +04:00
|
|
|
void setModifier(float mod);
|
2015-03-07 16:23:02 +01:00
|
|
|
|
|
|
|
// Maximum attribute damage is limited to the modified value.
|
2021-11-20 00:15:18 +01:00
|
|
|
// Note: MW applies damage directly to mModified, however it does track how much
|
|
|
|
// a damaged attribute that has been fortified beyond its base can be restored.
|
|
|
|
// Getting rid of mDamage would require calculating its value by ignoring active effects when restoring
|
2015-07-09 14:41:37 +02:00
|
|
|
void damage(float damage);
|
|
|
|
void restore(float amount);
|
2014-02-16 15:06:34 +01:00
|
|
|
|
2015-07-09 14:41:37 +02:00
|
|
|
float getDamage() const;
|
2015-03-07 16:23:02 +01:00
|
|
|
|
2018-12-23 15:18:33 +04:00
|
|
|
void writeState(ESM::StatState<float>& state) const;
|
|
|
|
void readState(const ESM::StatState<float>& state);
|
2014-01-03 03:46:30 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class SkillValue : public AttributeValue
|
|
|
|
{
|
|
|
|
float mProgress;
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2014-01-03 03:46:30 +01:00
|
|
|
public:
|
2015-07-09 14:41:37 +02:00
|
|
|
SkillValue();
|
|
|
|
float getProgress() const;
|
|
|
|
void setProgress(float progress);
|
2014-02-16 15:06:34 +01:00
|
|
|
|
2018-12-23 15:18:33 +04:00
|
|
|
void writeState(ESM::StatState<float>& state) const;
|
|
|
|
void readState(const ESM::StatState<float>& state);
|
2014-01-03 03:46:30 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
inline bool operator==(const AttributeValue& left, const AttributeValue& right)
|
|
|
|
{
|
|
|
|
return left.getBase() == right.getBase() && left.getModifier() == right.getModifier()
|
2015-03-07 16:23:02 +01:00
|
|
|
&& left.getDamage() == right.getDamage();
|
2014-01-03 03:46:30 +01:00
|
|
|
}
|
|
|
|
inline bool operator!=(const AttributeValue& left, const AttributeValue& right)
|
|
|
|
{
|
|
|
|
return !(left == right);
|
|
|
|
}
|
2014-01-13 07:05:52 +01:00
|
|
|
|
|
|
|
inline bool operator==(const SkillValue& left, const SkillValue& right)
|
|
|
|
{
|
2015-03-07 16:23:02 +01:00
|
|
|
return left.getBase() == right.getBase() && left.getModifier() == right.getModifier()
|
2014-01-13 07:05:52 +01:00
|
|
|
&& left.getDamage() == right.getDamage() && left.getProgress() == right.getProgress();
|
|
|
|
}
|
|
|
|
inline bool operator!=(const SkillValue& left, const SkillValue& right)
|
|
|
|
{
|
|
|
|
return !(left == right);
|
|
|
|
}
|
2010-07-26 12:52:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|