1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-30 03:32:36 +00:00
OpenMW/apps/openmw/mwmechanics/activespells.hpp

174 lines
5.6 KiB
C++

#ifndef GAME_MWMECHANICS_ACTIVESPELLS_H
#define GAME_MWMECHANICS_ACTIVESPELLS_H
#include <functional>
#include <list>
#include <queue>
#include <string>
#include <variant>
#include <vector>
#include <components/esm3/activespells.hpp>
#include "../mwworld/ptr.hpp"
#include "../mwworld/timestamp.hpp"
#include "spellcasting.hpp"
namespace ESM
{
struct Enchantment;
struct Spell;
}
namespace MWMechanics
{
/// \brief Lasting spell effects
///
/// \note The name of this class is slightly misleading, since it also handles lasting potion
/// effects.
class ActiveSpells
{
public:
using ActiveEffect = ESM::ActiveEffect;
class ActiveSpellParams
{
ESM::RefId mActiveSpellId;
ESM::RefId mSourceSpellId;
std::vector<ActiveEffect> mEffects;
std::string mDisplayName;
int mCasterActorId;
ESM::RefNum mItem;
ESM::ActiveSpells::Flags mFlags;
int mWorsenings;
MWWorld::TimeStamp mNextWorsening;
MWWorld::Ptr mSource;
ActiveSpellParams(const ESM::ActiveSpells::ActiveSpellParams& params);
ActiveSpellParams(const ESM::Spell* spell, const MWWorld::Ptr& actor, bool ignoreResistances = false);
ActiveSpellParams(
const MWWorld::ConstPtr& item, const ESM::Enchantment* enchantment, const MWWorld::Ptr& actor);
ActiveSpellParams(const ActiveSpellParams& params, const MWWorld::Ptr& actor);
ESM::ActiveSpells::ActiveSpellParams toEsm() const;
friend class ActiveSpells;
public:
ActiveSpellParams(
const MWWorld::Ptr& caster, const ESM::RefId& id, std::string_view sourceName, ESM::RefNum item);
ESM::RefId getActiveSpellId() const { return mActiveSpellId; }
void setActiveSpellId(ESM::RefId id) { mActiveSpellId = id; }
const ESM::RefId& getSourceSpellId() const { return mSourceSpellId; }
const std::vector<ActiveEffect>& getEffects() const { return mEffects; }
std::vector<ActiveEffect>& getEffects() { return mEffects; }
int getCasterActorId() const { return mCasterActorId; }
int getWorsenings() const { return mWorsenings; }
const std::string& getDisplayName() const { return mDisplayName; }
ESM::RefNum getItem() const { return mItem; }
ESM::RefId getEnchantment() const;
const ESM::Spell* getSpell() const;
bool hasFlag(ESM::ActiveSpells::Flags flags) const;
void setFlag(ESM::ActiveSpells::Flags flags);
// Increments worsenings count and sets the next timestamp
void worsen();
bool shouldWorsen() const;
void resetWorsenings();
};
typedef std::list<ActiveSpellParams> Collection;
typedef Collection::const_iterator TIterator;
void readState(const ESM::ActiveSpells& state);
void writeState(ESM::ActiveSpells& state) const;
TIterator begin() const;
TIterator end() const;
TIterator getActiveSpellById(const ESM::RefId& id);
void update(const MWWorld::Ptr& ptr, float duration);
private:
using ParamsPredicate = std::function<bool(const ActiveSpellParams&)>;
using EffectPredicate = std::function<bool(const ActiveSpellParams&, const ESM::ActiveEffect&)>;
using Predicate = std::variant<ParamsPredicate, EffectPredicate>;
struct IterationGuard
{
ActiveSpells& mActiveSpells;
IterationGuard(ActiveSpells& spells);
~IterationGuard();
};
std::list<ActiveSpellParams> mSpells;
std::vector<ActiveSpellParams> mQueue;
std::queue<Predicate> mPurges;
bool mIterating;
void addToSpells(const MWWorld::Ptr& ptr, const ActiveSpellParams& spell);
bool applyPurges(const MWWorld::Ptr& ptr, std::list<ActiveSpellParams>::iterator* currentSpell = nullptr,
std::vector<ActiveEffect>::iterator* currentEffect = nullptr);
public:
ActiveSpells();
/// Add lasting effects
///
/// \brief addSpell
/// \param id ID for stacking purposes.
///
void addSpell(const ActiveSpellParams& params);
/// Bypasses resistances
void addSpell(const ESM::Spell* spell, const MWWorld::Ptr& actor);
/// Removes the active effects from this spell/potion/.. with \a id
void removeEffectsBySourceSpellId(const MWWorld::Ptr& ptr, const ESM::RefId& id);
/// Removes the active effects of a specific active spell
void removeEffectsByActiveSpellId(const MWWorld::Ptr& ptr, const ESM::RefId& id);
/// Remove all active effects with this effect id
void purgeEffect(const MWWorld::Ptr& ptr, int effectId, ESM::RefId effectArg = {});
void purge(EffectPredicate predicate, const MWWorld::Ptr& ptr);
void purge(ParamsPredicate predicate, const MWWorld::Ptr& ptr);
/// Remove all effects that were cast by \a casterActorId
void purge(const MWWorld::Ptr& ptr, int casterActorId);
/// Remove all spells
void clear(const MWWorld::Ptr& ptr);
/// True if a spell associated with this id is active
/// \note For enchantments, this is the id of the enchanted item, not the enchantment itself
bool isSpellActive(const ESM::RefId& id) const;
/// True if the enchantment is active
bool isEnchantmentActive(const ESM::RefId& id) const;
void skipWorsenings(double hours);
void unloadActor(const MWWorld::Ptr& ptr);
};
}
#endif