summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpsi29a <psi29a@gmail.com>2021-12-26 19:47:09 +0000
committerpsi29a <psi29a@gmail.com>2021-12-26 19:47:09 +0000
commit01ac96e900d72165df193184a2d887d8fd4062cc (patch)
treef43efc3549c9bf2c83d0e0e7bdddf838053b909d
parent93e355801d90e94921b050576842675931679a32 (diff)
parentf1ec8db393f5ff7bae77bf0ba16540763c5b56e9 (diff)
Merge branch 'stats_gave_me_a_headache' into 'master'
Make Set- and ModStat behave as they should Closes #2036 See merge request OpenMW/openmw!1410
-rw-r--r--CHANGELOG.md1
-rw-r--r--apps/openmw/mwmechanics/stat.cpp15
-rw-r--r--apps/openmw/mwmechanics/stat.hpp7
-rw-r--r--apps/openmw/mwscript/statsextensions.cpp47
4 files changed, 38 insertions, 32 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e4094f0ec2..78abf58a1c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@
Bug #1751: Birthsign abilities increase modified attribute values instead of base ones
Bug #1930: Followers are still fighting if a target stops combat with a leader
+ Bug #2036: SetStat and ModStat instructions aren't implemented the same way as in Morrowind
Bug #3246: ESSImporter: Most NPCs are dead on save load
Bug #3488: AI combat aiming is too slow
Bug #3514: Editing a reference's position after loading an esp file makes the reference disappear
diff --git a/apps/openmw/mwmechanics/stat.cpp b/apps/openmw/mwmechanics/stat.cpp
index c87de2ccbb..ee484f5afd 100644
--- a/apps/openmw/mwmechanics/stat.cpp
+++ b/apps/openmw/mwmechanics/stat.cpp
@@ -246,14 +246,25 @@ namespace MWMechanics
return mModifier;
}
- void AttributeValue::setBase(float base)
+ void AttributeValue::setBase(float base, bool clearModifier)
{
mBase = base;
+ if(clearModifier)
+ {
+ mModifier = 0.f;
+ mDamage = 0.f;
+ }
}
void AttributeValue::setModifier(float mod)
{
- mModifier = mod;
+ if(mod < 0)
+ {
+ mModifier = 0.f;
+ mDamage -= mod;
+ }
+ else
+ mModifier = mod;
}
void AttributeValue::damage(float damage)
diff --git a/apps/openmw/mwmechanics/stat.hpp b/apps/openmw/mwmechanics/stat.hpp
index fb9dca9221..c80c5b1b70 100644
--- a/apps/openmw/mwmechanics/stat.hpp
+++ b/apps/openmw/mwmechanics/stat.hpp
@@ -133,13 +133,14 @@ namespace MWMechanics
float getBase() const;
float getModifier() const;
- void setBase(float base);
+ void setBase(float base, bool clearModifier = false);
void setModifier(float mod);
// Maximum attribute damage is limited to the modified value.
- // Note: I think MW applies damage directly to mModified, since you can also
- // "restore" drained attributes. We need to rewrite the magic effect system to support this.
+ // Note: MW applies damage directly to mModified, however it does track how much
+ // a damaged attribute that has been fortified beyond its base can be restored.
+ // Getting rid of mDamage would require calculating its value by ignoring active effects when restoring
void damage(float damage);
void restore(float amount);
diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp
index d7120af53a..186d1edf26 100644
--- a/apps/openmw/mwscript/statsextensions.cpp
+++ b/apps/openmw/mwscript/statsextensions.cpp
@@ -40,6 +40,22 @@ namespace
return factionId;
}
+
+ void modStat(MWMechanics::AttributeValue& stat, float amount)
+ {
+ float base = stat.getBase();
+ float modifier = stat.getModifier() - stat.getDamage();
+ float modified = base + modifier;
+ if(modified <= 0.f && amount < 0.f)
+ amount = 0.f;
+ else if(amount < 0.f && modified + amount < 0.f)
+ amount = -modified;
+ else if((modifier <= 0.f || base >= 100.f) && amount > 0.f)
+ amount = std::clamp(100.f - modified, 0.f, amount);
+ stat.setBase(std::min(base + amount, 100.f), true);
+ modifier += base - stat.getBase() + amount;
+ stat.setModifier(modifier);
+ }
}
namespace MWScript
@@ -122,7 +138,7 @@ namespace MWScript
runtime.pop();
MWMechanics::AttributeValue attribute = ptr.getClass().getCreatureStats(ptr).getAttribute(mIndex);
- attribute.setBase (value);
+ attribute.setBase(value, true);
ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute);
}
};
@@ -146,19 +162,7 @@ namespace MWScript
MWMechanics::AttributeValue attribute = ptr.getClass()
.getCreatureStats(ptr)
.getAttribute(mIndex);
-
- if (value == 0)
- return;
-
- if (((attribute.getBase() <= 0) && (value < 0))
- || ((attribute.getBase() >= 100) && (value > 0)))
- return;
-
- if (value < 0)
- attribute.setBase(std::max(0.f, attribute.getBase() + value));
- else
- attribute.setBase(std::min(100.f, attribute.getBase() + value));
-
+ modStat(attribute, value);
ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute);
}
};
@@ -372,7 +376,7 @@ namespace MWScript
MWMechanics::NpcStats& stats = ptr.getClass().getNpcStats (ptr);
- stats.getSkill (mIndex).setBase (value);
+ stats.getSkill(mIndex).setBase(value, true);
}
};
@@ -395,18 +399,7 @@ namespace MWScript
MWMechanics::SkillValue &skill = ptr.getClass()
.getNpcStats(ptr)
.getSkill(mIndex);
-
- if (value == 0)
- return;
-
- if (((skill.getBase() <= 0.f) && (value < 0.f))
- || ((skill.getBase() >= 100.f) && (value > 0.f)))
- return;
-
- if (value < 0)
- skill.setBase(std::max(0.f, skill.getBase() + value));
- else
- skill.setBase(std::min(100.f, skill.getBase() + value));
+ modStat(skill, value);
}
};