diff --git a/apps/esmtool/esmtool.cpp b/apps/esmtool/esmtool.cpp index b23ba72f9..a18736bf2 100644 --- a/apps/esmtool/esmtool.cpp +++ b/apps/esmtool/esmtool.cpp @@ -261,7 +261,7 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info) std::cout << " Faction: '" << ref.mFaction << "'" << std::endl; std::cout << " Faction rank: '" << ref.mFactionRank << "'" << std::endl; std::cout << " Enchantment charge: '" << ref.mEnchantmentCharge << "'\n"; - std::cout << " Uses/health: '" << ref.mChargeInt << "'\n"; + std::cout << " Uses/health: '" << ref.mCharge << "'\n"; std::cout << " Gold value: '" << ref.mGoldValue << "'\n"; std::cout << " Blocked: '" << static_cast(ref.mReferenceBlocked) << "'" << std::endl; std::cout << " Deleted: " << deleted << std::endl; diff --git a/apps/essimporter/convertinventory.cpp b/apps/essimporter/convertinventory.cpp index 31272bf5a..6a31be6a3 100644 --- a/apps/essimporter/convertinventory.cpp +++ b/apps/essimporter/convertinventory.cpp @@ -12,10 +12,10 @@ namespace ESSImport { ESM::ObjectState objstate; objstate.blank(); - objstate.mRef = *it; objstate.mRef.mRefID = Misc::StringUtils::lowerCase(it->mId); objstate.mCount = std::abs(it->mCount); // restocking items have negative count in the savefile // openmw handles them differently, so no need to set any flags + objstate.mRef.mCharge = it->mCondition; state.mItems.push_back(std::make_pair(objstate, it->mRelativeEquipmentSlot)); } } diff --git a/apps/essimporter/importinventory.cpp b/apps/essimporter/importinventory.cpp index a20584ff5..2f5c3c054 100644 --- a/apps/essimporter/importinventory.cpp +++ b/apps/essimporter/importinventory.cpp @@ -45,9 +45,9 @@ namespace ESSImport // for XSOL and XCHG seen so far, but probably others too item.ESM::CellRef::loadData(esm); - int charge=-1; - esm.getHNOT(charge, "XHLT"); - item.mChargeInt = charge; + item.mCondition = -1; + // FIXME: for Lights, this is actually a float + esm.getHNOT(item.mCondition, "XHLT"); } mItems.push_back(item); diff --git a/apps/essimporter/importinventory.hpp b/apps/essimporter/importinventory.hpp index 99fed9b20..8a1594465 100644 --- a/apps/essimporter/importinventory.hpp +++ b/apps/essimporter/importinventory.hpp @@ -20,6 +20,7 @@ namespace ESSImport { std::string mId; int mCount; + int mCondition; int mRelativeEquipmentSlot; }; std::vector mItems; diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index da14bb495..eba73cf0b 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -1053,13 +1053,13 @@ namespace CSMWorld virtual QVariant get (const Record& record) const { - return record.get().mChargeInt; + return record.get().mCharge; } virtual void set (Record& record, const QVariant& data) { ESXRecordT record2 = record.get(); - record2.mChargeInt = data.toInt(); + record2.mCharge = data.toInt(); record.setModified (record2); } diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 35a21b63e..c50ad52d8 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -26,6 +26,27 @@ #include "../mwrender/actors.hpp" #include "../mwrender/renderinginterface.hpp" +namespace +{ + struct LightCustomData : public MWWorld::CustomData + { + float mTime; + ///< Time remaining + + LightCustomData(MWWorld::Ptr ptr) + { + MWWorld::LiveCellRef *ref = ptr.get(); + mTime = ref->mBase->mData.mTime; + } + ///< Constructs this CustomData from the base values for Ptr. + + virtual MWWorld::CustomData *clone() const + { + return new LightCustomData (*this); + } + }; +} + namespace MWClass { std::string Light::getId (const MWWorld::Ptr& ptr) const @@ -198,16 +219,17 @@ namespace MWClass void Light::setRemainingUsageTime (const MWWorld::Ptr& ptr, float duration) const { - ptr.getCellRef().setChargeFloat(duration); + ensureCustomData(ptr); + + float &timeRemaining = dynamic_cast (*ptr.getRefData().getCustomData()).mTime; + timeRemaining = duration; } float Light::getRemainingUsageTime (const MWWorld::Ptr& ptr) const { - MWWorld::LiveCellRef *ref = ptr.get(); - if (ptr.getCellRef().getCharge() == -1) - return ref->mBase->mData.mTime; - else - return ptr.getCellRef().getChargeFloat(); + ensureCustomData(ptr); + + return dynamic_cast (*ptr.getRefData().getCustomData()).mTime; } MWWorld::Ptr @@ -219,6 +241,12 @@ namespace MWClass return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } + void Light::ensureCustomData (const MWWorld::Ptr& ptr) const + { + if (!ptr.getRefData().getCustomData()) + ptr.getRefData().setCustomData(new LightCustomData(ptr)); + } + bool Light::canSell (const MWWorld::Ptr& item, int npcServices) const { return npcServices & ESM::NPC::Lights; @@ -254,6 +282,22 @@ namespace MWClass return std::make_pair(1,""); } + void Light::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) + const + { + ensureCustomData (ptr); + + dynamic_cast (*ptr.getRefData().getCustomData()).mTime = state.mTime; + } + + void Light::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) + const + { + ensureCustomData (ptr); + + state.mTime = dynamic_cast (*ptr.getRefData().getCustomData()).mTime; + } + std::string Light::getSound(const MWWorld::Ptr& ptr) const { return ptr.get()->mBase->mSound; diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 8658375b7..bbca30113 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -10,6 +10,8 @@ namespace MWClass virtual MWWorld::Ptr copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + void ensureCustomData (const MWWorld::Ptr& ptr) const; + public: /// Return ID of \a ptr @@ -73,6 +75,14 @@ namespace MWClass std::pair canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const; + virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) + const; + ///< Read additional state from \a state into \a ptr. + + virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) + const; + ///< Write additional state from \a ptr into \a state. + virtual std::string getSound(const MWWorld::Ptr& ptr) const; }; } diff --git a/apps/openmw/mwworld/cellref.cpp b/apps/openmw/mwworld/cellref.cpp index 744e0e27a..aa6627de5 100644 --- a/apps/openmw/mwworld/cellref.cpp +++ b/apps/openmw/mwworld/cellref.cpp @@ -81,29 +81,15 @@ namespace MWWorld int CellRef::getCharge() const { - return mCellRef.mChargeInt; + return mCellRef.mCharge; } void CellRef::setCharge(int charge) { - if (charge != mCellRef.mChargeInt) + if (charge != mCellRef.mCharge) { mChanged = true; - mCellRef.mChargeInt = charge; - } - } - - float CellRef::getChargeFloat() const - { - return mCellRef.mChargeFloat; - } - - void CellRef::setChargeFloat(float charge) - { - if (charge != mCellRef.mChargeFloat) - { - mChanged = true; - mCellRef.mChargeFloat = charge; + mCellRef.mCharge = charge; } } diff --git a/apps/openmw/mwworld/cellref.hpp b/apps/openmw/mwworld/cellref.hpp index 054fd7fc6..a7ffbe08b 100644 --- a/apps/openmw/mwworld/cellref.hpp +++ b/apps/openmw/mwworld/cellref.hpp @@ -60,11 +60,8 @@ namespace MWWorld // For weapon or armor, this is the remaining item health. // For tools (lockpicks, probes, repair hammer) it is the remaining uses. - // If this returns int(-1) it means full health. int getCharge() const; - float getChargeFloat() const; // Implemented as union with int charge void setCharge(int charge); - void setChargeFloat(float charge); // 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.hpp b/apps/openmw/mwworld/manualref.hpp index f32b07471..4eb93543b 100644 --- a/apps/openmw/mwworld/manualref.hpp +++ b/apps/openmw/mwworld/manualref.hpp @@ -28,7 +28,7 @@ namespace MWWorld cellRef.mRefID = name; cellRef.mScale = 1; cellRef.mFactionRank = 0; - cellRef.mChargeInt = -1; + cellRef.mCharge = -1; cellRef.mGoldValue = 1; cellRef.mEnchantmentCharge = -1; cellRef.mTeleport = false; diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index dfc3052ee..cd9fe8570 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -46,12 +46,12 @@ void ESM::CellRef::loadData(ESMReader &esm) esm.getHNOT (mFactionRank, "INDX"); mGoldValue = 1; - mChargeInt = -1; + mCharge = -1; mEnchantmentCharge = -1; esm.getHNOT (mEnchantmentCharge, "XCHG"); - esm.getHNOT (mChargeInt, "INTV"); + esm.getHNOT (mCharge, "INTV"); esm.getHNOT (mGoldValue, "NAM9"); @@ -106,8 +106,8 @@ void ESM::CellRef::save (ESMWriter &esm, bool wideRefNum, bool inInventory) cons if (mEnchantmentCharge != -1) esm.writeHNT("XCHG", mEnchantmentCharge); - if (mChargeInt != -1) - esm.writeHNT("INTV", mChargeInt); + if (mCharge != -1) + esm.writeHNT("INTV", mCharge); if (mGoldValue != 1) { esm.writeHNT("NAM9", mGoldValue); @@ -146,7 +146,7 @@ void ESM::CellRef::blank() mSoul.clear(); mFaction.clear(); mFactionRank = -2; - mChargeInt = -1; + mCharge = -1; mEnchantmentCharge = -1; mGoldValue = 0; mDestCell.clear(); diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp index 56932aa4d..7aa0e4d44 100644 --- a/components/esm/cellref.hpp +++ b/components/esm/cellref.hpp @@ -59,11 +59,7 @@ namespace ESM // For weapon or armor, this is the remaining item health. // For tools (lockpicks, probes, repair hammer) it is the remaining uses. - union - { - int mChargeInt; - float mChargeFloat; - }; + int mCharge; // Remaining enchantment charge. This could be -1 if the charge was not touched yet (i.e. full). float mEnchantmentCharge; diff --git a/components/esm/objectstate.cpp b/components/esm/objectstate.cpp index 9ef1ccf80..66fd49663 100644 --- a/components/esm/objectstate.cpp +++ b/components/esm/objectstate.cpp @@ -24,9 +24,9 @@ void ESM::ObjectState::load (ESMReader &esm) esm.getHNOT (mLocalRotation, "LROT", 12); - // obsolete - int unused; - esm.getHNOT(unused, "LTIM"); + // used for lights only + mTime = 0; + esm.getHNOT (mTime, "LTIM"); // FIXME: assuming "false" as default would make more sense, but also break compatibility with older save files mHasCustomState = true; @@ -55,6 +55,9 @@ void ESM::ObjectState::save (ESMWriter &esm, bool inInventory) const esm.writeHNT ("LROT", mLocalRotation, 12); } + if (mTime) + esm.writeHNT ("LTIM", mTime); + if (!mHasCustomState) esm.writeHNT ("HCUS", false); } @@ -71,6 +74,7 @@ void ESM::ObjectState::blank() mPosition.rot[i] = 0; mLocalRotation[i] = 0; } + mTime = 0; mHasCustomState = true; } diff --git a/components/esm/objectstate.hpp b/components/esm/objectstate.hpp index d1077733a..b03689653 100644 --- a/components/esm/objectstate.hpp +++ b/components/esm/objectstate.hpp @@ -26,6 +26,8 @@ namespace ESM ESM::Position mPosition; float mLocalRotation[3]; + float mTime; // Used for lights only. Overhead should not be so awful, besides CellRef isn't OO either + // Is there any class-specific state following the ObjectState bool mHasCustomState;