summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/game-server/attribute.cpp55
-rw-r--r--src/game-server/attribute.hpp8
-rw-r--r--src/game-server/item.cpp2
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)