mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 15:59:54 +00:00
Implement effect removal for abilities (Fixes #3455)
This commit is contained in:
parent
252b27f0ef
commit
54f52f7bae
7 changed files with 85 additions and 16 deletions
|
@ -121,7 +121,7 @@ public:
|
|||
{
|
||||
mContext->mPlayer.mObject.mCreatureStats.mLevel = npc.mNpdt52.mLevel;
|
||||
mContext->mPlayerBase = npc;
|
||||
std::map<int, float> empty;
|
||||
ESM::SpellState::SpellParams empty;
|
||||
// FIXME: player start spells and birthsign spells aren't listed here,
|
||||
// need to fix openmw to account for this
|
||||
for (std::vector<std::string>::const_iterator it = npc.mSpells.mList.begin(); it != npc.mSpells.mList.end(); ++it)
|
||||
|
|
|
@ -513,6 +513,7 @@ namespace MWMechanics
|
|||
CastSpell cast(ptr, ptr);
|
||||
if (cast.applyInstantEffect(ptr, ptr, it->first, it->second.getMagnitude()))
|
||||
{
|
||||
creatureStats.getSpells().purgeEffect(it->first.mId);
|
||||
creatureStats.getActiveSpells().purgeEffect(it->first.mId);
|
||||
if (ptr.getClass().hasInventoryStore(ptr))
|
||||
ptr.getClass().getInventoryStore(ptr).purgeEffect(it->first.mId);
|
||||
|
|
|
@ -66,7 +66,9 @@ namespace MWMechanics
|
|||
mCorprusSpells[spell] = corprus;
|
||||
}
|
||||
|
||||
mSpells.insert (std::make_pair (spell, random));
|
||||
SpellParams params;
|
||||
params.mEffectRands = random;
|
||||
mSpells.insert (std::make_pair (spell, params));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,9 +126,12 @@ namespace MWMechanics
|
|||
int i=0;
|
||||
for (std::vector<ESM::ENAMstruct>::const_iterator it = spell->mEffects.mList.begin(); it != spell->mEffects.mList.end(); ++it)
|
||||
{
|
||||
if (iter->second.mPurgedEffects.find(i) != iter->second.mPurgedEffects.end())
|
||||
continue; // effect was purged
|
||||
|
||||
float random = 1.f;
|
||||
if (iter->second.find(i) != iter->second.end())
|
||||
random = iter->second.at(i);
|
||||
if (iter->second.mEffectRands.find(i) != iter->second.mEffectRands.end())
|
||||
random = iter->second.mEffectRands.at(i);
|
||||
|
||||
effects.add (*it, it->mMagnMin + (it->mMagnMax - it->mMagnMin) * random);
|
||||
++i;
|
||||
|
@ -259,9 +264,12 @@ namespace MWMechanics
|
|||
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = list.mList.begin();
|
||||
effectIt != list.mList.end(); ++effectIt, ++i)
|
||||
{
|
||||
if (it->second.mPurgedEffects.find(i) != it->second.mPurgedEffects.end())
|
||||
continue; // effect was purged
|
||||
|
||||
float random = 1.f;
|
||||
if (it->second.find(i) != it->second.end())
|
||||
random = it->second.at(i);
|
||||
if (it->second.mEffectRands.find(i) != it->second.mEffectRands.end())
|
||||
random = it->second.mEffectRands.at(i);
|
||||
|
||||
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random;
|
||||
visitor.visit(MWMechanics::EffectKey(*effectIt), spell->mName, spell->mId, -1, magnitude);
|
||||
|
@ -283,8 +291,8 @@ namespace MWMechanics
|
|||
if ((effectIt->mEffectID != ESM::MagicEffect::Corprus) && (magicEffect->mData.mFlags & ESM::MagicEffect::UncappedDamage)) // APPLIED_ONCE
|
||||
{
|
||||
float random = 1.f;
|
||||
if (mSpells[spell].find(i) != mSpells[spell].end())
|
||||
random = mSpells[spell].at(i);
|
||||
if (mSpells[spell].mEffectRands.find(i) != mSpells[spell].mEffectRands.end())
|
||||
random = mSpells[spell].mEffectRands.at(i);
|
||||
|
||||
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random;
|
||||
magnitude *= std::max(1, mCorprusSpells[spell].mWorsenings);
|
||||
|
@ -310,6 +318,36 @@ namespace MWMechanics
|
|||
return mCorprusSpells;
|
||||
}
|
||||
|
||||
void Spells::purgeEffect(int effectId)
|
||||
{
|
||||
for (TContainer::iterator spellIt = mSpells.begin(); spellIt != mSpells.end(); ++spellIt)
|
||||
{
|
||||
int i = 0;
|
||||
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = spellIt->first->mEffects.mList.begin(); effectIt != spellIt->first->mEffects.mList.end(); ++effectIt)
|
||||
{
|
||||
if (effectIt->mEffectID == effectId)
|
||||
spellIt->second.mPurgedEffects.insert(i);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Spells::purgeEffect(int effectId, const std::string & sourceId)
|
||||
{
|
||||
const ESM::Spell * spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(sourceId);
|
||||
TContainer::iterator spellIt = mSpells.find(spell);
|
||||
if (spellIt == mSpells.end())
|
||||
return;
|
||||
|
||||
int i = 0;
|
||||
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = spellIt->first->mEffects.mList.begin(); effectIt != spellIt->first->mEffects.mList.end(); ++effectIt)
|
||||
{
|
||||
if (effectIt->mEffectID == effectId)
|
||||
spellIt->second.mPurgedEffects.insert(i);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
bool Spells::canUsePower(const ESM::Spell* spell) const
|
||||
{
|
||||
std::map<SpellKey, MWWorld::TimeStamp>::const_iterator it = mUsedPowers.find(spell);
|
||||
|
@ -332,7 +370,8 @@ namespace MWMechanics
|
|||
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(it->first);
|
||||
if (spell)
|
||||
{
|
||||
mSpells[spell] = it->second;
|
||||
mSpells[spell].mEffectRands = it->second.mEffectRands;
|
||||
mSpells[spell].mPurgedEffects = it->second.mPurgedEffects;
|
||||
|
||||
if (it->first == state.mSelectedSpell)
|
||||
mSelectedSpell = it->first;
|
||||
|
@ -375,7 +414,12 @@ namespace MWMechanics
|
|||
void Spells::writeState(ESM::SpellState &state) const
|
||||
{
|
||||
for (TContainer::const_iterator it = mSpells.begin(); it != mSpells.end(); ++it)
|
||||
state.mSpells.insert(std::make_pair(it->first->mId, it->second));
|
||||
{
|
||||
ESM::SpellState::SpellParams params;
|
||||
params.mEffectRands = it->second.mEffectRands;
|
||||
params.mPurgedEffects = it->second.mPurgedEffects;
|
||||
state.mSpells.insert(std::make_pair(it->first->mId, params));
|
||||
}
|
||||
|
||||
state.mSelectedSpell = mSelectedSpell;
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
|
@ -32,8 +33,12 @@ namespace MWMechanics
|
|||
public:
|
||||
|
||||
typedef const ESM::Spell* SpellKey;
|
||||
struct SpellParams {
|
||||
std::map<int, float> mEffectRands; // <effect index, normalised random magnitude>
|
||||
std::set<int> mPurgedEffects; // indices of purged effects
|
||||
};
|
||||
|
||||
typedef std::map<SpellKey, std::map<int, float> > TContainer; // ID, <effect index, normalised random magnitude>
|
||||
typedef std::map<SpellKey, SpellParams> TContainer;
|
||||
typedef TContainer::const_iterator TIterator;
|
||||
|
||||
struct CorprusStats
|
||||
|
@ -67,6 +72,9 @@ namespace MWMechanics
|
|||
static bool hasCorprusEffect(const ESM::Spell *spell);
|
||||
const std::map<SpellKey, CorprusStats> & getCorprusSpells() const;
|
||||
|
||||
void purgeEffect(int effectId);
|
||||
void purgeEffect(int effectId, const std::string & sourceId);
|
||||
|
||||
bool canUsePower (const ESM::Spell* spell) const;
|
||||
void usePower (const ESM::Spell* spell);
|
||||
|
||||
|
|
|
@ -2687,6 +2687,7 @@ namespace MWWorld
|
|||
|
||||
void World::breakInvisibility(const Ptr &actor)
|
||||
{
|
||||
actor.getClass().getCreatureStats(actor).getSpells().purgeEffect(ESM::MagicEffect::Invisibility);
|
||||
actor.getClass().getCreatureStats(actor).getActiveSpells().purgeEffect(ESM::MagicEffect::Invisibility);
|
||||
if (actor.getClass().hasInventoryStore(actor))
|
||||
actor.getClass().getInventoryStore(actor).purgeEffect(ESM::MagicEffect::Invisibility);
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace ESM
|
|||
{
|
||||
std::string id = esm.getHString();
|
||||
|
||||
std::map<int, float> random;
|
||||
SpellParams state;
|
||||
while (esm.isNextSub("INDX"))
|
||||
{
|
||||
int index;
|
||||
|
@ -21,10 +21,16 @@ namespace ESM
|
|||
float magnitude;
|
||||
esm.getHNT(magnitude, "RAND");
|
||||
|
||||
random[index] = magnitude;
|
||||
state.mEffectRands[index] = magnitude;
|
||||
}
|
||||
|
||||
mSpells[id] = random;
|
||||
while (esm.isNextSub("PURG")) {
|
||||
int index;
|
||||
esm.getHT(index);
|
||||
state.mPurgedEffects.insert(index);
|
||||
}
|
||||
|
||||
mSpells[id] = state;
|
||||
}
|
||||
|
||||
while (esm.isNextSub("PERM"))
|
||||
|
@ -73,12 +79,16 @@ namespace ESM
|
|||
{
|
||||
esm.writeHNString("SPEL", it->first);
|
||||
|
||||
const std::map<int, float>& random = it->second;
|
||||
const std::map<int, float>& random = it->second.mEffectRands;
|
||||
for (std::map<int, float>::const_iterator rIt = random.begin(); rIt != random.end(); ++rIt)
|
||||
{
|
||||
esm.writeHNT("INDX", rIt->first);
|
||||
esm.writeHNT("RAND", rIt->second);
|
||||
}
|
||||
|
||||
const std::set<int>& purges = it->second.mPurgedEffects;
|
||||
for (std::set<int>::const_iterator pIt = purges.begin(); pIt != purges.end(); ++pIt)
|
||||
esm.writeHNT("PURG", *pIt);
|
||||
}
|
||||
|
||||
for (std::map<std::string, std::vector<PermanentSpellEffectInfo> >::const_iterator it = mPermanentSpellEffects.begin(); it != mPermanentSpellEffects.end(); ++it)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
#include "defs.hpp"
|
||||
|
||||
|
@ -28,7 +29,11 @@ namespace ESM
|
|||
float mMagnitude;
|
||||
};
|
||||
|
||||
typedef std::map<std::string, std::map<int, float> > TContainer;
|
||||
struct SpellParams {
|
||||
std::map<int, float> mEffectRands;
|
||||
std::set<int> mPurgedEffects;
|
||||
};
|
||||
typedef std::map<std::string, SpellParams> TContainer;
|
||||
TContainer mSpells;
|
||||
|
||||
std::map<std::string, std::vector<PermanentSpellEffectInfo> > mPermanentSpellEffects;
|
||||
|
|
Loading…
Reference in a new issue