From ead19d099af2989a28a8992dacb535353b19a50c Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Fri, 15 Aug 2025 13:17:17 +0200 Subject: [PATCH 1/3] Require cell arguments for Lua weather functions --- CMakeLists.txt | 2 +- apps/openmw/mwbase/world.hpp | 2 +- apps/openmw/mwlua/weatherbindings.cpp | 65 ++++++++++++++++++++++----- apps/openmw/mwworld/worldimp.cpp | 2 +- apps/openmw/mwworld/worldimp.hpp | 2 +- files/lua_api/openmw/core.lua | 24 ++++++---- 6 files changed, 73 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d81a67f26..fd7b4f32d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,7 +82,7 @@ message(STATUS "Configuring OpenMW...") set(OPENMW_VERSION_MAJOR 0) set(OPENMW_VERSION_MINOR 50) set(OPENMW_VERSION_RELEASE 0) -set(OPENMW_LUA_API_REVISION 92) +set(OPENMW_LUA_API_REVISION 93) set(OPENMW_POSTPROCESSING_API_REVISION 3) set(OPENMW_VERSION_COMMITHASH "") diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 74bd9f6a5c..983e2ef228 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -404,7 +404,7 @@ namespace MWBase ///< Apply a health difference to any actors colliding with \a object. /// To hurt actors, healthPerSecond should be a positive value. For a negative value, actors will be healed. - virtual float getWindSpeed() = 0; + virtual float getWindSpeed() const = 0; virtual void getContainersOwnedBy(const MWWorld::ConstPtr& npc, std::vector& out) = 0; ///< get all containers in active cells owned by this Npc diff --git a/apps/openmw/mwlua/weatherbindings.cpp b/apps/openmw/mwlua/weatherbindings.cpp index dffd708783..975b650d79 100644 --- a/apps/openmw/mwlua/weatherbindings.cpp +++ b/apps/openmw/mwlua/weatherbindings.cpp @@ -1,5 +1,7 @@ #include "weatherbindings.hpp" +#include + #include #include @@ -10,10 +12,13 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwworld/cellstore.hpp" #include "../mwworld/esmstore.hpp" +#include "../mwworld/scene.hpp" #include "../mwworld/weather.hpp" #include "context.hpp" +#include "object.hpp" namespace { @@ -35,6 +40,43 @@ namespace { return Misc::Color(color.r(), color.g(), color.b(), color.a()); } + + template + bool hasWeather(const Cell& cell) + { + if (!cell.mStore->isQuasiExterior() && !cell.mStore->isExterior()) + return false; + return MWBase::Environment::get().getWorldScene()->isCellActive(*cell.mStore); + } + + template + auto overloadForActiveCell(const Getter&& getter) + { + using Result = std::invoke_result_t; + return sol::overload( + [=](const MWLua::GCell& cell) -> Result { + if (!hasWeather(cell)) + return Result{}; + return getter(); + }, + [=](const MWLua::LCell& cell) -> Result { + if (!hasWeather(cell)) + return Result{}; + return getter(); + }); + } + + template + using WeatherGetter = T (MWBase::World::*)() const; + + template + auto overloadWeatherGetter(WeatherGetter getter) + { + return overloadForActiveCell([=]() -> std::optional { + const MWBase::World& world = *MWBase::Environment::get().getWorld(); + return (world.*getter)(); + }); + } } namespace MWLua @@ -140,12 +182,6 @@ namespace MWLua weatherT["scriptId"] = sol::readonly_property([](const MWWorld::Weather& w) { return w.mScriptId; }); weatherT["recordId"] = sol::readonly_property([](const MWWorld::Weather& w) { return w.mId.serializeText(); }); - api["getCurrent"] - = []() -> const MWWorld::Weather* { return &MWBase::Environment::get().getWorld()->getCurrentWeather(); }; - api["getNext"] - = []() -> const MWWorld::Weather* { return MWBase::Environment::get().getWorld()->getNextWeather(); }; - api["getTransition"] = []() { return MWBase::Environment::get().getWorld()->getWeatherTransition(); }; - api["changeWeather"] = [](std::string_view regionId, const MWWorld::Weather& weather) { ESM::RefId region = ESM::RefId::deserializeText(regionId); MWBase::Environment::get().getESMStore()->get().find(region); @@ -169,18 +205,23 @@ namespace MWLua // Provide access to the store. api["records"] = WeatherStore{}; - api["getCurrentSunLightDirection"] = []() { + api["getCurrent"] = overloadForActiveCell( + []() -> const MWWorld::Weather* { return &MWBase::Environment::get().getWorld()->getCurrentWeather(); }); + api["getNext"] = overloadForActiveCell( + []() -> const MWWorld::Weather* { return MWBase::Environment::get().getWorld()->getNextWeather(); }); + api["getTransition"] = overloadWeatherGetter(&MWBase::World::getWeatherTransition); + api["getCurrentSunLightDirection"] = overloadForActiveCell([]() -> std::optional { osg::Vec4f sunPos = MWBase::Environment::get().getWorld()->getSunLightPosition(); // normalize to get the direction towards the sun sunPos.normalize(); // and invert it to get the direction of the sun light return -sunPos; - }; - api["getCurrentSunVisibility"] = []() { return MWBase::Environment::get().getWorld()->getSunVisibility(); }; - api["getCurrentSunPercentage"] = []() { return MWBase::Environment::get().getWorld()->getSunPercentage(); }; - api["getCurrentWindSpeed"] = []() { return MWBase::Environment::get().getWorld()->getWindSpeed(); }; - api["getCurrentStormDirection"] = []() { return MWBase::Environment::get().getWorld()->getStormDirection(); }; + }); + api["getCurrentSunVisibility"] = overloadWeatherGetter(&MWBase::World::getSunVisibility); + api["getCurrentSunPercentage"] = overloadWeatherGetter(&MWBase::World::getSunPercentage); + api["getCurrentWindSpeed"] = overloadWeatherGetter(&MWBase::World::getWindSpeed); + api["getCurrentStormDirection"] = overloadWeatherGetter(&MWBase::World::getStormDirection); return LuaUtil::makeReadOnly(api); } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 8bb4d087a1..957ab98f24 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2546,7 +2546,7 @@ namespace MWWorld } } - float World::getWindSpeed() + float World::getWindSpeed() const { if (isCellExterior() || isCellQuasiExterior()) return mWeatherManager->getWindSpeed(); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index dfa0c33ecf..4b99f3c687 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -497,7 +497,7 @@ namespace MWWorld ///< Apply a health difference to any actors colliding with \a object. /// To hurt actors, healthPerSecond should be a positive value. For a negative value, actors will be healed. - float getWindSpeed() override; + float getWindSpeed() const override; void getContainersOwnedBy(const MWWorld::ConstPtr& npc, std::vector& out) override; ///< get all containers in active cells owned by this Npc diff --git a/files/lua_api/openmw/core.lua b/files/lua_api/openmw/core.lua index a7f8d5e8f1..4457c7c0e8 100644 --- a/files/lua_api/openmw/core.lua +++ b/files/lua_api/openmw/core.lua @@ -243,7 +243,7 @@ -- Can be used to move objects from an inventory or a container to the world. -- @function [parent=#GameObject] teleport -- @param self --- @param #any cellOrName A cell to define the destination worldspace; can be either #Cell, or cell name, or an empty string (empty string means the default exterior worldspace). +-- @param #any cellOrName A cell to define the destination worldspace; can be either @{#Cell}, or cell name, or an empty string (empty string means the default exterior worldspace). -- If the worldspace has multiple cells (i.e. an exterior), the destination cell is calculated using `position`. -- @param openmw.util#Vector3 position New position. -- @param #TeleportOptions options (optional) Either table @{#TeleportOptions} or @{openmw.util#Transform} rotation. @@ -1250,17 +1250,20 @@ --- -- Get the current weather -- @function [parent=#Weather] getCurrent --- @return #WeatherData +-- @param #Cell The cell to get the current weather for +-- @return #WeatherData or nil if the cell is inactive or has no weather --- -- Get the next weather if any -- @function [parent=#Weather] getNext +-- @param #Cell The cell to get the next weather for -- @return #any can be nil --- -- Get current weather transition value -- @function [parent=#Weather] getTransition --- @return #number +-- @param #Cell The cell to get the transition value for +-- @return #number or nil if the cell is inactive or has no weather --- -- Change the weather @@ -1271,27 +1274,32 @@ --- -- Get the current direction of the light of the sun. -- @function [parent=#Weather] getCurrentSunLightDirection --- @return openmw.util#Vector4 +-- @param #Cell The cell to get the sun direction for +-- @return openmw.util#Vector4 or nil if the cell is inactive or has no weather --- -- Get the current sun visibility taking weather transition into account. -- @function [parent=#Weather] getCurrentSunVisibility --- @return #number +-- @param #Cell The cell to get the sun visibility for +-- @return #number or nil if the cell is inactive or has no weather --- -- Get the current sun percentage taking weather transition into account. -- @function [parent=#Weather] getCurrentSunPercentage --- @return #number +-- @param #Cell The cell to get the sun percentage for +-- @return #number or nil if the cell is inactive or has no weather --- -- Get the current wind speed taking weather transition into account. -- @function [parent=#Weather] getCurrentWindSpeed --- @return #number +-- @param #Cell The cell to get the wind speed for +-- @return #number or nil if the cell is inactive or has no weather --- -- Get the current storm direction taking weather transition into account. -- @function [parent=#Weather] getCurrentStormDirection --- @return openmw.util#Vector3 +-- @param #Cell The cell to get the storm direction for +-- @return openmw.util#Vector3 or nil if the cell is inactive or has no weather --- -- Weather data From aa9978d720e6782e0c955819df15c05d51dbdf1f Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 17 Aug 2025 08:25:05 +0200 Subject: [PATCH 2/3] Expose getCurrentSunLightDirection in interiors and use perfect forwarding --- apps/openmw/mwlua/weatherbindings.cpp | 26 ++++++++++++++------------ files/lua_api/openmw/core.lua | 2 +- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwlua/weatherbindings.cpp b/apps/openmw/mwlua/weatherbindings.cpp index 975b650d79..1d813a2b92 100644 --- a/apps/openmw/mwlua/weatherbindings.cpp +++ b/apps/openmw/mwlua/weatherbindings.cpp @@ -42,25 +42,25 @@ namespace } template - bool hasWeather(const Cell& cell) + bool hasWeather(const Cell& cell, bool requireExterior) { - if (!cell.mStore->isQuasiExterior() && !cell.mStore->isExterior()) + if (requireExterior && !cell.mStore->isQuasiExterior() && !cell.mStore->isExterior()) return false; return MWBase::Environment::get().getWorldScene()->isCellActive(*cell.mStore); } template - auto overloadForActiveCell(const Getter&& getter) + auto overloadForActiveCell(Getter&& getter, bool requireExterior = true) { using Result = std::invoke_result_t; return sol::overload( [=](const MWLua::GCell& cell) -> Result { - if (!hasWeather(cell)) + if (!hasWeather(cell, requireExterior)) return Result{}; return getter(); }, [=](const MWLua::LCell& cell) -> Result { - if (!hasWeather(cell)) + if (!hasWeather(cell, requireExterior)) return Result{}; return getter(); }); @@ -210,14 +210,16 @@ namespace MWLua api["getNext"] = overloadForActiveCell( []() -> const MWWorld::Weather* { return MWBase::Environment::get().getWorld()->getNextWeather(); }); api["getTransition"] = overloadWeatherGetter(&MWBase::World::getWeatherTransition); - api["getCurrentSunLightDirection"] = overloadForActiveCell([]() -> std::optional { - osg::Vec4f sunPos = MWBase::Environment::get().getWorld()->getSunLightPosition(); - // normalize to get the direction towards the sun - sunPos.normalize(); + api["getCurrentSunLightDirection"] = overloadForActiveCell( + []() -> std::optional { + osg::Vec4f sunPos = MWBase::Environment::get().getWorld()->getSunLightPosition(); + // normalize to get the direction towards the sun + sunPos.normalize(); - // and invert it to get the direction of the sun light - return -sunPos; - }); + // and invert it to get the direction of the sun light + return -sunPos; + }, + false); api["getCurrentSunVisibility"] = overloadWeatherGetter(&MWBase::World::getSunVisibility); api["getCurrentSunPercentage"] = overloadWeatherGetter(&MWBase::World::getSunPercentage); api["getCurrentWindSpeed"] = overloadWeatherGetter(&MWBase::World::getWindSpeed); diff --git a/files/lua_api/openmw/core.lua b/files/lua_api/openmw/core.lua index 4457c7c0e8..25db0e57b5 100644 --- a/files/lua_api/openmw/core.lua +++ b/files/lua_api/openmw/core.lua @@ -1275,7 +1275,7 @@ -- Get the current direction of the light of the sun. -- @function [parent=#Weather] getCurrentSunLightDirection -- @param #Cell The cell to get the sun direction for --- @return openmw.util#Vector4 or nil if the cell is inactive or has no weather +-- @return openmw.util#Vector4 or nil if the cell is inactive --- -- Get the current sun visibility taking weather transition into account. From 6ff2a007fd57e1dccdca094c74400034aadb615e Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 17 Aug 2025 11:55:05 +0200 Subject: [PATCH 3/3] Fix parameter names --- files/lua_api/openmw/core.lua | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/files/lua_api/openmw/core.lua b/files/lua_api/openmw/core.lua index 25db0e57b5..a9c12de1f0 100644 --- a/files/lua_api/openmw/core.lua +++ b/files/lua_api/openmw/core.lua @@ -1250,56 +1250,56 @@ --- -- Get the current weather -- @function [parent=#Weather] getCurrent --- @param #Cell The cell to get the current weather for --- @return #WeatherData or nil if the cell is inactive or has no weather +-- @param #Cell cell The cell to get the current weather for +-- @return #Weather Can be nil if the cell is inactive or has no weather --- -- Get the next weather if any -- @function [parent=#Weather] getNext --- @param #Cell The cell to get the next weather for --- @return #any can be nil +-- @param #Cell cell The cell to get the next weather for +-- @return #Weather Can be nil --- -- Get current weather transition value -- @function [parent=#Weather] getTransition --- @param #Cell The cell to get the transition value for --- @return #number or nil if the cell is inactive or has no weather +-- @param #Cell cell The cell to get the transition value for +-- @return #number Can be nil if the cell is inactive or has no weather --- -- Change the weather -- @function [parent=#Weather] changeWeather -- @param #string regionId --- @param #WeatherData The weather to change to +-- @param #Weather weather The weather to change to --- -- Get the current direction of the light of the sun. -- @function [parent=#Weather] getCurrentSunLightDirection --- @param #Cell The cell to get the sun direction for --- @return openmw.util#Vector4 or nil if the cell is inactive +-- @param #Cell cell The cell to get the sun direction for +-- @return openmw.util#Vector4 Can be nil if the cell is inactive --- -- Get the current sun visibility taking weather transition into account. -- @function [parent=#Weather] getCurrentSunVisibility --- @param #Cell The cell to get the sun visibility for --- @return #number or nil if the cell is inactive or has no weather +-- @param #Cell cell The cell to get the sun visibility for +-- @return #number Can be nil if the cell is inactive or has no weather --- -- Get the current sun percentage taking weather transition into account. -- @function [parent=#Weather] getCurrentSunPercentage --- @param #Cell The cell to get the sun percentage for --- @return #number or nil if the cell is inactive or has no weather +-- @param #Cell cell The cell to get the sun percentage for +-- @return #number Can be nil if the cell is inactive or has no weather --- -- Get the current wind speed taking weather transition into account. -- @function [parent=#Weather] getCurrentWindSpeed --- @param #Cell The cell to get the wind speed for --- @return #number or nil if the cell is inactive or has no weather +-- @param #Cell cell The cell to get the wind speed for +-- @return #number Can be nil if the cell is inactive or has no weather --- -- Get the current storm direction taking weather transition into account. -- @function [parent=#Weather] getCurrentStormDirection --- @param #Cell The cell to get the storm direction for --- @return openmw.util#Vector3 or nil if the cell is inactive or has no weather +-- @param #Cell cell The cell to get the storm direction for +-- @return openmw.util#Vector3 Can be nil if the cell is inactive or has no weather --- -- Weather data