1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-26 18:35:20 +00:00
OpenMW/apps/openmw/mwmechanics/activespells.hpp
2023-05-23 18:11:44 +02:00

155 lines
4.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 mId;
std::vector<ActiveEffect> mEffects;
std::string mDisplayName;
int mCasterActorId;
int mSlot;
ESM::ActiveSpells::EffectType mType;
int mWorsenings;
MWWorld::TimeStamp mNextWorsening;
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, int slotIndex,
const MWWorld::Ptr& actor);
ActiveSpellParams(const ActiveSpellParams& params, const MWWorld::Ptr& actor);
ESM::ActiveSpells::ActiveSpellParams toEsm() const;
friend class ActiveSpells;
public:
ActiveSpellParams(const CastSpell& cast, const MWWorld::Ptr& caster);
const ESM::RefId& getId() const { return mId; }
const std::vector<ActiveEffect>& getEffects() const { return mEffects; }
std::vector<ActiveEffect>& getEffects() { return mEffects; }
ESM::ActiveSpells::EffectType getType() const { return mType; }
int getCasterActorId() const { return mCasterActorId; }
int getWorsenings() const { return mWorsenings; }
const std::string& getDisplayName() const { return mDisplayName; }
// 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;
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 removeEffects(const MWWorld::Ptr& ptr, const ESM::RefId& id);
/// Remove all active effects with this effect id
void purgeEffect(const MWWorld::Ptr& ptr, short effectId);
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);
bool isSpellActive(const ESM::RefId& id) const;
///< case insensitive
void skipWorsenings(double hours);
void unloadActor(const MWWorld::Ptr& ptr);
};
}
#endif