diff options
-rw-r--r-- | src/game-server/attribute.cpp | 55 | ||||
-rw-r--r-- | src/game-server/attribute.hpp | 8 | ||||
-rw-r--r-- | src/game-server/item.cpp | 2 |
3 files changed, 48 insertions, 17 deletions
diff --git a/src/game-server/attribute.cpp b/src/game-server/attribute.cpp index 0feb1fd0..c7bc43d2 100644 --- a/src/game-server/attribute.cpp +++ b/src/game-server/attribute.cpp @@ -125,21 +125,35 @@ bool AttributeModifiersEffect::remove(double value, unsigned int id, bool fullCh if (!fullCheck) mStates.sort(durationCompare); /* Search only through those with a duration of 0. */ bool ret = false; + double temp; for (std::list< AttributeModifierState * >::iterator it = mStates.begin(); - it != mStates.end() && (fullCheck || !(*it)->mDuration); - ++it) + it != mStates.end() && (fullCheck || !(*it)->mDuration);) { /* Check for a match */ if ((*it)->mValue != value || (*it)->mId != id) + { + ++it; continue; + } + + temp = (*it)->mValue; + + delete *it; + mStates.erase(it++); + + /* If this is stackable, we need to update for every modifier affected */ if (mSType == TY_ST) updateMod(); - delete *it; - mStates.erase(it); + + ret = true; if (!id) - return true; - else ret = true; + break; } + /* + * Non stackables only need to be updated once, since this is recomputed + * from scratch. This is done at the end after modifications have been + * made as necessary. + */ if (ret && mSType != TY_ST) updateMod(); return ret; @@ -152,7 +166,20 @@ void AttributeModifiersEffect::updateMod(double value) if (mEType == AME_ADD) mMod -= value; else if (mEType == AME_MULT) - mMod /= value; + { + if (value) + mMod /= value; + else + { + mMod = 1; + for (std::list< AttributeModifierState * >::const_iterator + it = mStates.begin(), + it_end = mStates.end(); + it != it_end; + ++it) + mMod *= (*it)->mValue; + } + } else LOG_ERROR("Attribute modifiers effect: unhandled type '" << mEType << "' as a stackable in cache update!"); } @@ -162,15 +189,13 @@ void AttributeModifiersEffect::updateMod(double value) { mMod = 0; for (std::list< AttributeModifierState * >::const_iterator - it2 = mStates.begin(), - it2_end = mStates.end(); - it2 != it2_end; - ++it2) - if ((*it2)->mValue > mMod) - mMod = (*it2)->mValue; + it = mStates.begin(), + it_end = mStates.end(); + it != it_end; + ++it) + if ((*it)->mValue > mMod) + mMod = (*it)->mValue; } - else LOG_ERROR("Attribute modifiers effect: unhandled type '" - << mEType << "' as a non-stackable in cache update!"); } else LOG_ERROR("Attribute modifiers effect: unknown modifier type '" << mSType << "' in cache update!"); diff --git a/src/game-server/attribute.hpp b/src/game-server/attribute.hpp index c5f833f0..e0696a4c 100644 --- a/src/game-server/attribute.hpp +++ b/src/game-server/attribute.hpp @@ -71,8 +71,14 @@ class AttributeModifiersEffect { /** * Performs the necessary modifications to mMod when the states change. + * @param value The value to alter. This is only used in stackable + * types, as the effect can be simply inverted there. + * For non stackable types (and stackable multiplicative types + * where the value is zero), mMod must be recalculated from all + * current modifiers. + * @note This /negates/ the effect of value. + * @note A parameter should always be provided when stackable. */ - void updateMod(double value = 0); /** diff --git a/src/game-server/item.cpp b/src/game-server/item.cpp index 35684470..a2b481d5 100644 --- a/src/game-server/item.cpp +++ b/src/game-server/item.cpp @@ -49,7 +49,7 @@ void ItemEffectAttrMod::dispell(Being *itemUser) { LOG_DEBUG("Dispelling modifier."); itemUser->removeModifier(mAttributeId, mMod, mAttributeLayer, - mId, mDuration); + mId, !mDuration); } bool ItemEffectAutoAttack::apply(Being *itemUser) |