You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw-tes3mp/apps/openmw/mwmechanics/creaturestats.hpp

331 lines
9.8 KiB
C++

#ifndef GAME_MWMECHANICS_CREATURESTATS_H
#define GAME_MWMECHANICS_CREATURESTATS_H
#include <set>
#include <string>
#include <stdexcept>
#include "stat.hpp"
#include "magiceffects.hpp"
#include "spells.hpp"
#include "activespells.hpp"
#include "aisequence.hpp"
#include "drawstate.hpp"
#include <components/esm/attr.hpp>
#include <components/esm/magiceffects.hpp>
namespace ESM
{
struct CreatureStats;
}
namespace MWMechanics
{
struct CorprusStats
{
static constexpr int sWorseningPeriod = 24;
int mWorsenings[ESM::Attribute::Length];
MWWorld::TimeStamp mNextWorsening;
};
/// \brief Common creature stats
///
///
class CreatureStats
{
static int sActorId;
DrawState_ mDrawState;
AttributeValue mAttributes[ESM::Attribute::Length];
DynamicStat<float> mDynamic[3]; // health, magicka, fatigue
Spells mSpells;
ActiveSpells mActiveSpells;
MagicEffects mMagicEffects;
Stat<int> mAiSettings[4];
AiSequence mAiSequence;
bool mDead;
bool mDeathAnimationFinished;
bool mDied; // flag for OnDeath script function
bool mMurdered;
int mFriendlyHits;
bool mTalkedTo;
bool mAlarmed;
bool mAttacked;
bool mKnockdown;
bool mKnockdownOneFrame;
bool mKnockdownOverOneFrame;
bool mHitRecovery;
bool mBlock;
unsigned int mMovementFlags;
float mFallHeight;
std::string mLastHitObject; // The last object to hit this actor
std::string mLastHitAttemptObject; // The last object to attempt to hit this actor
bool mRecalcMagicka;
// For merchants: the last time items were restocked and gold pool refilled.
MWWorld::TimeStamp mLastRestock;
// The pool of merchant gold (not in inventory)
int mGoldPool;
int mActorId;
int mHitAttemptActorId; // Stores an actor that attacked this actor. Only one is stored at a time,
// and it is not changed if a different actor attacks. It is cleared when combat ends.
// The index of the death animation that was played, or -1 if none played
signed char mDeathAnimation;
MWWorld::TimeStamp mTimeOfDeath;
// The difference between view direction and lower body direction.
float mSideMovementAngle;
private:
std::map<ESM::SummonKey, int> mSummonedCreatures; // <SummonKey, ActorId>
// Contains ActorIds of summoned creatures with an expired lifetime that have not been deleted yet.
// This may be necessary when the creature is in an inactive cell.
std::vector<int> mSummonGraveyard;
std::map<std::string, CorprusStats> mCorprusSpells;
protected:
int mLevel;
public:
CreatureStats();
DrawState_ getDrawState() const;
void setDrawState(DrawState_ state);
bool needToRecalcDynamicStats();
void setNeedRecalcDynamicStats(bool val);
float getFallHeight() const;
void addToFallHeight(float height);
/// Reset the fall height
/// @return total fall height
float land(bool isPlayer=false);
const AttributeValue & getAttribute(int index) const;
const DynamicStat<float> & getHealth() const;
const DynamicStat<float> & getMagicka() const;
const DynamicStat<float> & getFatigue() const;
const DynamicStat<float> & getDynamic (int index) const;
const Spells & getSpells() const;
const ActiveSpells & getActiveSpells() const;
const MagicEffects & getMagicEffects() const;
bool getAttackingOrSpell() const;
int getLevel() const;
Spells & getSpells();
ActiveSpells & getActiveSpells();
MagicEffects & getMagicEffects();
void setAttribute(int index, const AttributeValue &value);
// Shortcut to set only the base
void setAttribute(int index, float base);
void setHealth(const DynamicStat<float> &value);
void setMagicka(const DynamicStat<float> &value);
void setFatigue(const DynamicStat<float> &value);
void setDynamic (int index, const DynamicStat<float> &value);
/// Set Modifier for each magic effect according to \a effects. Does not touch Base values.
void modifyMagicEffects(const MagicEffects &effects);
void setAttackingOrSpell(bool attackingOrSpell);
void setLevel(int level);
enum AiSetting
{
AI_Hello = 0,
AI_Fight = 1,
AI_Flee = 2,
AI_Alarm = 3
};
void setAiSetting (AiSetting index, Stat<int> value);
void setAiSetting (AiSetting index, int base);
Stat<int> getAiSetting (AiSetting index) const;
const AiSequence& getAiSequence() const;
AiSequence& getAiSequence();
float getFatigueTerm() const;
///< Return effective fatigue
bool isParalyzed() const;
bool isDead() const;
bool isDeathAnimationFinished() const;
void setDeathAnimationFinished(bool finished);
void notifyDied();
bool hasDied() const;
void clearHasDied();
bool hasBeenMurdered() const;
void clearHasBeenMurdered();
void notifyMurder();
void resurrect();
bool hasCommonDisease() const;
bool hasBlightDisease() const;
int getFriendlyHits() const;
///< Number of friendly hits received.
/*
Start of tes3mp addition
Make it possible to set the number of friendly hits from elsewhere
*/
void setFriendlyHits(int hits);
/*
End of tes3mp addition
*/
void friendlyHit();
///< Increase number of friendly hits by one.
bool hasTalkedToPlayer() const;
///< Has this creature talked with the player before?
void talkedToPlayer();
bool isAlarmed() const;
void setAlarmed (bool alarmed);
bool getAttacked() const;
void setAttacked (bool attacked);
float getEvasion() const;
void setKnockedDown(bool value);
/// Returns true for the entire duration of the actor being knocked down or knocked out,
/// including transition animations (falling down & standing up)
bool getKnockedDown() const;
void setKnockedDownOneFrame(bool value);
///Returns true only for the first frame of the actor being knocked out; used for "onKnockedOut" command
bool getKnockedDownOneFrame() const;
void setKnockedDownOverOneFrame(bool value);
///Returns true for all but the first frame of being knocked out; used to know to not reset mKnockedDownOneFrame
bool getKnockedDownOverOneFrame() const;
void setHitRecovery(bool value);
bool getHitRecovery() const;
void setBlock(bool value);
bool getBlock() const;
std::map<ESM::SummonKey, int>& getSummonedCreatureMap(); // <SummonKey, ActorId of summoned creature>
std::vector<int>& getSummonedCreatureGraveyard(); // ActorIds
/*
Start of tes3mp addition
Make it possible to set a new actorId for summoned creatures, necessary for properly
initializing them after syncing them across players
*/
void setSummonedCreatureActorId(std::string refId, int actorId);
/*
End of tes3mp addition
*/
enum Flag
{
Flag_ForceRun = 1,
Flag_ForceSneak = 2,
Flag_Run = 4,
Flag_Sneak = 8,
Flag_ForceJump = 16,
Flag_ForceMoveJump = 32
};
enum Stance
{
Stance_Run,
Stance_Sneak
};
bool getMovementFlag (Flag flag) const;
void setMovementFlag (Flag flag, bool state);
/// Like getMovementFlag, but also takes into account if the flag is Forced
bool getStance (Stance flag) const;
void setLastHitObject(const std::string &objectid);
const std::string &getLastHitObject() const;
void setLastHitAttemptObject(const std::string &objectid);
const std::string &getLastHitAttemptObject() const;
void setHitAttemptActorId(const int actorId);
int getHitAttemptActorId() const;
// Note, this is just a cache to avoid checking the whole container store every frame. We don't need to store it in saves.
// TODO: Put it somewhere else?
std::set<int> mBoundItems;
void writeState (ESM::CreatureStats& state) const;
void readState (const ESM::CreatureStats& state);
static void writeActorIdCounter (ESM::ESMWriter& esm);
static void readActorIdCounter (ESM::ESMReader& esm);
void setLastRestockTime(MWWorld::TimeStamp tradeTime);
MWWorld::TimeStamp getLastRestockTime() const;
void setGoldPool(int pool);
int getGoldPool() const;
signed char getDeathAnimation() const; // -1 means not decided
void setDeathAnimation(signed char index);
MWWorld::TimeStamp getTimeOfDeath() const;
int getActorId();
///< Will generate an actor ID, if the actor does not have one yet.
bool matchesActorId (int id) const;
///< Check if \a id matches the actor ID of *this (if the actor does not have an ID
/// assigned this function will return false).
static void cleanup();
std::map<std::string, CorprusStats> & getCorprusSpells();
void addCorprusSpell(const std::string& sourceId, CorprusStats& stats);
void removeCorprusSpell(const std::string& sourceId);
float getSideMovementAngle() const { return mSideMovementAngle; }
void setSideMovementAngle(float angle) { mSideMovementAngle = angle; }
};
}
#endif