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