From abbe1d7317e25ef39de407d0a340abfab4d5b20d Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Tue, 18 Mar 2025 00:19:12 +0100 Subject: [PATCH 1/7] Bring jail time skill changes over to lua --- apps/openmw/mwgui/jailscreen.cpp | 32 +------- apps/openmw/mwlua/uibindings.cpp | 9 +++ .../omw/mechanics/playercontroller.lua | 80 +++++++++++++++---- files/data/scripts/omw/skillhandlers.lua | 33 +++++--- files/lua_api/openmw/ui.lua | 13 +++ 5 files changed, 112 insertions(+), 55 deletions(-) diff --git a/apps/openmw/mwgui/jailscreen.cpp b/apps/openmw/mwgui/jailscreen.cpp index 2fbaa8d8ac..3566dc072a 100644 --- a/apps/openmw/mwgui/jailscreen.cpp +++ b/apps/openmw/mwgui/jailscreen.cpp @@ -4,6 +4,7 @@ #include #include "../mwbase/environment.hpp" +#include "../mwbase/luamanager.hpp" #include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/windowmanager.hpp" #include "../mwbase/world.hpp" @@ -96,36 +97,7 @@ namespace MWGui skills.insert(skill); MWMechanics::SkillValue& value = player.getClass().getNpcStats(player).getSkill(skill->mId); - if (skill->mId == ESM::Skill::Security || skill->mId == ESM::Skill::Sneak) - value.setBase(std::min(100.f, value.getBase() + 1)); - else - value.setBase(std::max(0.f, value.getBase() - 1)); + MWBase::Environment::get().getLuaManager()->skillLevelUp(player, skill->mId, "jail"); } - - const MWWorld::Store& gmst - = MWBase::Environment::get().getESMStore()->get(); - - std::string message; - if (mDays == 1) - message = gmst.find("sNotifyMessage42")->mValue.getString(); - else - message = gmst.find("sNotifyMessage43")->mValue.getString(); - - message = Misc::StringUtils::format(message, mDays); - - for (const ESM::Skill* skill : skills) - { - int skillValue = player.getClass().getNpcStats(player).getSkill(skill->mId).getBase(); - std::string skillMsg = gmst.find("sNotifyMessage44")->mValue.getString(); - if (skill->mId == ESM::Skill::Sneak || skill->mId == ESM::Skill::Security) - skillMsg = gmst.find("sNotifyMessage39")->mValue.getString(); - - skillMsg = Misc::StringUtils::format(skillMsg, skill->mName, skillValue); - message += "\n" + skillMsg; - } - - std::vector buttons; - buttons.emplace_back("#{Interface:OK}"); - MWBase::Environment::get().getWindowManager()->interactiveMessageBox(message, buttons); } } diff --git a/apps/openmw/mwlua/uibindings.cpp b/apps/openmw/mwlua/uibindings.cpp index 826338ca7d..99ae2f3530 100644 --- a/apps/openmw/mwlua/uibindings.cpp +++ b/apps/openmw/mwlua/uibindings.cpp @@ -108,6 +108,15 @@ namespace MWLua } luaManager->addUIMessage(message, mode); }; + + api["showMessageBox"] = [windowManager] (std::string_view message, sol::optional options) { + std::string buttonText = "#{Interface:OK}"; + if (options) + { + buttonText = options->get_or("buttonText", buttonText); + } + windowManager->interactiveMessageBox(message, { buttonText }); + }; api["CONSOLE_COLOR"] = LuaUtil::makeStrictReadOnly(LuaUtil::tableFromPairs(lua, { { "Default", Misc::Color::fromHex(MWBase::WindowManager::sConsoleColor_Default.substr(1)) }, diff --git a/files/data/scripts/omw/mechanics/playercontroller.lua b/files/data/scripts/omw/mechanics/playercontroller.lua index 6de31afdea..dd9b825a0f 100644 --- a/files/data/scripts/omw/mechanics/playercontroller.lua +++ b/files/data/scripts/omw/mechanics/playercontroller.lua @@ -37,9 +37,33 @@ local function processAutomaticDoors() end end +local jailDays = 0 +local jailReport = nil + local function skillLevelUpHandler(skillid, source, params) + if not params.skillIncreaseValue then + return + end + + if source == 'jail' then + -- All jail time skill changes are reported one by one, and then collected into + -- a single report after all changes are made. + if not jailReport then + jailReport = {} + jailDays = 0 + end + -- Record the skill change for use by the report in determining if the skill + -- increased or decreased + jailReport[skillid] = params.skillIncreaseValue + (jailReport[skillid] or 0) + + -- For now we can know that this will be called exactly once per day in jail. + -- Allowing this script to track how many days were spent in jail. + jailDays = jailDays + 1 + end + local skillStat = NPC.stats.skills[skillid](self) - if skillStat.base >= 100 then + if (skillStat.base >= 100 and params.skillIncreaseValue > 0) or + (skillStat.base <= 0 and params.skillIncreaseValue < 0) then return false end @@ -62,25 +86,50 @@ local function skillLevelUpHandler(skillid, source, params) = levelStat.skillIncreasesForSpecialization[params.levelUpSpecialization] + params.levelUpSpecializationIncreaseValue; end - local skillRecord = Skill.record(skillid) - local npcRecord = NPC.record(self) - local class = NPC.classes.record(npcRecord.class) + if source ~= 'jail' then + local skillRecord = Skill.record(skillid) + local npcRecord = NPC.record(self) + local class = NPC.classes.record(npcRecord.class) - ambient.playSound("skillraise") + ambient.playSound("skillraise") - local message = string.format(core.getGMST('sNotifyMessage39'),skillRecord.name,skillStat.base) + local message = string.format(core.getGMST('sNotifyMessage39'),skillRecord.name,skillStat.base) - if source == I.SkillProgression.SKILL_INCREASE_SOURCES.Book then - message = '#{sBookSkillMessage}\n'..message + if source == I.SkillProgression.SKILL_INCREASE_SOURCES.Book then + message = '#{sBookSkillMessage}\n'..message + end + + ui.showMessage(message, { showInDialogue = false }) + + if levelStat.progress >= core.getGMST('iLevelUpTotal') then + ui.showMessage('#{sLevelUpMsg}', { showInDialogue = false }) + end + + if not source or source == I.SkillProgression.SKILL_INCREASE_SOURCES.Usage then skillStat.progress = 0 end end +end - ui.showMessage(message, { showInDialogue = false }) +local function doJailReport() + local message = '' + if days == 1 then + message = string.format(core.getGMST('sNotifyMessage42'), jailDays) + else + message = string.format(core.getGMST('sNotifyMessage43'), jailDays) + end + for skillid, diff in pairs(jailReport) do + local skillBase = NPC.stats.skills[skillid](self).base + local skillMsg = core.getGMST('sNotifyMessage39') + if diff < 0 then + skillMsg = core.getGMST('sNotifyMessage44') + end + local skillRecord = Skill.record(skillid) + message = message..'\n'..string.format(skillMsg, skillRecord.name, skillBase) + end - if levelStat.progress >= core.getGMST('iLevelUpTotal') then - ui.showMessage('#{sLevelUpMsg}', { showInDialogue = false }) - end - - if not source or source == I.SkillProgression.SKILL_INCREASE_SOURCES.Usage then skillStat.progress = 0 end + ui.showMessageBox(message) + + jailReport = nil + jailDays = 0 end local function skillUsedHandler(skillid, params) @@ -106,6 +155,9 @@ local function onUpdate(dt) onCellChange() end processAutomaticDoors() + if jailReport then + doJailReport() + end end I.SkillProgression.addSkillUsedHandler(skillUsedHandler) diff --git a/files/data/scripts/omw/skillhandlers.lua b/files/data/scripts/omw/skillhandlers.lua index d3a224dc46..cba4a16add 100644 --- a/files/data/scripts/omw/skillhandlers.lua +++ b/files/data/scripts/omw/skillhandlers.lua @@ -38,6 +38,7 @@ local Skill = core.stats.Skill -- Table of all existing sources for skill increases. Any sources not listed below will be treated as equal to Trainer. -- @type SkillLevelUpSource -- @field #string Book book +-- @field #string Jail jail -- @field #string Trainer trainer -- @field #string Usage usage @@ -131,15 +132,17 @@ local function skillLevelUp(skillid, source) levelUpAttributeIncreaseValue = core.getGMST('iLevelUpMajorMultAttribute') end - local options = - { - skillIncreaseValue = 1, - levelUpProgress = levelUpProgress, - levelUpAttribute = skillRecord.attribute, - levelUpAttributeIncreaseValue = levelUpAttributeIncreaseValue, - levelUpSpecialization = skillRecord.specialization, - levelUpSpecializationIncreaseValue = core.getGMST('iLevelupSpecialization'), - } + local options = {} + if source == 'jail' and not (skillid == 'security' or skillid == 'sneak') then + options.skillIncreaseValue = -1 + else + options.skillIncreaseValue = 1 + options.levelUpProgress = levelUpProgress + options.levelUpAttribute = skillRecord.attribute + options.levelUpAttributeIncreaseValue = levelUpAttributeIncreaseValue + options.levelUpSpecialization = skillRecord.specialization + options.levelUpSpecializationIncreaseValue = core.getGMST('iLevelupSpecialization') + end for i = #skillLevelUpHandlers, 1, -1 do if skillLevelUpHandlers[i](skillid, source, options) == false then @@ -156,8 +159,15 @@ return { -- @context local -- @usage local I = require('openmw.interfaces') -- + -- -- Make jail time hurt sneak skill instead of benefitting it + -- I.SkillProgression.addSkillLevelUpHandler(function(skillid, source, options) + -- if skillid == 'sneak' and source == 'jail' and options.skillIncreaseValue > 0 then + -- options.skillIncreaseValue = -options.skillIncreaseValue + -- end + -- end) + -- -- -- Forbid increasing destruction skill past 50 - -- I.SkillProgression.addSkillLevelUpHandler(function(skillid, options) + -- I.SkillProgression.addSkillLevelUpHandler(function(skillid, source, options) -- if skillid == 'destruction' and types.NPC.stats.skills.destruction(self).base >= 50 then -- return false -- end @@ -263,7 +273,7 @@ return { --- Trigger a skill level up, activating relevant handlers -- @function [parent=#SkillProgression] skillLevelUp -- @param #string skillid The id of the skill to level up. - -- @param #SkillLevelUpSource source The source of the skill increase. + -- @param #SkillLevelUpSource source The source of the skill increase. Note that passing a value of @{#SkillLevelUpSource.Jail} will cause a skill decrease for all skills except sneak and security, and will cause a jail time report to be generated in the next frame. skillLevelUp = skillLevelUp, --- @{#SkillLevelUpSource} @@ -272,6 +282,7 @@ return { Book = 'book', Usage = 'usage', Trainer = 'trainer', + Jail = 'jail', }, --- Compute the total skill gain required to level up a skill based on its current level, and other modifying factors such as major skills and specialization. diff --git a/files/lua_api/openmw/ui.lua b/files/lua_api/openmw/ui.lua index 598fbacca4..3b95c619dc 100644 --- a/files/lua_api/openmw/ui.lua +++ b/files/lua_api/openmw/ui.lua @@ -35,6 +35,19 @@ -- @field Flex Aligns widgets in a row or column -- @field Container Automatically wraps around its contents +--- +-- Shows given message as a message box +-- @function [parent=#ui] showMessageBox +-- @param #string msg +-- @param #table options An optional table with additional optional arguments. Can contain: +-- +-- * `buttonText` - Changes the text of the button (default: OK (localized)) + +-- @usage local params = { +-- buttonText="Bene" +-- }; +-- ui.showMessageBox("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque quis justo in orci pharetra semper in lobortis tortor. Suspendisse et sapien sapien.", params) + --- -- Shows given message at the bottom of the screen. -- @function [parent=#ui] showMessage From d694d1f219e1a415b97f8e9ac50939037853ecc5 Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Tue, 18 Mar 2025 00:23:29 +0100 Subject: [PATCH 2/7] clang format --- apps/openmw/mwlua/uibindings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwlua/uibindings.cpp b/apps/openmw/mwlua/uibindings.cpp index 99ae2f3530..2f498f6b1f 100644 --- a/apps/openmw/mwlua/uibindings.cpp +++ b/apps/openmw/mwlua/uibindings.cpp @@ -109,7 +109,7 @@ namespace MWLua luaManager->addUIMessage(message, mode); }; - api["showMessageBox"] = [windowManager] (std::string_view message, sol::optional options) { + api["showMessageBox"] = [windowManager](std::string_view message, sol::optional options) { std::string buttonText = "#{Interface:OK}"; if (options) { From 525aac7a15a44935cbac87615155e5ee5586ab3f Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Tue, 18 Mar 2025 19:41:20 +0100 Subject: [PATCH 3/7] showMessageBox -> showInteractiveMessage --- apps/openmw/mwlua/uibindings.cpp | 2 +- files/lua_api/openmw/ui.lua | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwlua/uibindings.cpp b/apps/openmw/mwlua/uibindings.cpp index 2f498f6b1f..16bd4a1626 100644 --- a/apps/openmw/mwlua/uibindings.cpp +++ b/apps/openmw/mwlua/uibindings.cpp @@ -109,7 +109,7 @@ namespace MWLua luaManager->addUIMessage(message, mode); }; - api["showMessageBox"] = [windowManager](std::string_view message, sol::optional options) { + api["showInteractiveMessage"] = [windowManager](std::string_view message, sol::optional options) { std::string buttonText = "#{Interface:OK}"; if (options) { diff --git a/files/lua_api/openmw/ui.lua b/files/lua_api/openmw/ui.lua index 3b95c619dc..73655a8428 100644 --- a/files/lua_api/openmw/ui.lua +++ b/files/lua_api/openmw/ui.lua @@ -37,7 +37,7 @@ --- -- Shows given message as a message box --- @function [parent=#ui] showMessageBox +-- @function [parent=#ui] showInteractiveMessage -- @param #string msg -- @param #table options An optional table with additional optional arguments. Can contain: -- @@ -46,7 +46,7 @@ -- @usage local params = { -- buttonText="Bene" -- }; --- ui.showMessageBox("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque quis justo in orci pharetra semper in lobortis tortor. Suspendisse et sapien sapien.", params) +-- ui.showInteractiveMessage("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque quis justo in orci pharetra semper in lobortis tortor. Suspendisse et sapien sapien.", params) --- -- Shows given message at the bottom of the screen. From 7943d1147f70c688218046bdcc1b620df7f5cffd Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Wed, 19 Mar 2025 22:15:05 +0100 Subject: [PATCH 4/7] Rewrite showInteractiveMessage to be more future proof, and hide it behind the UI interface. --- apps/openmw/mwlua/uibindings.cpp | 9 ++------- files/data/scripts/omw/ui.lua | 7 +++++++ files/lua_api/openmw/ui.lua | 13 ------------- 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/apps/openmw/mwlua/uibindings.cpp b/apps/openmw/mwlua/uibindings.cpp index 16bd4a1626..8d9892005c 100644 --- a/apps/openmw/mwlua/uibindings.cpp +++ b/apps/openmw/mwlua/uibindings.cpp @@ -109,13 +109,8 @@ namespace MWLua luaManager->addUIMessage(message, mode); }; - api["showInteractiveMessage"] = [windowManager](std::string_view message, sol::optional options) { - std::string buttonText = "#{Interface:OK}"; - if (options) - { - buttonText = options->get_or("buttonText", buttonText); - } - windowManager->interactiveMessageBox(message, { buttonText }); + api["_showInteractiveMessage"] = [windowManager](std::string_view message, sol::optional) { + windowManager->interactiveMessageBox(message, { "#{Interface:OK}" }); }; api["CONSOLE_COLOR"] = LuaUtil::makeStrictReadOnly(LuaUtil::tableFromPairs(lua, { diff --git a/files/data/scripts/omw/ui.lua b/files/data/scripts/omw/ui.lua index 31502fd6ee..b10dc0c2ef 100644 --- a/files/data/scripts/omw/ui.lua +++ b/files/data/scripts/omw/ui.lua @@ -254,6 +254,13 @@ return { -- @return #boolean isWindowVisible = isWindowVisible, + --- + -- Shows a message as an interactive message box pausing the game, with a single button with the localized text OK. + -- @function [parent=#UI] showInteractiveMessage + -- @param #string message Message to display + -- @param #table options Options (none yet) + showInteractiveMessage = ui._showInteractiveMessage + -- TODO -- registerHudElement = function(name, showFn, hideFn) end, -- showHudElement = function(name, bool) end, diff --git a/files/lua_api/openmw/ui.lua b/files/lua_api/openmw/ui.lua index 73655a8428..598fbacca4 100644 --- a/files/lua_api/openmw/ui.lua +++ b/files/lua_api/openmw/ui.lua @@ -35,19 +35,6 @@ -- @field Flex Aligns widgets in a row or column -- @field Container Automatically wraps around its contents ---- --- Shows given message as a message box --- @function [parent=#ui] showInteractiveMessage --- @param #string msg --- @param #table options An optional table with additional optional arguments. Can contain: --- --- * `buttonText` - Changes the text of the button (default: OK (localized)) - --- @usage local params = { --- buttonText="Bene" --- }; --- ui.showInteractiveMessage("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque quis justo in orci pharetra semper in lobortis tortor. Suspendisse et sapien sapien.", params) - --- -- Shows given message at the bottom of the screen. -- @function [parent=#ui] showMessage From c970f38e9600b9688dbab2182ea4782612916764 Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Wed, 19 Mar 2025 22:29:11 +0100 Subject: [PATCH 5/7] Write an _onJailTimeServed engine handler and do all of jail skill modifications in lua. --- apps/openmw/mwbase/luamanager.hpp | 1 + apps/openmw/mwgui/jailscreen.cpp | 13 +--- apps/openmw/mwlua/engineevents.cpp | 9 +++ apps/openmw/mwlua/engineevents.hpp | 7 +- apps/openmw/mwlua/localscripts.cpp | 2 +- apps/openmw/mwlua/localscripts.hpp | 2 + apps/openmw/mwlua/luamanagerimp.cpp | 6 ++ apps/openmw/mwlua/luamanagerimp.hpp | 1 + .../omw/mechanics/playercontroller.lua | 69 +++++++++---------- 9 files changed, 59 insertions(+), 51 deletions(-) diff --git a/apps/openmw/mwbase/luamanager.hpp b/apps/openmw/mwbase/luamanager.hpp index 61574de3ac..5772c555a3 100644 --- a/apps/openmw/mwbase/luamanager.hpp +++ b/apps/openmw/mwbase/luamanager.hpp @@ -75,6 +75,7 @@ namespace MWBase const MWRender::AnimPriority& priority, int blendMask, bool autodisable, float speedmult, std::string_view start, std::string_view stop, float startpoint, uint32_t loops, bool loopfallback) = 0; + virtual void jailTimeServed(const MWWorld::Ptr& actor, int days) = 0; virtual void skillLevelUp(const MWWorld::Ptr& actor, ESM::RefId skillId, std::string_view source) = 0; virtual void skillUse(const MWWorld::Ptr& actor, ESM::RefId skillId, int useType, float scale) = 0; virtual void onHit(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, const MWWorld::Ptr& weapon, diff --git a/apps/openmw/mwgui/jailscreen.cpp b/apps/openmw/mwgui/jailscreen.cpp index 3566dc072a..9244e9dd2f 100644 --- a/apps/openmw/mwgui/jailscreen.cpp +++ b/apps/openmw/mwgui/jailscreen.cpp @@ -87,17 +87,6 @@ namespace MWGui // We should not worsen corprus when in prison player.getClass().getCreatureStats(player).getActiveSpells().skipWorsenings(mDays * 24); - - const auto& skillStore = MWBase::Environment::get().getESMStore()->get(); - std::set skills; - for (int day = 0; day < mDays; ++day) - { - auto& prng = MWBase::Environment::get().getWorld()->getPrng(); - const ESM::Skill* skill = skillStore.searchRandom({}, prng); - skills.insert(skill); - - MWMechanics::SkillValue& value = player.getClass().getNpcStats(player).getSkill(skill->mId); - MWBase::Environment::get().getLuaManager()->skillLevelUp(player, skill->mId, "jail"); - } + MWBase::Environment::get().getLuaManager()->jailTimeServed(player, mDays); } } diff --git a/apps/openmw/mwlua/engineevents.cpp b/apps/openmw/mwlua/engineevents.cpp index 6c652bccba..be7d249bfc 100644 --- a/apps/openmw/mwlua/engineevents.cpp +++ b/apps/openmw/mwlua/engineevents.cpp @@ -113,6 +113,15 @@ namespace MWLua scripts->onSkillLevelUp(event.mSkill, event.mSource); } + void operator()(const OnJailTimeServed& event) const + { + MWWorld::Ptr actor = getPtr(event.mActor); + if (actor.isEmpty()) + return; + if (auto* scripts = getLocalScripts(actor)) + scripts->onJailTimeServed(event.mDays); + } + private: MWWorld::Ptr getPtr(ESM::RefNum id) const { diff --git a/apps/openmw/mwlua/engineevents.hpp b/apps/openmw/mwlua/engineevents.hpp index fb9183eb7c..407739d60e 100644 --- a/apps/openmw/mwlua/engineevents.hpp +++ b/apps/openmw/mwlua/engineevents.hpp @@ -70,8 +70,13 @@ namespace MWLua std::string mSkill; std::string mSource; }; + struct OnJailTimeServed + { + ESM::RefNum mActor; + int mDays; + }; using Event = std::variant; + OnAnimationTextKey, OnSkillUse, OnSkillLevelUp, OnJailTimeServed>; void clear() { mQueue.clear(); } void addToQueue(Event e) { mQueue.push_back(std::move(e)); } diff --git a/apps/openmw/mwlua/localscripts.cpp b/apps/openmw/mwlua/localscripts.cpp index d784328035..ad2913dd49 100644 --- a/apps/openmw/mwlua/localscripts.cpp +++ b/apps/openmw/mwlua/localscripts.cpp @@ -232,7 +232,7 @@ namespace MWLua [&](LuaUtil::LuaView& view) { addPackage("openmw.self", sol::make_object(view.sol(), &mData)); }); registerEngineHandlers({ &mOnActiveHandlers, &mOnInactiveHandlers, &mOnConsumeHandlers, &mOnActivatedHandlers, &mOnTeleportedHandlers, &mOnAnimationTextKeyHandlers, &mOnPlayAnimationHandlers, &mOnSkillUse, - &mOnSkillLevelUp }); + &mOnSkillLevelUp, &mOnJailTimeServed }); } void LocalScripts::setActive(bool active, bool callHandlers) diff --git a/apps/openmw/mwlua/localscripts.hpp b/apps/openmw/mwlua/localscripts.hpp index b3ec647d0e..bc34576509 100644 --- a/apps/openmw/mwlua/localscripts.hpp +++ b/apps/openmw/mwlua/localscripts.hpp @@ -89,6 +89,7 @@ namespace MWLua { callEngineHandlers(mOnSkillLevelUp, skillId, source); } + void onJailTimeServed(int days) { callEngineHandlers(mOnJailTimeServed, days); } void applyStatsCache(); @@ -118,6 +119,7 @@ namespace MWLua EngineHandlerList mOnPlayAnimationHandlers{ "_onPlayAnimation" }; EngineHandlerList mOnSkillUse{ "_onSkillUse" }; EngineHandlerList mOnSkillLevelUp{ "_onSkillLevelUp" }; + EngineHandlerList mOnJailTimeServed{ "_onJailTimeServed" }; }; } diff --git a/apps/openmw/mwlua/luamanagerimp.cpp b/apps/openmw/mwlua/luamanagerimp.cpp index df9c9cd50f..34f6fcb7af 100644 --- a/apps/openmw/mwlua/luamanagerimp.cpp +++ b/apps/openmw/mwlua/luamanagerimp.cpp @@ -490,6 +490,12 @@ namespace MWLua EngineEvents::OnSkillLevelUp{ getId(actor), skillId.serializeText(), std::string(source) }); } + void LuaManager::jailTimeServed(const MWWorld::Ptr& actor, int days) + { + mEngineEvents.addToQueue( + EngineEvents::OnJailTimeServed{ getId(actor), days }); + } + void LuaManager::onHit(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, const MWWorld::Ptr& weapon, const MWWorld::Ptr& ammo, int attackType, float attackStrength, float damage, bool isHealth, const osg::Vec3f& hitPos, bool successful, MWMechanics::DamageSourceType sourceType) diff --git a/apps/openmw/mwlua/luamanagerimp.hpp b/apps/openmw/mwlua/luamanagerimp.hpp index f47b6f96cf..bd4ab0d30e 100644 --- a/apps/openmw/mwlua/luamanagerimp.hpp +++ b/apps/openmw/mwlua/luamanagerimp.hpp @@ -92,6 +92,7 @@ namespace MWLua bool loopfallback) override; void skillUse(const MWWorld::Ptr& actor, ESM::RefId skillId, int useType, float scale) override; void skillLevelUp(const MWWorld::Ptr& actor, ESM::RefId skillId, std::string_view source) override; + void jailTimeServed(const MWWorld::Ptr& actor, int days) override; void onHit(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, const MWWorld::Ptr& weapon, const MWWorld::Ptr& ammo, int attackType, float attackStrength, float damage, bool isHealth, const osg::Vec3f& hitPos, bool successful, MWMechanics::DamageSourceType sourceType) override; diff --git a/files/data/scripts/omw/mechanics/playercontroller.lua b/files/data/scripts/omw/mechanics/playercontroller.lua index dd9b825a0f..3abd60e729 100644 --- a/files/data/scripts/omw/mechanics/playercontroller.lua +++ b/files/data/scripts/omw/mechanics/playercontroller.lua @@ -37,30 +37,7 @@ local function processAutomaticDoors() end end -local jailDays = 0 -local jailReport = nil - local function skillLevelUpHandler(skillid, source, params) - if not params.skillIncreaseValue then - return - end - - if source == 'jail' then - -- All jail time skill changes are reported one by one, and then collected into - -- a single report after all changes are made. - if not jailReport then - jailReport = {} - jailDays = 0 - end - -- Record the skill change for use by the report in determining if the skill - -- increased or decreased - jailReport[skillid] = params.skillIncreaseValue + (jailReport[skillid] or 0) - - -- For now we can know that this will be called exactly once per day in jail. - -- Allowing this script to track how many days were spent in jail. - jailDays = jailDays + 1 - end - local skillStat = NPC.stats.skills[skillid](self) if (skillStat.base >= 100 and params.skillIncreaseValue > 0) or (skillStat.base <= 0 and params.skillIncreaseValue < 0) then @@ -109,27 +86,44 @@ local function skillLevelUpHandler(skillid, source, params) end end -local function doJailReport() +local function jailTimeServed(days) + if not days or days <= 0 then + return + end + + local oldSkillLevels = {} + local skillByNumber = {} + for skillid, skillStat in pairs(NPC.stats.skills) do + oldSkillLevels[skillid] = skillStat(self).base + skillByNumber[#skillByNumber+1] = skillid + end + + math.randomseed(core.getSimulationTime()) + for day=1,days do + local skillid = skillByNumber[math.random(#skillByNumber)] + -- skillLevelUp() handles skill-based increase/decrease + I.SkillProgression.skillLevelUp(skillid, I.SkillProgression.SKILL_INCREASE_SOURCES.Jail) + end + local message = '' if days == 1 then - message = string.format(core.getGMST('sNotifyMessage42'), jailDays) + message = string.format(core.getGMST('sNotifyMessage42'), days) else - message = string.format(core.getGMST('sNotifyMessage43'), jailDays) + message = string.format(core.getGMST('sNotifyMessage43'), days) end - for skillid, diff in pairs(jailReport) do - local skillBase = NPC.stats.skills[skillid](self).base - local skillMsg = core.getGMST('sNotifyMessage39') - if diff < 0 then - skillMsg = core.getGMST('sNotifyMessage44') + for skillid, skillStat in pairs(NPC.stats.skills) do + local diff = skillStat(self).base - oldSkillLevels[skillid] + if diff ~= 0 then + local skillMsg = core.getGMST('sNotifyMessage39') + if diff < 0 then + skillMsg = core.getGMST('sNotifyMessage44') + end + local skillRecord = Skill.record(skillid) + message = message..'\n'..string.format(skillMsg, skillRecord.name, skillStat(self).base) end - local skillRecord = Skill.record(skillid) - message = message..'\n'..string.format(skillMsg, skillRecord.name, skillBase) end - ui.showMessageBox(message) - - jailReport = nil - jailDays = 0 + I.UI.showInteractiveMessage(message) end local function skillUsedHandler(skillid, params) @@ -166,6 +160,7 @@ I.SkillProgression.addSkillLevelUpHandler(skillLevelUpHandler) return { engineHandlers = { onUpdate = onUpdate, + _onJailTimeServed = jailTimeServed, }, eventHandlers = { From ca5ab026a2fb9f7597affd13b1d6ac8862316b1d Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Wed, 19 Mar 2025 22:37:13 +0100 Subject: [PATCH 6/7] doc update. clang. --- apps/openmw/mwlua/luamanagerimp.cpp | 3 +-- files/data/scripts/omw/skillhandlers.lua | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwlua/luamanagerimp.cpp b/apps/openmw/mwlua/luamanagerimp.cpp index 34f6fcb7af..850dd87eed 100644 --- a/apps/openmw/mwlua/luamanagerimp.cpp +++ b/apps/openmw/mwlua/luamanagerimp.cpp @@ -492,8 +492,7 @@ namespace MWLua void LuaManager::jailTimeServed(const MWWorld::Ptr& actor, int days) { - mEngineEvents.addToQueue( - EngineEvents::OnJailTimeServed{ getId(actor), days }); + mEngineEvents.addToQueue(EngineEvents::OnJailTimeServed{ getId(actor), days }); } void LuaManager::onHit(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, const MWWorld::Ptr& weapon, diff --git a/files/data/scripts/omw/skillhandlers.lua b/files/data/scripts/omw/skillhandlers.lua index cba4a16add..9b58d81174 100644 --- a/files/data/scripts/omw/skillhandlers.lua +++ b/files/data/scripts/omw/skillhandlers.lua @@ -197,7 +197,7 @@ return { -- a modifiable table of skill level up values, and can be modified to change the behavior of later handlers. -- These values are calculated based on vanilla mechanics. Setting any value to nil will cause that mechanic to be skipped. By default contains these values: -- - -- * `skillIncreaseValue` - The numeric amount of skill levels gained. + -- * `skillIncreaseValue` - The numeric amount of skill levels gained. By default this is 1, except when the source is jail in which case it will instead be -1 for all skills except sneak and security. -- * `levelUpProgress` - The numeric amount of level up progress gained. -- * `levelUpAttribute` - The string identifying the attribute that should receive points from this skill level up. -- * `levelUpAttributeIncreaseValue` - The numeric amount of attribute increase points received. This contributes to the amount of each attribute the character receives during a vanilla level up. @@ -273,7 +273,7 @@ return { --- Trigger a skill level up, activating relevant handlers -- @function [parent=#SkillProgression] skillLevelUp -- @param #string skillid The id of the skill to level up. - -- @param #SkillLevelUpSource source The source of the skill increase. Note that passing a value of @{#SkillLevelUpSource.Jail} will cause a skill decrease for all skills except sneak and security, and will cause a jail time report to be generated in the next frame. + -- @param #SkillLevelUpSource source The source of the skill increase. Note that passing a value of @{#SkillLevelUpSource.Jail} will cause a skill decrease for all skills except sneak and security. skillLevelUp = skillLevelUp, --- @{#SkillLevelUpSource} From 7be9e8892614bce889f210454c6ca92a6bb1eabd Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Fri, 1 Aug 2025 18:54:23 +0200 Subject: [PATCH 7/7] Capo reviews. Bump relevant API versions --- CMakeLists.txt | 2 +- files/data/scripts/omw/mechanics/playercontroller.lua | 3 --- files/data/scripts/omw/ui.lua | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b4ef872eb6..57ebeefcfd 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 86) +set(OPENMW_LUA_API_REVISION 87) set(OPENMW_POSTPROCESSING_API_REVISION 3) set(OPENMW_VERSION_COMMITHASH "") diff --git a/files/data/scripts/omw/mechanics/playercontroller.lua b/files/data/scripts/omw/mechanics/playercontroller.lua index 3abd60e729..a0d1b11362 100644 --- a/files/data/scripts/omw/mechanics/playercontroller.lua +++ b/files/data/scripts/omw/mechanics/playercontroller.lua @@ -149,9 +149,6 @@ local function onUpdate(dt) onCellChange() end processAutomaticDoors() - if jailReport then - doJailReport() - end end I.SkillProgression.addSkillUsedHandler(skillUsedHandler) diff --git a/files/data/scripts/omw/ui.lua b/files/data/scripts/omw/ui.lua index b10dc0c2ef..c63c085fab 100644 --- a/files/data/scripts/omw/ui.lua +++ b/files/data/scripts/omw/ui.lua @@ -171,7 +171,7 @@ return { interface = { --- Interface version -- @field [parent=#UI] #number version - version = 2, + version = 3, --- All available UI modes. -- Use `view(I.UI.MODE)` in `luap` console mode to see the list.