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