summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpsi29a <psi29a@gmail.com>2022-01-04 10:27:48 +0000
committerpsi29a <psi29a@gmail.com>2022-01-04 10:27:48 +0000
commit0766e1310b899d4323ccfd704c1d0fcb2b9148c0 (patch)
tree20d17fd60ca21e3926aefcbe8ef282f7fbe9f9f8
parente16245278e7ebd9325087cec883df78914b383d3 (diff)
parentdebdcf29539d0ed9edecdb87aa07bf3e6979fa31 (diff)
Merge branch 'lunacy' into 'master'
Don't touch base stats when turning into a werewolf Closes #6333 See merge request OpenMW/openmw!1511
-rw-r--r--CHANGELOG.md1
-rw-r--r--apps/openmw/mwmechanics/mechanicsmanagerimp.cpp4
-rw-r--r--apps/openmw/mwworld/player.cpp63
-rw-r--r--apps/openmw/mwworld/player.hpp4
-rw-r--r--components/esm/player.cpp48
-rw-r--r--components/esm/player.hpp5
-rw-r--r--components/esm/savedgame.cpp2
7 files changed, 83 insertions, 44 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 02d86f8802..419727c87d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -77,6 +77,7 @@
Bug #6324: Special Slave Companions: Can't buy the slave companions
Bug #6326: Detect Enchantment/Key should detect items in unresolved containers
Bug #6327: Blocking roots the character in place
+ Bug #6333: Werewolf stat changes should be implemented as damage/fortifications
Bug #6343: Magic projectile speed doesn't take race weight into account
Bug #6347: PlaceItem/PlaceItemCell/PlaceAt should work with levelled creatures
Bug #6354: SFX abruptly cut off after crossing max distance; implement soft fading of sound effects
diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp
index fa5aaa82ef..e0d2da497b 100644
--- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp
+++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp
@@ -1865,8 +1865,8 @@ namespace MWMechanics
{
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
MWMechanics::NpcStats &stats = actor.getClass().getNpcStats(actor);
-
- stats.getSkill(ESM::Skill::Acrobatics).setBase(gmst.find("fWerewolfAcrobatics")->mValue.getInteger());
+ auto& skill = stats.getSkill(ESM::Skill::Acrobatics);
+ skill.setModifier(gmst.find("fWerewolfAcrobatics")->mValue.getFloat() - skill.getModified());
}
void MechanicsManager::cleanupSummonedCreature(const MWWorld::Ptr &caster, int creatureActorId)
diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp
index 4687a4eddd..270889a23e 100644
--- a/apps/openmw/mwworld/player.cpp
+++ b/apps/openmw/mwworld/player.cpp
@@ -58,9 +58,9 @@ namespace MWWorld
MWMechanics::NpcStats& stats = getPlayer().getClass().getNpcStats(getPlayer());
for (int i=0; i<ESM::Skill::Length; ++i)
- mSaveSkills[i] = stats.getSkill(i);
+ mSaveSkills[i] = stats.getSkill(i).getModified();
for (int i=0; i<ESM::Attribute::Length; ++i)
- mSaveAttributes[i] = stats.getAttribute(i);
+ mSaveAttributes[i] = stats.getAttribute(i).getModified();
}
void Player::restoreStats()
@@ -69,11 +69,20 @@ namespace MWWorld
MWMechanics::CreatureStats& creatureStats = getPlayer().getClass().getCreatureStats(getPlayer());
MWMechanics::NpcStats& npcStats = getPlayer().getClass().getNpcStats(getPlayer());
MWMechanics::DynamicStat<float> health = creatureStats.getDynamic(0);
- creatureStats.setHealth(int(health.getBase() / gmst.find("fWereWolfHealth")->mValue.getFloat()));
+ creatureStats.setHealth(health.getBase() / gmst.find("fWereWolfHealth")->mValue.getFloat());
for (int i=0; i<ESM::Skill::Length; ++i)
- npcStats.setSkill(i, mSaveSkills[i]);
+ {
+ auto& skill = npcStats.getSkill(i);
+ skill.restore(skill.getDamage());
+ skill.setModifier(mSaveSkills[i] - skill.getBase());
+ }
for (int i=0; i<ESM::Attribute::Length; ++i)
- npcStats.setAttribute(i, mSaveAttributes[i]);
+ {
+ auto attribute = npcStats.getAttribute(i);
+ attribute.restore(attribute.getDamage());
+ attribute.setModifier(mSaveAttributes[i] - attribute.getBase());
+ npcStats.setAttribute(i, attribute);
+ }
}
void Player::setWerewolfStats()
@@ -82,7 +91,7 @@ namespace MWWorld
MWMechanics::CreatureStats& creatureStats = getPlayer().getClass().getCreatureStats(getPlayer());
MWMechanics::NpcStats& npcStats = getPlayer().getClass().getNpcStats(getPlayer());
MWMechanics::DynamicStat<float> health = creatureStats.getDynamic(0);
- creatureStats.setHealth(int(health.getBase() * gmst.find("fWereWolfHealth")->mValue.getFloat()));
+ creatureStats.setHealth(health.getBase() * gmst.find("fWereWolfHealth")->mValue.getFloat());
for(size_t i = 0;i < ESM::Attribute::Length;++i)
{
// Oh, Bethesda. It's "Intelligence".
@@ -90,7 +99,7 @@ namespace MWWorld
ESM::Attribute::sAttributeNames[i]);
MWMechanics::AttributeValue value = npcStats.getAttribute(i);
- value.setBase(int(gmst.find(name)->mValue.getFloat()));
+ value.setModifier(gmst.find(name)->mValue.getFloat() - value.getModified());
npcStats.setAttribute(i, value);
}
@@ -104,9 +113,8 @@ namespace MWWorld
std::string name = "fWerewolf"+((i==ESM::Skill::Mercantile) ? std::string("Merchantile") :
ESM::Skill::sSkillNames[i]);
- MWMechanics::SkillValue value = npcStats.getSkill(i);
- value.setBase(int(gmst.find(name)->mValue.getFloat()));
- npcStats.setSkill(i, value);
+ MWMechanics::SkillValue& value = npcStats.getSkill(i);
+ value.setModifier(gmst.find(name)->mValue.getFloat() - value.getModified());
}
}
@@ -316,14 +324,12 @@ namespace MWWorld
for (int i=0; i<ESM::Skill::Length; ++i)
{
- mSaveSkills[i].setBase(0);
- mSaveSkills[i].setModifier(0);
+ mSaveSkills[i] = 0.f;
}
for (int i=0; i<ESM::Attribute::Length; ++i)
{
- mSaveAttributes[i].setBase(0);
- mSaveAttributes[i].setModifier(0);
+ mSaveAttributes[i] = 0.f;
}
mMarkedPosition.pos[0] = 0;
@@ -360,9 +366,9 @@ namespace MWWorld
player.mHasMark = false;
for (int i=0; i<ESM::Attribute::Length; ++i)
- mSaveAttributes[i].writeState(player.mSaveAttributes[i]);
+ player.mSaveAttributes[i] = mSaveAttributes[i];
for (int i=0; i<ESM::Skill::Length; ++i)
- mSaveSkills[i].writeState(player.mSaveSkills[i]);
+ player.mSaveSkills[i] = mSaveSkills[i];
player.mPreviousItems = mPreviousItems;
@@ -384,13 +390,7 @@ namespace MWWorld
throw std::runtime_error ("invalid player state record (object state)");
}
if (reader.getFormat() < 17)
- {
convertMagicEffects(player.mObject.mCreatureStats, player.mObject.mInventory, &player.mObject.mNpcStats);
- for(std::size_t i = 0; i < ESM::Attribute::Length; ++i)
- player.mSaveAttributes[i].mMod = 0.f;
- for(std::size_t i = 0; i < ESM::Skill::Length; ++i)
- player.mSaveSkills[i].mMod = 0.f;
- }
if (!player.mObject.mEnabled)
{
@@ -401,14 +401,23 @@ namespace MWWorld
mPlayer.load (player.mObject);
for (int i=0; i<ESM::Attribute::Length; ++i)
- mSaveAttributes[i].readState(player.mSaveAttributes[i]);
+ mSaveAttributes[i] = player.mSaveAttributes[i];
for (int i=0; i<ESM::Skill::Length; ++i)
- mSaveSkills[i].readState(player.mSaveSkills[i]);
+ mSaveSkills[i] = player.mSaveSkills[i];
- if (player.mObject.mNpcStats.mWerewolfDeprecatedData && player.mObject.mNpcStats.mIsWerewolf)
+ if (player.mObject.mNpcStats.mIsWerewolf)
{
- saveStats();
- setWerewolfStats();
+ if (player.mObject.mNpcStats.mWerewolfDeprecatedData)
+ {
+ saveStats();
+ setWerewolfStats();
+ }
+ else if (reader.getFormat() < 19)
+ {
+ setWerewolfStats();
+ if (player.mSetWerewolfAcrobatics)
+ MWBase::Environment::get().getMechanicsManager()->applyWerewolfAcrobatics(getPlayer());
+ }
}
getPlayer().getClass().getCreatureStats(getPlayer()).getAiSequence().clear();
diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp
index a7e42d95e1..1a9744e8a3 100644
--- a/apps/openmw/mwworld/player.hpp
+++ b/apps/openmw/mwworld/player.hpp
@@ -53,8 +53,8 @@ namespace MWWorld
PreviousItems mPreviousItems;
// Saved stats prior to becoming a werewolf
- MWMechanics::SkillValue mSaveSkills[ESM::Skill::Length];
- MWMechanics::AttributeValue mSaveAttributes[ESM::Attribute::Length];
+ float mSaveSkills[ESM::Skill::Length];
+ float mSaveAttributes[ESM::Attribute::Length];
bool mAttackingOrSpell;
bool mJumping;
diff --git a/components/esm/player.cpp b/components/esm/player.cpp
index e2e9219e22..028a042809 100644
--- a/components/esm/player.cpp
+++ b/components/esm/player.cpp
@@ -44,13 +44,43 @@ void ESM::Player::load (ESMReader &esm)
checkPrevItems = false;
}
- bool intFallback = esm.getFormat() < 11;
- if (esm.hasMoreSubs())
+ if(esm.getFormat() < 19)
{
- for (int i=0; i<ESM::Attribute::Length; ++i)
- mSaveAttributes[i].load(esm, intFallback);
- for (int i=0; i<ESM::Skill::Length; ++i)
- mSaveSkills[i].load(esm, intFallback);
+ bool intFallback = esm.getFormat() < 11;
+ bool clearModified = esm.getFormat() < 17 && !mObject.mNpcStats.mIsWerewolf;
+ if (esm.hasMoreSubs())
+ {
+ for (int i=0; i<ESM::Attribute::Length; ++i)
+ {
+ StatState<float> attribute;
+ attribute.load(esm, intFallback);
+ if (clearModified)
+ attribute.mMod = 0.f;
+ mSaveAttributes[i] = attribute.mBase + attribute.mMod - attribute.mDamage;
+ if (mObject.mNpcStats.mIsWerewolf)
+ mObject.mCreatureStats.mAttributes[i] = attribute;
+ }
+ for (int i=0; i<ESM::Skill::Length; ++i)
+ {
+ StatState<float> skill;
+ skill.load(esm, intFallback);
+ if (clearModified)
+ skill.mMod = 0.f;
+ mSaveSkills[i] = skill.mBase + skill.mMod - skill.mDamage;
+ if (mObject.mNpcStats.mIsWerewolf)
+ {
+ if(i == ESM::Skill::Acrobatics)
+ mSetWerewolfAcrobatics = mObject.mNpcStats.mSkills[i].mBase != skill.mBase;
+ mObject.mNpcStats.mSkills[i] = skill;
+ }
+ }
+ }
+ }
+ else
+ {
+ mSetWerewolfAcrobatics = false;
+ esm.getHNT(mSaveAttributes, "WWAT");
+ esm.getHNT(mSaveSkills, "WWSK");
}
}
@@ -79,8 +109,6 @@ void ESM::Player::save (ESMWriter &esm) const
esm.writeHNString ("PREV", it->second);
}
- for (int i=0; i<ESM::Attribute::Length; ++i)
- mSaveAttributes[i].save(esm);
- for (int i=0; i<ESM::Skill::Length; ++i)
- mSaveSkills[i].save(esm);
+ esm.writeHNT("WWAT", mSaveAttributes);
+ esm.writeHNT("WWSK", mSaveSkills);
}
diff --git a/components/esm/player.hpp b/components/esm/player.hpp
index 78bd5ab6e7..bea29cf74a 100644
--- a/components/esm/player.hpp
+++ b/components/esm/player.hpp
@@ -23,6 +23,7 @@ namespace ESM
CellId mCellId;
float mLastKnownExteriorPosition[3];
unsigned char mHasMark;
+ bool mSetWerewolfAcrobatics;
ESM::Position mMarkedPosition;
CellId mMarkedCell;
std::string mBirthsign;
@@ -30,8 +31,8 @@ namespace ESM
int mCurrentCrimeId;
int mPaidCrimeId;
- StatState<float> mSaveAttributes[ESM::Attribute::Length];
- StatState<float> mSaveSkills[ESM::Skill::Length];
+ float mSaveAttributes[ESM::Attribute::Length];
+ float mSaveSkills[ESM::Skill::Length];
typedef std::map<std::string, std::string> PreviousItems; // previous equipped items, needed for bound spells
PreviousItems mPreviousItems;
diff --git a/components/esm/savedgame.cpp b/components/esm/savedgame.cpp
index 4ce0876bb8..6cecf26489 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 = 18;
+int ESM::SavedGame::sCurrentFormat = 19;
void ESM::SavedGame::load (ESMReader &esm)
{