From e27858cfabf2e8489787e93a32595cc63b16730b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jul 2020 18:24:09 +0200 Subject: [PATCH] these were supposed to be included --- apps/openmw/mwmechanics/spelllist.cpp | 175 ++++++++++++++++++++++++++ apps/openmw/mwmechanics/spelllist.hpp | 60 +++++++++ 2 files changed, 235 insertions(+) create mode 100644 apps/openmw/mwmechanics/spelllist.cpp create mode 100644 apps/openmw/mwmechanics/spelllist.hpp diff --git a/apps/openmw/mwmechanics/spelllist.cpp b/apps/openmw/mwmechanics/spelllist.cpp new file mode 100644 index 000000000..891b28619 --- /dev/null +++ b/apps/openmw/mwmechanics/spelllist.cpp @@ -0,0 +1,175 @@ +#include "spelllist.hpp" + +#include + +#include +#include + +#include "spells.hpp" + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" + +#include "../mwworld/esmstore.hpp" + +namespace +{ + template + const std::vector getSpellList(const std::string& id) + { + return MWBase::Environment::get().getWorld()->getStore().get().find(id)->mSpells.mList; + } + + template + bool withBaseRecord(const std::string& id, const std::function&)>& function) + { + T copy = *MWBase::Environment::get().getWorld()->getStore().get().find(id); + bool changed = function(copy.mSpells.mList); + if(changed) + MWBase::Environment::get().getWorld()->createOverrideRecord(copy); + return changed; + } +} + +namespace MWMechanics +{ + SpellList::SpellList(const std::string& id, int type) : mId(id), mType(type) {} + + bool SpellList::withBaseRecord(const std::function&)>& function) + { + switch(mType) + { + case ESM::REC_CREA: + return ::withBaseRecord(mId, function); + case ESM::REC_NPC_: + return ::withBaseRecord(mId, function); + default: + throw std::logic_error("failed to update base record for " + mId); + } + } + + const std::vector SpellList::getSpells() const + { + switch(mType) + { + case ESM::REC_CREA: + return getSpellList(mId); + case ESM::REC_NPC_: + return getSpellList(mId); + default: + throw std::logic_error("failed to get spell list for " + mId); + } + } + + const ESM::Spell* SpellList::getSpell(const std::string& id) + { + return MWBase::Environment::get().getWorld()->getStore().get().find(id); + } + + void SpellList::add (const ESM::Spell* spell) + { + auto& id = spell->mId; + bool changed = withBaseRecord([&] (auto& spells) + { + for(auto it : spells) + { + if(Misc::StringUtils::ciEqual(id, it)) + return false; + } + spells.push_back(id); + return true; + }); + if(changed) + { + for(auto listener : mListeners) + listener->addSpell(spell); + } + } + + void SpellList::remove (const ESM::Spell* spell) + { + auto& id = spell->mId; + bool changed = withBaseRecord([&] (auto& spells) + { + for(auto it = spells.begin(); it != spells.end(); it++) + { + if(Misc::StringUtils::ciEqual(id, *it)) + { + spells.erase(it); + return true; + } + } + return false; + }); + if(changed) + { + for(auto listener : mListeners) + listener->removeSpell(spell); + } + } + + void SpellList::removeAll (const std::vector& ids) + { + bool changed = withBaseRecord([&] (auto& spells) + { + const auto it = std::remove_if(spells.begin(), spells.end(), [&] (const auto& spell) + { + const auto isSpell = [&] (const auto& id) { return Misc::StringUtils::ciEqual(spell, id); }; + return ids.end() != std::find_if(ids.begin(), ids.end(), isSpell); + }); + if (it == spells.end()) + return false; + spells.erase(it, spells.end()); + return true; + }); + if(changed) + { + for(auto listener : mListeners) + { + for(auto& id : ids) + { + const auto spell = getSpell(id); + listener->removeSpell(spell); + } + } + } + } + + void SpellList::clear() + { + bool changed = withBaseRecord([] (auto& spells) + { + if(spells.empty()) + return false; + spells.clear(); + return true; + }); + if(changed) + { + for(auto listener : mListeners) + listener->removeAllSpells(); + } + } + + void SpellList::addListener(Spells* spells) + { + for(const auto ptr : mListeners) + { + if(ptr == spells) + return; + } + mListeners.push_back(spells); + } + + void SpellList::removeListener(Spells* spells) + { + for(auto it = mListeners.begin(); it != mListeners.end(); it++) + { + if(*it == spells) + { + mListeners.erase(it); + break; + } + } + } +} diff --git a/apps/openmw/mwmechanics/spelllist.hpp b/apps/openmw/mwmechanics/spelllist.hpp new file mode 100644 index 000000000..87420082f --- /dev/null +++ b/apps/openmw/mwmechanics/spelllist.hpp @@ -0,0 +1,60 @@ +#ifndef GAME_MWMECHANICS_SPELLLIST_H +#define GAME_MWMECHANICS_SPELLLIST_H + +#include +#include +#include +#include +#include + +#include + +#include "magiceffects.hpp" + +namespace ESM +{ + struct SpellState; +} + +namespace MWMechanics +{ + struct SpellParams + { + std::map mEffectRands; // + std::set mPurgedEffects; // indices of purged effects + }; + + class Spells; + + class SpellList + { + const std::string mId; + const int mType; + std::vector mListeners; + + bool withBaseRecord(const std::function&)>& function); + public: + SpellList(const std::string& id, int type); + + /// Get spell from ID, throws exception if not found + static const ESM::Spell* getSpell(const std::string& id); + + void add (const ESM::Spell* spell); + ///< Adding a spell that is already listed in *this is a no-op. + + void remove (const ESM::Spell* spell); + + void removeAll(const std::vector& spells); + + void clear(); + ///< Remove all spells of all types. + + void addListener(Spells* spells); + + void removeListener(Spells* spells); + + const std::vector getSpells() const; + }; +} + +#endif