From 924f634bda9c2b30504a728cd6821334e900ca9b Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Mon, 8 Jun 2020 15:19:25 +0400 Subject: [PATCH] Support for multiple summons with same ID in the single spell --- apps/openmw/mwgui/spellicons.cpp | 4 ++-- apps/openmw/mwgui/spellicons.hpp | 4 ++-- apps/openmw/mwmechanics/activespells.cpp | 7 +++--- apps/openmw/mwmechanics/activespells.hpp | 2 +- apps/openmw/mwmechanics/actors.cpp | 26 +++++++++++---------- apps/openmw/mwmechanics/creaturestats.hpp | 2 +- apps/openmw/mwmechanics/linkedeffects.cpp | 1 + apps/openmw/mwmechanics/magiceffects.hpp | 4 ++-- apps/openmw/mwmechanics/spellabsorption.cpp | 4 ++-- apps/openmw/mwmechanics/spellcasting.cpp | 6 +++-- apps/openmw/mwmechanics/spells.cpp | 22 +++++++++++------ apps/openmw/mwmechanics/summoning.cpp | 17 +++++++------- apps/openmw/mwmechanics/summoning.hpp | 6 ++--- apps/openmw/mwworld/inventorystore.cpp | 7 ++++-- apps/openmw/mwworld/inventorystore.hpp | 2 +- apps/openmw/mwworld/worldimp.cpp | 2 +- components/esm/activespells.cpp | 3 +++ components/esm/activespells.hpp | 1 + components/esm/creaturestats.cpp | 13 +++++++---- components/esm/creaturestats.hpp | 2 +- components/esm/savedgame.cpp | 2 +- 21 files changed, 81 insertions(+), 56 deletions(-) diff --git a/apps/openmw/mwgui/spellicons.cpp b/apps/openmw/mwgui/spellicons.cpp index 8a501e598..e6a10ee32 100644 --- a/apps/openmw/mwgui/spellicons.cpp +++ b/apps/openmw/mwgui/spellicons.cpp @@ -25,8 +25,8 @@ namespace MWGui { - void EffectSourceVisitor::visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, + void EffectSourceVisitor::visit (MWMechanics::EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, float magnitude, float remainingTime, float totalTime) { MagicEffectInfo newEffectSource; diff --git a/apps/openmw/mwgui/spellicons.hpp b/apps/openmw/mwgui/spellicons.hpp index 26761f2fc..67351688f 100644 --- a/apps/openmw/mwgui/spellicons.hpp +++ b/apps/openmw/mwgui/spellicons.hpp @@ -46,8 +46,8 @@ namespace MWGui virtual ~EffectSourceVisitor() {} - virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, + virtual void visit (MWMechanics::EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, float magnitude, float remainingTime = -1, float totalTime = -1); }; diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp index 2ccffcc91..928293e64 100644 --- a/apps/openmw/mwmechanics/activespells.cpp +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -210,9 +210,8 @@ namespace MWMechanics std::string name = it->second.mDisplayName; float magnitude = effectIt->mMagnitude; - if (magnitude) - visitor.visit(MWMechanics::EffectKey(effectIt->mEffectId, effectIt->mArg), name, it->first, it->second.mCasterActorId, magnitude, effectIt->mTimeLeft, effectIt->mDuration); + visitor.visit(MWMechanics::EffectKey(effectIt->mEffectId, effectIt->mArg), effectIt->mEffectIndex, name, it->first, it->second.mCasterActorId, magnitude, effectIt->mTimeLeft, effectIt->mDuration); } } } @@ -258,14 +257,14 @@ namespace MWMechanics mSpellsChanged = true; } - void ActiveSpells::purgeEffect(short effectId, const std::string& sourceId) + void ActiveSpells::purgeEffect(short effectId, const std::string& sourceId, int effectIndex) { for (TContainer::iterator it = mSpells.begin(); it != mSpells.end(); ++it) { for (std::vector::iterator effectIt = it->second.mEffects.begin(); effectIt != it->second.mEffects.end();) { - if (effectIt->mEffectId == effectId && it->first == sourceId) + if (effectIt->mEffectId == effectId && it->first == sourceId && (effectIndex < 0 || effectIndex == effectIt->mEffectIndex)) effectIt = it->second.mEffects.erase(effectIt); else ++effectIt; diff --git a/apps/openmw/mwmechanics/activespells.hpp b/apps/openmw/mwmechanics/activespells.hpp index 9a1783bc9..4d36c717e 100644 --- a/apps/openmw/mwmechanics/activespells.hpp +++ b/apps/openmw/mwmechanics/activespells.hpp @@ -85,7 +85,7 @@ namespace MWMechanics void purgeEffect (short effectId); /// Remove all active effects with this effect id and source id - void purgeEffect (short effectId, const std::string& sourceId); + void purgeEffect (short effectId, const std::string& sourceId, int effectIndex=-1); /// Remove all active effects, if roll succeeds (for each effect) void purgeAll(float chance, bool spellOnly = false); diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 14a2e17c9..21f71ce5d 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -88,12 +88,13 @@ class CheckActorCommanded : public MWMechanics::EffectSourceVisitor MWWorld::Ptr mActor; public: bool mCommanded; + CheckActorCommanded(const MWWorld::Ptr& actor) : mActor(actor) - , mCommanded(false){} + , mCommanded(false){} - virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, + virtual void visit (MWMechanics::EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, float magnitude, float remainingTime = -1, float totalTime = -1) { if (((key.mId == ESM::MagicEffect::CommandHumanoid && mActor.getClass().isNpc()) @@ -156,8 +157,8 @@ namespace MWMechanics GetStuntedMagickaDuration(const MWWorld::Ptr& actor) : mRemainingTime(0.f){} - virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, + virtual void visit (MWMechanics::EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, float magnitude, float remainingTime = -1, float totalTime = -1) { if (mRemainingTime == -1) return; @@ -186,8 +187,8 @@ namespace MWMechanics { } - virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, + virtual void visit (MWMechanics::EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, float magnitude, float remainingTime = -1, float totalTime = -1) { if (magnitude <= 0) @@ -206,8 +207,8 @@ namespace MWMechanics { public: - virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, + virtual void visit (MWMechanics::EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, float magnitude, float remainingTime = -1, float totalTime = -1) { if (key.mId != ESM::MagicEffect::Corprus) @@ -231,8 +232,8 @@ namespace MWMechanics { } - virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, + virtual void visit (MWMechanics::EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, float magnitude, float remainingTime = -1, float totalTime = -1) { if (mTrapped) @@ -894,7 +895,7 @@ namespace MWMechanics { } - virtual void visit (MWMechanics::EffectKey key, + virtual void visit (MWMechanics::EffectKey key, int /*effectIndex*/, const std::string& /*sourceName*/, const std::string& /*sourceId*/, int /*casterActorId*/, float magnitude, float remainingTime = -1, float /*totalTime*/ = -1) { @@ -1196,6 +1197,7 @@ namespace MWMechanics { UpdateSummonedCreatures updateSummonedCreatures(ptr); creatureStats.getActiveSpells().visitEffectSources(updateSummonedCreatures); + creatureStats.getSpells().visitEffectSources(updateSummonedCreatures); if (ptr.getClass().hasInventoryStore(ptr)) ptr.getClass().getInventoryStore(ptr).visitEffectSources(updateSummonedCreatures); updateSummonedCreatures.process(mTimerDisposeSummonsCorpses == 0.f); diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 5e91a1b5a..9a1996ddb 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -84,7 +84,7 @@ namespace MWMechanics float mSideMovementAngle; public: - typedef std::pair SummonKey; // + typedef std::tuple SummonKey; // private: std::map mSummonedCreatures; // diff --git a/apps/openmw/mwmechanics/linkedeffects.cpp b/apps/openmw/mwmechanics/linkedeffects.cpp index 364358433..b0defac7d 100644 --- a/apps/openmw/mwmechanics/linkedeffects.cpp +++ b/apps/openmw/mwmechanics/linkedeffects.cpp @@ -58,6 +58,7 @@ namespace MWMechanics std::vector absorbEffects; ActiveSpells::ActiveEffect absorbEffect = appliedEffect; absorbEffect.mMagnitude *= -1; + absorbEffect.mEffectIndex = appliedEffect.mEffectIndex; absorbEffects.emplace_back(absorbEffect); // Morrowind negates reflected Absorb spells so the original caster won't be harmed. diff --git a/apps/openmw/mwmechanics/magiceffects.hpp b/apps/openmw/mwmechanics/magiceffects.hpp index 86f5a1804..12735a87f 100644 --- a/apps/openmw/mwmechanics/magiceffects.hpp +++ b/apps/openmw/mwmechanics/magiceffects.hpp @@ -74,8 +74,8 @@ namespace MWMechanics { virtual ~EffectSourceVisitor() { } - virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, + virtual void visit (EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, float magnitude, float remainingTime = -1, float totalTime = -1) = 0; }; diff --git a/apps/openmw/mwmechanics/spellabsorption.cpp b/apps/openmw/mwmechanics/spellabsorption.cpp index f38fd78e2..f22cef3f6 100644 --- a/apps/openmw/mwmechanics/spellabsorption.cpp +++ b/apps/openmw/mwmechanics/spellabsorption.cpp @@ -23,8 +23,8 @@ namespace MWMechanics GetAbsorptionProbability() = default; - virtual void visit (MWMechanics::EffectKey key, - const std::string& /*sourceName*/, const std::string& /*sourceId*/, int /*casterActorId*/, + virtual void visit (MWMechanics::EffectKey key, int /*effectIndex*/, + const std::string& /*sourceName*/, const std::string& /*sourceId*/, int /*casterActorId*/, float magnitude, float /*remainingTime*/, float /*totalTime*/) { if (key.mId == ESM::MagicEffect::SpellAbsorption) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 9f7108239..fb195bb6d 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -121,8 +121,9 @@ namespace MWMechanics // Try absorbing the spell. Some handling must still happen for absorbed effects. bool absorbed = absorbSpell(spell, caster, target); + int currentEffectIndex = 0; for (std::vector::const_iterator effectIt (effects.mList.begin()); - !target.isEmpty() && effectIt != effects.mList.end(); ++effectIt) + !target.isEmpty() && effectIt != effects.mList.end(); ++effectIt, ++currentEffectIndex) { if (effectIt->mRange != range) continue; @@ -189,6 +190,7 @@ namespace MWMechanics effect.mArg = MWMechanics::EffectKey(*effectIt).mArg; effect.mMagnitude = magnitude; effect.mTimeLeft = 0.f; + effect.mEffectIndex = currentEffectIndex; // Avoid applying absorb effects if the caster is the target // We still need the spell to be added @@ -268,7 +270,7 @@ namespace MWMechanics if (isSummoningEffect(effectIt->mEffectID) && !target.isEmpty() && target.getClass().isActor()) { CreatureStats& targetStats = target.getClass().getCreatureStats(target); - std::map::iterator findCreature = targetStats.getSummonedCreatureMap().find(std::make_pair(effectIt->mEffectID, mId)); + std::map::iterator findCreature = targetStats.getSummonedCreatureMap().find(std::make_tuple(effectIt->mEffectID, mId, currentEffectIndex)); if (findCreature != targetStats.getSummonedCreatureMap().end()) { MWBase::Environment::get().getMechanicsManager()->cleanupSummonedCreature(target, findCreature->second); diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index a66c267cc..d292c015d 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -50,7 +50,10 @@ namespace MWMechanics for (const auto& effect : spell->mEffects.mList) { if (iter.second.mPurgedEffects.find(i) != iter.second.mPurgedEffects.end()) + { + ++i; continue; // effect was purged + } float random = 1.f; if (iter.second.mEffectRands.find(i) != iter.second.mEffectRands.end()) @@ -108,7 +111,7 @@ namespace MWMechanics SpellParams params; params.mEffectRands = random; - mSpells.insert (std::make_pair (spell, params)); + mSpells.emplace(spell, params); mSpellsChanged = true; } } @@ -272,7 +275,8 @@ namespace MWMechanics const ESM::Spell * spell = it.first; for (const auto& effectIt : it.second) { - visitor.visit(effectIt.first, spell->mName, spell->mId, -1, effectIt.second.getMagnitude()); + // FIXME: since Spells merges effects with the same ID, there is no sense to use multiple effects with same ID here + visitor.visit(effectIt.first, -1, spell->mName, spell->mId, -1, effectIt.second.getMagnitude()); } } } @@ -308,20 +312,24 @@ namespace MWMechanics void Spells::purgeEffect(int effectId, const std::string & sourceId) { - const ESM::Spell * spell = SpellList::getSpell(sourceId); + // Effect source may be not a spell + const ESM::Spell * spell = MWBase::Environment::get().getWorld()->getStore().get().search(sourceId); + if (spell == nullptr) + return; + auto spellIt = mSpells.find(spell); if (spellIt == mSpells.end()) return; - int i = 0; + int index = 0; for (auto& effectIt : spellIt->first->mEffects.mList) { if (effectIt.mEffectID == effectId) { - spellIt->second.mPurgedEffects.insert(i); + spellIt->second.mPurgedEffects.insert(index); mSpellsChanged = true; } - ++i; + ++index; } } @@ -441,7 +449,7 @@ namespace MWMechanics 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.mSpells.emplace(it.first->mId, params); } } diff --git a/apps/openmw/mwmechanics/summoning.cpp b/apps/openmw/mwmechanics/summoning.cpp index 03fd0d681..acb58ea8e 100644 --- a/apps/openmw/mwmechanics/summoning.cpp +++ b/apps/openmw/mwmechanics/summoning.cpp @@ -65,11 +65,11 @@ namespace MWMechanics { } - void UpdateSummonedCreatures::visit(EffectKey key, const std::string &sourceName, const std::string &sourceId, int casterActorId, float magnitude, float remainingTime, float totalTime) + void UpdateSummonedCreatures::visit(EffectKey key, int effectIndex, const std::string &sourceName, const std::string &sourceId, int casterActorId, float magnitude, float remainingTime, float totalTime) { if (isSummoningEffect(key.mId) && magnitude > 0) { - mActiveEffects.insert(std::make_pair(key.mId, sourceId)); + mActiveEffects.insert(std::make_tuple(key.mId, sourceId, effectIndex)); } } @@ -78,12 +78,12 @@ namespace MWMechanics MWMechanics::CreatureStats& creatureStats = mActor.getClass().getCreatureStats(mActor); std::map& creatureMap = creatureStats.getSummonedCreatureMap(); - for (std::set >::iterator it = mActiveEffects.begin(); it != mActiveEffects.end(); ++it) + for (std::set::iterator it = mActiveEffects.begin(); it != mActiveEffects.end(); ++it) { - bool found = creatureMap.find(std::make_pair(it->first, it->second)) != creatureMap.end(); + bool found = creatureMap.find(*it) != creatureMap.end(); if (!found) { - std::string creatureID = getSummonedCreature(it->first); + std::string creatureID = getSummonedCreature(std::get<0>(*it)); if (!creatureID.empty()) { int creatureActorId = -1; @@ -115,7 +115,7 @@ namespace MWMechanics // still insert into creatureMap so we don't try to spawn again every frame, that would spam the warning log } - creatureMap.insert(std::make_pair(*it, creatureActorId)); + creatureMap.emplace(*it, creatureActorId); } } } @@ -149,9 +149,10 @@ namespace MWMechanics if (ptr.isEmpty() || (ptr.getClass().getCreatureStats(ptr).isDead() && ptr.getClass().getCreatureStats(ptr).isDeathAnimationFinished())) { // Purge the magic effect so a new creature can be summoned if desired - creatureStats.getActiveSpells().purgeEffect(it->first.first, it->first.second); + creatureStats.getActiveSpells().purgeEffect(std::get<0>(it->first), std::get<1>(it->first), std::get<2>(it->first)); + creatureStats.getSpells().purgeEffect(std::get<0>(it->first), std::get<1>(it->first)); if (mActor.getClass().hasInventoryStore(mActor)) - mActor.getClass().getInventoryStore(mActor).purgeEffect(it->first.first, it->first.second); + mActor.getClass().getInventoryStore(mActor).purgeEffect(std::get<0>(it->first), std::get<1>(it->first), false, std::get<2>(it->first)); MWBase::Environment::get().getMechanicsManager()->cleanupSummonedCreature(mActor, it->second); creatureMap.erase(it++); diff --git a/apps/openmw/mwmechanics/summoning.hpp b/apps/openmw/mwmechanics/summoning.hpp index f24413120..78a1969a9 100644 --- a/apps/openmw/mwmechanics/summoning.hpp +++ b/apps/openmw/mwmechanics/summoning.hpp @@ -20,8 +20,8 @@ namespace MWMechanics UpdateSummonedCreatures(const MWWorld::Ptr& actor); virtual ~UpdateSummonedCreatures() = default; - virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, + virtual void visit (MWMechanics::EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, float magnitude, float remainingTime = -1, float totalTime = -1); /// To call after all effect sources have been visited @@ -30,7 +30,7 @@ namespace MWMechanics private: MWWorld::Ptr mActor; - std::set > mActiveEffects; + std::set> mActiveEffects; }; } diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index ada211470..d67a22884 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -917,7 +917,7 @@ void MWWorld::InventoryStore::visitEffectSources(MWMechanics::EffectSourceVisito float magnitude = effect.mMagnMin + (effect.mMagnMax - effect.mMagnMin) * params.mRandom; magnitude *= params.mMultiplier; if (magnitude > 0) - visitor.visit(MWMechanics::EffectKey(effect), (**iter).getClass().getName(**iter), (**iter).getCellRef().getRefId(), -1, magnitude); + visitor.visit(MWMechanics::EffectKey(effect), i-1, (**iter).getClass().getName(**iter), (**iter).getCellRef().getRefId(), -1, magnitude); } } } @@ -931,7 +931,7 @@ void MWWorld::InventoryStore::purgeEffect(short effectId, bool wholeSpell) } } -void MWWorld::InventoryStore::purgeEffect(short effectId, const std::string &sourceId, bool wholeSpell) +void MWWorld::InventoryStore::purgeEffect(short effectId, const std::string &sourceId, bool wholeSpell, int effectIndex) { TEffectMagnitudes::iterator effectMagnitudeIt = mPermanentMagicEffectMagnitudes.find(sourceId); if (effectMagnitudeIt == mPermanentMagicEffectMagnitudes.end()) @@ -964,6 +964,9 @@ void MWWorld::InventoryStore::purgeEffect(short effectId, const std::string &sou if (effectIt->mEffectID != effectId) continue; + if (effectIndex >= 0 && effectIndex != i) + continue; + if (wholeSpell) { mPermanentMagicEffectMagnitudes.erase(sourceId); diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index d597e5f30..97ca931e7 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -206,7 +206,7 @@ namespace MWWorld void purgeEffect (short effectId, bool wholeSpell = false); ///< Remove a magic effect - void purgeEffect (short effectId, const std::string& sourceId, bool wholeSpell = false); + void purgeEffect (short effectId, const std::string& sourceId, bool wholeSpell = false, int effectIndex=-1); ///< Remove a magic effect virtual void clear(); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index dafd84388..265a7663c 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -3119,7 +3119,7 @@ namespace MWWorld { } - virtual void visit (MWMechanics::EffectKey key, + virtual void visit (MWMechanics::EffectKey key, int /*effectIndex*/, const std::string& /*sourceName*/, const std::string& /*sourceId*/, int /*casterActorId*/, float /*magnitude*/, float /*remainingTime*/ = -1, float /*totalTime*/ = -1) { diff --git a/components/esm/activespells.cpp b/components/esm/activespells.cpp index 46558ceb7..4017a4933 100644 --- a/components/esm/activespells.cpp +++ b/components/esm/activespells.cpp @@ -24,6 +24,7 @@ namespace ESM esm.writeHNT ("ARG_", effectIt->mArg); esm.writeHNT ("MAGN", effectIt->mMagnitude); esm.writeHNT ("DURA", effectIt->mDuration); + esm.writeHNT ("EIND", effectIt->mEffectIndex); esm.writeHNT ("LEFT", effectIt->mTimeLeft); } } @@ -53,6 +54,8 @@ namespace ESM esm.getHNOT(effect.mArg, "ARG_"); esm.getHNT (effect.mMagnitude, "MAGN"); esm.getHNT (effect.mDuration, "DURA"); + effect.mEffectIndex = -1; + esm.getHNOT (effect.mEffectIndex, "EIND"); if (format < 9) effect.mTimeLeft = effect.mDuration; else diff --git a/components/esm/activespells.hpp b/components/esm/activespells.hpp index 20b2f652d..1b7f8b319 100644 --- a/components/esm/activespells.hpp +++ b/components/esm/activespells.hpp @@ -22,6 +22,7 @@ namespace ESM int mArg; // skill or attribute float mDuration; float mTimeLeft; + int mEffectIndex; }; // format 0, saved games only diff --git a/components/esm/creaturestats.cpp b/components/esm/creaturestats.cpp index 6f0b36f8d..4ffe567c6 100644 --- a/components/esm/creaturestats.cpp +++ b/components/esm/creaturestats.cpp @@ -115,9 +115,11 @@ void ESM::CreatureStats::load (ESMReader &esm) int magicEffect; esm.getHT(magicEffect); std::string source = esm.getHNOString("SOUR"); + int effectIndex = -1; + esm.getHNOT (effectIndex, "EIND"); int actorId; esm.getHNT (actorId, "ACID"); - mSummonedCreatureMap[std::make_pair(magicEffect, source)] = actorId; + mSummonedCreatureMap[std::make_tuple(magicEffect, source, effectIndex)] = actorId; } while (esm.isNextSub("GRAV")) @@ -212,10 +214,13 @@ void ESM::CreatureStats::save (ESMWriter &esm) const mAiSequence.save(esm); mMagicEffects.save(esm); - for (std::map, int>::const_iterator it = mSummonedCreatureMap.begin(); it != mSummonedCreatureMap.end(); ++it) + for (std::map, int>::const_iterator it = mSummonedCreatureMap.begin(); it != mSummonedCreatureMap.end(); ++it) { - esm.writeHNT ("SUMM", it->first.first); - esm.writeHNString ("SOUR", it->first.second); + esm.writeHNT ("SUMM", std::get<0>(it->first)); + esm.writeHNString ("SOUR", std::get<1>(it->first)); + int effectIndex = std::get<2>(it->first); + if (effectIndex != -1) + esm.writeHNT ("EIND", effectIndex); esm.writeHNT ("ACID", it->second); } diff --git a/components/esm/creaturestats.hpp b/components/esm/creaturestats.hpp index 79a576587..e79d430ce 100644 --- a/components/esm/creaturestats.hpp +++ b/components/esm/creaturestats.hpp @@ -39,7 +39,7 @@ namespace ESM bool mHasAiSettings; StatState mAiSettings[4]; - std::map, int> mSummonedCreatureMap; + std::map, int> mSummonedCreatureMap; std::vector mSummonGraveyard; ESM::TimeStamp mTradeTime; diff --git a/components/esm/savedgame.cpp b/components/esm/savedgame.cpp index 4b0529703..0fc84e309 100644 --- a/components/esm/savedgame.cpp +++ b/components/esm/savedgame.cpp @@ -4,7 +4,7 @@ #include "esmwriter.hpp" unsigned int ESM::SavedGame::sRecordId = ESM::REC_SAVE; -int ESM::SavedGame::sCurrentFormat = 13; +int ESM::SavedGame::sCurrentFormat = 14; void ESM::SavedGame::load (ESMReader &esm) {