diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 72f0cddff..6b1707218 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -980,8 +980,10 @@ namespace MWMechanics if (charge == 0) return false; - // FIXME: charge should be a float, not int so that damage < 1 per frame can be applied. - // This was also a bug in the original engine. + // Store remainder of disintegrate amount (automatically subtracted if > 1) + item->getCellRef().applyChargeRemainderToBeSubtracted(disintegrate - std::floor(disintegrate)); + + charge = item->getClass().getItemHealth(*item); charge -= std::min(static_cast(disintegrate), charge); diff --git a/apps/openmw/mwworld/cellref.cpp b/apps/openmw/mwworld/cellref.cpp index 0d81e0636..9180e9e20 100644 --- a/apps/openmw/mwworld/cellref.cpp +++ b/apps/openmw/mwworld/cellref.cpp @@ -93,6 +93,25 @@ namespace MWWorld } } + void CellRef::applyChargeRemainderToBeSubtracted(float chargeRemainder) + { + mCellRef.mChargeIntRemainder += std::abs(chargeRemainder); + if (mCellRef.mChargeIntRemainder > 1.0f) + { + float newChargeRemainder = (mCellRef.mChargeIntRemainder - std::floor(mCellRef.mChargeIntRemainder)); + if (mCellRef.mChargeInt <= static_cast(mCellRef.mChargeIntRemainder)) + { + mCellRef.mChargeInt = 0; + } + else + { + mCellRef.mChargeInt -= static_cast(mCellRef.mChargeIntRemainder); + } + + mCellRef.mChargeIntRemainder = newChargeRemainder; + } + } + float CellRef::getChargeFloat() const { return mCellRef.mChargeFloat; diff --git a/apps/openmw/mwworld/cellref.hpp b/apps/openmw/mwworld/cellref.hpp index b8e85f286..c8c4529e9 100644 --- a/apps/openmw/mwworld/cellref.hpp +++ b/apps/openmw/mwworld/cellref.hpp @@ -65,6 +65,7 @@ namespace MWWorld float getChargeFloat() const; // Implemented as union with int charge void setCharge(int charge); void setChargeFloat(float charge); + void applyChargeRemainderToBeSubtracted(float chargeRemainder); // The NPC that owns this object (and will get angry if you steal it) std::string getOwner() const; diff --git a/apps/openmw/mwworld/manualref.cpp b/apps/openmw/mwworld/manualref.cpp index c683f7e03..48270d224 100644 --- a/apps/openmw/mwworld/manualref.cpp +++ b/apps/openmw/mwworld/manualref.cpp @@ -16,6 +16,7 @@ namespace cellRef.mScale = 1; cellRef.mFactionRank = 0; cellRef.mChargeInt = -1; + cellRef.mChargeIntRemainder = 0.0f; cellRef.mGoldValue = 1; cellRef.mEnchantmentCharge = -1; cellRef.mTeleport = false; diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index 74d45bb0c..e41201d6e 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -196,6 +196,7 @@ void ESM::CellRef::blank() mFaction.clear(); mFactionRank = -2; mChargeInt = -1; + mChargeIntRemainder = 0.0f; mEnchantmentCharge = -1; mGoldValue = 0; mDestCell.clear(); diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp index 3c646cc61..a3c56cf13 100644 --- a/components/esm/cellref.hpp +++ b/components/esm/cellref.hpp @@ -69,6 +69,7 @@ namespace ESM int mChargeInt; // Used by everything except lights float mChargeFloat; // Used only by lights }; + float mChargeIntRemainder; // Used by everythign except lights (amount of charge not applied to mChargeInt) // Remaining enchantment charge. This could be -1 if the charge was not touched yet (i.e. full). float mEnchantmentCharge;