diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 8933491e68..931ed73dfe 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -91,11 +91,6 @@ namespace MWClass return ptr.get()->mBase->mData.mFlags & ESM::Light::Carry; } - bool Light::isLight(const MWWorld::ConstPtr& ptr) const - { - return true; - } - std::unique_ptr Light::activate(const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index d5119aa0b5..70d6852ff8 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -38,8 +38,6 @@ namespace MWClass bool isItem(const MWWorld::ConstPtr&) const override; - bool isLight(const MWWorld::ConstPtr&) const override; - std::unique_ptr activate(const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const override; ///< Generate action for activation diff --git a/apps/openmw/mwlua/itemdata.cpp b/apps/openmw/mwlua/itemdata.cpp index 33a1a21310..0741b5ebe2 100644 --- a/apps/openmw/mwlua/itemdata.cpp +++ b/apps/openmw/mwlua/itemdata.cpp @@ -71,10 +71,11 @@ namespace MWLua if (prop == "condition") { MWWorld::Ptr o = mObject.ptr(); - if (o.getClass().isLight(o)) + if (o.mRef->getType() == ESM::REC_LIGH) return sol::make_object(context.mLua->sol(), o.getClass().getRemainingUsageTime(o)); else if (o.getClass().hasItemHealth(o)) - return sol::make_object(context.mLua->sol(), o.getClass().getItemHealth(o)); + return sol::make_object( + context.mLua->sol(), o.getClass().getItemHealth(o) + o.getCellRef().getChargeIntRemainder()); } return sol::lua_nil; @@ -84,14 +85,26 @@ namespace MWLua { if (prop == "condition") { - double cond = value.as(); - if (ptr.getClass().isLight(ptr)) + float cond = LuaUtil::cast(value); + if (ptr.mRef->getType() == ESM::REC_LIGH) ptr.getClass().setRemainingUsageTime(ptr, cond); else if (ptr.getClass().hasItemHealth(ptr)) - ptr.getCellRef().setCharge(std::max(0, static_cast(cond))); - else /*ignore or error?*/ + { + const float lastChargeRemainder = ptr.getCellRef().getChargeIntRemainder(); + // if the value set is less than 0, chargeInt and chargeIntRemainder is set to 0 + ptr.getCellRef().setChargeIntRemainder(std::max(0.f, std::modf(cond, &cond))); + ptr.getCellRef().setCharge(std::max(0.f, cond)); + // resolve the remaining charge remainder to be subtracted + if (lastChargeRemainder < 0) + ptr.getCellRef().applyChargeRemainderToBeSubtracted(lastChargeRemainder); + } + else invalidPropErr(prop, ptr); + return; } + + /*ignore or error?*/ + invalidPropErr(prop, ptr); } }; } diff --git a/apps/openmw/mwlua/stats.cpp b/apps/openmw/mwlua/stats.cpp index 5c1e536dd6..35273a64e8 100644 --- a/apps/openmw/mwlua/stats.cpp +++ b/apps/openmw/mwlua/stats.cpp @@ -85,7 +85,7 @@ namespace MWLua public: sol::object getCurrent(const Context& context) const { - return getValue(context, mObject, &LevelStat::setValue, 0, "current", + return getValue(context, mObject, &LevelStat::setValue, std::monostate{}, "current", [](const MWWorld::Ptr& ptr) { return ptr.getClass().getCreatureStats(ptr).getLevel(); }); } @@ -93,7 +93,7 @@ namespace MWLua { SelfObject* obj = mObject.asSelfObject(); addStatUpdateAction(context.mLuaManager, *obj); - obj->mStatsCache[SelfObject::CachedStat{ &LevelStat::setValue, 0, "current" }] = value; + obj->mStatsCache[SelfObject::CachedStat{ &LevelStat::setValue, std::monostate{}, "current" }] = value; } sol::object getProgress(const Context& context) const diff --git a/apps/openmw/mwworld/cellref.cpp b/apps/openmw/mwworld/cellref.cpp index 37e1be0ddf..73fd3d4ac8 100644 --- a/apps/openmw/mwworld/cellref.cpp +++ b/apps/openmw/mwworld/cellref.cpp @@ -188,19 +188,14 @@ namespace MWWorld void CellRef::applyChargeRemainderToBeSubtracted(float chargeRemainder) { auto esm3Visit = [&](ESM::CellRef& cellRef3) { - cellRef3.mChargeIntRemainder += std::abs(chargeRemainder); - if (cellRef3.mChargeIntRemainder > 1.0f) + cellRef3.mChargeIntRemainder -= std::abs(chargeRemainder); + if (cellRef3.mChargeIntRemainder <= -1.0f) { - float newChargeRemainder = (cellRef3.mChargeIntRemainder - std::floor(cellRef3.mChargeIntRemainder)); - if (cellRef3.mChargeInt <= static_cast(cellRef3.mChargeIntRemainder)) - { - cellRef3.mChargeInt = 0; - } - else - { - cellRef3.mChargeInt -= static_cast(cellRef3.mChargeIntRemainder); - } + float newChargeRemainder = std::modf(cellRef3.mChargeIntRemainder, &cellRef3.mChargeIntRemainder); + cellRef3.mChargeInt += static_cast(cellRef3.mChargeIntRemainder); cellRef3.mChargeIntRemainder = newChargeRemainder; + if (cellRef3.mChargeInt < 0) + cellRef3.mChargeInt = 0; } }; std::visit(ESM::VisitOverload{ @@ -211,6 +206,16 @@ namespace MWWorld mCellRef.mVariant); } + void CellRef::setChargeIntRemainder(float chargeRemainder) + { + std::visit(ESM::VisitOverload{ + [&](ESM4::Reference& /*ref*/) {}, + [&](ESM4::ActorCharacter&) {}, + [&](ESM::CellRef& ref) { ref.mChargeIntRemainder = chargeRemainder; }, + }, + mCellRef.mVariant); + } + void CellRef::setChargeFloat(float charge) { std::visit(ESM::VisitOverload{ diff --git a/apps/openmw/mwworld/cellref.hpp b/apps/openmw/mwworld/cellref.hpp index 73e721278e..a1ddd8d0f0 100644 --- a/apps/openmw/mwworld/cellref.hpp +++ b/apps/openmw/mwworld/cellref.hpp @@ -118,10 +118,23 @@ namespace MWWorld }; return std::visit(Visitor(), mCellRef.mVariant); } // Implemented as union with int charge + float getChargeIntRemainder() const + { + struct Visitor + { + float operator()(const ESM::CellRef& ref) { return ref.mChargeIntRemainder; } + float operator()(const ESM4::Reference& /*ref*/) { return 0; } + float operator()(const ESM4::ActorCharacter&) { throw std::logic_error("Not applicable"); } + }; + return std::visit(Visitor(), mCellRef.mVariant); + } void setCharge(int charge); void setChargeFloat(float charge); void applyChargeRemainderToBeSubtracted(float chargeRemainder); // Stores remainders and applies if > 1 + // Stores fractional part of mChargeInt + void setChargeIntRemainder(float chargeRemainder); + // The NPC that owns this object (and will get angry if you steal it) ESM::RefId getOwner() const { diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 162fa88a34..7b7e9135ba 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -332,8 +332,6 @@ namespace MWWorld // True if it is an item that can be picked up. virtual bool isItem(const MWWorld::ConstPtr& ptr) const { return false; } - virtual bool isLight(const MWWorld::ConstPtr& ptr) const { return false; } - virtual bool isBipedal(const MWWorld::ConstPtr& ptr) const; virtual bool canFly(const MWWorld::ConstPtr& ptr) const; virtual bool canSwim(const MWWorld::ConstPtr& ptr) const; diff --git a/components/esm3/cellref.hpp b/components/esm3/cellref.hpp index 10ab4505ce..55e5afcbf5 100644 --- a/components/esm3/cellref.hpp +++ b/components/esm3/cellref.hpp @@ -60,7 +60,7 @@ namespace ESM int32_t mChargeInt; // Used by everything except lights float mChargeFloat; // Used only by lights }; - float mChargeIntRemainder; // Stores amount of charge not subtracted from mChargeInt + float mChargeIntRemainder; // Fractional part of mChargeInt // Remaining enchantment charge. This could be -1 if the charge was not touched yet (i.e. full). float mEnchantmentCharge;