From 4707d7602d4d273395cb1a48770ad5c9d70b04d9 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Tue, 12 Aug 2025 11:02:10 +0200 Subject: [PATCH 01/25] Check for nullptr before dereferencing pathgrids --- apps/openmw/mwmechanics/aiwander.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index ad4fc730df..332f7e6545 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -636,6 +636,12 @@ namespace MWMechanics const MWWorld::Cell& cell = *actor.getCell()->getCell(); const ESM::Pathgrid* pathgrid = world.getStore().get().search(cell); + // Moved to a cell without a pathgrid + if (pathgrid == nullptr) + { + storage.mAllowedPositions.clear(); + return; + } const PathgridGraph& pathgridGraph = getPathGridGraph(pathgrid); const Misc::CoordinateConverter converter = Misc::makeCoordinateConverter(cell); From ead19d099af2989a28a8992dacb535353b19a50c Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Fri, 15 Aug 2025 13:17:17 +0200 Subject: [PATCH 02/25] 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 d5b9e261829dbeab40812f5ad4ee669c410e9839 Mon Sep 17 00:00:00 2001 From: Joakim Berg Date: Sat, 16 Aug 2025 10:33:51 +0200 Subject: [PATCH 03/25] small fixes to be consisten --- files/lang/launcher_sv.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/files/lang/launcher_sv.ts b/files/lang/launcher_sv.ts index 5cc7876cce..1a70f066f8 100644 --- a/files/lang/launcher_sv.ts +++ b/files/lang/launcher_sv.ts @@ -931,7 +931,7 @@ de ordinarie fonterna i Morrowind. Bocka denna ruta om du ändå föredrar ordin <html><head/><body><p>Whether or not the chance of success will be displayed in the enchanting menu.</p><p>The default value is false.</p></body></html> - <html><head/><body><p>Huruvida chansen att lyckas kommer visas i förtrollningsmenyn.</p><p>Förvalt är av.</p></body></html> + <html><head/><body><p>Huruvida chansen att lyckas kommer visas i förtrollningsmenyn (enchanting).</p><p>Förvalt är av.</p></body></html> <html><head/><body><p>Prevents merchants from equipping items that are sold to them.</p></body></html> @@ -939,7 +939,7 @@ de ordinarie fonterna i Morrowind. Bocka denna ruta om du ändå föredrar ordin <html><head/><body><p>Trainers now only choose which skills to train using their base skill points, allowing mercantile improving effects to be used without making mercantile an offered skill.</p></body></html> - <html><head/><body><p>Tränare väljer nu endast de färdigheter som kan tränas genom att använda deras basfärdighetsvärde, vilket tillåter förbättring av merkantil utan att göra merkantil till en erbjuden färdighet.</p></body></html> + <html><head/><body><p>Tränare väljer nu endast de färdigheter som kan tränas genom att använda deras basfärdighetsvärde, vilket tillåter förbättring av färdigheten "merchantile" utan att göra den till en erbjuden färdighet.</p></body></html> Miscellaneous From f073d021b7cf196372b1308846d57e686d9d7b47 Mon Sep 17 00:00:00 2001 From: Joakim Berg Date: Sat, 16 Aug 2025 10:43:29 +0200 Subject: [PATCH 04/25] Update file launcher_sv.ts --- files/lang/launcher_sv.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/lang/launcher_sv.ts b/files/lang/launcher_sv.ts index 1a70f066f8..5b09c9c3fd 100644 --- a/files/lang/launcher_sv.ts +++ b/files/lang/launcher_sv.ts @@ -939,7 +939,7 @@ de ordinarie fonterna i Morrowind. Bocka denna ruta om du ändå föredrar ordin <html><head/><body><p>Trainers now only choose which skills to train using their base skill points, allowing mercantile improving effects to be used without making mercantile an offered skill.</p></body></html> - <html><head/><body><p>Tränare väljer nu endast de färdigheter som kan tränas genom att använda deras basfärdighetsvärde, vilket tillåter förbättring av färdigheten "merchantile" utan att göra den till en erbjuden färdighet.</p></body></html> + <html><head/><body><p>Tränare väljer nu endast de färdigheter som kan tränas genom att använda deras basfärdighetsvärde, vilket tillåter förbättring av färdigheten "mercantile" utan att göra den till en erbjuden färdighet.</p></body></html> Miscellaneous From cf3d0b7dd3f3c3442339b0ccf46ac69abbed15e4 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sat, 16 Aug 2025 13:46:34 +0200 Subject: [PATCH 05/25] Use std::format in components/fx --- apps/openmw/mwlua/postprocessingbindings.cpp | 1 + components/fx/lexer.cpp | 10 +-- components/fx/pass.cpp | 2 +- components/fx/technique.cpp | 92 ++++++++++---------- components/fx/types.hpp | 40 ++++----- components/fx/widgets.hpp | 5 +- 6 files changed, 70 insertions(+), 80 deletions(-) diff --git a/apps/openmw/mwlua/postprocessingbindings.cpp b/apps/openmw/mwlua/postprocessingbindings.cpp index 6d0c33848a..8b3779d084 100644 --- a/apps/openmw/mwlua/postprocessingbindings.cpp +++ b/apps/openmw/mwlua/postprocessingbindings.cpp @@ -3,6 +3,7 @@ #include "MyGUI_LanguageManager.h" #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" diff --git a/components/fx/lexer.cpp b/components/fx/lexer.cpp index cab59df314..4369febbcb 100644 --- a/components/fx/lexer.cpp +++ b/components/fx/lexer.cpp @@ -2,11 +2,7 @@ #include #include -#include -#include -#include - -#include +#include namespace Fx { @@ -126,7 +122,7 @@ namespace Fx [[noreturn]] void Lexer::error(const std::string& msg) { - throw LexerException(Misc::StringUtils::format("Line %zu Col %zu. %s", mLine + 1, mColumn, msg)); + throw LexerException(std::format("Line {} Col {}. {}", mLine + 1, mColumn, msg)); } void Lexer::advance() @@ -209,7 +205,7 @@ namespace Fx advance(); return { Comma{} }; default: - error(Misc::StringUtils::format("unexpected token <%c>", head())); + error(std::format("unexpected token <{}>", head())); } } diff --git a/components/fx/pass.cpp b/components/fx/pass.cpp index 85b420f4fd..eceffa188f 100644 --- a/components/fx/pass.cpp +++ b/components/fx/pass.cpp @@ -300,7 +300,7 @@ float omw_EstimateFogCoverageFromUV(vec2 uv) header.replace(pos, define.size(), value); for (const auto& target : mRenderTargets) - header.append("uniform sampler2D " + std::string(target) + ";"); + header.append("uniform sampler2D " + target + ";"); for (auto& uniform : technique.getUniformMap()) if (auto glsl = uniform->getGLSL()) diff --git a/components/fx/technique.cpp b/components/fx/technique.cpp index ee41ac4f12..b675e7ddad 100644 --- a/components/fx/technique.cpp +++ b/components/fx/technique.cpp @@ -1,6 +1,7 @@ #include "technique.hpp" #include +#include #include #include @@ -91,10 +92,7 @@ namespace Fx std::string Technique::getBlockWithLineDirective() { auto block = mLexer->getLastJumpBlock(); - std::string content = std::string(block.content); - - content = "\n#line " + std::to_string(block.line + 1) + "\n" + std::string(block.content) + "\n"; - return content; + return std::format("\n#line {}\n{}\n", block.line + 1, block.content); } Technique::UniformMap::iterator Technique::findUniform(const std::string& name) @@ -140,9 +138,9 @@ namespace Fx if (it == mPassMap.end()) error( - Misc::StringUtils::format("pass '%s' was found in the pass list, but there was no matching " - "'fragment', 'vertex' or 'compute' block", - std::string(name))); + std::format("pass '{}' was found in the pass list, but there was no matching 'fragment', " + "'vertex' or 'compute' block", + name)); if (mLastAppliedType != Pass::Type::None && mLastAppliedType != it->second->mType) { @@ -167,7 +165,7 @@ namespace Fx { auto rtIt = mRenderTargets.find(it->second->mTarget); if (rtIt == mRenderTargets.end()) - error(Misc::StringUtils::format("target '%s' not defined", std::string(it->second->mTarget))); + error(std::format("target '{}' not defined", it->second->mTarget)); } mPasses.emplace_back(it->second); @@ -212,7 +210,7 @@ namespace Fx void Technique::parseBlockImp() { if (!mLexer->jump()) - error(Misc::StringUtils::format("unterminated 'shared' block, expected closing brackets")); + error("unterminated 'shared' block, expected closing brackets"); if (!mShared.empty()) error("repeated 'shared' block, only one allowed per technique file"); @@ -255,7 +253,7 @@ namespace Fx else if (key == "glsl_profile") { expect(); - mGLSLProfile = std::string(std::get(mToken).value); + mGLSLProfile = std::get(mToken).value; } else if (key == "glsl_extensions") { @@ -265,7 +263,7 @@ namespace Fx else if (key == "dynamic") mDynamic = parseBool(); else - error(Misc::StringUtils::format("unexpected key '%s'", std::string{ key })); + error(std::format("unexpected key '{}'", key)); expect(); } @@ -278,7 +276,7 @@ namespace Fx void Technique::parseBlockImp() { if (mRenderTargets.count(mBlockName)) - error(Misc::StringUtils::format("redeclaration of render target '%s'", std::string(mBlockName))); + error(std::format("redeclaration of render target '{}'", mBlockName)); Fx::Types::RenderTarget rt; rt.mTarget->setTextureSize(mWidth, mHeight); @@ -324,7 +322,7 @@ namespace Fx else if (key == "clear_color") rt.mClearColor = parseVec(); else - error(Misc::StringUtils::format("unexpected key '%s'", std::string(key))); + error(std::format("unexpected key '{}'", key)); expect(); } @@ -336,7 +334,7 @@ namespace Fx void Technique::parseBlockImp() { if (!mLexer->jump()) - error(Misc::StringUtils::format("unterminated 'vertex' block, expected closing brackets")); + error("unterminated 'vertex' block, expected closing brackets"); auto& pass = mPassMap[mBlockName]; @@ -346,11 +344,11 @@ namespace Fx pass->mName = mBlockName; if (pass->mCompute) - error(Misc::StringUtils::format("'compute' block already defined. Usage is ambiguous.")); + error("'compute' block already defined. Usage is ambiguous."); else if (!pass->mVertex) pass->mVertex = new osg::Shader(osg::Shader::VERTEX, getBlockWithLineDirective()); else - error(Misc::StringUtils::format("duplicate vertex shader for block '%s'", std::string(mBlockName))); + error(std::format("duplicate vertex shader for block '{}'", mBlockName)); pass->mType = Pass::Type::Pixel; } @@ -359,7 +357,7 @@ namespace Fx void Technique::parseBlockImp() { if (!mLexer->jump()) - error(Misc::StringUtils::format("unterminated 'fragment' block, expected closing brackets")); + error("unterminated 'fragment' block, expected closing brackets"); auto& pass = mPassMap[mBlockName]; @@ -370,11 +368,11 @@ namespace Fx pass->mName = mBlockName; if (pass->mCompute) - error(Misc::StringUtils::format("'compute' block already defined. Usage is ambiguous.")); + error("'compute' block already defined. Usage is ambiguous."); else if (!pass->mFragment) pass->mFragment = new osg::Shader(osg::Shader::FRAGMENT, getBlockWithLineDirective()); else - error(Misc::StringUtils::format("duplicate vertex shader for block '%s'", std::string(mBlockName))); + error(std::format("duplicate vertex shader for block '{}'", mBlockName)); pass->mType = Pass::Type::Pixel; } @@ -383,7 +381,7 @@ namespace Fx void Technique::parseBlockImp() { if (!mLexer->jump()) - error(Misc::StringUtils::format("unterminated 'compute' block, expected closing brackets")); + error("unterminated 'compute' block, expected closing brackets"); auto& pass = mPassMap[mBlockName]; @@ -393,13 +391,13 @@ namespace Fx pass->mName = mBlockName; if (pass->mFragment) - error(Misc::StringUtils::format("'fragment' block already defined. Usage is ambiguous.")); + error("'fragment' block already defined. Usage is ambiguous."); else if (pass->mVertex) - error(Misc::StringUtils::format("'vertex' block already defined. Usage is ambiguous.")); + error("'vertex' block already defined. Usage is ambiguous."); else if (!pass->mFragment) pass->mCompute = new osg::Shader(osg::Shader::COMPUTE, getBlockWithLineDirective()); else - error(Misc::StringUtils::format("duplicate vertex shader for block '%s'", std::string(mBlockName))); + error(std::format("duplicate vertex shader for block '{}'", mBlockName)); pass->mType = Pass::Type::Compute; } @@ -408,7 +406,7 @@ namespace Fx void Technique::parseSampler() { if (findUniform(std::string(mBlockName)) != mDefinedUniforms.end()) - error(Misc::StringUtils::format("redeclaration of uniform '%s'", std::string(mBlockName))); + error(std::format("redeclaration of uniform '{}'", mBlockName)); ProxyTextureData proxy; osg::ref_ptr sampler; @@ -466,13 +464,12 @@ namespace Fx } } else - error(Misc::StringUtils::format("unexpected key '%s'", std::string{ key })); + error(std::format("unexpected key '{}'", key)); expect(); } if (!sampler) - error(Misc::StringUtils::format( - "%s '%s' requires a filename", std::string(T::repr), std::string{ mBlockName })); + error(std::format("{} '{}' requires a filename", T::repr, mBlockName)); if (!is1D) { @@ -497,7 +494,7 @@ namespace Fx std::shared_ptr uniform = std::make_shared(); uniform->mSamplerType = type; - uniform->mName = std::string(mBlockName); + uniform->mName = mBlockName; mDefinedUniforms.emplace_back(std::move(uniform)); } @@ -534,7 +531,7 @@ namespace Fx void Technique::parseUniform() { if (findUniform(std::string(mBlockName)) != mDefinedUniforms.end()) - error(Misc::StringUtils::format("redeclaration of uniform '%s'", std::string(mBlockName))); + error(std::format("redeclaration of uniform '{}'", mBlockName)); std::shared_ptr uniform = std::make_shared(); Types::Uniform data = Types::Uniform(); @@ -591,7 +588,7 @@ namespace Fx parseWidgetType(data); } else - error(Misc::StringUtils::format("unexpected key '%s'", std::string{ key })); + error(std::format("unexpected key '{}'", key)); expect(); } @@ -599,7 +596,7 @@ namespace Fx if (data.isArray()) uniform->mStatic = false; - uniform->mName = std::string(mBlockName); + uniform->mName = mBlockName; uniform->mData = data; uniform->mTechniqueName = mName; @@ -680,9 +677,9 @@ namespace Fx if (!std::holds_alternative(mToken)) { if (err.empty()) - error(Misc::StringUtils::format("Expected %s", std::string(T::repr))); + error(std::format("Expected {}", T::repr)); else - error(Misc::StringUtils::format("%s. Expected %s", err, std::string(T::repr))); + error(std::format("{}. Expected {}", err, T::repr)); } } @@ -693,10 +690,9 @@ namespace Fx if (!std::holds_alternative(mToken) && !std::holds_alternative(mToken)) { if (err.empty()) - error(Misc::StringUtils::format( - "%s. Expected %s or %s", err, std::string(T::repr), std::string(T2::repr))); + error(std::format("{}. Expected {} or {}", err, T::repr, T2::repr)); else - error(Misc::StringUtils::format("Expected %s or %s", std::string(T::repr), std::string(T2::repr))); + error(std::format("Expected {} or {}", T::repr, T2::repr)); } } @@ -856,14 +852,14 @@ namespace Fx pass->mBlendEq = blendEq; } else - error(Misc::StringUtils::format("unrecognized key '%s' in block header", std::string(key))); + error(std::format("unrecognized key '{}' in block header", key)); mToken = mLexer->next(); if (std::holds_alternative(mToken)) { if (std::holds_alternative(mLexer->peek())) - error(Misc::StringUtils::format("leading comma in '%s' is not allowed", std::string(mBlockName))); + error(std::format("leading comma in '{}' is not allowed", mBlockName)); else continue; } @@ -888,7 +884,7 @@ namespace Fx if (Misc::StringUtils::ciEqual(term, identifer)) return bit; } - error(Misc::StringUtils::format("unrecognized flag '%s'", std::string(term))); + error(std::format("unrecognized flag '{}'", term)); }; FlagsType flag = 0; @@ -908,7 +904,7 @@ namespace Fx return mode; } - error(Misc::StringUtils::format("unrecognized filter mode '%s'", std::string{ asLiteral() })); + error(std::format("unrecognized filter mode '{}'", asLiteral())); } osg::Texture::WrapMode Technique::parseWrapMode() @@ -926,7 +922,7 @@ namespace Fx "unsupported wrap mode 'clamp'; 'clamp_to_edge' was likely intended, look for an updated shader or " "contact author"); - error(Misc::StringUtils::format("unrecognized wrap mode '%s'", std::string{ asLiteral() })); + error(std::format("unrecognized wrap mode '{}'", asLiteral())); } osg::Texture::InternalFormatMode Technique::parseCompression() @@ -939,7 +935,7 @@ namespace Fx return mode; } - error(Misc::StringUtils::format("unrecognized compression '%s'", std::string{ asLiteral() })); + error(std::format("unrecognized compression '{}'", asLiteral())); } int Technique::parseInternalFormat() @@ -952,7 +948,7 @@ namespace Fx return mode; } - error(Misc::StringUtils::format("unrecognized internal format '%s'", std::string{ asLiteral() })); + error(std::format("unrecognized internal format '{}'", asLiteral())); } int Technique::parseSourceType() @@ -965,7 +961,7 @@ namespace Fx return mode; } - error(Misc::StringUtils::format("unrecognized source type '%s'", std::string{ asLiteral() })); + error(std::format("unrecognized source type '{}'", asLiteral())); } int Technique::parseSourceFormat() @@ -978,7 +974,7 @@ namespace Fx return mode; } - error(Misc::StringUtils::format("unrecognized source format '%s'", std::string{ asLiteral() })); + error(std::format("unrecognized source format '{}'", asLiteral())); } osg::BlendEquation::Equation Technique::parseBlendEquation() @@ -991,7 +987,7 @@ namespace Fx return mode; } - error(Misc::StringUtils::format("unrecognized blend equation '%s'", std::string{ asLiteral() })); + error(std::format("unrecognized blend equation '{}'", asLiteral())); } osg::BlendFunc::BlendFuncMode Technique::parseBlendFuncMode() @@ -1004,7 +1000,7 @@ namespace Fx return mode; } - error(Misc::StringUtils::format("unrecognized blend function '%s'", std::string{ asLiteral() })); + error(std::format("unrecognized blend function '{}'", asLiteral())); } template @@ -1057,7 +1053,7 @@ namespace Fx } else { - error(Misc::StringUtils::format("unrecognized widget type '%s'", std::string{ asLiteral() })); + error(std::format("unrecognized widget type '{}'", asLiteral())); } } diff --git a/components/fx/types.hpp b/components/fx/types.hpp index 440bc69470..7897156d7f 100644 --- a/components/fx/types.hpp +++ b/components/fx/types.hpp @@ -1,6 +1,7 @@ #ifndef OPENMW_COMPONENTS_FX_TYPES_HPP #define OPENMW_COMPONENTS_FX_TYPES_HPP +#include #include #include @@ -8,7 +9,6 @@ #include #include -#include #include #include @@ -236,11 +236,11 @@ namespace Fx switch (mSamplerType.value()) { case Texture_1D: - return Misc::StringUtils::format("uniform sampler1D %s;", mName); + return std::format("uniform sampler1D {};", mName); case Texture_2D: - return Misc::StringUtils::format("uniform sampler2D %s;", mName); + return std::format("uniform sampler2D {};", mName); case Texture_3D: - return Misc::StringUtils::format("uniform sampler3D %s;", mName); + return std::format("uniform sampler3D {};", mName); } } @@ -253,54 +253,52 @@ namespace Fx const bool useUniform = arg.isArray() || (Settings::ShaderManager::get().getMode() == Settings::ShaderManager::Mode::Debug || mStatic == false); - const std::string uname = arg.isArray() - ? Misc::StringUtils::format("%s[%zu]", mName, arg.getArray().size()) - : mName; + const std::string uname + = arg.isArray() ? std::format("{}[{}]", mName, arg.getArray().size()) : mName; if constexpr (std::is_same_v) { if (useUniform) - return Misc::StringUtils::format("uniform vec2 %s;", uname); + return std::format("uniform vec2 {};", uname); - return Misc::StringUtils::format("const vec2 %s=vec2(%f,%f);", mName, value[0], value[1]); + return std::format("const vec2 {}=vec2({},{});", mName, value[0], value[1]); } else if constexpr (std::is_same_v) { if (useUniform) - return Misc::StringUtils::format("uniform vec3 %s;", uname); + return std::format("uniform vec3 {};", uname); - return Misc::StringUtils::format( - "const vec3 %s=vec3(%f,%f,%f);", mName, value[0], value[1], value[2]); + return std::format("const vec3 {}=vec3({},{},{});", mName, value[0], value[1], value[2]); } else if constexpr (std::is_same_v) { if (useUniform) - return Misc::StringUtils::format("uniform vec4 %s;", uname); + return std::format("uniform vec4 {};", uname); - return Misc::StringUtils::format( - "const vec4 %s=vec4(%f,%f,%f,%f);", mName, value[0], value[1], value[2], value[3]); + return std::format( + "const vec4 {}=vec4({},{},{},{});", mName, value[0], value[1], value[2], value[3]); } else if constexpr (std::is_same_v) { if (useUniform) - return Misc::StringUtils::format("uniform float %s;", uname); + return std::format("uniform float {};", uname); - return Misc::StringUtils::format("const float %s=%f;", mName, value); + return std::format("const float {}={};", mName, value); } else if constexpr (std::is_same_v) { if (useUniform) - return Misc::StringUtils::format("uniform int %s;", uname); + return std::format("uniform int {};", uname); - return Misc::StringUtils::format("const int %s=%i;", mName, value); + return std::format("const int {}={};", mName, value); } else { static_assert(std::is_same_v, "Non-exhaustive visitor"); if (useUniform) - return Misc::StringUtils::format("uniform bool %s;", uname); + return std::format("uniform bool {};", uname); - return Misc::StringUtils::format("const bool %s=%s;", mName, value ? "true" : "false"); + return std::format("const bool {}={};", mName, value ? "true" : "false"); } }, mData); diff --git a/components/fx/widgets.hpp b/components/fx/widgets.hpp index c91fa01c4e..ca1b76f2e1 100644 --- a/components/fx/widgets.hpp +++ b/components/fx/widgets.hpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -18,8 +19,6 @@ #include #include -#include - #include "types.hpp" namespace Gui @@ -88,7 +87,7 @@ namespace Fx { mValue = value; if constexpr (std::is_floating_point_v) - mValueLabel->setCaption(Misc::StringUtils::format("%.3f", mValue)); + mValueLabel->setCaption(std::format("{:.3f}", mValue)); else mValueLabel->setCaption(std::to_string(mValue)); From 55c72ecb296b19fdc96c77af0573631ae4c0afd7 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sat, 16 Aug 2025 13:49:07 +0200 Subject: [PATCH 06/25] Use string_view in components/fx --- components/fx/lexer.cpp | 2 +- components/fx/lexer.hpp | 2 +- components/fx/technique.cpp | 14 +++++++------- components/fx/technique.hpp | 8 ++++---- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/components/fx/lexer.cpp b/components/fx/lexer.cpp index 4369febbcb..39cad9970a 100644 --- a/components/fx/lexer.cpp +++ b/components/fx/lexer.cpp @@ -120,7 +120,7 @@ namespace Fx return mLastJumpBlock; } - [[noreturn]] void Lexer::error(const std::string& msg) + [[noreturn]] void Lexer::error(std::string_view msg) { throw LexerException(std::format("Line {} Col {}. {}", mLine + 1, mColumn, msg)); } diff --git a/components/fx/lexer.hpp b/components/fx/lexer.hpp index 1b32298608..f49dbcd694 100644 --- a/components/fx/lexer.hpp +++ b/components/fx/lexer.hpp @@ -46,7 +46,7 @@ namespace Fx Block getLastJumpBlock() const; - [[noreturn]] void error(const std::string& msg); + [[noreturn]] void error(std::string_view msg); private: void drop(); diff --git a/components/fx/technique.cpp b/components/fx/technique.cpp index b675e7ddad..38db49bc7a 100644 --- a/components/fx/technique.cpp +++ b/components/fx/technique.cpp @@ -95,10 +95,10 @@ namespace Fx return std::format("\n#line {}\n{}\n", block.line + 1, block.content); } - Technique::UniformMap::iterator Technique::findUniform(const std::string& name) + Technique::UniformMap::iterator Technique::findUniform(std::string_view name) { return std::find_if(mDefinedUniforms.begin(), mDefinedUniforms.end(), - [&name](const auto& uniform) { return uniform->mName == name; }); + [=](const auto& uniform) { return uniform->mName == name; }); } bool Technique::compile() @@ -201,7 +201,7 @@ namespace Fx return isDirty; } - [[noreturn]] void Technique::error(const std::string& msg) + [[noreturn]] void Technique::error(std::string_view msg) { mLexer->error(msg); } @@ -405,7 +405,7 @@ namespace Fx template void Technique::parseSampler() { - if (findUniform(std::string(mBlockName)) != mDefinedUniforms.end()) + if (findUniform(mBlockName) != mDefinedUniforms.end()) error(std::format("redeclaration of uniform '{}'", mBlockName)); ProxyTextureData proxy; @@ -530,7 +530,7 @@ namespace Fx template void Technique::parseUniform() { - if (findUniform(std::string(mBlockName)) != mDefinedUniforms.end()) + if (findUniform(mBlockName) != mDefinedUniforms.end()) error(std::format("redeclaration of uniform '{}'", mBlockName)); std::shared_ptr uniform = std::make_shared(); @@ -671,7 +671,7 @@ namespace Fx } template - void Technique::expect(const std::string& err) + void Technique::expect(std::string_view err) { mToken = mLexer->next(); if (!std::holds_alternative(mToken)) @@ -684,7 +684,7 @@ namespace Fx } template - void Technique::expect(const std::string& err) + void Technique::expect(std::string_view err) { mToken = mLexer->next(); if (!std::holds_alternative(mToken) && !std::holds_alternative(mToken)) diff --git a/components/fx/technique.hpp b/components/fx/technique.hpp index ebf3fe30f5..3db46447dd 100644 --- a/components/fx/technique.hpp +++ b/components/fx/technique.hpp @@ -172,7 +172,7 @@ namespace Fx std::string getLastError() const { return mLastError; } - UniformMap::iterator findUniform(const std::string& name); + UniformMap::iterator findUniform(std::string_view name); bool getDynamic() const { return mDynamic; } @@ -183,17 +183,17 @@ namespace Fx bool getInternal() const { return mInternal; } private: - [[noreturn]] void error(const std::string& msg); + [[noreturn]] void error(std::string_view msg); void clear(); std::string_view asLiteral() const; template - void expect(const std::string& err = ""); + void expect(std::string_view err = {}); template - void expect(const std::string& err = ""); + void expect(std::string_view err = {}); template bool isNext(); From 86e40f5b6b260c97e5c56ef134c83f8072b08bef Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sat, 16 Aug 2025 14:01:21 +0200 Subject: [PATCH 07/25] Remove potential sources of UB --- components/fx/lexer.cpp | 20 +++++++------------- components/fx/lexer.hpp | 2 +- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/components/fx/lexer.cpp b/components/fx/lexer.cpp index 39cad9970a..9844a6de6e 100644 --- a/components/fx/lexer.cpp +++ b/components/fx/lexer.cpp @@ -1,7 +1,7 @@ #include "lexer.hpp" #include -#include +#include #include namespace Fx @@ -132,7 +132,7 @@ namespace Fx mColumn++; } - char Lexer::head() + unsigned char Lexer::head() { return *mHead; } @@ -289,21 +289,15 @@ namespace Fx Token Lexer::scanNumber() { double buffer; - - char* endPtr; - buffer = std::strtod(mHead, &endPtr); - - if (endPtr == nullptr) + const auto [endPtr, ec] = std::from_chars(mHead, mTail, buffer); + if (ec != std::errc()) error("critical error while parsing number"); - const char* tmp = mHead; + std::string_view literal(mHead, endPtr); mHead = endPtr; - for (; tmp != endPtr; ++tmp) - { - if ((*tmp == '.')) - return Float{ static_cast(buffer) }; - } + if (literal.find('.') != std::string_view::npos) + return Float{ static_cast(buffer) }; return Integer{ static_cast(buffer) }; } diff --git a/components/fx/lexer.hpp b/components/fx/lexer.hpp index f49dbcd694..c9120698aa 100644 --- a/components/fx/lexer.hpp +++ b/components/fx/lexer.hpp @@ -51,7 +51,7 @@ namespace Fx private: void drop(); void advance(); - char head(); + unsigned char head(); bool peekChar(char c); Token scanToken(); From 1f97172662eddd908c7c312ccc65947dab8fbec5 Mon Sep 17 00:00:00 2001 From: Joakim Berg Date: Sat, 16 Aug 2025 21:42:00 +0200 Subject: [PATCH 08/25] =?UTF-8?q?tried=20changing=20from=20"=20to=20?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- files/lang/launcher_sv.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/lang/launcher_sv.ts b/files/lang/launcher_sv.ts index 5b09c9c3fd..f30c85fe70 100644 --- a/files/lang/launcher_sv.ts +++ b/files/lang/launcher_sv.ts @@ -939,7 +939,7 @@ de ordinarie fonterna i Morrowind. Bocka denna ruta om du ändå föredrar ordin <html><head/><body><p>Trainers now only choose which skills to train using their base skill points, allowing mercantile improving effects to be used without making mercantile an offered skill.</p></body></html> - <html><head/><body><p>Tränare väljer nu endast de färdigheter som kan tränas genom att använda deras basfärdighetsvärde, vilket tillåter förbättring av färdigheten "mercantile" utan att göra den till en erbjuden färdighet.</p></body></html> + <html><head/><body><p>Tränare väljer nu endast de färdigheter som kan tränas genom att använda deras basfärdighetsvärde, vilket tillåter förbättring av färdigheten ”mercantile” utan att göra den till en erbjuden färdighet.</p></body></html> Miscellaneous From aa9978d720e6782e0c955819df15c05d51dbdf1f Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 17 Aug 2025 08:25:05 +0200 Subject: [PATCH 09/25] 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 5f3f3a7e1da6bfe651afa13546700d1a610f89c8 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 17 Aug 2025 08:48:04 +0200 Subject: [PATCH 10/25] Address feedback --- components/fx/lexer.cpp | 2 +- components/fx/technique.cpp | 10 +++++----- components/fx/types.hpp | 20 ++++++++------------ 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/components/fx/lexer.cpp b/components/fx/lexer.cpp index 9844a6de6e..e2759e7af0 100644 --- a/components/fx/lexer.cpp +++ b/components/fx/lexer.cpp @@ -205,7 +205,7 @@ namespace Fx advance(); return { Comma{} }; default: - error(std::format("unexpected token <{}>", head())); + error(std::format("unexpected token <{:c}>", head())); } } diff --git a/components/fx/technique.cpp b/components/fx/technique.cpp index 38db49bc7a..ac55a16b6f 100644 --- a/components/fx/technique.cpp +++ b/components/fx/technique.cpp @@ -98,7 +98,7 @@ namespace Fx Technique::UniformMap::iterator Technique::findUniform(std::string_view name) { return std::find_if(mDefinedUniforms.begin(), mDefinedUniforms.end(), - [=](const auto& uniform) { return uniform->mName == name; }); + [name](const auto& uniform) { return uniform->mName == name; }); } bool Technique::compile() @@ -372,7 +372,7 @@ namespace Fx else if (!pass->mFragment) pass->mFragment = new osg::Shader(osg::Shader::FRAGMENT, getBlockWithLineDirective()); else - error(std::format("duplicate vertex shader for block '{}'", mBlockName)); + error(std::format("duplicate fragment shader for block '{}'", mBlockName)); pass->mType = Pass::Type::Pixel; } @@ -397,7 +397,7 @@ namespace Fx else if (!pass->mFragment) pass->mCompute = new osg::Shader(osg::Shader::COMPUTE, getBlockWithLineDirective()); else - error(std::format("duplicate vertex shader for block '{}'", mBlockName)); + error(std::format("duplicate compute shader for block '{}'", mBlockName)); pass->mType = Pass::Type::Compute; } @@ -690,9 +690,9 @@ namespace Fx if (!std::holds_alternative(mToken) && !std::holds_alternative(mToken)) { if (err.empty()) - error(std::format("{}. Expected {} or {}", err, T::repr, T2::repr)); - else error(std::format("Expected {} or {}", T::repr, T2::repr)); + else + error(std::format("{}. Expected {} or {}", err, T::repr, T2::repr)); } } diff --git a/components/fx/types.hpp b/components/fx/types.hpp index 7897156d7f..bdb46a76c1 100644 --- a/components/fx/types.hpp +++ b/components/fx/types.hpp @@ -112,12 +112,7 @@ namespace Fx size_t getNumElements() const { - return std::visit( - [&](auto&& arg) { - ; - return arg.isArray() ? arg.getArray().size() : 1; - }, - mData); + return std::visit([](auto&& arg) { return arg.isArray() ? arg.getArray().size() : 1; }, mData); } template @@ -261,29 +256,30 @@ namespace Fx if (useUniform) return std::format("uniform vec2 {};", uname); - return std::format("const vec2 {}=vec2({},{});", mName, value[0], value[1]); + return std::format("const vec2 {}=vec2({:f},{:f});", mName, value[0], value[1]); } else if constexpr (std::is_same_v) { if (useUniform) return std::format("uniform vec3 {};", uname); - return std::format("const vec3 {}=vec3({},{},{});", mName, value[0], value[1], value[2]); + return std::format( + "const vec3 {}=vec3({:f},{:f},{:f});", mName, value[0], value[1], value[2]); } else if constexpr (std::is_same_v) { if (useUniform) return std::format("uniform vec4 {};", uname); - return std::format( - "const vec4 {}=vec4({},{},{},{});", mName, value[0], value[1], value[2], value[3]); + return std::format("const vec4 {}=vec4({:f},{:f},{:f},{:f});", mName, value[0], value[1], + value[2], value[3]); } else if constexpr (std::is_same_v) { if (useUniform) return std::format("uniform float {};", uname); - return std::format("const float {}={};", mName, value); + return std::format("const float {}={:f};", mName, value); } else if constexpr (std::is_same_v) { @@ -298,7 +294,7 @@ namespace Fx if (useUniform) return std::format("uniform bool {};", uname); - return std::format("const bool {}={};", mName, value ? "true" : "false"); + return std::format("const bool {}={};", mName, value); } }, mData); From 3f2fd06514c5ecadf123e455bf9d7d5e193c605a Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 17 Aug 2025 11:26:30 +0200 Subject: [PATCH 11/25] Work around Apple Clang --- components/fx/lexer.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/components/fx/lexer.cpp b/components/fx/lexer.cpp index e2759e7af0..07d7f060a4 100644 --- a/components/fx/lexer.cpp +++ b/components/fx/lexer.cpp @@ -1,9 +1,14 @@ #include "lexer.hpp" #include -#include #include +#ifndef __cpp_lib_to_chars +#include +#else +#include +#endif + namespace Fx { namespace Lexer @@ -289,8 +294,14 @@ namespace Fx Token Lexer::scanNumber() { double buffer; +#ifndef __cpp_lib_to_chars + char* endPtr = nullptr; + buffer = std::strtod(mHead, &endPtr); + if (endPtr == nullptr || endPtr == mHead) +#else const auto [endPtr, ec] = std::from_chars(mHead, mTail, buffer); if (ec != std::errc()) +#endif error("critical error while parsing number"); std::string_view literal(mHead, endPtr); From 6ff2a007fd57e1dccdca094c74400034aadb615e Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 17 Aug 2025 11:55:05 +0200 Subject: [PATCH 12/25] 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 From 7560229f1f74770e98e25afda60d5e76d58fc8ac Mon Sep 17 00:00:00 2001 From: uramer Date: Sun, 17 Aug 2025 14:08:56 +0200 Subject: [PATCH 13/25] Fix type and name conflicts --- files/data/scripts/omw/crimes.lua | 2 +- files/lua_api/openmw/types.lua | 84 +++++++++++++++---------------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/files/data/scripts/omw/crimes.lua b/files/data/scripts/omw/crimes.lua index ae6612b34f..e0e15ac0a1 100644 --- a/files/data/scripts/omw/crimes.lua +++ b/files/data/scripts/omw/crimes.lua @@ -5,7 +5,7 @@ local I = require('openmw.interfaces') -- Table with information needed to commit crimes. -- @type CommitCrimeInputs -- @field openmw.core#GameObject victim The victim of the crime (optional) --- @field openmw.types#OFFENSE_TYPE type The type of the crime to commit. See @{openmw.types#OFFENSE_TYPE} (required) +-- @field openmw.types#OFFENSE_TYPE_IDS type The type of the crime to commit. See @{openmw.types#OFFENSE_TYPE_IDS} (required) -- @field #string faction ID of the faction the crime is committed against (optional) -- @field #number arg The amount to increase the player bounty by, if the crime type is theft. Ignored otherwise (optional, defaults to 0) -- @field #boolean victimAware Whether the victim is aware of the crime (optional, defaults to false) diff --git a/files/lua_api/openmw/types.lua b/files/lua_api/openmw/types.lua index e35ae2474c..add678a37f 100644 --- a/files/lua_api/openmw/types.lua +++ b/files/lua_api/openmw/types.lua @@ -741,7 +741,7 @@ --- -- @type NpcStats --- @extends ActorStats +-- @extends #ActorStats -- @field #SkillStats skills @@ -1157,34 +1157,34 @@ -- @field openmw.util#Transform rotation Destination rotation for this TravelDestination. -------------------------------------------------------------------------------- --- @{#Player} functions --- @field [parent=#types] #Player Player +-- @{#PLAYER} functions +-- @field [parent=#types] #PLAYER Player --- --- @type Player +-- @type PLAYER -- @extends #NPC -- @field #NPC baseType @{#NPC} --- -- Whether the object is a player. --- @function [parent=#Player] objectIsInstance +-- @function [parent=#PLAYER] objectIsInstance -- @param openmw.core#GameObject object -- @return #boolean --- -- Returns the bounty or crime level of the player --- @function [parent=#Player] getCrimeLevel +-- @function [parent=#PLAYER] getCrimeLevel -- @param openmw.core#GameObject player -- @return #number --- -- Sets the bounty or crime level of the player, may only be used in global scripts --- @function [parent=#Player] setCrimeLevel +-- @function [parent=#PLAYER] setCrimeLevel -- @param openmw.core#GameObject player -- @param #number crimeLevel The requested crime level --- --- @type OFFENSE_TYPE +-- @type OFFENSE_TYPE_IDS -- @field #number Theft -- @field #number Assault -- @field #number Murder @@ -1193,32 +1193,32 @@ -- @field #number Pickpocket --- --- Available @{#OFFENSE_TYPE} values. Used in `I.Crimes.commitCrime`. --- @field [parent=#Player] #OFFENSE_TYPE OFFENSE_TYPE +-- Available @{#OFFENSE_TYPE_IDS} values. Used in `I.Crimes.commitCrime`. +-- @field [parent=#PLAYER] #OFFENSE_TYPE_IDS OFFENSE_TYPE --- -- Whether the character generation for this player is finished. --- @function [parent=#Player] isCharGenFinished +-- @function [parent=#PLAYER] isCharGenFinished -- @param openmw.core#GameObject player -- @return #boolean --- -- Whether teleportation for this player is enabled. --- @function [parent=#Player] isTeleportingEnabled +-- @function [parent=#PLAYER] isTeleportingEnabled -- @param openmw.core#GameObject player -- @return #boolean --- -- Enables or disables teleportation for this player. --- @function [parent=#Player] setTeleportingEnabled +-- @function [parent=#PLAYER] setTeleportingEnabled -- @param openmw.core#GameObject player -- @param #boolean state True to enable teleporting, false to disable. --- --- Returns a list containing quests @{#PlayerQuest} for the specified player, indexed by quest ID. --- @function [parent=#Player] quests +-- Returns a list containing quests @{#PLAYERQuest} for the specified player, indexed by quest ID. +-- @function [parent=#PLAYER] quests -- @param openmw.core#GameObject player --- @return #list<#PlayerQuest> +-- @return #list<#PLAYERQuest> -- @usage -- Get stage of a specific quest -- stage = types.Player.quests(player)["ms_fargothring"].stage -- @usage -- Start a new quest, add it to the player's quest list but don't add any journal entries @@ -1227,7 +1227,7 @@ --- -- Returns @{#PlayerJournal}, which contains the read-only access to journal text data accumulated by the player. -- Not the same as @{openmw_core#Dialogue.journal} which holds raw game records: with placeholders for dynamic variables and no player-specific info. --- @function [parent=#Player] journal +-- @function [parent=#PLAYER] journal -- @param openmw.core#GameObject player -- @return #PlayerJournal -- @usage -- Get text of the 1st journal entry player made @@ -1306,14 +1306,14 @@ --- -- Sets the quest stage for the given quest, on the given player, and adds the entry to the journal, if there is an entry at the specified stage. Can only be used in global or player scripts. --- @function [parent=#PlayerQuest] addJournalEntry +-- @function [parent=#PLAYERQuest] addJournalEntry -- @param self -- @param #number stage Quest stage -- @param openmw.core#GameObject actor (optional) The actor who is the source of the journal entry, it may be used in journal entries with variables such as `%name(The speaker's name)` or `%race(The speaker's race)`. --- -- Get state of a control switch. I.e. is the player able to move/fight/jump/etc. --- @function [parent=#Player] getControlSwitch +-- @function [parent=#PLAYER] getControlSwitch -- @param openmw.core#GameObject player -- @param #ControlSwitch key Control type (see @{openmw.types#CONTROL_SWITCH}) -- @return #boolean @@ -1321,7 +1321,7 @@ --- -- Set state of a control switch. I.e. forbid or allow the player to move/fight/jump/etc. -- Can be used only in global or player scripts. --- @function [parent=#Player] setControlSwitch +-- @function [parent=#PLAYER] setControlSwitch -- @param openmw.core#GameObject player -- @param #ControlSwitch key Control type (see @{openmw.types#CONTROL_SWITCH}) -- @param #boolean value @@ -1342,21 +1342,21 @@ --- -- Values that can be used with getControlSwitch/setControlSwitch. --- @field [parent=#Player] #CONTROL_SWITCH CONTROL_SWITCH +-- @field [parent=#PLAYER] #CONTROL_SWITCH CONTROL_SWITCH --- --- @function [parent=#Player] getBirthSign +-- @function [parent=#PLAYER] getBirthSign -- @param openmw.core#GameObject player -- @return #string The player's birth sign --- -- Can be used only in global scripts. Note that this does not update the player's spells. --- @function [parent=#Player] setBirthSign +-- @function [parent=#PLAYER] setBirthSign -- @param openmw.core#GameObject player -- @param #any recordOrId Record or string ID of the birth sign to assign --- @{#BirthSigns}: Birth Sign Data --- @field [parent=#Player] #BirthSigns birthSigns +-- @field [parent=#PLAYER] #BirthSigns birthSigns --- -- A read-only list of all @{#BirthSignRecord}s in the world database. @@ -1382,7 +1382,7 @@ --- -- Send an event to menu scripts. --- @function [parent=#Player] sendMenuEvent +-- @function [parent=#PLAYER] sendMenuEvent -- @param openmw.core#GameObject player -- @param #string eventName -- @param eventData @@ -1654,62 +1654,62 @@ -- @field #list effects The effects (@{#list}) of the ingredient ---- @{#Lockable} functions --- @field [parent=#types] #Lockable Lockable +--- @{#LOCKABLE} functions +-- @field [parent=#types] #LOCKABLE Lockable --- -- Whether the object is a Lockable. --- @function [parent=#Lockable] objectIsInstance +-- @function [parent=#LOCKABLE] objectIsInstance -- @param openmw.core#GameObject object -- @return #boolean --- -- Returns the key record of a lockable object(door, container) --- @function [parent=#Lockable] getKeyRecord +-- @function [parent=#LOCKABLE] getKeyRecord -- @param openmw.core#GameObject object -- @return #MiscellaneousRecord --- -- Sets the key of a lockable object(door, container); removes it if empty string is provided. Must be used in a global script. --- @function [parent=#Lockable] setKeyRecord +-- @function [parent=#LOCKABLE] setKeyRecord -- @param openmw.core#GameObject object -- @param #any miscOrId @{#MiscellaneousRecord} or string misc item id Record ID of the key to use. --- -- Returns the trap spell of a lockable object(door, container) --- @function [parent=#Lockable] getTrapSpell +-- @function [parent=#LOCKABLE] getTrapSpell -- @param openmw.core#GameObject object -- @return openmw.core#Spell --- -- Sets the trap spell of a lockable object(door, container); removes it if empty string is provided. Must be used in a global script. --- @function [parent=#Lockable] setTrapSpell +-- @function [parent=#LOCKABLE] setTrapSpell -- @param openmw.core#GameObject object -- @param #any spellOrId @{openmw.core#Spell} or string spell id Record ID for the trap to use --- -- Returns the lock level of a lockable object(door, container). Does not determine if an object is locked or not, if an object is locked while this is set above 0, this value will be used if no other value is specified. --- @function [parent=#Lockable] getLockLevel +-- @function [parent=#LOCKABLE] getLockLevel -- @param openmw.core#GameObject object -- @return #number --- -- Returns true if the lockable object is locked, and false if it is not. --- @function [parent=#Lockable] isLocked +-- @function [parent=#LOCKABLE] isLocked -- @param openmw.core#GameObject object -- @return #boolean --- -- Sets the lock level level of a lockable object(door, container);Locks if not already locked; Must be used in a global script. --- @function [parent=#Lockable] lock +-- @function [parent=#LOCKABLE] lock -- @param openmw.core#GameObject object -- @param #number lockLevel Level to lock the object at. Optional, if not specified, then 1 will be used, or the previous level if it was locked before. --- -- Unlocks the lockable object. Does not change the lock level, it can be kept for future use. --- @function [parent=#Lockable] unlock +-- @function [parent=#LOCKABLE] unlock -- @param openmw.core#GameObject object @@ -2168,8 +2168,8 @@ --- -- @type Container --- @extends #Lockable --- @field #Lockable baseType @{#Lockable} +-- @extends #LOCKABLE +-- @field #LOCKABLE baseType @{#LOCKABLE} --- -- A read-only list of all @{#ContainerRecord}s in the world database. @@ -2230,8 +2230,8 @@ --- -- @type Door --- @extends #Lockable --- @field #Lockable baseType @{#Lockable} +-- @extends #LOCKABLE +-- @field #LOCKABLE baseType @{#LOCKABLE} --- Door.STATE -- @type DoorSTATE @@ -2485,8 +2485,8 @@ --- -- @type ESM4Door --- @extends #Lockable --- @field #Lockable baseType @{#Lockable} +-- @extends #LOCKABLE +-- @field #LOCKABLE baseType @{#LOCKABLE} --- -- Whether the object is a ESM4Door. From 676047a9e32d735eabf4304c748cd4642b4c398f Mon Sep 17 00:00:00 2001 From: uramer Date: Sun, 17 Aug 2025 16:31:14 +0200 Subject: [PATCH 14/25] Switch to openmwluadocumentor with Teal interfaces --- CI/teal_ci.sh | 4 ++-- docs/source/install_luadocumentor_in_docker.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CI/teal_ci.sh b/CI/teal_ci.sh index 6f5953f1be..ed4af253f4 100755 --- a/CI/teal_ci.sh +++ b/CI/teal_ci.sh @@ -7,8 +7,8 @@ pushd . echo "Install Teal Cyan" git clone https://github.com/teal-language/cyan.git cd cyan -git checkout v0.4.0 -luarocks make cyan-0.4.0-1.rockspec +git checkout v0.4.1 +luarocks make cyan-0.4.1-1.rockspec popd cyan version diff --git a/docs/source/install_luadocumentor_in_docker.sh b/docs/source/install_luadocumentor_in_docker.sh index 388ba8b739..07272554d3 100755 --- a/docs/source/install_luadocumentor_in_docker.sh +++ b/docs/source/install_luadocumentor_in_docker.sh @@ -33,7 +33,7 @@ PATH=$PATH:~/luarocks/bin echo "Install openmwluadocumentor" git clone https://gitlab.com/ptmikheev/openmw-luadocumentor.git cd openmw-luadocumentor -git checkout 122e4f55c5f2dd62076135211e03edfb8dec3a55 -luarocks make luarocks/openmwluadocumentor-0.2.0-1.rockspec +git checkout df58ac589dcb550977d0a3a9a65d32c5f3f2ae7d +luarocks make luarocks/openmwluadocumentor-0.2.1-1.rockspec cd ~ rm -r openmw-luadocumentor From c11ff30b0ab7be8ce5433a2dfd6096c17e0ce517 Mon Sep 17 00:00:00 2001 From: uramer Date: Mon, 18 Aug 2025 09:32:15 +0000 Subject: [PATCH 15/25] Switch to OpenMW's group luadocumentor repo --- docs/source/install_luadocumentor_in_docker.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/install_luadocumentor_in_docker.sh b/docs/source/install_luadocumentor_in_docker.sh index 07272554d3..cefddb49d4 100755 --- a/docs/source/install_luadocumentor_in_docker.sh +++ b/docs/source/install_luadocumentor_in_docker.sh @@ -31,9 +31,9 @@ rm -r luarocks-$luarocksV PATH=$PATH:~/luarocks/bin echo "Install openmwluadocumentor" -git clone https://gitlab.com/ptmikheev/openmw-luadocumentor.git +git clone https://gitlab.com/openmw/openmw-luadocumentor.git cd openmw-luadocumentor -git checkout df58ac589dcb550977d0a3a9a65d32c5f3f2ae7d +git checkout 6bb0b799661fcf1ee4bca007420843c78ee0ac85 luarocks make luarocks/openmwluadocumentor-0.2.1-1.rockspec cd ~ rm -r openmw-luadocumentor From a6c942b33aa3b3572ca92d2a85ef2d695a3e3ba7 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Mon, 18 Aug 2025 19:52:28 +0200 Subject: [PATCH 16/25] Account for numeric precision and infinities. Also pretend to be more like GLSL --- apps/components_tests/fx/lexer.cpp | 11 ++++ apps/components_tests/fx/technique.cpp | 91 ++++++++++++++++++++++---- components/fx/lexer.cpp | 43 ++++++++---- components/fx/technique.cpp | 2 +- 4 files changed, 121 insertions(+), 26 deletions(-) diff --git a/apps/components_tests/fx/lexer.cpp b/apps/components_tests/fx/lexer.cpp index 976f88d7a3..f8996118da 100644 --- a/apps/components_tests/fx/lexer.cpp +++ b/apps/components_tests/fx/lexer.cpp @@ -135,6 +135,17 @@ namespace EXPECT_EQ(std::get(token).value, 123); } + TEST(LexerTest, float_suffix_should_be_float) + { + Lexer lexer(R"( + 123f + )"); + + auto token = lexer.next(); + EXPECT_TRUE(std::holds_alternative(token)); + EXPECT_FLOAT_EQ(std::get(token).value, 123.f); + } + TEST(LexerTest, simple_string) { Lexer lexer(R"( diff --git a/apps/components_tests/fx/technique.cpp b/apps/components_tests/fx/technique.cpp index b04ff5c52a..63d65ef95f 100644 --- a/apps/components_tests/fx/technique.cpp +++ b/apps/components_tests/fx/technique.cpp @@ -90,6 +90,56 @@ namespace technique { passes = main; } )" }; + constexpr VFS::Path::NormalizedView invalidNumberInfPath("shaders/invalid_number_inf.omwfx"); + + TestingOpenMW::VFSTestFile invalidNumberInf{ R"( + uniform_vec4 uVec4 { + step = inf; + } + fragment main { } + technique { passes = main; } +)" }; + + constexpr VFS::Path::NormalizedView invalidNumberNegativeInfPath("shaders/invalid_number_negative_inf.omwfx"); + + TestingOpenMW::VFSTestFile invalidNumberNegativeInf{ R"( + uniform_vec4 uVec4 { + step = -inf; + } + fragment main { } + technique { passes = main; } +)" }; + + constexpr VFS::Path::NormalizedView invalidNumberUnsignedLongPath("shaders/invalid_number_ulong.omwfx"); + + TestingOpenMW::VFSTestFile invalidNumberUnsignedLong{ R"( + uniform_vec4 uVec4 { + step = 18446744073709551615; + } + fragment main { } + technique { passes = main; } +)" }; + + constexpr VFS::Path::NormalizedView invalidNumberHexFloatPath("shaders/invalid_number_hex.omwfx"); + + TestingOpenMW::VFSTestFile invalidNumberHexFloat{ R"( + uniform_vec4 uVec4 { + step = 0x1.fffffep+12; + } + fragment main { } + technique { passes = main; } +)" }; + + constexpr VFS::Path::NormalizedView invalidNumberDoublePath("shaders/invalid_number_double.omwfx"); + + TestingOpenMW::VFSTestFile invalidNumberDouble{ R"( + uniform_vec4 uVec4 { + step = 1.79769e+50; + } + fragment main { } + technique { passes = main; } +)" }; + using namespace testing; using namespace Fx; @@ -106,6 +156,11 @@ namespace { uniformPropertiesPath, &uniformProperties }, { missingSamplerSourcePath, &missingSamplerSource }, { repeatedSharedBlockPath, &repeatedSharedBlock }, + { invalidNumberInfPath, &invalidNumberInf }, + { invalidNumberNegativeInfPath, &invalidNumberNegativeInf }, + { invalidNumberUnsignedLongPath, &invalidNumberUnsignedLong }, + { invalidNumberHexFloatPath, &invalidNumberHexFloat }, + { invalidNumberDoublePath, &invalidNumberDouble }, })) , mImageManager(mVFS.get(), 0) { @@ -117,6 +172,17 @@ namespace *mVFS.get(), mImageManager, Technique::makeFileName(name), name, 1, 1, true, true); mTechnique->compile(); } + + void expectFailure(const std::string& name, std::string_view errorString) + { + internal::CaptureStdout(); + + compile(name); + + std::string output = internal::GetCapturedStdout(); + Log(Debug::Error) << output; + EXPECT_THAT(output, HasSubstr(errorString)); + } }; TEST_F(TechniqueTest, technique_properties) @@ -183,23 +249,24 @@ namespace TEST_F(TechniqueTest, fail_with_missing_source_for_sampler) { - internal::CaptureStdout(); - - compile("missing_sampler_source"); - - std::string output = internal::GetCapturedStdout(); - Log(Debug::Error) << output; - EXPECT_THAT(output, HasSubstr("sampler_1d 'mysampler1d' requires a filename")); + expectFailure("missing_sampler_source", "sampler_1d 'mysampler1d' requires a filename"); } TEST_F(TechniqueTest, fail_with_repeated_shared_block) { - internal::CaptureStdout(); + expectFailure("repeated_shared_block", "repeated 'shared' block"); + } - compile("repeated_shared_block"); + TEST_F(TechniqueTest, fail_with_invalid_float) + { + expectFailure("invalid_number_inf", "expected float value"); + expectFailure("invalid_number_negative_inf", "expected float value"); + expectFailure("invalid_number_hex", "expected float value"); + } - std::string output = internal::GetCapturedStdout(); - Log(Debug::Error) << output; - EXPECT_THAT(output, HasSubstr("repeated 'shared' block")); + TEST_F(TechniqueTest, fail_with_out_of_range) + { + expectFailure("invalid_number_ulong", "number out of range"); + expectFailure("invalid_number_double", "number out of range"); } } diff --git a/components/fx/lexer.cpp b/components/fx/lexer.cpp index 07d7f060a4..43ce17717f 100644 --- a/components/fx/lexer.cpp +++ b/components/fx/lexer.cpp @@ -1,13 +1,11 @@ #include "lexer.hpp" #include +#include +#include #include -#ifndef __cpp_lib_to_chars -#include -#else -#include -#endif +#include namespace Fx { @@ -294,23 +292,42 @@ namespace Fx Token Lexer::scanNumber() { double buffer; -#ifndef __cpp_lib_to_chars char* endPtr = nullptr; buffer = std::strtod(mHead, &endPtr); if (endPtr == nullptr || endPtr == mHead) -#else - const auto [endPtr, ec] = std::from_chars(mHead, mTail, buffer); - if (ec != std::errc()) -#endif error("critical error while parsing number"); + bool isDefinitelyAFloat = false; + // GLSL allows floats to end on f/F + if (endPtr != mTail && Misc::StringUtils::toLower(*endPtr) == 'f') + { + isDefinitelyAFloat = true; + ++endPtr; + } + std::string_view literal(mHead, endPtr); mHead = endPtr; - if (literal.find('.') != std::string_view::npos) - return Float{ static_cast(buffer) }; + // Disallow -inf, -nan, and values that cannot be represented as doubles + if (!std::isfinite(buffer)) + return Literal{ literal }; + // Disallow hex notation (not allowed in GLSL so confusing to partially allow) + if (Misc::StringUtils::ciStartsWith(literal, "0x") || Misc::StringUtils::ciStartsWith(literal, "-0x")) + return Literal{ literal }; - return Integer{ static_cast(buffer) }; + constexpr std::string_view floatCharacters = ".eE"; + if (!isDefinitelyAFloat && literal.find_first_of(floatCharacters) == std::string_view::npos) + { + // This is supposed to be an int, but that doesn't mean it can fit in one + int intValue = static_cast(buffer); + if (intValue != buffer) + error("number out of range"); + return Integer{ intValue }; + } + float floatValue = static_cast(buffer); + if (!std::isfinite(floatValue)) + error("number out of range"); + return Float{ floatValue }; } } } diff --git a/components/fx/technique.cpp b/components/fx/technique.cpp index ac55a16b6f..945a3cf1b1 100644 --- a/components/fx/technique.cpp +++ b/components/fx/technique.cpp @@ -758,7 +758,7 @@ namespace Fx if (named) { - expect("name is required for preceeding block decleration"); + expect("name is required for preceeding block declaration"); mBlockName = std::get(mToken).value; From 3067294f0d16da4491b5a76b31d974ef91e752b5 Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 6 Aug 2025 23:44:18 +0200 Subject: [PATCH 17/25] Add and fix -Wshadow --- CMakeLists.txt | 2 +- .../misc/testresourcehelpers.cpp | 7 +- .../nifloader/testbulletnifloader.cpp | 2 +- apps/esmtool/tes4.cpp | 10 +- apps/opencs/model/world/universalid.cpp | 6 +- apps/opencs/view/filter/editwidget.cpp | 6 +- apps/opencs/view/filter/editwidget.hpp | 2 +- apps/opencs/view/filter/filterbox.cpp | 4 +- apps/opencs/view/filter/filterbox.hpp | 2 +- apps/opencs/view/filter/recordfilterbox.cpp | 4 +- apps/opencs/view/filter/recordfilterbox.hpp | 2 +- apps/opencs/view/render/pathgridmode.cpp | 16 +- apps/opencs/view/render/pathgridmode.hpp | 8 +- apps/opencs/view/render/previewwidget.cpp | 8 +- apps/opencs/view/render/previewwidget.hpp | 3 +- apps/opencs/view/render/worldspacewidget.cpp | 2 +- apps/opencs/view/world/bodypartcreator.cpp | 5 +- apps/opencs/view/world/bodypartcreator.hpp | 2 +- apps/opencs/view/world/cellcreator.cpp | 4 +- apps/opencs/view/world/cellcreator.hpp | 2 +- apps/opencs/view/world/dialoguecreator.cpp | 4 +- apps/opencs/view/world/dialoguecreator.hpp | 3 +- apps/opencs/view/world/genericcreator.cpp | 4 +- apps/opencs/view/world/genericcreator.hpp | 4 +- apps/opencs/view/world/globalcreator.cpp | 4 +- apps/opencs/view/world/globalcreator.hpp | 2 +- apps/opencs/view/world/infocreator.cpp | 4 +- apps/opencs/view/world/infocreator.hpp | 2 +- apps/opencs/view/world/landcreator.cpp | 4 +- apps/opencs/view/world/landcreator.hpp | 2 +- apps/opencs/view/world/pathgridcreator.cpp | 6 +- apps/opencs/view/world/pathgridcreator.hpp | 2 +- .../view/world/referenceablecreator.cpp | 4 +- .../view/world/referenceablecreator.hpp | 3 +- apps/opencs/view/world/referencecreator.cpp | 4 +- apps/opencs/view/world/referencecreator.hpp | 2 +- apps/opencs/view/world/startscriptcreator.cpp | 4 +- apps/opencs/view/world/startscriptcreator.hpp | 2 +- apps/openmw/mwdialogue/quest.cpp | 4 +- apps/openmw/mwgui/bookpage.cpp | 34 ++-- apps/openmw/mwgui/journalviewmodel.cpp | 18 +- apps/openmw/mwgui/postprocessorhud.cpp | 4 +- apps/openmw/mwgui/quickkeysmenu.cpp | 4 +- apps/openmw/mwlua/inputbindings.cpp | 8 +- apps/openmw/mwlua/magicbindings.cpp | 183 +++++++++--------- apps/openmw/mwlua/menuscripts.cpp | 18 +- apps/openmw/mwlua/objectbindings.cpp | 12 +- apps/openmw/mwlua/postprocessingbindings.cpp | 102 +++++----- apps/openmw/mwlua/recordstore.hpp | 17 +- apps/openmw/mwlua/stats.cpp | 9 +- apps/openmw/mwlua/types/actor.cpp | 32 +-- apps/openmw/mwlua/types/book.cpp | 3 +- apps/openmw/mwlua/types/door.cpp | 30 +-- apps/openmw/mwlua/types/npc.cpp | 4 +- apps/openmw/mwlua/types/player.cpp | 78 ++++---- apps/openmw/mwlua/types/types.cpp | 12 +- apps/openmw/mwlua/uibindings.cpp | 26 +-- apps/openmw/mwlua/vfsbindings.cpp | 14 +- .../mwmechanics/mechanicsmanagerimp.cpp | 2 +- apps/openmw/mwworld/esmstore.cpp | 6 +- apps/openmw/mwworld/manualref.cpp | 10 +- apps/openmw/mwworld/scene.cpp | 14 +- apps/wizard/mainwizard.cpp | 3 +- apps/wizard/unshield/unshieldworker.cpp | 14 +- components/CMakeLists.txt | 4 + components/compiler/scanner.hpp | 4 +- .../detournavigator/asyncnavmeshupdater.cpp | 12 +- .../offmeshconnectionsmanager.cpp | 4 +- .../detournavigator/recastmeshbuilder.cpp | 2 +- components/files/configurationmanager.cpp | 6 +- components/files/configurationmanager.hpp | 2 +- components/lua/luastate.hpp | 8 +- components/lua/scriptscontainer.cpp | 6 +- components/lua/utilpackage.cpp | 6 +- components/nif/recordptr.hpp | 20 +- components/nifosg/controller.cpp | 2 +- components/stereo/stereomanager.cpp | 6 +- 77 files changed, 455 insertions(+), 445 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d81a67f26..5c5d16413e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -618,7 +618,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" OR CMAKE_CXX_COMPILER_FRONTEND_VARIANT add_compile_options("/WX") endif() else () - add_compile_options("-Wall" "-Wextra" "-Wundef" "-Wextra-semi" "-Wno-unused-parameter" "-pedantic" "-Wno-long-long" "-Wnon-virtual-dtor" "-Wunused") + add_compile_options("-Wall" "-Wextra" "-Wundef" "-Wextra-semi" "-Wno-unused-parameter" "-pedantic" "-Wno-long-long" "-Wnon-virtual-dtor" "-Wunused" "-Wshadow") if (CMAKE_CXX_COMPILER_ID STREQUAL Clang AND NOT APPLE) if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 3.6 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 3.6) diff --git a/apps/components_tests/misc/testresourcehelpers.cpp b/apps/components_tests/misc/testresourcehelpers.cpp index b21ecb2e14..95db3ce581 100644 --- a/apps/components_tests/misc/testresourcehelpers.cpp +++ b/apps/components_tests/misc/testresourcehelpers.cpp @@ -24,8 +24,11 @@ namespace TEST(CorrectSoundPath, corrected_path_does_not_check_existence_in_vfs) { std::unique_ptr mVFS = TestingOpenMW::createTestVFS({}); - constexpr VFS::Path::NormalizedView path("sound/foo.wav"); - EXPECT_EQ(correctSoundPath(path, *mVFS), "sound/foo.mp3"); + + { + constexpr VFS::Path::NormalizedView path("sound/foo.wav"); + EXPECT_EQ(correctSoundPath(path, *mVFS), "sound/foo.mp3"); + } auto correctESM4SoundPath = [](auto path, auto* vfs) { return Misc::ResourceHelpers::correctResourcePath({ { "sound" } }, path, vfs, ".mp3"); diff --git a/apps/components_tests/nifloader/testbulletnifloader.cpp b/apps/components_tests/nifloader/testbulletnifloader.cpp index c6df103858..4143e1d127 100644 --- a/apps/components_tests/nifloader/testbulletnifloader.cpp +++ b/apps/components_tests/nifloader/testbulletnifloader.cpp @@ -47,7 +47,7 @@ namespace bool isNear(const btVector3& lhs, const btVector3& rhs) { return std::equal(static_cast(lhs), static_cast(lhs) + 3, - static_cast(rhs), [](btScalar lhs, btScalar rhs) { return isNear(lhs, rhs); }); + static_cast(rhs), [](btScalar l, btScalar r) { return isNear(l, r); }); } bool isNear(const btMatrix3x3& lhs, const btMatrix3x3& rhs) diff --git a/apps/esmtool/tes4.cpp b/apps/esmtool/tes4.cpp index 4ff632a217..c11d936c68 100644 --- a/apps/esmtool/tes4.cpp +++ b/apps/esmtool/tes4.cpp @@ -572,13 +572,13 @@ namespace EsmTool } } - auto visitorRec = [¶ms](ESM4::Reader& reader) { return readRecord(params, reader); }; - auto visitorGroup = [¶ms](ESM4::Reader& reader) { + auto visitorRec = [¶ms](ESM4::Reader& r) { return readRecord(params, r); }; + auto visitorGroup = [¶ms](ESM4::Reader& r) { if (params.mQuite) return; - auto groupType = static_cast(reader.hdr().group.type); - std::cout << "\nGroup: " << toString(groupType) << " " - << ESM::NAME(reader.hdr().group.typeId).toStringView() << '\n'; + auto groupType = static_cast(r.hdr().group.type); + std::cout << "\nGroup: " << toString(groupType) << " " << ESM::NAME(r.hdr().group.typeId).toStringView() + << '\n'; }; ESM4::ReaderUtils::readAll(reader, visitorRec, visitorGroup); } diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 0ebccd6253..1a11f6b7d0 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -245,10 +245,10 @@ CSMWorld::UniversalId::UniversalId(const std::string& universalId) std::istringstream stream(universalId.substr(index + 2)); - int index = 0; - if (stream >> index) + int indexValue = 0; + if (stream >> indexValue) { - mValue = index; + mValue = indexValue; return; } diff --git a/apps/opencs/view/filter/editwidget.cpp b/apps/opencs/view/filter/editwidget.cpp index 8076e99e63..54ed388441 100644 --- a/apps/opencs/view/filter/editwidget.cpp +++ b/apps/opencs/view/filter/editwidget.cpp @@ -25,16 +25,16 @@ #include "../../model/world/data.hpp" #include "../../model/world/idtablebase.hpp" -CSVFilter::EditWidget::EditWidget(CSMWorld::Data& data, QWidget* parent) +CSVFilter::EditWidget::EditWidget(CSMWorld::Data& worldData, QWidget* parent) : QLineEdit(parent) - , mParser(data) + , mParser(worldData) , mIsEmpty(true) { mPalette = palette(); connect(this, &QLineEdit::textChanged, this, &EditWidget::textChanged); const CSMWorld::IdTableBase* model - = static_cast(data.getTableModel(CSMWorld::UniversalId::Type_Filters)); + = static_cast(worldData.getTableModel(CSMWorld::UniversalId::Type_Filters)); connect(model, &CSMWorld::IdTableBase::dataChanged, this, &EditWidget::filterDataChanged, Qt::QueuedConnection); connect(model, &CSMWorld::IdTableBase::rowsRemoved, this, &EditWidget::filterRowsRemoved, Qt::QueuedConnection); diff --git a/apps/opencs/view/filter/editwidget.hpp b/apps/opencs/view/filter/editwidget.hpp index 7efbd8e7a3..d623c6880a 100644 --- a/apps/opencs/view/filter/editwidget.hpp +++ b/apps/opencs/view/filter/editwidget.hpp @@ -71,7 +71,7 @@ namespace CSVFilter QAction* mHelpAction; public: - EditWidget(CSMWorld::Data& data, QWidget* parent = nullptr); + explicit EditWidget(CSMWorld::Data& worldData, QWidget* parent = nullptr); void createFilterRequest(const std::vector& sourceFilter, Qt::DropAction action); diff --git a/apps/opencs/view/filter/filterbox.cpp b/apps/opencs/view/filter/filterbox.cpp index e79b83ed51..e309f939a8 100644 --- a/apps/opencs/view/filter/filterbox.cpp +++ b/apps/opencs/view/filter/filterbox.cpp @@ -16,14 +16,14 @@ #include #include -CSVFilter::FilterBox::FilterBox(CSMWorld::Data& data, QWidget* parent) +CSVFilter::FilterBox::FilterBox(CSMWorld::Data& worldData, QWidget* parent) : QWidget(parent) { QHBoxLayout* layout = new QHBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); - mRecordFilterBox = new RecordFilterBox(data, this); + mRecordFilterBox = new RecordFilterBox(worldData, this); layout->addWidget(mRecordFilterBox); diff --git a/apps/opencs/view/filter/filterbox.hpp b/apps/opencs/view/filter/filterbox.hpp index bb53b94558..c0b43c0eb4 100644 --- a/apps/opencs/view/filter/filterbox.hpp +++ b/apps/opencs/view/filter/filterbox.hpp @@ -38,7 +38,7 @@ namespace CSVFilter RecordFilterBox* mRecordFilterBox; public: - FilterBox(CSMWorld::Data& data, QWidget* parent = nullptr); + explicit FilterBox(CSMWorld::Data& worldData, QWidget* parent = nullptr); void setRecordFilter(const std::string& filter); diff --git a/apps/opencs/view/filter/recordfilterbox.cpp b/apps/opencs/view/filter/recordfilterbox.cpp index deed76bfb8..48f3f46d0f 100644 --- a/apps/opencs/view/filter/recordfilterbox.cpp +++ b/apps/opencs/view/filter/recordfilterbox.cpp @@ -9,7 +9,7 @@ #include "editwidget.hpp" #include "filterdata.hpp" -CSVFilter::RecordFilterBox::RecordFilterBox(CSMWorld::Data& data, QWidget* parent) +CSVFilter::RecordFilterBox::RecordFilterBox(CSMWorld::Data& worldData, QWidget* parent) : QWidget(parent) { QHBoxLayout* layout = new QHBoxLayout(this); @@ -20,7 +20,7 @@ CSVFilter::RecordFilterBox::RecordFilterBox(CSMWorld::Data& data, QWidget* paren label->setIndent(2); layout->addWidget(label); - mEdit = new EditWidget(data, this); + mEdit = new EditWidget(worldData, this); layout->addWidget(mEdit); diff --git a/apps/opencs/view/filter/recordfilterbox.hpp b/apps/opencs/view/filter/recordfilterbox.hpp index d7fdb5cbac..0fc56eae1b 100644 --- a/apps/opencs/view/filter/recordfilterbox.hpp +++ b/apps/opencs/view/filter/recordfilterbox.hpp @@ -33,7 +33,7 @@ namespace CSVFilter EditWidget* mEdit; public: - RecordFilterBox(CSMWorld::Data& data, QWidget* parent = nullptr); + explicit RecordFilterBox(CSMWorld::Data& worldData, QWidget* parent = nullptr); void setFilter(const std::string& filter); diff --git a/apps/opencs/view/render/pathgridmode.cpp b/apps/opencs/view/render/pathgridmode.cpp index 9800f825bc..3a5b80cf11 100644 --- a/apps/opencs/view/render/pathgridmode.cpp +++ b/apps/opencs/view/render/pathgridmode.cpp @@ -39,7 +39,7 @@ namespace CSVRender PathgridMode::PathgridMode(WorldspaceWidget* worldspaceWidget, QWidget* parent) : EditMode(worldspaceWidget, Misc::ScalableIcon::load(":scenetoolbar/editing-pathgrid"), Mask_Pathgrid | Mask_Terrain | Mask_Reference, getTooltip(), parent) - , mDragMode(DragMode_None) + , mDragMode(DragMode::None) , mFromNode(0) , mSelectionMode(nullptr) { @@ -174,7 +174,7 @@ namespace CSVRender if (!selection.empty()) { - mDragMode = DragMode_Move; + mDragMode = DragMode::Move; return true; } @@ -188,7 +188,7 @@ namespace CSVRender { if (PathgridTag* tag = dynamic_cast(hit.tag.get())) { - mDragMode = DragMode_Edge; + mDragMode = DragMode::Edge; mEdgeId = tag->getPathgrid()->getId(); mFromNode = SceneUtil::getPathgridNode(hit.index0); @@ -202,7 +202,7 @@ namespace CSVRender void PathgridMode::drag(const QPoint& pos, int diffX, int diffY, double speedFactor) { - if (mDragMode == DragMode_Move) + if (mDragMode == DragMode::Move) { std::vector> selection = getWorldspaceWidget().getSelection(Mask_Pathgrid); @@ -219,7 +219,7 @@ namespace CSVRender } } } - else if (mDragMode == DragMode_Edge) + else if (mDragMode == DragMode::Edge) { WorldspaceHitResult hit = getWorldspaceWidget().mousePick(pos, getWorldspaceWidget().getInteractionMask()); @@ -243,7 +243,7 @@ namespace CSVRender void PathgridMode::dragCompleted(const QPoint& pos) { - if (mDragMode == DragMode_Move) + if (mDragMode == DragMode::Move) { std::vector> selection = getWorldspaceWidget().getSelection(Mask_Pathgrid); for (std::vector>::iterator it = selection.begin(); it != selection.end(); ++it) @@ -258,7 +258,7 @@ namespace CSVRender } } } - else if (mDragMode == DragMode_Edge) + else if (mDragMode == DragMode::Edge) { WorldspaceHitResult hit = getWorldspaceWidget().mousePick(pos, getWorldspaceWidget().getInteractionMask()); @@ -283,7 +283,7 @@ namespace CSVRender mFromNode = 0; } - mDragMode = DragMode_None; + mDragMode = DragMode::None; getWorldspaceWidget().reset(Mask_Pathgrid); } diff --git a/apps/opencs/view/render/pathgridmode.hpp b/apps/opencs/view/render/pathgridmode.hpp index 39ba5158d3..ba63c9d8e2 100644 --- a/apps/opencs/view/render/pathgridmode.hpp +++ b/apps/opencs/view/render/pathgridmode.hpp @@ -50,11 +50,11 @@ namespace CSVRender void dragAborted() override; private: - enum DragMode + enum class DragMode { - DragMode_None, - DragMode_Move, - DragMode_Edge + None, + Move, + Edge }; DragMode mDragMode; diff --git a/apps/opencs/view/render/previewwidget.cpp b/apps/opencs/view/render/previewwidget.cpp index 0f9064aaac..c26c8ffd95 100644 --- a/apps/opencs/view/render/previewwidget.cpp +++ b/apps/opencs/view/render/previewwidget.cpp @@ -12,10 +12,10 @@ class QWidget; CSVRender::PreviewWidget::PreviewWidget( - CSMWorld::Data& data, const std::string& id, bool referenceable, QWidget* parent) - : SceneWidget(data.getResourceSystem(), parent) - , mData(data) - , mObject(data, mRootNode, id, referenceable) + CSMWorld::Data& worldData, const std::string& id, bool referenceable, QWidget* parent) + : SceneWidget(worldData.getResourceSystem(), parent) + , mData(worldData) + , mObject(worldData, mRootNode, id, referenceable) { selectNavigationMode("orbit"); diff --git a/apps/opencs/view/render/previewwidget.hpp b/apps/opencs/view/render/previewwidget.hpp index 9f926d4640..c6e283e869 100644 --- a/apps/opencs/view/render/previewwidget.hpp +++ b/apps/opencs/view/render/previewwidget.hpp @@ -26,7 +26,8 @@ namespace CSVRender CSVRender::Object mObject; public: - PreviewWidget(CSMWorld::Data& data, const std::string& id, bool referenceable, QWidget* parent = nullptr); + explicit PreviewWidget( + CSMWorld::Data& worldData, const std::string& id, bool referenceable, QWidget* parent = nullptr); signals: diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 76bea2c4ee..d5beacabe8 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -454,7 +454,7 @@ CSVRender::WorldspaceHitResult CSVRender::WorldspaceWidget::mousePick( std::vector validIntersections = { intersections.begin(), intersections.end() }; - const auto& removeBackfaces = [direction = direction](const osgUtil::LineSegmentIntersector::Intersection& i) { + const auto& removeBackfaces = [direction](const osgUtil::LineSegmentIntersector::Intersection& i) { return direction * i.getWorldIntersectNormal() > 0; }; diff --git a/apps/opencs/view/world/bodypartcreator.cpp b/apps/opencs/view/world/bodypartcreator.cpp index 9c26b84465..3ecbb8f4e2 100644 --- a/apps/opencs/view/world/bodypartcreator.cpp +++ b/apps/opencs/view/world/bodypartcreator.cpp @@ -19,8 +19,9 @@ std::string CSVWorld::BodyPartCreator::getId() const return id; } -CSVWorld::BodyPartCreator::BodyPartCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id) - : GenericCreator(data, undoStack, id) +CSVWorld::BodyPartCreator::BodyPartCreator( + CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id) + : GenericCreator(worldData, undoStack, id) { mFirstPerson = new QCheckBox("First Person", this); insertBeforeButtons(mFirstPerson, false); diff --git a/apps/opencs/view/world/bodypartcreator.hpp b/apps/opencs/view/world/bodypartcreator.hpp index adb795eace..0dcdfb2c23 100644 --- a/apps/opencs/view/world/bodypartcreator.hpp +++ b/apps/opencs/view/world/bodypartcreator.hpp @@ -25,7 +25,7 @@ namespace CSVWorld std::string getId() const override; public: - BodyPartCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id); + explicit BodyPartCreator(CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id); /// \return Error description for current user input. std::string getErrors() const override; diff --git a/apps/opencs/view/world/cellcreator.cpp b/apps/opencs/view/world/cellcreator.cpp index 7545a5c082..47039076cb 100644 --- a/apps/opencs/view/world/cellcreator.cpp +++ b/apps/opencs/view/world/cellcreator.cpp @@ -37,8 +37,8 @@ void CSVWorld::CellCreator::configureCreateCommand(CSMWorld::CreateCommand& comm command.addNestedValue(parentIndex, index, mType->currentIndex() == 0); } -CSVWorld::CellCreator::CellCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id) - : GenericCreator(data, undoStack, id) +CSVWorld::CellCreator::CellCreator(CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id) + : GenericCreator(worldData, undoStack, id) { mY = new QSpinBox(this); mY->setVisible(false); diff --git a/apps/opencs/view/world/cellcreator.hpp b/apps/opencs/view/world/cellcreator.hpp index 0e0b4324a5..6350331a7f 100644 --- a/apps/opencs/view/world/cellcreator.hpp +++ b/apps/opencs/view/world/cellcreator.hpp @@ -38,7 +38,7 @@ namespace CSVWorld void configureCreateCommand(CSMWorld::CreateCommand& command) const override; public: - CellCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id); + explicit CellCreator(CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id); void reset() override; diff --git a/apps/opencs/view/world/dialoguecreator.cpp b/apps/opencs/view/world/dialoguecreator.cpp index db78c35245..c88228119b 100644 --- a/apps/opencs/view/world/dialoguecreator.cpp +++ b/apps/opencs/view/world/dialoguecreator.cpp @@ -21,8 +21,8 @@ void CSVWorld::DialogueCreator::configureCreateCommand(CSMWorld::CreateCommand& } CSVWorld::DialogueCreator::DialogueCreator( - CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, int type) - : GenericCreator(data, undoStack, id, true) + CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id, int type) + : GenericCreator(worldData, undoStack, id, true) , mType(type) { } diff --git a/apps/opencs/view/world/dialoguecreator.hpp b/apps/opencs/view/world/dialoguecreator.hpp index 6a89387b88..846cb4652a 100644 --- a/apps/opencs/view/world/dialoguecreator.hpp +++ b/apps/opencs/view/world/dialoguecreator.hpp @@ -29,7 +29,8 @@ namespace CSVWorld void configureCreateCommand(CSMWorld::CreateCommand& command) const override; public: - DialogueCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, int type); + explicit DialogueCreator( + CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id, int type); }; class TopicCreatorFactory : public CreatorFactoryBase diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index 0e87ab727f..d1bcb2b8d4 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -149,8 +149,8 @@ void CSVWorld::GenericCreator::addScope(const QString& name, CSMWorld::Scope sco } CSVWorld::GenericCreator::GenericCreator( - CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, bool relaxedIdRules) - : mData(data) + CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id, bool relaxedIdRules) + : mData(worldData) , mUndoStack(undoStack) , mListId(id) , mLocked(false) diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index a39b530ef2..615a0d733c 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -95,8 +95,8 @@ namespace CSVWorld void addScope(const QString& name, CSMWorld::Scope scope, const QString& tooltip); public: - GenericCreator( - CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, bool relaxedIdRules = false); + explicit GenericCreator(CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id, + bool relaxedIdRules = false); void setEditLock(bool locked) override; diff --git a/apps/opencs/view/world/globalcreator.cpp b/apps/opencs/view/world/globalcreator.cpp index 43c1210590..56466e4070 100644 --- a/apps/opencs/view/world/globalcreator.cpp +++ b/apps/opencs/view/world/globalcreator.cpp @@ -23,8 +23,8 @@ namespace CSVWorld command.addValue(index, type); } - GlobalCreator::GlobalCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id) - : GenericCreator(data, undoStack, id, true) + GlobalCreator::GlobalCreator(CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id) + : GenericCreator(worldData, undoStack, id, true) { } } diff --git a/apps/opencs/view/world/globalcreator.hpp b/apps/opencs/view/world/globalcreator.hpp index 81f4c7c88e..7243f99e13 100644 --- a/apps/opencs/view/world/globalcreator.hpp +++ b/apps/opencs/view/world/globalcreator.hpp @@ -21,7 +21,7 @@ namespace CSVWorld Q_OBJECT public: - GlobalCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id); + explicit GlobalCreator(CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id); protected: void configureCreateCommand(CSMWorld::CreateCommand& command) const override; diff --git a/apps/opencs/view/world/infocreator.cpp b/apps/opencs/view/world/infocreator.cpp index 5ce83cc849..5335878347 100644 --- a/apps/opencs/view/world/infocreator.cpp +++ b/apps/opencs/view/world/infocreator.cpp @@ -81,9 +81,9 @@ void CSVWorld::InfoCreator::configureCreateCommand(CSMWorld::CreateCommand& comm } } -CSVWorld::InfoCreator::InfoCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, +CSVWorld::InfoCreator::InfoCreator(CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager) - : GenericCreator(data, undoStack, id) + : GenericCreator(worldData, undoStack, id) { // Determine if we're dealing with topics or journals. CSMWorld::ColumnBase::Display displayType = CSMWorld::ColumnBase::Display_Topic; diff --git a/apps/opencs/view/world/infocreator.hpp b/apps/opencs/view/world/infocreator.hpp index 0c4a9fd4d3..ae79986801 100644 --- a/apps/opencs/view/world/infocreator.hpp +++ b/apps/opencs/view/world/infocreator.hpp @@ -40,7 +40,7 @@ namespace CSVWorld void configureCreateCommand(CSMWorld::CreateCommand& command) const override; public: - InfoCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, + explicit InfoCreator(CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager); void cloneMode(const std::string& originId, const CSMWorld::UniversalId::Type type) override; diff --git a/apps/opencs/view/world/landcreator.cpp b/apps/opencs/view/world/landcreator.cpp index 5f1d3ffa1d..a26b4194d9 100644 --- a/apps/opencs/view/world/landcreator.cpp +++ b/apps/opencs/view/world/landcreator.cpp @@ -15,8 +15,8 @@ namespace CSVWorld { - LandCreator::LandCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id) - : GenericCreator(data, undoStack, id) + LandCreator::LandCreator(CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id) + : GenericCreator(worldData, undoStack, id) , mXLabel(nullptr) , mYLabel(nullptr) , mX(nullptr) diff --git a/apps/opencs/view/world/landcreator.hpp b/apps/opencs/view/world/landcreator.hpp index ae7eecf758..8479285234 100644 --- a/apps/opencs/view/world/landcreator.hpp +++ b/apps/opencs/view/world/landcreator.hpp @@ -30,7 +30,7 @@ namespace CSVWorld QSpinBox* mY; public: - LandCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id); + explicit LandCreator(CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id); void cloneMode(const std::string& originId, const CSMWorld::UniversalId::Type type) override; diff --git a/apps/opencs/view/world/pathgridcreator.cpp b/apps/opencs/view/world/pathgridcreator.cpp index 51c3b1d282..f3ea16a8a6 100644 --- a/apps/opencs/view/world/pathgridcreator.cpp +++ b/apps/opencs/view/world/pathgridcreator.cpp @@ -30,9 +30,9 @@ CSMWorld::IdTable& CSVWorld::PathgridCreator::getPathgridsTable() const return dynamic_cast(*getData().getTableModel(getCollectionId())); } -CSVWorld::PathgridCreator::PathgridCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, - CSMWorld::IdCompletionManager& completionManager) - : GenericCreator(data, undoStack, id) +CSVWorld::PathgridCreator::PathgridCreator(CSMWorld::Data& worldData, QUndoStack& undoStack, + const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager) + : GenericCreator(worldData, undoStack, id) { setManualEditing(false); diff --git a/apps/opencs/view/world/pathgridcreator.hpp b/apps/opencs/view/world/pathgridcreator.hpp index ce26dc370e..153432905a 100644 --- a/apps/opencs/view/world/pathgridcreator.hpp +++ b/apps/opencs/view/world/pathgridcreator.hpp @@ -42,7 +42,7 @@ namespace CSVWorld CSMWorld::IdTable& getPathgridsTable() const; public: - PathgridCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, + explicit PathgridCreator(CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager); /// \brief Set cell ID input widget to ID of record to be cloned. diff --git a/apps/opencs/view/world/referenceablecreator.cpp b/apps/opencs/view/world/referenceablecreator.cpp index c4e20adf72..215e4aeea9 100644 --- a/apps/opencs/view/world/referenceablecreator.cpp +++ b/apps/opencs/view/world/referenceablecreator.cpp @@ -25,8 +25,8 @@ void CSVWorld::ReferenceableCreator::configureCreateCommand(CSMWorld::CreateComm } CSVWorld::ReferenceableCreator::ReferenceableCreator( - CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id) - : GenericCreator(data, undoStack, id) + CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id) + : GenericCreator(worldData, undoStack, id) { QLabel* label = new QLabel("Type", this); insertBeforeButtons(label, false); diff --git a/apps/opencs/view/world/referenceablecreator.hpp b/apps/opencs/view/world/referenceablecreator.hpp index 9858327968..4d8f7397f3 100644 --- a/apps/opencs/view/world/referenceablecreator.hpp +++ b/apps/opencs/view/world/referenceablecreator.hpp @@ -29,7 +29,8 @@ namespace CSVWorld void configureCreateCommand(CSMWorld::CreateCommand& command) const override; public: - ReferenceableCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id); + explicit ReferenceableCreator( + CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id); void reset() override; diff --git a/apps/opencs/view/world/referencecreator.cpp b/apps/opencs/view/world/referencecreator.cpp index 925ae53789..d41a8b29d0 100644 --- a/apps/opencs/view/world/referencecreator.cpp +++ b/apps/opencs/view/world/referencecreator.cpp @@ -33,9 +33,9 @@ void CSVWorld::ReferenceCreator::configureCreateCommand(CSMWorld::CreateCommand& command.addValue(cellIdColumn, mCell->text()); } -CSVWorld::ReferenceCreator::ReferenceCreator(CSMWorld::Data& data, QUndoStack& undoStack, +CSVWorld::ReferenceCreator::ReferenceCreator(CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager) - : GenericCreator(data, undoStack, id) + : GenericCreator(worldData, undoStack, id) { QLabel* label = new QLabel("Cell", this); insertBeforeButtons(label, false); diff --git a/apps/opencs/view/world/referencecreator.hpp b/apps/opencs/view/world/referencecreator.hpp index 1e6ab5a746..3e0f6c4241 100644 --- a/apps/opencs/view/world/referencecreator.hpp +++ b/apps/opencs/view/world/referencecreator.hpp @@ -44,7 +44,7 @@ namespace CSVWorld void configureCreateCommand(CSMWorld::CreateCommand& command) const override; public: - ReferenceCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, + explicit ReferenceCreator(CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager); void cloneMode(const std::string& originId, const CSMWorld::UniversalId::Type type) override; diff --git a/apps/opencs/view/world/startscriptcreator.cpp b/apps/opencs/view/world/startscriptcreator.cpp index fcbbc76159..a243779624 100644 --- a/apps/opencs/view/world/startscriptcreator.cpp +++ b/apps/opencs/view/world/startscriptcreator.cpp @@ -29,9 +29,9 @@ CSMWorld::IdTable& CSVWorld::StartScriptCreator::getStartScriptsTable() const return dynamic_cast(*getData().getTableModel(getCollectionId())); } -CSVWorld::StartScriptCreator::StartScriptCreator(CSMWorld::Data& data, QUndoStack& undoStack, +CSVWorld::StartScriptCreator::StartScriptCreator(CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager) - : GenericCreator(data, undoStack, id) + : GenericCreator(worldData, undoStack, id) { setManualEditing(false); diff --git a/apps/opencs/view/world/startscriptcreator.hpp b/apps/opencs/view/world/startscriptcreator.hpp index 8d8f51bd8e..c651d6db20 100644 --- a/apps/opencs/view/world/startscriptcreator.hpp +++ b/apps/opencs/view/world/startscriptcreator.hpp @@ -45,7 +45,7 @@ namespace CSVWorld CSMWorld::IdTable& getStartScriptsTable() const; public: - StartScriptCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, + explicit StartScriptCreator(CSMWorld::Data& worldData, QUndoStack& undoStack, const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager); /// \brief Set script ID input widget to ID of record to be cloned. diff --git a/apps/openmw/mwdialogue/quest.cpp b/apps/openmw/mwdialogue/quest.cpp index 68d7fdc627..ca40fed89a 100644 --- a/apps/openmw/mwdialogue/quest.cpp +++ b/apps/openmw/mwdialogue/quest.cpp @@ -71,8 +71,8 @@ namespace MWDialogue const ESM::Dialogue* dialogue = MWBase::Environment::get().getESMStore()->get().find(entry.mTopic); - auto info = std::find_if(dialogue->mInfo.begin(), dialogue->mInfo.end(), - [&](const auto& info) { return info.mId == entry.mInfoId; }); + auto info = std::find_if( + dialogue->mInfo.begin(), dialogue->mInfo.end(), [&](const auto& i) { return i.mId == entry.mInfoId; }); if (info == dialogue->mInfo.end() || info->mData.mJournalIndex == -1) throw std::runtime_error("unknown journal entry for topic " + mTopic.toDebugString()); diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index 24133dd34e..a0b2cb5626 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -1122,10 +1122,10 @@ namespace MWGui struct CreateActiveFormat { - PageDisplay* this_; + PageDisplay* mPageDisplay; - CreateActiveFormat(PageDisplay* this_) - : this_(this_) + explicit CreateActiveFormat(PageDisplay* pageDisplay) + : mPageDisplay(pageDisplay) { } @@ -1133,15 +1133,15 @@ namespace MWGui { MyGUI::IFont* const font = run.mStyle->mFont; - ActiveTextFormats::iterator j = this_->mActiveTextFormats.find(font); + ActiveTextFormats::iterator j = mPageDisplay->mActiveTextFormats.find(font); - if (j == this_->mActiveTextFormats.end()) + if (j == mPageDisplay->mActiveTextFormats.end()) { - auto textFormat = std::make_unique(font, this_); + auto textFormat = std::make_unique(font, mPageDisplay); textFormat->mTexture = font->getTextureFont(); - j = this_->mActiveTextFormats.insert(std::make_pair(font, std::move(textFormat))).first; + j = mPageDisplay->mActiveTextFormats.insert(std::make_pair(font, std::move(textFormat))).first; } j->second->mCountVertex += run.mPrintableChars * 6; @@ -1189,24 +1189,24 @@ namespace MWGui struct RenderRun { - PageDisplay* this_; - GlyphStream& glyphStream; + PageDisplay* mPageDisplay; + GlyphStream& mGlyphStream; - RenderRun(PageDisplay* this_, GlyphStream& glyphStream) - : this_(this_) - , glyphStream(glyphStream) + explicit RenderRun(PageDisplay* pageDisplay, GlyphStream& glyphStream) + : mPageDisplay(pageDisplay) + , mGlyphStream(glyphStream) { } void operator()(Section const& section, Line const& line, Run const& run) const { - bool isActive = run.mStyle->mInteractiveId && (run.mStyle == this_->mFocusItem); + bool isActive = run.mStyle->mInteractiveId && (run.mStyle == mPageDisplay->mFocusItem); MyGUI::Colour colour = isActive - ? (this_->mItemActive ? run.mStyle->mActiveColour : run.mStyle->mHotColour) + ? (mPageDisplay->mItemActive ? run.mStyle->mActiveColour : run.mStyle->mHotColour) : run.mStyle->mNormalColour; - glyphStream.reset(static_cast(section.mRect.left + line.mRect.left + run.mLeft), + mGlyphStream.reset(static_cast(section.mRect.left + line.mRect.left + run.mLeft), static_cast(line.mRect.top), colour); Utf8Stream stream(run.mRange); @@ -1219,9 +1219,9 @@ namespace MWGui continue; if (!ucsSpace(codePoint)) - glyphStream.emitGlyph(codePoint); + mGlyphStream.emitGlyph(codePoint); else - glyphStream.emitSpace(codePoint); + mGlyphStream.emitSpace(codePoint); } } }; diff --git a/apps/openmw/mwgui/journalviewmodel.cpp b/apps/openmw/mwgui/journalviewmodel.cpp index 2bb93cf0db..68711ac479 100644 --- a/apps/openmw/mwgui/journalviewmodel.cpp +++ b/apps/openmw/mwgui/journalviewmodel.cpp @@ -75,11 +75,11 @@ namespace MWGui { typedef t_iterator iterator_t; - iterator_t itr; + iterator_t mItr; JournalViewModelImpl const* mModel; BaseEntry(JournalViewModelImpl const* model, iterator_t itr) - : itr(itr) + : mItr(itr) , mModel(model) , loaded(false) { @@ -235,7 +235,7 @@ namespace MWGui template struct JournalEntryImpl : BaseEntry { - using BaseEntry::itr; + using BaseEntry::mItr; mutable std::string timestamp_buffer; @@ -244,7 +244,7 @@ namespace MWGui { } - std::string getText() const override { return itr->getText(); } + std::string getText() const override { return mItr->getText(); } Utf8Span timestamp() const override { @@ -254,9 +254,9 @@ namespace MWGui std::ostringstream os; - os << itr->mDayOfMonth << ' ' - << MWBase::Environment::get().getWorld()->getTimeManager()->getMonthName(itr->mMonth) << " (" - << dayStr << " " << (itr->mDay) << ')'; + os << mItr->mDayOfMonth << ' ' + << MWBase::Environment::get().getWorld()->getTimeManager()->getMonthName(mItr->mMonth) << " (" + << dayStr << " " << (mItr->mDay) << ')'; timestamp_buffer = os.str(); } @@ -334,9 +334,9 @@ namespace MWGui { } - std::string getText() const override { return itr->getText(); } + std::string getText() const override { return mItr->getText(); } - Utf8Span source() const override { return toUtf8Span(itr->mActorName); } + Utf8Span source() const override { return toUtf8Span(mItr->mActorName); } }; void visitTopicEntries(TopicId topicId, std::function visitor) const override diff --git a/apps/openmw/mwgui/postprocessorhud.cpp b/apps/openmw/mwgui/postprocessorhud.cpp index eaa42162af..f6b2966e7f 100644 --- a/apps/openmw/mwgui/postprocessorhud.cpp +++ b/apps/openmw/mwgui/postprocessorhud.cpp @@ -465,11 +465,11 @@ namespace MWGui } } - auto tryFocus = [this](ListWrapper* widget, const std::string& hint) { + auto tryFocus = [this](ListWrapper* widget, const std::string& focusHint) { MyGUI::Widget* oldFocus = MyGUI::InputManager::getInstance().getKeyFocusWidget(); if (oldFocus == mFilter) return; - size_t index = widget->findItemIndexWith(hint); + size_t index = widget->findItemIndexWith(focusHint); if (index != MyGUI::ITEM_NONE) { diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index 1f45b72eac..ab735fd1e6 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -626,8 +626,8 @@ namespace MWGui MWWorld::Ptr player = MWMechanics::getPlayer(); MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player); - auto assign = [this](auto type, MWWorld::Ptr item) { - if (type == ESM::QuickKeys::Type::Item) + auto assign = [this](ESM::QuickKeys::Type keyType, MWWorld::Ptr item) { + if (keyType == ESM::QuickKeys::Type::Item) assignItem(item); else // if (quickKey.mType == ESM::QuickKeys::Type::MagicItem) onAssignMagicItem(item); diff --git a/apps/openmw/mwlua/inputbindings.cpp b/apps/openmw/mwlua/inputbindings.cpp index 6f9b82d8a9..167d234f0e 100644 --- a/apps/openmw/mwlua/inputbindings.cpp +++ b/apps/openmw/mwlua/inputbindings.cpp @@ -84,7 +84,7 @@ namespace MWLua inputActions[sol::meta_function::index] = [](LuaUtil::InputAction::Registry& registry, std::string_view key) { return registry[key]; }; { - auto pairs = [](LuaUtil::InputAction::Registry& registry) { + auto pairs = [](LuaUtil::InputAction::Registry& self) { auto next = [](LuaUtil::InputAction::Registry& registry, std::string_view key) -> sol::optional> { std::optional nextKey(registry.nextKey(key)); @@ -93,7 +93,7 @@ namespace MWLua else return std::make_tuple(*nextKey, registry[*nextKey].value()); }; - return std::make_tuple(next, registry, registry.firstKey()); + return std::make_tuple(next, self, self.firstKey()); }; inputActions[sol::meta_function::pairs] = pairs; } @@ -122,7 +122,7 @@ namespace MWLua inputTriggers[sol::meta_function::index] = [](LuaUtil::InputTrigger::Registry& registry, std::string_view key) { return registry[key]; }; { - auto pairs = [](LuaUtil::InputTrigger::Registry& registry) { + auto pairs = [](LuaUtil::InputTrigger::Registry& self) { auto next = [](LuaUtil::InputTrigger::Registry& registry, std::string_view key) -> sol::optional> { std::optional nextKey(registry.nextKey(key)); @@ -131,7 +131,7 @@ namespace MWLua else return std::make_tuple(*nextKey, registry[*nextKey].value()); }; - return std::make_tuple(next, registry, registry.firstKey()); + return std::make_tuple(next, self, self.firstKey()); }; inputTriggers[sol::meta_function::pairs] = pairs; } diff --git a/apps/openmw/mwlua/magicbindings.cpp b/apps/openmw/mwlua/magicbindings.cpp index d2afde9536..3831cf656e 100644 --- a/apps/openmw/mwlua/magicbindings.cpp +++ b/apps/openmw/mwlua/magicbindings.cpp @@ -214,18 +214,18 @@ namespace MWLua sol::table initCoreMagicBindings(const Context& context) { - sol::state_view lua = context.sol(); - sol::table magicApi(lua, sol::create); + sol::state_view state = context.sol(); + sol::table magicApi(state, sol::create); // Constants - magicApi["RANGE"] = LuaUtil::makeStrictReadOnly(LuaUtil::tableFromPairs(lua, + magicApi["RANGE"] = LuaUtil::makeStrictReadOnly(LuaUtil::tableFromPairs(state, { { "Self", ESM::RT_Self }, { "Touch", ESM::RT_Touch }, { "Target", ESM::RT_Target }, })); magicApi["SPELL_TYPE"] - = LuaUtil::makeStrictReadOnly(LuaUtil::tableFromPairs(lua, + = LuaUtil::makeStrictReadOnly(LuaUtil::tableFromPairs(state, { { "Spell", ESM::Spell::ST_Spell }, { "Ability", ESM::Spell::ST_Ability }, @@ -235,7 +235,7 @@ namespace MWLua { "Power", ESM::Spell::ST_Power }, })); magicApi["ENCHANTMENT_TYPE"] - = LuaUtil::makeStrictReadOnly(LuaUtil::tableFromPairs(lua, + = LuaUtil::makeStrictReadOnly(LuaUtil::tableFromPairs(state, { { "CastOnce", ESM::Enchantment::Type::CastOnce }, { "CastOnStrike", ESM::Enchantment::Type::WhenStrikes }, @@ -243,7 +243,7 @@ namespace MWLua { "ConstantEffect", ESM::Enchantment::Type::ConstantEffect }, })); - sol::table effect(lua, sol::create); + sol::table effect(state, sol::create); magicApi["EFFECT_TYPE"] = LuaUtil::makeStrictReadOnly(effect); for (const auto& name : ESM::MagicEffect::sIndexNames) { @@ -251,22 +251,22 @@ namespace MWLua } // Spell store - sol::table spells(lua, sol::create); + sol::table spells(state, sol::create); addRecordFunctionBinding(spells, context); magicApi["spells"] = LuaUtil::makeReadOnly(spells); // Enchantment store - sol::table enchantments(lua, sol::create); + sol::table enchantments(state, sol::create); addRecordFunctionBinding(enchantments, context); magicApi["enchantments"] = LuaUtil::makeReadOnly(enchantments); // MagicEffect store - sol::table magicEffects(lua, sol::create); + sol::table magicEffects(state, sol::create); magicApi["effects"] = LuaUtil::makeReadOnly(magicEffects); using MagicEffectStore = MWWorld::Store; const MagicEffectStore* magicEffectStore = &MWBase::Environment::get().getWorld()->getStore().get(); - auto magicEffectStoreT = lua.new_usertype("ESM3_MagicEffectStore"); + auto magicEffectStoreT = state.new_usertype("ESM3_MagicEffectStore"); magicEffectStoreT[sol::meta_function::to_string] = [](const MagicEffectStore& store) { return "ESM3_MagicEffectStore{" + std::to_string(store.getSize()) + " effects}"; }; @@ -276,7 +276,7 @@ namespace MWLua int index = ESM::MagicEffect::indexNameToIndex(id); return store.search(index); }); - auto magicEffectsIter = [magicEffectStore](sol::this_state lua, const sol::object& /*store*/, + auto magicEffectsIter = [magicEffectStore](sol::this_state thisState, const sol::object& /*store*/, sol::optional id) -> std::tuple { MagicEffectStore::iterator iter; if (id.has_value()) @@ -288,19 +288,20 @@ namespace MWLua else iter = magicEffectStore->begin(); if (iter != magicEffectStore->end()) - return std::make_tuple(sol::make_object(lua, iter->first), sol::make_object(lua, &iter->second)); + return std::make_tuple( + sol::make_object(thisState, iter->first), sol::make_object(thisState, &iter->second)); else return std::make_tuple(sol::nil, sol::nil); }; magicEffectStoreT[sol::meta_function::pairs] - = [iter = sol::make_object(lua, magicEffectsIter)] { return iter; }; + = [iter = sol::make_object(state, magicEffectsIter)] { return iter; }; magicEffectStoreT[sol::meta_function::ipairs] - = [iter = sol::make_object(lua, magicEffectsIter)] { return iter; }; + = [iter = sol::make_object(state, magicEffectsIter)] { return iter; }; magicEffects["records"] = magicEffectStore; // Spell record - auto spellT = lua.new_usertype("ESM3_Spell"); + auto spellT = state.new_usertype("ESM3_Spell"); spellT[sol::meta_function::to_string] = [](const ESM::Spell& rec) -> std::string { return "ESM3_Spell[" + rec.mId.toDebugString() + "]"; }; spellT["id"] = sol::readonly_property([](const ESM::Spell& rec) { return rec.mId.serializeText(); }); @@ -313,12 +314,12 @@ namespace MWLua [](const ESM::Spell& rec) -> bool { return !!(rec.mData.mFlags & ESM::Spell::F_PCStart); }); spellT["autocalcFlag"] = sol::readonly_property( [](const ESM::Spell& rec) -> bool { return !!(rec.mData.mFlags & ESM::Spell::F_Autocalc); }); - spellT["effects"] = sol::readonly_property([lua = lua.lua_state()](const ESM::Spell& rec) -> sol::table { + spellT["effects"] = sol::readonly_property([lua = state.lua_state()](const ESM::Spell& rec) -> sol::table { return effectParamsListToTable(lua, rec.mEffects.mList); }); // Enchantment record - auto enchantT = lua.new_usertype("ESM3_Enchantment"); + auto enchantT = state.new_usertype("ESM3_Enchantment"); enchantT[sol::meta_function::to_string] = [](const ESM::Enchantment& rec) -> std::string { return "ESM3_Enchantment[" + rec.mId.toDebugString() + "]"; }; @@ -330,12 +331,12 @@ namespace MWLua enchantT["charge"] = sol::readonly_property([](const ESM::Enchantment& rec) -> int { return rec.mData.mCharge; }); enchantT["effects"] - = sol::readonly_property([lua = lua.lua_state()](const ESM::Enchantment& rec) -> sol::table { + = sol::readonly_property([lua = state.lua_state()](const ESM::Enchantment& rec) -> sol::table { return effectParamsListToTable(lua, rec.mEffects.mList); }); // Effect params - auto effectParamsT = lua.new_usertype("ESM3_EffectParams"); + auto effectParamsT = state.new_usertype("ESM3_EffectParams"); effectParamsT[sol::meta_function::to_string] = [magicEffectStore](const ESM::IndexedENAMstruct& params) { const ESM::MagicEffect* const rec = magicEffectStore->find(params.mData.mEffectID); return "ESM3_EffectParams[" + ESM::MagicEffect::indexToGmstString(rec->mIndex) + "]"; @@ -376,7 +377,7 @@ namespace MWLua = sol::readonly_property([](const ESM::IndexedENAMstruct& params) -> int { return params.mIndex; }); // MagicEffect record - auto magicEffectT = lua.new_usertype("ESM3_MagicEffect"); + auto magicEffectT = state.new_usertype("ESM3_MagicEffect"); magicEffectT[sol::meta_function::to_string] = [](const ESM::MagicEffect& rec) { return "ESM3_MagicEffect[" + ESM::MagicEffect::indexToGmstString(rec.mIndex) + "]"; @@ -444,78 +445,78 @@ namespace MWLua // magicEffectT["projectileSpeed"] // = sol::readonly_property([](const ESM::MagicEffect& rec) -> float { return rec.mData.mSpeed; }); - auto activeSpellEffectT = lua.new_usertype("ActiveSpellEffect"); - activeSpellEffectT[sol::meta_function::to_string] = [](const ESM::ActiveEffect& effect) { - return "ActiveSpellEffect[" + ESM::MagicEffect::indexToGmstString(effect.mEffectId) + "]"; + auto activeSpellEffectT = state.new_usertype("ActiveSpellEffect"); + activeSpellEffectT[sol::meta_function::to_string] = [](const ESM::ActiveEffect& self) { + return "ActiveSpellEffect[" + ESM::MagicEffect::indexToGmstString(self.mEffectId) + "]"; }; - activeSpellEffectT["id"] = sol::readonly_property([](const ESM::ActiveEffect& effect) -> std::string { - auto name = ESM::MagicEffect::indexToName(effect.mEffectId); + activeSpellEffectT["id"] = sol::readonly_property([](const ESM::ActiveEffect& self) -> std::string { + auto name = ESM::MagicEffect::indexToName(self.mEffectId); return Misc::StringUtils::lowerCase(name); }); activeSpellEffectT["index"] - = sol::readonly_property([](const ESM::ActiveEffect& effect) -> int { return effect.mEffectIndex; }); - activeSpellEffectT["name"] = sol::readonly_property([](const ESM::ActiveEffect& effect) -> std::string { - return MWMechanics::EffectKey(effect.mEffectId, effect.getSkillOrAttribute()).toString(); + = sol::readonly_property([](const ESM::ActiveEffect& self) -> int { return self.mEffectIndex; }); + activeSpellEffectT["name"] = sol::readonly_property([](const ESM::ActiveEffect& self) -> std::string { + return MWMechanics::EffectKey(self.mEffectId, self.getSkillOrAttribute()).toString(); }); activeSpellEffectT["affectedSkill"] - = sol::readonly_property([magicEffectStore](const ESM::ActiveEffect& effect) -> sol::optional { - auto* rec = magicEffectStore->find(effect.mEffectId); + = sol::readonly_property([magicEffectStore](const ESM::ActiveEffect& self) -> sol::optional { + auto* rec = magicEffectStore->find(self.mEffectId); if (rec->mData.mFlags & ESM::MagicEffect::TargetSkill) - return effect.getSkillOrAttribute().serializeText(); + return self.getSkillOrAttribute().serializeText(); else return sol::nullopt; }); activeSpellEffectT["affectedAttribute"] - = sol::readonly_property([magicEffectStore](const ESM::ActiveEffect& effect) -> sol::optional { - auto* rec = magicEffectStore->find(effect.mEffectId); + = sol::readonly_property([magicEffectStore](const ESM::ActiveEffect& self) -> sol::optional { + auto* rec = magicEffectStore->find(self.mEffectId); if (rec->mData.mFlags & ESM::MagicEffect::TargetAttribute) - return effect.getSkillOrAttribute().serializeText(); + return self.getSkillOrAttribute().serializeText(); else return sol::nullopt; }); activeSpellEffectT["magnitudeThisFrame"] - = sol::readonly_property([magicEffectStore](const ESM::ActiveEffect& effect) -> sol::optional { - auto* rec = magicEffectStore->find(effect.mEffectId); + = sol::readonly_property([magicEffectStore](const ESM::ActiveEffect& self) -> sol::optional { + auto* rec = magicEffectStore->find(self.mEffectId); if (rec->mData.mFlags & ESM::MagicEffect::Flags::NoMagnitude) return sol::nullopt; - return effect.mMagnitude; + return self.mMagnitude; }); activeSpellEffectT["minMagnitude"] - = sol::readonly_property([magicEffectStore](const ESM::ActiveEffect& effect) -> sol::optional { - auto* rec = magicEffectStore->find(effect.mEffectId); + = sol::readonly_property([magicEffectStore](const ESM::ActiveEffect& self) -> sol::optional { + auto* rec = magicEffectStore->find(self.mEffectId); if (rec->mData.mFlags & ESM::MagicEffect::Flags::NoMagnitude) return sol::nullopt; - return effect.mMinMagnitude; + return self.mMinMagnitude; }); activeSpellEffectT["maxMagnitude"] - = sol::readonly_property([magicEffectStore](const ESM::ActiveEffect& effect) -> sol::optional { - auto* rec = magicEffectStore->find(effect.mEffectId); + = sol::readonly_property([magicEffectStore](const ESM::ActiveEffect& self) -> sol::optional { + auto* rec = magicEffectStore->find(self.mEffectId); if (rec->mData.mFlags & ESM::MagicEffect::Flags::NoMagnitude) return sol::nullopt; - return effect.mMaxMagnitude; + return self.mMaxMagnitude; }); activeSpellEffectT["durationLeft"] - = sol::readonly_property([magicEffectStore](const ESM::ActiveEffect& effect) -> sol::optional { + = sol::readonly_property([magicEffectStore](const ESM::ActiveEffect& self) -> sol::optional { // Permanent/constant effects, abilities, etc. will have a negative duration - if (effect.mDuration < 0) + if (self.mDuration < 0) return sol::nullopt; - auto* rec = magicEffectStore->find(effect.mEffectId); + auto* rec = magicEffectStore->find(self.mEffectId); if (rec->mData.mFlags & ESM::MagicEffect::Flags::NoDuration) return sol::nullopt; - return effect.mTimeLeft; + return self.mTimeLeft; }); activeSpellEffectT["duration"] - = sol::readonly_property([magicEffectStore](const ESM::ActiveEffect& effect) -> sol::optional { + = sol::readonly_property([magicEffectStore](const ESM::ActiveEffect& self) -> sol::optional { // Permanent/constant effects, abilities, etc. will have a negative duration - if (effect.mDuration < 0) + if (self.mDuration < 0) return sol::nullopt; - auto* rec = magicEffectStore->find(effect.mEffectId); + auto* rec = magicEffectStore->find(self.mEffectId); if (rec->mData.mFlags & ESM::MagicEffect::Flags::NoDuration) return sol::nullopt; - return effect.mDuration; + return self.mDuration; }); - auto activeSpellT = lua.new_usertype("ActiveSpellParams"); + auto activeSpellT = state.new_usertype("ActiveSpellParams"); activeSpellT[sol::meta_function::to_string] = [](const ActiveSpell& activeSpell) { return "ActiveSpellParams[" + activeSpell.mParams.getSourceSpellId().serializeText() + "]"; }; @@ -525,7 +526,7 @@ namespace MWLua return activeSpell.mParams.getSourceSpellId().serializeText(); }); activeSpellT["item"] - = sol::readonly_property([lua = lua.lua_state()](const ActiveSpell& activeSpell) -> sol::object { + = sol::readonly_property([lua = state.lua_state()](const ActiveSpell& activeSpell) -> sol::object { auto item = activeSpell.mParams.getItem(); if (!item.isSet()) return sol::nil; @@ -538,7 +539,7 @@ namespace MWLua return sol::make_object(lua, LObject(itemPtr)); }); activeSpellT["caster"] - = sol::readonly_property([lua = lua.lua_state()](const ActiveSpell& activeSpell) -> sol::object { + = sol::readonly_property([lua = state.lua_state()](const ActiveSpell& activeSpell) -> sol::object { auto caster = MWBase::Environment::get().getWorld()->searchPtrViaActorId( activeSpell.mParams.getCasterActorId()); if (caster.isEmpty()) @@ -552,14 +553,14 @@ namespace MWLua } }); activeSpellT["effects"] - = sol::readonly_property([lua = lua.lua_state()](const ActiveSpell& activeSpell) -> sol::table { + = sol::readonly_property([lua = state.lua_state()](const ActiveSpell& activeSpell) -> sol::table { sol::table res(lua, sol::create); size_t tableIndex = 0; - for (const ESM::ActiveEffect& effect : activeSpell.mParams.getEffects()) + for (const ESM::ActiveEffect& e : activeSpell.mParams.getEffects()) { - if (!(effect.mFlags & ESM::ActiveEffect::Flag_Applied)) + if (!(e.mFlags & ESM::ActiveEffect::Flag_Applied)) continue; - res[++tableIndex] = effect; // ESM::ActiveEffect (effect params) + res[++tableIndex] = e; // ESM::ActiveEffect (effect params) } return res; }); @@ -579,39 +580,39 @@ namespace MWLua return activeSpell.mParams.getActiveSpellId().serializeText(); }); - auto activeEffectT = lua.new_usertype("ActiveEffect"); + auto activeEffectT = state.new_usertype("ActiveEffect"); - activeEffectT[sol::meta_function::to_string] = [](const ActiveEffect& effect) { - return "ActiveEffect[" + ESM::MagicEffect::indexToGmstString(effect.key.mId) + "]"; + activeEffectT[sol::meta_function::to_string] = [](const ActiveEffect& self) { + return "ActiveEffect[" + ESM::MagicEffect::indexToGmstString(self.key.mId) + "]"; }; - activeEffectT["id"] = sol::readonly_property([](const ActiveEffect& effect) -> std::string { - auto name = ESM::MagicEffect::indexToName(effect.key.mId); + activeEffectT["id"] = sol::readonly_property([](const ActiveEffect& self) -> std::string { + auto name = ESM::MagicEffect::indexToName(self.key.mId); return Misc::StringUtils::lowerCase(name); }); activeEffectT["name"] - = sol::readonly_property([](const ActiveEffect& effect) -> std::string { return effect.key.toString(); }); + = sol::readonly_property([](const ActiveEffect& self) -> std::string { return self.key.toString(); }); activeEffectT["affectedSkill"] - = sol::readonly_property([magicEffectStore](const ActiveEffect& effect) -> sol::optional { - auto* rec = magicEffectStore->find(effect.key.mId); + = sol::readonly_property([magicEffectStore](const ActiveEffect& self) -> sol::optional { + auto* rec = magicEffectStore->find(self.key.mId); if (rec->mData.mFlags & ESM::MagicEffect::TargetSkill) - return effect.key.mArg.serializeText(); + return self.key.mArg.serializeText(); return sol::nullopt; }); activeEffectT["affectedAttribute"] - = sol::readonly_property([magicEffectStore](const ActiveEffect& effect) -> sol::optional { - auto* rec = magicEffectStore->find(effect.key.mId); + = sol::readonly_property([magicEffectStore](const ActiveEffect& self) -> sol::optional { + auto* rec = magicEffectStore->find(self.key.mId); if (rec->mData.mFlags & ESM::MagicEffect::TargetAttribute) - return effect.key.mArg.serializeText(); + return self.key.mArg.serializeText(); return sol::nullopt; }); activeEffectT["magnitude"] - = sol::readonly_property([](const ActiveEffect& effect) { return effect.param.getMagnitude(); }); + = sol::readonly_property([](const ActiveEffect& self) { return self.param.getMagnitude(); }); activeEffectT["magnitudeBase"] - = sol::readonly_property([](const ActiveEffect& effect) { return effect.param.getBase(); }); + = sol::readonly_property([](const ActiveEffect& self) { return self.param.getBase(); }); activeEffectT["magnitudeModifier"] - = sol::readonly_property([](const ActiveEffect& effect) { return effect.param.getModifier(); }); + = sol::readonly_property([](const ActiveEffect& self) { return self.param.getModifier(); }); return LuaUtil::makeReadOnly(magicApi); } @@ -633,10 +634,10 @@ namespace MWLua const MWWorld::ESMStore& esmStore = *MWBase::Environment::get().getESMStore(); - auto getEffectsFromIndexes = [&](const ESM::EffectList& effects) { + auto getEffectsFromIndexes = [&](const ESM::EffectList& effectList) { std::vector enams; for (auto index : effectIndexes) - enams.push_back(effects.mList.at(index)); + enams.push_back(effectList.mList.at(index)); return enams; }; @@ -690,24 +691,24 @@ namespace MWLua void addActorMagicBindings(sol::table& actor, const Context& context) { - auto lua = context.sol(); + sol::state_view state = context.sol(); const MWWorld::Store* spellStore = &MWBase::Environment::get().getWorld()->getStore().get(); // types.Actor.spells(o) - actor["spells"] = [](const sol::object& actor) { return ActorSpells{ actor }; }; - auto spellsT = lua.new_usertype("ActorSpells"); + actor["spells"] = [](const sol::object& object) { return ActorSpells{ object }; }; + auto spellsT = state.new_usertype("ActorSpells"); spellsT[sol::meta_function::to_string] = [](const ActorSpells& spells) { return "ActorSpells[" + spells.mActor.object().toString() + "]"; }; - actor["activeSpells"] = [](const sol::object& actor) { return ActorActiveSpells{ actor }; }; - auto activeSpellsT = lua.new_usertype("ActorActiveSpells"); + actor["activeSpells"] = [](const sol::object& object) { return ActorActiveSpells{ object }; }; + auto activeSpellsT = state.new_usertype("ActorActiveSpells"); activeSpellsT[sol::meta_function::to_string] = [](const ActorActiveSpells& spells) { return "ActorActiveSpells[" + spells.mActor.object().toString() + "]"; }; - actor["activeEffects"] = [](const sol::object& actor) { return ActorActiveEffects{ actor }; }; - auto activeEffectsT = lua.new_usertype("ActorActiveEffects"); + actor["activeEffects"] = [](const sol::object& object) { return ActorActiveEffects{ object }; }; + auto activeEffectsT = state.new_usertype("ActorActiveEffects"); activeEffectsT[sol::meta_function::to_string] = [](const ActorActiveEffects& effects) { return "ActorActiveEffects[" + effects.mActor.object().toString() + "]"; }; @@ -741,15 +742,15 @@ namespace MWLua throw std::runtime_error("Ability or disease can not be casted: " + spellId.toDebugString()); } context.mLuaManager->addAction([obj = Object(ptr), spellId]() { - const MWWorld::Ptr& ptr = obj.ptr(); - auto& stats = ptr.getClass().getCreatureStats(ptr); + const MWWorld::Ptr& objPtr = obj.ptr(); + auto& stats = objPtr.getClass().getCreatureStats(objPtr); // We need to deselect any enchant items before we can select a spell otherwise the item will be // reselected const auto resetEnchantItem = [&]() { - if (ptr.getClass().hasInventoryStore(ptr)) + if (objPtr.getClass().hasInventoryStore(objPtr)) { - MWWorld::InventoryStore& inventory = ptr.getClass().getInventoryStore(ptr); + MWWorld::InventoryStore& inventory = objPtr.getClass().getInventoryStore(objPtr); inventory.setSelectedEnchantItem(inventory.end()); } }; @@ -757,7 +758,7 @@ namespace MWLua if (spellId.empty()) { resetEnchantItem(); - if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) + if (objPtr == MWBase::Environment::get().getWorld()->getPlayerPtr()) MWBase::Environment::get().getWindowManager()->unsetSelectedSpell(); else stats.getSpells().setSelectedSpell(ESM::RefId()); @@ -767,9 +768,9 @@ namespace MWLua throw std::runtime_error("Actor doesn't know spell " + spellId.toDebugString()); resetEnchantItem(); - if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) + if (objPtr == MWBase::Environment::get().getWorld()->getPlayerPtr()) { - int chance = MWMechanics::getSpellSuccessChance(spellId, ptr); + int chance = MWMechanics::getSpellSuccessChance(spellId, objPtr); MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, chance); } else @@ -821,10 +822,10 @@ namespace MWLua }); // pairs(types.Actor.spells(o)) - spellsT[sol::meta_function::pairs] = lua["ipairsForArray"].template get(); + spellsT[sol::meta_function::pairs] = state["ipairsForArray"].template get(); // ipairs(types.Actor.spells(o)) - spellsT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get(); + spellsT[sol::meta_function::ipairs] = state["ipairsForArray"].template get(); // types.Actor.spells(o):add(id) spellsT["add"] = [context](const ActorSpells& spells, const sol::object& spellOrId) { diff --git a/apps/openmw/mwlua/menuscripts.cpp b/apps/openmw/mwlua/menuscripts.cpp index cf747c1ecb..6387a3dce1 100644 --- a/apps/openmw/mwlua/menuscripts.cpp +++ b/apps/openmw/mwlua/menuscripts.cpp @@ -81,16 +81,16 @@ namespace MWLua manager->saveGame(description, slot); }; - auto getSaves = [](sol::state_view lua, const MWState::Character& character) { - sol::table saves(lua, sol::create); + auto getSaves = [](sol::state_view currentState, const MWState::Character& character) { + sol::table saves(currentState, sol::create); for (const MWState::Slot& slot : character) { - sol::table slotInfo(lua, sol::create); + sol::table slotInfo(currentState, sol::create); slotInfo["description"] = slot.mProfile.mDescription; slotInfo["playerName"] = slot.mProfile.mPlayerName; slotInfo["playerLevel"] = slot.mProfile.mPlayerLevel; slotInfo["timePlayed"] = slot.mProfile.mTimePlayed; - sol::table contentFiles(lua, sol::create); + sol::table contentFiles(currentState, sol::create); for (size_t i = 0; i < slot.mProfile.mContentFiles.size(); ++i) contentFiles[LuaUtil::toLuaIndex(i)] = Misc::StringUtils::lowerCase(slot.mProfile.mContentFiles[i]); @@ -106,18 +106,18 @@ namespace MWLua return saves; }; - api["getSaves"] = [getSaves](sol::this_state lua, std::string_view dir) -> sol::table { + api["getSaves"] = [getSaves](sol::this_state thisState, std::string_view dir) -> sol::table { const MWState::Character* character = findCharacter(dir); if (!character) throw std::runtime_error("Saves not found: " + std::string(dir)); - return getSaves(lua, *character); + return getSaves(thisState, *character); }; - api["getAllSaves"] = [getSaves](sol::this_state lua) -> sol::table { - sol::table saves(lua, sol::create); + api["getAllSaves"] = [getSaves](sol::this_state thisState) -> sol::table { + sol::table saves(thisState, sol::create); MWBase::StateManager* manager = MWBase::Environment::get().getStateManager(); for (auto it = manager->characterBegin(); it != manager->characterEnd(); ++it) - saves[it->getPath().filename().string()] = getSaves(lua, *it); + saves[it->getPath().filename().string()] = getSaves(thisState, *it); return saves; }; diff --git a/apps/openmw/mwlua/objectbindings.cpp b/apps/openmw/mwlua/objectbindings.cpp index 0a73acfc42..2a0aa87d15 100644 --- a/apps/openmw/mwlua/objectbindings.cpp +++ b/apps/openmw/mwlua/objectbindings.cpp @@ -445,16 +445,16 @@ namespace MWLua if (!ptr.getContainerStore() && currentCount > countToRemove) return std::nullopt; // Delayed action to trigger side effects - return [signedCountToRemove](MWWorld::Ptr ptr) { + return [signedCountToRemove](MWWorld::Ptr p) { // Restore the original count - ptr.getCellRef().setCount(ptr.getCellRef().getCount(false) + signedCountToRemove); + p.getCellRef().setCount(p.getCellRef().getCount(false) + signedCountToRemove); // And now remove properly - if (ptr.getContainerStore()) - ptr.getContainerStore()->remove(ptr, std::abs(signedCountToRemove), false); + if (p.getContainerStore()) + p.getContainerStore()->remove(p, std::abs(signedCountToRemove), false); else { - MWBase::Environment::get().getWorld()->disable(ptr); - MWBase::Environment::get().getWorld()->deleteObject(ptr); + MWBase::Environment::get().getWorld()->disable(p); + MWBase::Environment::get().getWorld()->deleteObject(p); } }; }; diff --git a/apps/openmw/mwlua/postprocessingbindings.cpp b/apps/openmw/mwlua/postprocessingbindings.cpp index 6d0c33848a..eb272ed18a 100644 --- a/apps/openmw/mwlua/postprocessingbindings.cpp +++ b/apps/openmw/mwlua/postprocessingbindings.cpp @@ -110,67 +110,69 @@ namespace MWLua sol::state_view lua = context.sol(); sol::table api(lua, sol::create); - sol::usertype shader = lua.new_usertype("Shader"); - shader[sol::meta_function::to_string] = [](const Shader& shader) { return shader.toString(); }; + { + sol::usertype shader = lua.new_usertype("Shader"); + shader[sol::meta_function::to_string] = [](const Shader& self) { return self.toString(); }; - shader["enable"] = [context](Shader& shader, sol::optional optPos) { - std::optional pos = std::nullopt; - if (optPos) - pos = optPos.value(); + shader["enable"] = [context](Shader& self, sol::optional optPos) { + std::optional pos = std::nullopt; + if (optPos) + pos = optPos.value(); - if (shader.mShader && shader.mShader->isValid()) - shader.mQueuedAction = Shader::Action_Enable; + if (self.mShader && self.mShader->isValid()) + self.mQueuedAction = Shader::Action_Enable; - context.mLuaManager->addAction([=, &shader] { - shader.mQueuedAction = Shader::Action_None; + context.mLuaManager->addAction([=, &self] { + self.mQueuedAction = Shader::Action_None; - if (MWBase::Environment::get().getWorld()->getPostProcessor()->enableTechnique(shader.mShader, pos) - == MWRender::PostProcessor::Status_Error) - throw std::runtime_error("Failed enabling shader '" + shader.mShader->getName() + "'"); - }); - }; + if (MWBase::Environment::get().getWorld()->getPostProcessor()->enableTechnique(self.mShader, pos) + == MWRender::PostProcessor::Status_Error) + throw std::runtime_error("Failed enabling shader '" + self.mShader->getName() + "'"); + }); + }; - shader["disable"] = [context](Shader& shader) { - shader.mQueuedAction = Shader::Action_Disable; + shader["disable"] = [context](Shader& self) { + self.mQueuedAction = Shader::Action_Disable; - context.mLuaManager->addAction([&] { - shader.mQueuedAction = Shader::Action_None; + context.mLuaManager->addAction([&] { + self.mQueuedAction = Shader::Action_None; - if (MWBase::Environment::get().getWorld()->getPostProcessor()->disableTechnique(shader.mShader) - == MWRender::PostProcessor::Status_Error) - throw std::runtime_error("Failed disabling shader '" + shader.mShader->getName() + "'"); - }); - }; + if (MWBase::Environment::get().getWorld()->getPostProcessor()->disableTechnique(self.mShader) + == MWRender::PostProcessor::Status_Error) + throw std::runtime_error("Failed disabling shader '" + self.mShader->getName() + "'"); + }); + }; - shader["isEnabled"] = [](const Shader& shader) { - if (shader.mQueuedAction == Shader::Action_Enable) - return true; - else if (shader.mQueuedAction == Shader::Action_Disable) - return false; - return MWBase::Environment::get().getWorld()->getPostProcessor()->isTechniqueEnabled(shader.mShader); - }; + shader["isEnabled"] = [](const Shader& self) { + if (self.mQueuedAction == Shader::Action_Enable) + return true; + else if (self.mQueuedAction == Shader::Action_Disable) + return false; + return MWBase::Environment::get().getWorld()->getPostProcessor()->isTechniqueEnabled(self.mShader); + }; - shader["name"] = sol::readonly_property( - [](const Shader& shader) { return getLocalizedMyGUIString(shader.mShader->getName()); }); - shader["author"] = sol::readonly_property( - [](const Shader& shader) { return getLocalizedMyGUIString(shader.mShader->getAuthor()); }); - shader["description"] = sol::readonly_property( - [](const Shader& shader) { return getLocalizedMyGUIString(shader.mShader->getDescription()); }); - shader["version"] = sol::readonly_property( - [](const Shader& shader) { return getLocalizedMyGUIString(shader.mShader->getVersion()); }); + shader["name"] = sol::readonly_property( + [](const Shader& self) { return getLocalizedMyGUIString(self.mShader->getName()); }); + shader["author"] = sol::readonly_property( + [](const Shader& self) { return getLocalizedMyGUIString(self.mShader->getAuthor()); }); + shader["description"] = sol::readonly_property( + [](const Shader& self) { return getLocalizedMyGUIString(self.mShader->getDescription()); }); + shader["version"] = sol::readonly_property( + [](const Shader& self) { return getLocalizedMyGUIString(self.mShader->getVersion()); }); - shader["setBool"] = getSetter(context); - shader["setFloat"] = getSetter(context); - shader["setInt"] = getSetter(context); - shader["setVector2"] = getSetter(context); - shader["setVector3"] = getSetter(context); - shader["setVector4"] = getSetter(context); + shader["setBool"] = getSetter(context); + shader["setFloat"] = getSetter(context); + shader["setInt"] = getSetter(context); + shader["setVector2"] = getSetter(context); + shader["setVector3"] = getSetter(context); + shader["setVector4"] = getSetter(context); - shader["setFloatArray"] = getArraySetter(context); - shader["setIntArray"] = getArraySetter(context); - shader["setVector2Array"] = getArraySetter(context); - shader["setVector3Array"] = getArraySetter(context); - shader["setVector4Array"] = getArraySetter(context); + shader["setFloatArray"] = getArraySetter(context); + shader["setIntArray"] = getArraySetter(context); + shader["setVector2Array"] = getArraySetter(context); + shader["setVector3Array"] = getArraySetter(context); + shader["setVector4Array"] = getArraySetter(context); + } api["load"] = [](const std::string& name) { Shader shader{ MWBase::Environment::get().getWorld()->getPostProcessor()->loadTechnique(name, false) }; diff --git a/apps/openmw/mwlua/recordstore.hpp b/apps/openmw/mwlua/recordstore.hpp index f2fb4ed453..4f6e37a6b8 100644 --- a/apps/openmw/mwlua/recordstore.hpp +++ b/apps/openmw/mwlua/recordstore.hpp @@ -47,18 +47,18 @@ namespace MWLua using StoreT = MWWorld::Store; sol::state_view lua = context.sol(); sol::usertype storeT = lua.new_usertype(recordName + "WorldStore"); - storeT[sol::meta_function::to_string] = [recordName](const StoreT& store) { - return "{" + std::to_string(store.getSize()) + " " + recordName + " records}"; + storeT[sol::meta_function::to_string] = [recordName](const StoreT& self) { + return "{" + std::to_string(self.getSize()) + " " + recordName + " records}"; }; - storeT[sol::meta_function::length] = [](const StoreT& store) { return store.getSize(); }; + storeT[sol::meta_function::length] = [](const StoreT& self) { return self.getSize(); }; storeT[sol::meta_function::index] = sol::overload( - [](const StoreT& store, size_t index) -> const T* { - if (index == 0 || index > store.getSize()) + [](const StoreT& self, size_t index) -> const T* { + if (index == 0 || index > self.getSize()) return nullptr; - return store.at(LuaUtil::fromLuaIndex(index)); + return self.at(LuaUtil::fromLuaIndex(index)); }, - [](const StoreT& store, std::string_view id) -> const T* { - return store.search(ESM::RefId::deserializeText(id)); + [](const StoreT& self, std::string_view id) -> const T* { + return self.search(ESM::RefId::deserializeText(id)); }); storeT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get(); storeT[sol::meta_function::pairs] = lua["ipairsForArray"].template get(); @@ -67,4 +67,5 @@ namespace MWLua table["records"] = &store; } } + #endif // MWLUA_RECORDSTORE_H diff --git a/apps/openmw/mwlua/stats.cpp b/apps/openmw/mwlua/stats.cpp index 8b103d5943..52e4986e40 100644 --- a/apps/openmw/mwlua/stats.cpp +++ b/apps/openmw/mwlua/stats.cpp @@ -107,8 +107,7 @@ namespace MWLua sol::object get(const Context& context, ESM::StringRefId attributeId) const { - const auto& ptr = mObject.ptr(); - if (!ptr.getClass().isNpc()) + if (!mObject.ptr().getClass().isNpc()) return sol::nil; return getValue(context, mObject, &setNpcValue, attributeId, "skillIncreasesForAttribute", @@ -142,8 +141,7 @@ namespace MWLua sol::object get(const Context& context, int specialization) const { - const auto& ptr = mObject.ptr(); - if (!ptr.getClass().isNpc()) + if (!mObject.ptr().getClass().isNpc()) return sol::nil; return getValue(context, mObject, &setNpcValue, specialization, "skillIncreasesForSpecialization", @@ -192,8 +190,7 @@ namespace MWLua sol::object getProgress(const Context& context) const { - const auto& ptr = mObject.ptr(); - if (!ptr.getClass().isNpc()) + if (!mObject.ptr().getClass().isNpc()) return sol::nil; return getValue(context, mObject, &setNpcValue, std::monostate{}, "progress", diff --git a/apps/openmw/mwlua/types/actor.cpp b/apps/openmw/mwlua/types/actor.cpp index 29882f6dcb..8ce7473061 100644 --- a/apps/openmw/mwlua/types/actor.cpp +++ b/apps/openmw/mwlua/types/actor.cpp @@ -248,7 +248,7 @@ namespace MWLua stats.setDrawState(newDrawState); }; - actor["getSelectedEnchantedItem"] = [](sol::this_state lua, const Object& o) -> sol::object { + actor["getSelectedEnchantedItem"] = [](sol::this_state thisState, const Object& o) -> sol::object { const MWWorld::Ptr& ptr = o.ptr(); if (!ptr.getClass().hasInventoryStore(ptr)) return sol::nil; @@ -258,9 +258,9 @@ namespace MWLua return sol::nil; MWBase::Environment::get().getWorldModel()->registerPtr(*it); if (dynamic_cast(&o)) - return sol::make_object(lua, GObject(*it)); + return sol::make_object(thisState, GObject(*it)); else - return sol::make_object(lua, LObject(*it)); + return sol::make_object(thisState, LObject(*it)); }; actor["setSelectedEnchantedItem"] = [context](const SelfObject& obj, const sol::object& item) { const MWWorld::Ptr& ptr = obj.ptr(); @@ -310,9 +310,9 @@ namespace MWLua actor["inventory"] = sol::overload([](const LObject& o) { return Inventory{ o }; }, [](const GObject& o) { return Inventory{ o }; }); - auto getAllEquipment = [](sol::this_state lua, const Object& o) { + auto getAllEquipment = [](sol::this_state thisState, const Object& o) { const MWWorld::Ptr& ptr = o.ptr(); - sol::table equipment(lua, sol::create); + sol::table equipment(thisState, sol::create); if (!ptr.getClass().hasInventoryStore(ptr)) return equipment; @@ -324,13 +324,13 @@ namespace MWLua continue; MWBase::Environment::get().getWorldModel()->registerPtr(*it); if (dynamic_cast(&o)) - equipment[slot] = sol::make_object(lua, GObject(*it)); + equipment[slot] = sol::make_object(thisState, GObject(*it)); else - equipment[slot] = sol::make_object(lua, LObject(*it)); + equipment[slot] = sol::make_object(thisState, LObject(*it)); } return equipment; }; - auto getEquipmentFromSlot = [](sol::this_state lua, const Object& o, int slot) -> sol::object { + auto getEquipmentFromSlot = [](sol::this_state thisState, const Object& o, int slot) -> sol::object { const MWWorld::Ptr& ptr = o.ptr(); if (!ptr.getClass().hasInventoryStore(ptr)) return sol::nil; @@ -340,9 +340,9 @@ namespace MWLua return sol::nil; MWBase::Environment::get().getWorldModel()->registerPtr(*it); if (dynamic_cast(&o)) - return sol::make_object(lua, GObject(*it)); + return sol::make_object(thisState, GObject(*it)); else - return sol::make_object(lua, LObject(*it)); + return sol::make_object(thisState, LObject(*it)); }; actor["getEquipment"] = sol::overload(getAllEquipment, getEquipmentFromSlot); actor["equipment"] = actor["getEquipment"]; // for compatibility; should be removed later @@ -373,10 +373,10 @@ namespace MWLua context.mLuaManager->addAction( [obj = Object(ptr), eqp = std::move(eqp)] { setEquipment(obj.ptr(), eqp); }, "SetEquipmentAction"); }; - actor["getPathfindingAgentBounds"] = [](sol::this_state lua, const LObject& o) { + actor["getPathfindingAgentBounds"] = [](sol::this_state thisState, const LObject& o) { const DetourNavigator::AgentBounds agentBounds = MWBase::Environment::get().getWorld()->getPathfindingAgentBounds(o.ptr()); - sol::table result(lua, sol::create); + sol::table result(thisState, sol::create); result["shapeType"] = agentBounds.mShapeType; result["halfExtents"] = agentBounds.mHalfExtents; return result; @@ -410,13 +410,13 @@ namespace MWLua return target.getClass().getCreatureStats(target).isDeathAnimationFinished(); }; - actor["getEncumbrance"] = [](const Object& actor) -> float { - const MWWorld::Ptr ptr = actor.ptr(); + actor["getEncumbrance"] = [](const Object& object) -> float { + const MWWorld::Ptr ptr = object.ptr(); return ptr.getClass().getEncumbrance(ptr); }; - actor["getCapacity"] = [](const Object& actor) -> float { - const MWWorld::Ptr ptr = actor.ptr(); + actor["getCapacity"] = [](const Object& object) -> float { + const MWWorld::Ptr ptr = object.ptr(); return ptr.getClass().getCapacity(ptr); }; diff --git a/apps/openmw/mwlua/types/book.cpp b/apps/openmw/mwlua/types/book.cpp index b133a90c3a..006fbd8092 100644 --- a/apps/openmw/mwlua/types/book.cpp +++ b/apps/openmw/mwlua/types/book.cpp @@ -120,8 +120,7 @@ namespace MWLua record["enchantCapacity"] = sol::readonly_property([](const ESM::Book& rec) -> float { return rec.mData.mEnchant * 0.1f; }); record["skill"] = sol::readonly_property([](const ESM::Book& rec) -> sol::optional { - ESM::RefId skill = ESM::Skill::indexToRefId(rec.mData.mSkillId); - return LuaUtil::serializeRefId(skill); + return LuaUtil::serializeRefId(ESM::Skill::indexToRefId(rec.mData.mSkillId)); }); } } diff --git a/apps/openmw/mwlua/types/door.cpp b/apps/openmw/mwlua/types/door.cpp index 5db6f9b875..61dcc66a45 100644 --- a/apps/openmw/mwlua/types/door.cpp +++ b/apps/openmw/mwlua/types/door.cpp @@ -51,20 +51,20 @@ namespace MWLua { "Closing", MWWorld::DoorState::Closing }, })); door["getDoorState"] = [](const Object& o) -> MWWorld::DoorState { - const MWWorld::Ptr& door = doorPtr(o); - return door.getClass().getDoorState(door); + const MWWorld::Ptr& ptr = doorPtr(o); + return ptr.getClass().getDoorState(ptr); }; door["isOpen"] = [](const Object& o) { - const MWWorld::Ptr& door = doorPtr(o); - bool doorIsIdle = door.getClass().getDoorState(door) == MWWorld::DoorState::Idle; - bool doorIsOpen = door.getRefData().getPosition().rot[2] != door.getCellRef().getPosition().rot[2]; + const MWWorld::Ptr& ptr = doorPtr(o); + bool doorIsIdle = ptr.getClass().getDoorState(ptr) == MWWorld::DoorState::Idle; + bool doorIsOpen = ptr.getRefData().getPosition().rot[2] != ptr.getCellRef().getPosition().rot[2]; return doorIsIdle && doorIsOpen; }; door["isClosed"] = [](const Object& o) { - const MWWorld::Ptr& door = doorPtr(o); - bool doorIsIdle = door.getClass().getDoorState(door) == MWWorld::DoorState::Idle; - bool doorIsOpen = door.getRefData().getPosition().rot[2] != door.getCellRef().getPosition().rot[2]; + const MWWorld::Ptr& ptr = doorPtr(o); + bool doorIsIdle = ptr.getClass().getDoorState(ptr) == MWWorld::DoorState::Idle; + bool doorIsOpen = ptr.getRefData().getPosition().rot[2] != ptr.getCellRef().getPosition().rot[2]; return doorIsIdle && !doorIsOpen; }; @@ -74,15 +74,15 @@ namespace MWLua if (!allowChanges) throw std::runtime_error("Can only be used in global scripts or in local scripts on self."); - const MWWorld::Ptr& door = doorPtr(o); + const MWWorld::Ptr& ptr = doorPtr(o); auto world = MWBase::Environment::get().getWorld(); if (!openState.has_value()) - world->activateDoor(door); + world->activateDoor(ptr); else if (*openState) - world->activateDoor(door, MWWorld::DoorState::Opening); + world->activateDoor(ptr, MWWorld::DoorState::Opening); else - world->activateDoor(door, MWWorld::DoorState::Closing); + world->activateDoor(ptr, MWWorld::DoorState::Closing); }; door["isTeleport"] = [](const Object& o) { return doorPtr(o).getCellRef().getTeleport(); }; door["destPosition"] @@ -90,15 +90,15 @@ namespace MWLua door["destRotation"] = [](const Object& o) -> LuaUtil::TransformQ { return { Misc::Convert::makeOsgQuat(doorPtr(o).getCellRef().getDoorDest().rot) }; }; - door["destCell"] = [](sol::this_state lua, const Object& o) -> sol::object { + door["destCell"] = [](sol::this_state thisState, const Object& o) -> sol::object { const MWWorld::CellRef& cellRef = doorPtr(o).getCellRef(); if (!cellRef.getTeleport()) return sol::nil; MWWorld::CellStore& cell = MWBase::Environment::get().getWorldModel()->getCell(cellRef.getDestCell()); if (dynamic_cast(&o)) - return sol::make_object(lua, GCell{ &cell }); + return sol::make_object(thisState, GCell{ &cell }); else - return sol::make_object(lua, LCell{ &cell }); + return sol::make_object(thisState, LCell{ &cell }); }; addRecordFunctionBinding(door, context); diff --git a/apps/openmw/mwlua/types/npc.cpp b/apps/openmw/mwlua/types/npc.cpp index e847357bd9..15022b79c7 100644 --- a/apps/openmw/mwlua/types/npc.cpp +++ b/apps/openmw/mwlua/types/npc.cpp @@ -466,10 +466,10 @@ namespace MWLua ESM::RefId factionId = parseFactionId(faction); return ptr.getClass().getNpcStats(ptr).getExpelled(factionId); }; - npc["getFactions"] = [](sol::this_state lua, const Object& actor) { + npc["getFactions"] = [](sol::this_state thisState, const Object& actor) { const MWWorld::Ptr ptr = actor.ptr(); MWMechanics::NpcStats& npcStats = ptr.getClass().getNpcStats(ptr); - sol::table res(lua, sol::create); + sol::table res(thisState, sol::create); if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) { for (const auto& [factionId, _] : npcStats.getFactionRanks()) diff --git a/apps/openmw/mwlua/types/player.cpp b/apps/openmw/mwlua/types/player.cpp index db794b2301..d8dda4202d 100644 --- a/apps/openmw/mwlua/types/player.cpp +++ b/apps/openmw/mwlua/types/player.cpp @@ -289,28 +289,28 @@ namespace MWLua sol::state_view lua = context.sol(); addJournalEntryBindings(player, lua, journal); - player["quests"] = [](const Object& player) { - verifyPlayer(player); - bool allowChanges = dynamic_cast(&player) != nullptr - || dynamic_cast(&player) != nullptr; + player["quests"] = [](const Object& object) { + verifyPlayer(object); + bool allowChanges = dynamic_cast(&object) != nullptr + || dynamic_cast(&object) != nullptr; return Quests{ .mMutable = allowChanges }; }; sol::usertype quests = lua.new_usertype("Quests"); - quests[sol::meta_function::to_string] = [](const Quests& quests) { return "Quests"; }; - quests[sol::meta_function::index] = [](const Quests& quests, std::string_view questId) -> sol::optional { + quests[sol::meta_function::to_string] = [](const Quests& /*self*/) { return "Quests"; }; + quests[sol::meta_function::index] = [](const Quests& self, std::string_view questId) -> sol::optional { ESM::RefId quest = ESM::RefId::deserializeText(questId); const ESM::Dialogue* dial = MWBase::Environment::get().getESMStore()->get().search(quest); if (dial == nullptr || dial->mType != ESM::Dialogue::Journal) return sol::nullopt; - return Quest{ .mQuestId = quest, .mMutable = quests.mMutable }; + return Quest{ .mQuestId = quest, .mMutable = self.mMutable }; }; - quests[sol::meta_function::pairs] = [journal](const Quests& quests) { + quests[sol::meta_function::pairs] = [journal](const Quests& self) { std::vector ids; for (auto it = journal->questBegin(); it != journal->questEnd(); ++it) ids.push_back(it->first); size_t i = 0; return [ids = std::move(ids), i, - allowChanges = quests.mMutable]() mutable -> sol::optional> { + allowChanges = self.mMutable]() mutable -> sol::optional> { if (i >= ids.size()) return sol::nullopt; const ESM::RefId& id = ids[i++]; @@ -320,19 +320,19 @@ namespace MWLua sol::usertype quest = lua.new_usertype("Quest"); quest[sol::meta_function::to_string] - = [](const Quest& quest) { return "Quest[" + quest.mQuestId.serializeText() + "]"; }; + = [](const Quest& self) { return "Quest[" + self.mQuestId.serializeText() + "]"; }; - auto getQuestStage = [journal](const Quest& q) -> int { - const MWDialogue::Quest* quest = journal->getQuestOrNull(q.mQuestId); - if (quest == nullptr) + auto getQuestStage = [journal](const Quest& self) -> int { + const MWDialogue::Quest* questPtr = journal->getQuestOrNull(self.mQuestId); + if (questPtr == nullptr) return 0; - return journal->getJournalIndex(q.mQuestId); + return journal->getJournalIndex(self.mQuestId); }; - auto setQuestStage = [context](const Quest& q, int stage) { - if (!q.mMutable) + auto setQuestStage = [context](const Quest& self, int stage) { + if (!self.mMutable) throw std::runtime_error("Value can only be changed in global or player scripts!"); context.mLuaManager->addAction( - [q, stage] { MWBase::Environment::get().getJournal()->setJournalIndex(q.mQuestId, stage); }, + [self, stage] { MWBase::Environment::get().getJournal()->setJournalIndex(self.mQuestId, stage); }, "setQuestStageAction"); }; quest["stage"] = sol::property(getQuestStage, setQuestStage); @@ -342,10 +342,10 @@ namespace MWLua [journal](const Quest& q) { return journal->getQuestOrNull(q.mQuestId) != nullptr; }); quest["finished"] = sol::property( [journal](const Quest& q) -> bool { - const MWDialogue::Quest* quest = journal->getQuestOrNull(q.mQuestId); - if (quest == nullptr) + const MWDialogue::Quest* questPtr = journal->getQuestOrNull(q.mQuestId); + if (questPtr == nullptr) return false; - return quest->isFinished(); + return questPtr->isFinished(); }, [journal, context](const Quest& q, bool finished) { if (!q.mMutable) @@ -382,28 +382,28 @@ namespace MWLua })); MWBase::InputManager* input = MWBase::Environment::get().getInputManager(); - player["getControlSwitch"] = [input](const Object& player, std::string_view key) { - verifyPlayer(player); + player["getControlSwitch"] = [input](const Object& object, std::string_view key) { + verifyPlayer(object); return input->getControlSwitch(key); }; - player["setControlSwitch"] = [input](const Object& player, std::string_view key, bool v) { - verifyPlayer(player); - if (dynamic_cast(&player) && !dynamic_cast(&player)) + player["setControlSwitch"] = [input](const Object& object, std::string_view key, bool v) { + verifyPlayer(object); + if (dynamic_cast(&object) && !dynamic_cast(&object)) throw std::runtime_error("Only player and global scripts can toggle control switches."); input->toggleControlSwitch(key, v); }; - player["isTeleportingEnabled"] = [](const Object& player) -> bool { - verifyPlayer(player); + player["isTeleportingEnabled"] = [](const Object& object) -> bool { + verifyPlayer(object); return MWBase::Environment::get().getWorld()->isTeleportingEnabled(); }; - player["setTeleportingEnabled"] = [](const Object& player, bool state) { - verifyPlayer(player); - if (dynamic_cast(&player) && !dynamic_cast(&player)) + player["setTeleportingEnabled"] = [](const Object& object, bool state) { + verifyPlayer(object); + if (dynamic_cast(&object) && !dynamic_cast(&object)) throw std::runtime_error("Only player and global scripts can toggle teleportation."); MWBase::Environment::get().getWorld()->enableTeleporting(state); }; - player["addTopic"] = [](const Object& player, std::string_view topicId) { - verifyPlayer(player); + player["addTopic"] = [](const Object& object, std::string_view topicId) { + verifyPlayer(object); ESM::RefId topic = ESM::RefId::deserializeText(topicId); const ESM::Dialogue* dialogueRecord @@ -418,8 +418,8 @@ namespace MWLua MWBase::Environment::get().getDialogueManager()->addTopic(topic); }; - player["sendMenuEvent"] = [context](const Object& player, std::string eventName, const sol::object& eventData) { - verifyPlayer(player); + player["sendMenuEvent"] = [context](const Object& object, std::string eventName, const sol::object& eventData) { + verifyPlayer(object); context.mLuaEvents->addMenuEvent({ std::move(eventName), LuaUtil::serialize(eventData) }); }; @@ -471,13 +471,13 @@ namespace MWLua }; player["birthSigns"] = initBirthSignRecordBindings(context); - player["getBirthSign"] = [](const Object& player) -> std::string { - verifyPlayer(player); + player["getBirthSign"] = [](const Object& object) -> std::string { + verifyPlayer(object); return MWBase::Environment::get().getWorld()->getPlayer().getBirthSign().serializeText(); }; - player["setBirthSign"] = [](const Object& player, const sol::object& recordOrId) { - verifyPlayer(player); - if (!dynamic_cast(&player)) + player["setBirthSign"] = [](const Object& object, const sol::object& recordOrId) { + verifyPlayer(object); + if (!dynamic_cast(&object)) throw std::runtime_error("Only global scripts can change birth signs"); MWBase::Environment::get().getWorld()->getPlayer().setBirthSign(toBirthSignId(recordOrId)); }; diff --git a/apps/openmw/mwlua/types/types.cpp b/apps/openmw/mwlua/types/types.cpp index c7b0b6e9c4..037b9c742e 100644 --- a/apps/openmw/mwlua/types/types.cpp +++ b/apps/openmw/mwlua/types/types.cpp @@ -173,18 +173,18 @@ namespace MWLua sol::table types(lua, sol::create); auto addType = [&](std::string_view name, std::vector recTypes, std::optional base = std::nullopt) -> sol::table { - sol::table t(lua, sol::create); - sol::table ro = LuaUtil::makeReadOnly(t); + sol::table table(lua, sol::create); + sol::table ro = LuaUtil::makeReadOnly(table); sol::table meta = ro[sol::metatable_key]; meta[sol::meta_function::to_string] = [name]() { return name; }; if (base) { - t["baseType"] = types[*base]; + table["baseType"] = types[*base]; sol::table baseMeta(lua, sol::create); baseMeta[sol::meta_function::index] = LuaUtil::getMutableFromReadOnly(types[*base]); - t[sol::metatable_key] = baseMeta; + table[sol::metatable_key] = baseMeta; } - t["objectIsInstance"] = [types = recTypes](const Object& o) { + table["objectIsInstance"] = [types = recTypes](const Object& o) { unsigned int type = getLiveCellRefType(o.ptr().mRef); for (ESM::RecNameInts t : types) if (t == type) @@ -192,7 +192,7 @@ namespace MWLua return false; }; types[name] = ro; - return t; + return table; }; addActorBindings( diff --git a/apps/openmw/mwlua/uibindings.cpp b/apps/openmw/mwlua/uibindings.cpp index 8faf4615ce..7c708fefa9 100644 --- a/apps/openmw/mwlua/uibindings.cpp +++ b/apps/openmw/mwlua/uibindings.cpp @@ -245,14 +245,14 @@ namespace MWLua api["screenSize"] = []() { return osg::Vec2f(Settings::video().mResolutionX, Settings::video().mResolutionY); }; - api["_getAllUiModes"] = [](sol::this_state lua) { - sol::table res(lua, sol::create); + api["_getAllUiModes"] = [](sol::this_state thisState) { + sol::table res(thisState, sol::create); for (const auto& [_, name] : modeToName) res[name] = name; return res; }; - api["_getUiModeStack"] = [windowManager](sol::this_state lua) { - sol::table res(lua, sol::create); + api["_getUiModeStack"] = [windowManager](sol::this_state thisState) { + sol::table res(thisState, sol::create); int i = 1; for (MWGui::GuiMode m : windowManager->getGuiModeStack()) res[i++] = modeToName.at(m); @@ -283,14 +283,14 @@ namespace MWLua }, "Set UI modes"); }; - api["_getAllWindowIds"] = [windowManager](sol::this_state lua) { - sol::table res(lua, sol::create); + api["_getAllWindowIds"] = [windowManager](sol::this_state thisState) { + sol::table res(thisState, sol::create); for (std::string_view name : windowManager->getAllWindowIds()) res[name] = name; return res; }; - api["_getAllowedWindows"] = [windowManager](sol::this_state lua, std::string_view mode) { - sol::table res(lua, sol::create); + api["_getAllowedWindows"] = [windowManager](sol::this_state thisState, std::string_view mode) { + sol::table res(thisState, sol::create); for (std::string_view name : windowManager->getAllowedWindowIds(nameToMode.at(mode))) res[name] = name; return res; @@ -313,23 +313,23 @@ namespace MWLua { if (context.initializeOnce("openmw_ui_usertypes")) { - auto element = context.sol().new_usertype("UiElement"); - element[sol::meta_function::to_string] = [](const LuaUi::Element& element) { + auto uiElement = context.sol().new_usertype("UiElement"); + uiElement[sol::meta_function::to_string] = [](const LuaUi::Element& element) { std::stringstream res; res << "UiElement"; if (element.mLayer != "") res << "[" << element.mLayer << "]"; return res.str(); }; - element["layout"] = sol::property([](const LuaUi::Element& element) { return element.mLayout; }, + uiElement["layout"] = sol::property([](const LuaUi::Element& element) { return element.mLayout; }, [](LuaUi::Element& element, const sol::main_table& layout) { element.mLayout = layout; }); - element["update"] = [luaManager = context.mLuaManager](const std::shared_ptr& element) { + uiElement["update"] = [luaManager = context.mLuaManager](const std::shared_ptr& element) { if (element->mState != LuaUi::Element::Created) return; element->mState = LuaUi::Element::Update; luaManager->addAction([element] { wrapAction(element, [&] { element->update(); }); }, "Update UI"); }; - element["destroy"] = [luaManager = context.mLuaManager](const std::shared_ptr& element) { + uiElement["destroy"] = [luaManager = context.mLuaManager](const std::shared_ptr& element) { if (element->mState == LuaUi::Element::Destroyed) return; element->mState = LuaUi::Element::Destroy; diff --git a/apps/openmw/mwlua/vfsbindings.cpp b/apps/openmw/mwlua/vfsbindings.cpp index 330bf871e7..8a07d69e08 100644 --- a/apps/openmw/mwlua/vfsbindings.cpp +++ b/apps/openmw/mwlua/vfsbindings.cpp @@ -167,13 +167,13 @@ namespace MWLua auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS(); - sol::usertype handle = context.sol().new_usertype("FileHandle"); - handle["fileName"] + sol::usertype fileHandle = context.sol().new_usertype("FileHandle"); + fileHandle["fileName"] = sol::readonly_property([](const FileHandle& self) -> std::string_view { return self.mFileName; }); - handle[sol::meta_function::to_string] = [](const FileHandle& self) { + fileHandle[sol::meta_function::to_string] = [](const FileHandle& self) { return "FileHandle{'" + self.mFileName + "'" + (!self.mFilePtr ? ", closed" : "") + "}"; }; - handle["seek"] = sol::overload( + fileHandle["seek"] = sol::overload( [](sol::this_state lua, FileHandle& self, std::string_view whence, sol::optional offset) { validateFile(self); @@ -189,7 +189,7 @@ namespace MWLua return seek(lua, self, std::ios_base::cur, off); }); - handle["lines"] = [](sol::this_main_state lua, sol::main_object self) { + fileHandle["lines"] = [](sol::this_main_state lua, sol::main_object self) { if (!self.is()) throw std::runtime_error("self should be a file handle"); return sol::as_function([lua, self]() -> sol::object { @@ -212,7 +212,7 @@ namespace MWLua }); }; - handle["close"] = [](sol::this_state lua, FileHandle& self) { + fileHandle["close"] = [](sol::this_state lua, FileHandle& self) { sol::variadic_results values; try { @@ -236,7 +236,7 @@ namespace MWLua return values; }; - handle["read"] = [](sol::this_state lua, FileHandle& self, const sol::variadic_args args) { + fileHandle["read"] = [](sol::this_state lua, FileHandle& self, const sol::variadic_args args) { validateFile(self); if (args.size() > sMaximumReadArguments) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index df6ba53e35..f70605b809 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -157,7 +157,7 @@ namespace MWMechanics int bonus = 0; int index = ESM::Skill::refIdToIndex(skill.mId); auto bonusIt = std::find_if(race->mData.mBonus.begin(), race->mData.mBonus.end(), - [&](const auto& bonus) { return bonus.mSkill == index; }); + [&](const auto& v) { return v.mSkill == index; }); if (bonusIt != race->mData.mBonus.end()) bonus = bonusIt->mBonus; diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index eb26c00f9e..ab476cddcc 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -472,10 +472,10 @@ namespace MWWorld { if (listener != nullptr) listener->setProgressRange(::EsmLoader::fileProgress); - auto visitorRec = [this, listener](ESM4::Reader& reader) { - bool result = ESMStoreImp::readRecord(reader, *this); + auto visitorRec = [this, listener](ESM4::Reader& r) { + bool result = ESMStoreImp::readRecord(r, *this); if (listener != nullptr) - listener->setProgress(::EsmLoader::fileProgress * reader.getFileOffset() / reader.getFileSize()); + listener->setProgress(::EsmLoader::fileProgress * r.getFileOffset() / r.getFileSize()); return result; }; ESM4::ReaderUtils::readAll(reader, visitorRec, [](ESM4::Reader&) {}); diff --git a/apps/openmw/mwworld/manualref.cpp b/apps/openmw/mwworld/manualref.cpp index 81ab4b5419..ba24e7d160 100644 --- a/apps/openmw/mwworld/manualref.cpp +++ b/apps/openmw/mwworld/manualref.cpp @@ -8,9 +8,9 @@ namespace { template - void create(const MWWorld::Store& list, const ESM::RefId& name, std::any& refValue, MWWorld::Ptr& ptrValue) + void create(const MWWorld::Store& store, const ESM::RefId& name, std::any& refValue, MWWorld::Ptr& ptrValue) { - const T* base = list.find(name); + const T* base = store.find(name); ESM::CellRef cellRef; cellRef.blank(); @@ -22,7 +22,7 @@ namespace template void create( - const MWWorld::Store& list, const MWWorld::Ptr& templatePtr, std::any& refValue, MWWorld::Ptr& ptrValue) + const MWWorld::Store& /*store*/, const MWWorld::Ptr& templatePtr, std::any& refValue, MWWorld::Ptr& ptrValue) { refValue = *static_cast*>(templatePtr.getBase()); ptrValue = MWWorld::Ptr(&std::any_cast&>(refValue), nullptr); @@ -92,7 +92,7 @@ namespace MWWorld::ManualRef::ManualRef(const MWWorld::ESMStore& store, const ESM::RefId& name, const int count) { - auto cb = [&](const auto& store) { create(store, name, mRef, mPtr); }; + auto cb = [&](const auto& typedStore) { create(typedStore, name, mRef, mPtr); }; visitRefStore(store, name, cb); mPtr.getCellRef().setCount(count); @@ -100,7 +100,7 @@ MWWorld::ManualRef::ManualRef(const MWWorld::ESMStore& store, const ESM::RefId& MWWorld::ManualRef::ManualRef(const ESMStore& store, const Ptr& template_, const int count) { - auto cb = [&](const auto& store) { create(store, template_, mRef, mPtr); }; + auto cb = [&](const auto& typedStore) { create(typedStore, template_, mRef, mPtr); }; visitRefStore(store, template_.getCellRef().getRefId(), cb); mPtr.getCellRef().setCount(count); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 1a68142c15..7e55bc8ba9 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -401,11 +401,11 @@ namespace MWWorld mNavigator.removeWater(osg::Vec2i(cellX, cellY), navigatorUpdateGuard); ESM::visit(ESM::VisitOverload{ - [&](const ESM::Cell& cell) { - if (const auto pathgrid = mWorld.getStore().get().search(cell)) + [&](const ESM::Cell& c) { + if (const auto pathgrid = mWorld.getStore().get().search(c)) mNavigator.removePathgrid(*pathgrid); }, - [&](const ESM4::Cell& cell) {}, + [&](const ESM4::Cell& /*c*/) {}, }, *cell->getCell()); @@ -482,11 +482,11 @@ namespace MWWorld } ESM::visit(ESM::VisitOverload{ - [&](const ESM::Cell& cell) { - if (const auto pathgrid = mWorld.getStore().get().search(cell)) - mNavigator.addPathgrid(cell, *pathgrid); + [&](const ESM::Cell& c) { + if (const auto pathgrid = mWorld.getStore().get().search(c)) + mNavigator.addPathgrid(c, *pathgrid); }, - [&](const ESM4::Cell& cell) {}, + [&](const ESM4::Cell& /*c*/) {}, }, *cell.getCell()); diff --git a/apps/wizard/mainwizard.cpp b/apps/wizard/mainwizard.cpp index 0b5cadd979..83cbd473ae 100644 --- a/apps/wizard/mainwizard.cpp +++ b/apps/wizard/mainwizard.cpp @@ -335,8 +335,7 @@ void Wizard::MainWizard::addInstallation(const QString& path) // Add it to the openmw.cfg too const auto& dataDirs = mGameSettings.getDataDirs(); - if (std::none_of( - dataDirs.begin(), dataDirs.end(), [&](const Config::SettingValue& dir) { return dir.value == path; })) + if (std::none_of(dataDirs.begin(), dataDirs.end(), [&](const Config::SettingValue& d) { return d.value == path; })) { mGameSettings.setMultiValue(QLatin1String("data"), { path }); mGameSettings.addDataDir({ path }); diff --git a/apps/wizard/unshield/unshieldworker.cpp b/apps/wizard/unshield/unshieldworker.cpp index 438c3c1fef..7aa19f35e6 100644 --- a/apps/wizard/unshield/unshieldworker.cpp +++ b/apps/wizard/unshield/unshieldworker.cpp @@ -361,9 +361,9 @@ bool Wizard::UnshieldWorker::installDirectories( QStringList directories(findDirectories(dirName, path, recursive)); - for (const QString& dir : directories) + for (const QString& subDir : directories) { - QFileInfo info(dir); + QFileInfo info(subDir); emit textChanged(tr("Installing: %1 directory").arg(info.fileName())); if (!copyDirectory(info.absoluteFilePath(), getPath() + QDir::separator() + info.fileName(), keepSource)) return false; @@ -769,15 +769,15 @@ bool Wizard::UnshieldWorker::installComponent(Component component, const QString QStringList datafiles(findDirectories(QLatin1String("Data Files"), temp.absolutePath())); datafiles.append(findDirectories(QLatin1String("Data Files"), info.absolutePath())); - for (const QString& dir : datafiles) + for (const QString& dataDir : datafiles) { - QFileInfo info(dir); - emit textChanged(tr("Installing: %1 directory").arg(info.fileName())); + QFileInfo dataDirInfo(dataDir); + emit textChanged(tr("Installing: %1 directory").arg(dataDirInfo.fileName())); - if (!copyDirectory(info.absoluteFilePath(), getPath())) + if (!copyDirectory(dataDirInfo.absoluteFilePath(), getPath())) { emit error(tr("Could not install directory!"), - tr("Installing %1 to %2 failed.").arg(info.absoluteFilePath(), getPath())); + tr("Installing %1 to %2 failed.").arg(dataDirInfo.absoluteFilePath(), getPath())); return false; } } diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 6b7fe32d40..f23d54eb56 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -324,6 +324,10 @@ add_component_dir (files istreamptr streamwithbuffer ) +if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND NOT CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") + set_source_files_properties(files/configfileparser.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow) +endif() + add_component_dir (compiler context controlparser errorhandler exception exprparser extensions fileparser generator lineparser literals locals output parser scanner scriptparser skipparser streamerrorhandler diff --git a/components/compiler/scanner.hpp b/components/compiler/scanner.hpp index 7520903625..5132bfe452 100644 --- a/components/compiler/scanner.hpp +++ b/components/compiler/scanner.hpp @@ -209,7 +209,7 @@ namespace Compiler bool mIgnoreSpecial; public: - enum keyword + enum Keyword { K_begin, K_end, @@ -228,7 +228,7 @@ namespace Compiler K_to }; - enum special + enum Special { S_newline, S_open, diff --git a/components/detournavigator/asyncnavmeshupdater.cpp b/components/detournavigator/asyncnavmeshupdater.cpp index 5f82c85cf9..fe8cadd703 100644 --- a/components/detournavigator/asyncnavmeshupdater.cpp +++ b/components/detournavigator/asyncnavmeshupdater.cpp @@ -316,7 +316,7 @@ namespace DetourNavigator { if (mPushed.emplace(agentBounds, changedTile).second) { - const auto processTime = [&, changedTile = changedTile, changeType = changeType] { + const std::chrono::steady_clock::time_point processTime = [&] { if (changeType != ChangeType::update) return std::chrono::steady_clock::time_point(); const auto lastUpdate = mLastUpdates.find(std::tie(agentBounds, changedTile)); @@ -947,11 +947,11 @@ namespace DetourNavigator mNextTileId = TileId(mDb->getMaxTileId() + 1); Log(Debug::Info) << "Updated navmeshdb tile_id to: " << mNextTileId; } - catch (const std::exception& e) + catch (const std::exception& exception) { mWriteToDb = false; - Log(Debug::Warning) - << "Failed to update next tile_id, writes to navmeshdb are disabled: " << e.what(); + Log(Debug::Warning) << "Failed to update next tile_id, writes to navmeshdb are disabled: " + << exception.what(); } } } @@ -960,12 +960,12 @@ namespace DetourNavigator if (isWritingDbJob(*job)) { - process([&](JobIt job) { processWritingJob(job); }); + process([&](JobIt it) { processWritingJob(it); }); mUpdater.removeJob(job); return; } - process([&](JobIt job) { processReadingJob(job); }); + process([&](JobIt it) { processReadingJob(it); }); job->mState = JobState::WithDbResult; mUpdater.enqueueJob(job); } diff --git a/components/detournavigator/offmeshconnectionsmanager.cpp b/components/detournavigator/offmeshconnectionsmanager.cpp index 0cedd31241..47c380c371 100644 --- a/components/detournavigator/offmeshconnectionsmanager.cpp +++ b/components/detournavigator/offmeshconnectionsmanager.cpp @@ -77,8 +77,8 @@ namespace DetourNavigator if (itByTilePosition == values->mByTilePosition.end()) return result; - std::for_each(itByTilePosition->second.begin(), itByTilePosition->second.end(), [&](const ObjectId v) { - const auto byId = values->mById.equal_range(v); + std::for_each(itByTilePosition->second.begin(), itByTilePosition->second.end(), [&](const ObjectId id) { + const auto byId = values->mById.equal_range(id); std::for_each(byId.first, byId.second, [&](const auto& v) { if (getTilePosition(mSettings, v.second.mStart) == tilePosition || getTilePosition(mSettings, v.second.mEnd) == tilePosition) diff --git a/components/detournavigator/recastmeshbuilder.cpp b/components/detournavigator/recastmeshbuilder.cpp index 6c15b441e7..d443a5e5b2 100644 --- a/components/detournavigator/recastmeshbuilder.cpp +++ b/components/detournavigator/recastmeshbuilder.cpp @@ -237,7 +237,7 @@ namespace DetourNavigator BulletHelpers::getHeightfieldShift(cellPosition.x(), cellPosition.y(), cellSize, minHeight, maxHeight)); const float stepSize = getHeightfieldScale(cellSize, size); const int halfCellSize = cellSize / 2; - const auto local = [&](float v, float shift) { return (v - shift + halfCellSize) / stepSize; }; + const auto local = [&](float v, float offset) { return (v - offset + halfCellSize) / stepSize; }; const auto index = [&](float v, int add) { return std::clamp(static_cast(v) + add, 0, size); }; const std::size_t minX = index(std::round(local(intersection->mMin.x(), shift.x())), -1); const std::size_t minY = index(std::round(local(intersection->mMin.y(), shift.y())), -1); diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index bef98b73f0..174920fc0d 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -475,11 +475,11 @@ namespace Files return istream; } - PathContainer asPathContainer(const MaybeQuotedPathContainer& MaybeQuotedPathContainer) + PathContainer asPathContainer(const MaybeQuotedPathContainer& value) { PathContainer res; - res.reserve(MaybeQuotedPathContainer.size()); - for (const auto& maybeQuotedPath : MaybeQuotedPathContainer) + res.reserve(value.size()); + for (const auto& maybeQuotedPath : value) { res.emplace_back(maybeQuotedPath.u8string()); // This call to u8string is redundant, but required to build // on MSVC 14.26 due to implementation bugs. diff --git a/components/files/configurationmanager.hpp b/components/files/configurationmanager.hpp index da4397146b..ed97bc1951 100644 --- a/components/files/configurationmanager.hpp +++ b/components/files/configurationmanager.hpp @@ -97,7 +97,7 @@ namespace Files typedef std::vector MaybeQuotedPathContainer; - PathContainer asPathContainer(const MaybeQuotedPathContainer& MaybeQuotedPathContainer); + PathContainer asPathContainer(const MaybeQuotedPathContainer& value); } /* namespace Files */ diff --git a/components/lua/luastate.hpp b/components/lua/luastate.hpp index 7ce9a0ec94..f4ce9d4f0c 100644 --- a/components/lua/luastate.hpp +++ b/components/lua/luastate.hpp @@ -89,18 +89,18 @@ namespace LuaUtil // Pushing to the stack from outside a Lua context crashes the engine if no memory can be allocated to grow the // stack - template - [[nodiscard]] int invokeProtectedCall(Lambda&& f) const + template + [[nodiscard]] int invokeProtectedCall(Function&& function) const { if (!lua_checkstack(mSol.lua_state(), 2)) return LUA_ERRMEM; lua_pushcfunction(mSol.lua_state(), [](lua_State* L) { void* f = lua_touserdata(L, 1); LuaView view(L); - (*static_cast(f))(view); + (*static_cast(f))(view); return 0; }); - lua_pushlightuserdata(mSol.lua_state(), &f); + lua_pushlightuserdata(mSol.lua_state(), &function); return lua_pcall(mSol.lua_state(), 1, 0, 0); } diff --git a/components/lua/scriptscontainer.cpp b/components/lua/scriptscontainer.cpp index cdeb528205..f5b5605e37 100644 --- a/components/lua/scriptscontainer.cpp +++ b/components/lua/scriptscontainer.cpp @@ -359,10 +359,10 @@ namespace LuaUtil if (it == data.mEventHandlers.end()) return; mLua.protectedCall([&](LuaView& view) { - sol::object data; + sol::object object; try { - data = LuaUtil::deserialize(view.sol(), eventData, mSerializer); + object = LuaUtil::deserialize(view.sol(), eventData, mSerializer); } catch (std::exception& e) { @@ -375,7 +375,7 @@ namespace LuaUtil const Handler& h = list[i]; try { - sol::object res = LuaUtil::call({ this, h.mScriptId }, h.mFn, data); + sol::object res = LuaUtil::call({ this, h.mScriptId }, h.mFn, object); if (res.is() && !res.as()) break; // Skip other handlers if 'false' was returned. } diff --git a/components/lua/utilpackage.cpp b/components/lua/utilpackage.cpp index bf03789180..7e84338e40 100644 --- a/components/lua/utilpackage.cpp +++ b/components/lua/utilpackage.cpp @@ -394,12 +394,12 @@ namespace LuaUtil } util["loadCode"] = [](const std::string& code, const sol::table& env, sol::this_state s) { - sol::state_view lua(s); - sol::load_result res = lua.load(code, "", sol::load_mode::text); + sol::state_view thisState(s); + sol::load_result res = thisState.load(code, "", sol::load_mode::text); if (!res.valid()) throw std::runtime_error("Lua error: " + res.get()); sol::function fn = res; - sol::environment newEnv(lua, sol::create, env); + sol::environment newEnv(thisState, sol::create, env); newEnv[sol::metatable_key][sol::meta_function::new_index] = env; sol::set_environment(newEnv, fn); return fn; diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index d6311241d7..105b4c7320 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -19,7 +19,7 @@ namespace Nif union { intptr_t index; - X* ptr; + X* mPtr; }; public: @@ -29,7 +29,7 @@ namespace Nif } RecordPtrT(X* ptr) - : ptr(ptr) + : mPtr(ptr) { } @@ -48,26 +48,26 @@ namespace Nif void post(Reader& nif) { if (index < 0) - ptr = nullptr; + mPtr = nullptr; else { Record* r = nif.getRecord(index); // And cast it - ptr = dynamic_cast(r); - assert(ptr != nullptr); + mPtr = dynamic_cast(r); + assert(mPtr != nullptr); } } /// Look up the actual object from the index const X* getPtr() const { - assert(ptr != nullptr); - return ptr; + assert(mPtr != nullptr); + return mPtr; } X* getPtr() { - assert(ptr != nullptr); - return ptr; + assert(mPtr != nullptr); + return mPtr; } const X& get() const { return *getPtr(); } @@ -78,7 +78,7 @@ namespace Nif X* operator->() { return getPtr(); } /// Pointers are allowed to be empty - bool empty() const { return ptr == nullptr; } + bool empty() const { return mPtr == nullptr; } }; /** A list of references to other records. These are read as a list, diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index ee3d0dd45e..bd11344ed8 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -375,7 +375,7 @@ namespace NifOsg return true; auto iter = std::upper_bound(mData->begin(), mData->end(), time, - [](float time, const std::pair& key) { return time < key.first; }); + [](float t, const std::pair& key) { return t < key.first; }); if (iter != mData->begin()) --iter; return iter->second; diff --git a/components/stereo/stereomanager.cpp b/components/stereo/stereomanager.cpp index c3d7f1d320..a2b7b2c7f3 100644 --- a/components/stereo/stereomanager.cpp +++ b/components/stereo/stereomanager.cpp @@ -32,18 +32,18 @@ namespace Stereo { public: StereoUpdateCallback(Manager* stereoView) - : stereoView(stereoView) + : mStereoView(stereoView) { } bool run(osg::Object* object, osg::Object* data) override { auto b = traverse(object, data); - stereoView->update(); + mStereoView->update(); return b; } - Manager* stereoView; + Manager* mStereoView; }; // Update states during cull From 6453d3e201d81e0fea44db66b10f38e3ba091ab3 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 20 Aug 2025 19:51:02 +0200 Subject: [PATCH 18/25] Use std::from_chars in MessageFormatParser --- components/misc/messageformatparser.cpp | 42 +++++++++++++++---------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/components/misc/messageformatparser.cpp b/components/misc/messageformatparser.cpp index a40dcccd52..f98544d380 100644 --- a/components/misc/messageformatparser.cpp +++ b/components/misc/messageformatparser.cpp @@ -1,12 +1,32 @@ #include "messageformatparser.hpp" +#include + +namespace +{ + int parseNumber(std::size_t& i, std::string_view m) + { + if (i < m.size() && m[i] >= '0' && m[i] <= '9') + { + size_t start = i++; + while (i < m.size() && m[i] >= '0' && m[i] <= '9') + ++i; + int parsed; + auto [ptr, ec] = std::from_chars(m.data() + start, m.data() + i, parsed); + if (ec == std::errc()) + return parsed; + } + return -1; + } +} + namespace Misc { - MessageFormatParser::~MessageFormatParser() {} + MessageFormatParser::~MessageFormatParser() = default; void MessageFormatParser::process(std::string_view m) { - for (unsigned int i = 0; i < m.size(); ++i) + for (std::size_t i = 0; i < m.size(); ++i) { if (m[i] == '%') { @@ -23,31 +43,19 @@ namespace Misc ++i; } - int width = 0; - bool widthSet = false; - while (i < m.size() && m[i] >= '0' && m[i] <= '9') - { - width = width * 10 + (m[i] - '0'); - widthSet = true; - ++i; - } + int width = parseNumber(i, m); if (i < m.size()) { int precision = -1; if (m[i] == '.') { - precision = 0; - while (++i < m.size() && m[i] >= '0' && m[i] <= '9') - { - precision = precision * 10 + (m[i] - '0'); - } + ++i; + precision = parseNumber(i, m); } if (i < m.size()) { - width = (widthSet) ? width : -1; - if (m[i] == 'S' || m[i] == 's') visitedPlaceholder(StringPlaceholder, pad, width, precision, FixedNotation); else if (m[i] == 'd' || m[i] == 'i') From 8caf68ad30b93f8332faafc46ab30dacebd222c1 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 20 Aug 2025 21:47:57 +0200 Subject: [PATCH 19/25] Count pathgrids with 0-1 nodes as non-existent --- apps/openmw/mwmechanics/aiwander.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 332f7e6545..4499304303 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -637,7 +637,7 @@ namespace MWMechanics const MWWorld::Cell& cell = *actor.getCell()->getCell(); const ESM::Pathgrid* pathgrid = world.getStore().get().search(cell); // Moved to a cell without a pathgrid - if (pathgrid == nullptr) + if (pathgrid == nullptr || pathgrid->mPoints.size() < 2) { storage.mAllowedPositions.clear(); return; From 86605f353108e7419b89c60bb1d60b849232974a Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Thu, 21 Aug 2025 08:57:00 +0200 Subject: [PATCH 20/25] Make 0-width precision be 0 --- components/misc/messageformatparser.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/misc/messageformatparser.cpp b/components/misc/messageformatparser.cpp index f98544d380..89dd58e1f0 100644 --- a/components/misc/messageformatparser.cpp +++ b/components/misc/messageformatparser.cpp @@ -4,7 +4,7 @@ namespace { - int parseNumber(std::size_t& i, std::string_view m) + int parseNumber(std::size_t& i, std::string_view m, int fallback) { if (i < m.size() && m[i] >= '0' && m[i] <= '9') { @@ -16,7 +16,7 @@ namespace if (ec == std::errc()) return parsed; } - return -1; + return fallback; } } @@ -43,7 +43,7 @@ namespace Misc ++i; } - int width = parseNumber(i, m); + int width = parseNumber(i, m, -1); if (i < m.size()) { @@ -51,7 +51,7 @@ namespace Misc if (m[i] == '.') { ++i; - precision = parseNumber(i, m); + precision = parseNumber(i, m, 0); } if (i < m.size()) From 59753d8b8e6635656211558a84141e986c3ed9d9 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Thu, 21 Aug 2025 09:42:02 +0200 Subject: [PATCH 21/25] Leave from_chars to figure out the length --- components/misc/messageformatparser.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/components/misc/messageformatparser.cpp b/components/misc/messageformatparser.cpp index 89dd58e1f0..4b77a9da7a 100644 --- a/components/misc/messageformatparser.cpp +++ b/components/misc/messageformatparser.cpp @@ -8,11 +8,10 @@ namespace { if (i < m.size() && m[i] >= '0' && m[i] <= '9') { - size_t start = i++; - while (i < m.size() && m[i] >= '0' && m[i] <= '9') - ++i; + const char* start = m.data() + i; int parsed; - auto [ptr, ec] = std::from_chars(m.data() + start, m.data() + i, parsed); + auto [ptr, ec] = std::from_chars(start, m.data() + m.size(), parsed); + i += ptr - start; if (ec == std::errc()) return parsed; } From d66b86f2c9b9a063a8c7594985baa9707173a4c3 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Thu, 21 Aug 2025 22:00:00 +0200 Subject: [PATCH 22/25] Implement missing hex float format options --- components/interpreter/miscopcodes.hpp | 15 +++++++++++++-- components/misc/messageformatparser.cpp | 16 +++++++++++----- components/misc/messageformatparser.hpp | 10 ++++++---- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/components/interpreter/miscopcodes.hpp b/components/interpreter/miscopcodes.hpp index 72cc1439d2..0b49b3c248 100644 --- a/components/interpreter/miscopcodes.hpp +++ b/components/interpreter/miscopcodes.hpp @@ -57,12 +57,12 @@ namespace Interpreter float value = mRuntime[0].mFloat; mRuntime.pop(); - if (notation == FixedNotation) + if (notation == Notation::Fixed) { out << std::fixed << value; mFormattedMessage += out.str(); } - else if (notation == ShortestNotation) + else if (notation == Notation::Shortest) { out << value; std::string standard = out.str(); @@ -75,6 +75,17 @@ namespace Interpreter mFormattedMessage += standard.length() < scientific.length() ? standard : scientific; } + // TODO switch to std::format so the precision argument applies to these two + else if (notation == Notation::HexLower) + { + out << std::hexfloat << value; + mFormattedMessage += out.str(); + } + else if (notation == Notation::HexUpper) + { + out << std::uppercase << std::hexfloat << value; + mFormattedMessage += out.str(); + } else { out << std::scientific << value; diff --git a/components/misc/messageformatparser.cpp b/components/misc/messageformatparser.cpp index 4b77a9da7a..649d0184d3 100644 --- a/components/misc/messageformatparser.cpp +++ b/components/misc/messageformatparser.cpp @@ -56,15 +56,21 @@ namespace Misc if (i < m.size()) { if (m[i] == 'S' || m[i] == 's') - visitedPlaceholder(StringPlaceholder, pad, width, precision, FixedNotation); + visitedPlaceholder(StringPlaceholder, pad, width, precision, Notation::Fixed); else if (m[i] == 'd' || m[i] == 'i') - visitedPlaceholder(IntegerPlaceholder, pad, width, precision, FixedNotation); + visitedPlaceholder(IntegerPlaceholder, pad, width, precision, Notation::Fixed); else if (m[i] == 'f' || m[i] == 'F') - visitedPlaceholder(FloatPlaceholder, pad, width, precision, FixedNotation); + visitedPlaceholder(FloatPlaceholder, pad, width, precision, Notation::Fixed); else if (m[i] == 'e' || m[i] == 'E') - visitedPlaceholder(FloatPlaceholder, pad, width, precision, ScientificNotation); + visitedPlaceholder(FloatPlaceholder, pad, width, precision, Notation::Scientific); else if (m[i] == 'g' || m[i] == 'G') - visitedPlaceholder(FloatPlaceholder, pad, width, precision, ShortestNotation); + visitedPlaceholder(FloatPlaceholder, pad, width, precision, Notation::Shortest); + else if (m[i] == 'a') + visitedPlaceholder(FloatPlaceholder, pad, width, precision, Notation::HexLower); + else if (m[i] == 'A') + visitedPlaceholder(FloatPlaceholder, pad, width, precision, Notation::HexUpper); + else + visitedCharacter(m[i]); } } } diff --git a/components/misc/messageformatparser.hpp b/components/misc/messageformatparser.hpp index dc7ce09884..eeef29234d 100644 --- a/components/misc/messageformatparser.hpp +++ b/components/misc/messageformatparser.hpp @@ -15,11 +15,13 @@ namespace Misc FloatPlaceholder }; - enum Notation + enum class Notation { - FixedNotation, - ScientificNotation, - ShortestNotation + Fixed, + Scientific, + Shortest, + HexUpper, + HexLower }; virtual void visitedPlaceholder( From 13711a631eaa4bbbf9ff62d71266741cadd7eeb7 Mon Sep 17 00:00:00 2001 From: SkyHasACat Date: Fri, 22 Aug 2025 07:54:00 -0700 Subject: [PATCH 23/25] New name --- AUTHORS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS.md b/AUTHORS.md index 6f30324217..27cb45b939 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -238,7 +238,7 @@ Programmers trav tri4ng1e Thoronador - Tobias Tribble (zackhasacat) + Hailey Tribble (daisyhasacat) Tom Lowe (Vulpen) Tom Mason (wheybags) Torben Leif Carrington (TorbenC) From b90e19b242216377b2965b51ed90e7426c76840a Mon Sep 17 00:00:00 2001 From: SkyHasACat Date: Fri, 22 Aug 2025 07:54:38 -0700 Subject: [PATCH 24/25] New name --- AUTHORS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS.md b/AUTHORS.md index 27cb45b939..28a1a3a33a 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -99,6 +99,7 @@ Programmers Gohan1989 gugus/gus guidoj + Hailey Tribble (daisyhasacat) Haoda Wang (h313) holorat hristoast @@ -238,7 +239,6 @@ Programmers trav tri4ng1e Thoronador - Hailey Tribble (daisyhasacat) Tom Lowe (Vulpen) Tom Mason (wheybags) Torben Leif Carrington (TorbenC) From 567ceccd8f374747eee1fecd3e479a2e71274a2c Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Fri, 22 Aug 2025 17:13:48 +0200 Subject: [PATCH 25/25] Fix weather type in docs --- files/lua_api/openmw/core.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/files/lua_api/openmw/core.lua b/files/lua_api/openmw/core.lua index a9c12de1f0..56ebdf5e9b 100644 --- a/files/lua_api/openmw/core.lua +++ b/files/lua_api/openmw/core.lua @@ -1251,13 +1251,13 @@ -- Get the current weather -- @function [parent=#Weather] getCurrent -- @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 +-- @return #WeatherRecord Can be nil if the cell is inactive or has no weather --- -- Get the next weather if any -- @function [parent=#Weather] getNext -- @param #Cell cell The cell to get the next weather for --- @return #Weather Can be nil +-- @return #WeatherRecord Can be nil --- -- Get current weather transition value @@ -1269,7 +1269,7 @@ -- Change the weather -- @function [parent=#Weather] changeWeather -- @param #string regionId --- @param #Weather weather The weather to change to +-- @param #WeatherRecord weather The weather to change to --- -- Get the current direction of the light of the sun.