1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-27 12:35:46 +00:00

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
This commit is contained in:
psi29a 2021-12-26 19:47:09 +00:00
commit 01ac96e900
4 changed files with 38 additions and 32 deletions

View File

@ -3,6 +3,7 @@
Bug #1751: Birthsign abilities increase modified attribute values instead of base ones 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 #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 #3246: ESSImporter: Most NPCs are dead on save load
Bug #3488: AI combat aiming is too slow Bug #3488: AI combat aiming is too slow
Bug #3514: Editing a reference's position after loading an esp file makes the reference disappear Bug #3514: Editing a reference's position after loading an esp file makes the reference disappear

View File

@ -246,14 +246,25 @@ namespace MWMechanics
return mModifier; return mModifier;
} }
void AttributeValue::setBase(float base) void AttributeValue::setBase(float base, bool clearModifier)
{ {
mBase = base; mBase = base;
if(clearModifier)
{
mModifier = 0.f;
mDamage = 0.f;
}
} }
void AttributeValue::setModifier(float mod) void AttributeValue::setModifier(float mod)
{ {
mModifier = mod; if(mod < 0)
{
mModifier = 0.f;
mDamage -= mod;
}
else
mModifier = mod;
} }
void AttributeValue::damage(float damage) void AttributeValue::damage(float damage)

View File

@ -133,13 +133,14 @@ namespace MWMechanics
float getBase() const; float getBase() const;
float getModifier() const; float getModifier() const;
void setBase(float base); void setBase(float base, bool clearModifier = false);
void setModifier(float mod); void setModifier(float mod);
// Maximum attribute damage is limited to the modified value. // Maximum attribute damage is limited to the modified value.
// Note: I think MW applies damage directly to mModified, since you can also // Note: MW applies damage directly to mModified, however it does track how much
// "restore" drained attributes. We need to rewrite the magic effect system to support this. // 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 damage(float damage);
void restore(float amount); void restore(float amount);

View File

@ -40,6 +40,22 @@ namespace
return factionId; 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 namespace MWScript
@ -122,7 +138,7 @@ namespace MWScript
runtime.pop(); runtime.pop();
MWMechanics::AttributeValue attribute = ptr.getClass().getCreatureStats(ptr).getAttribute(mIndex); MWMechanics::AttributeValue attribute = ptr.getClass().getCreatureStats(ptr).getAttribute(mIndex);
attribute.setBase (value); attribute.setBase(value, true);
ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute); ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute);
} }
}; };
@ -146,19 +162,7 @@ namespace MWScript
MWMechanics::AttributeValue attribute = ptr.getClass() MWMechanics::AttributeValue attribute = ptr.getClass()
.getCreatureStats(ptr) .getCreatureStats(ptr)
.getAttribute(mIndex); .getAttribute(mIndex);
modStat(attribute, value);
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));
ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute); ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute);
} }
}; };
@ -372,7 +376,7 @@ namespace MWScript
MWMechanics::NpcStats& stats = ptr.getClass().getNpcStats (ptr); 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() MWMechanics::SkillValue &skill = ptr.getClass()
.getNpcStats(ptr) .getNpcStats(ptr)
.getSkill(mIndex); .getSkill(mIndex);
modStat(skill, value);
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));
} }
}; };