From f7aa9f8d945a73a3a198a8636d13fa3e4a407d7b Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 7 Feb 2024 18:08:06 +0100 Subject: [PATCH 1/3] Expose birth signs to Lua --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwlua/birthsignbindings.cpp | 55 +++++++++++++++++++++++++ apps/openmw/mwlua/birthsignbindings.hpp | 13 ++++++ apps/openmw/mwlua/types/player.cpp | 3 ++ files/lua_api/openmw/types.lua | 22 ++++++++++ 5 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 apps/openmw/mwlua/birthsignbindings.cpp create mode 100644 apps/openmw/mwlua/birthsignbindings.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index cc0cba1a1a..f92a601b82 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -64,7 +64,7 @@ add_openmw_dir (mwlua context menuscripts globalscripts localscripts playerscripts luabindings objectbindings cellbindings mwscriptbindings camerabindings vfsbindings uibindings soundbindings inputbindings nearbybindings postprocessingbindings stats debugbindings corebindings worldbindings worker magicbindings factionbindings - classbindings itemdata inputprocessor animationbindings + classbindings itemdata inputprocessor animationbindings birthsignbindings types/types types/door types/item types/actor types/container types/lockable types/weapon types/npc types/creature types/player types/activator types/book types/lockpick types/probe types/apparatus types/potion types/ingredient types/misc types/repair types/armor types/light types/static diff --git a/apps/openmw/mwlua/birthsignbindings.cpp b/apps/openmw/mwlua/birthsignbindings.cpp new file mode 100644 index 0000000000..5592179fee --- /dev/null +++ b/apps/openmw/mwlua/birthsignbindings.cpp @@ -0,0 +1,55 @@ +#include +#include +#include +#include + +#include "../mwbase/environment.hpp" +#include "../mwworld/class.hpp" +#include "../mwworld/esmstore.hpp" + +#include "birthsignbindings.hpp" +#include "luamanagerimp.hpp" +#include "types/types.hpp" + +namespace sol +{ + template <> + struct is_automagical : std::false_type + { + }; + template <> + struct is_automagical> : std::false_type + { + }; +} + +namespace MWLua +{ + sol::table initCoreBirthSignBindings(const Context& context) + { + sol::state_view& lua = context.mLua->sol(); + sol::table birthSigns(context.mLua->sol(), sol::create); + addRecordFunctionBinding(birthSigns, context); + + auto signT = lua.new_usertype("ESM3_BirthSign"); + signT[sol::meta_function::to_string] = [](const ESM::BirthSign& rec) -> std::string { + return "ESM3_BirthSign[" + rec.mId.toDebugString() + "]"; + }; + signT["id"] = sol::readonly_property([](const ESM::BirthSign& rec) { return rec.mId.serializeText(); }); + signT["name"] = sol::readonly_property([](const ESM::BirthSign& rec) -> std::string_view { return rec.mName; }); + signT["description"] + = sol::readonly_property([](const ESM::BirthSign& rec) -> std::string_view { return rec.mDescription; }); + auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS(); + signT["texture"] = sol::readonly_property([vfs](const ESM::BirthSign& rec) -> std::string { + return Misc::ResourceHelpers::correctTexturePath(rec.mTexture, vfs); + }); + signT["spells"] = sol::readonly_property([lua](const ESM::BirthSign& rec) -> sol::table { + sol::table res(lua, sol::create); + for (size_t i = 0; i < rec.mPowers.mList.size(); ++i) + res[i + 1] = rec.mPowers.mList[i].serializeText(); + return res; + }); + + return LuaUtil::makeReadOnly(birthSigns); + } +} diff --git a/apps/openmw/mwlua/birthsignbindings.hpp b/apps/openmw/mwlua/birthsignbindings.hpp new file mode 100644 index 0000000000..7c88b8cccb --- /dev/null +++ b/apps/openmw/mwlua/birthsignbindings.hpp @@ -0,0 +1,13 @@ +#ifndef MWLUA_BIRTHSIGNBINDINGS_H +#define MWLUA_BIRTHSIGNBINDINGS_H + +#include + +#include "context.hpp" + +namespace MWLua +{ + sol::table initCoreBirthSignBindings(const Context& context); +} + +#endif // MWLUA_BIRTHSIGNBINDINGS_H diff --git a/apps/openmw/mwlua/types/player.cpp b/apps/openmw/mwlua/types/player.cpp index d2a9c5d920..462bfa888e 100644 --- a/apps/openmw/mwlua/types/player.cpp +++ b/apps/openmw/mwlua/types/player.cpp @@ -1,5 +1,6 @@ #include "types.hpp" +#include "../birthsignbindings.hpp" #include "../luamanagerimp.hpp" #include "apps/openmw/mwbase/inputmanager.hpp" @@ -170,5 +171,7 @@ namespace MWLua player["isCharGenFinished"] = [](const Object&) -> bool { return MWBase::Environment::get().getWorld()->getGlobalFloat(MWWorld::Globals::sCharGenState) == -1; }; + + player["birthSigns"] = initCoreBirthSignBindings(context); } } diff --git a/files/lua_api/openmw/types.lua b/files/lua_api/openmw/types.lua index 4eb8459a6b..a14c44ebdb 100644 --- a/files/lua_api/openmw/types.lua +++ b/files/lua_api/openmw/types.lua @@ -1045,6 +1045,28 @@ -- Values that can be used with getControlSwitch/setControlSwitch. -- @field [parent=#Player] #CONTROL_SWITCH CONTROL_SWITCH +--- @{#BirthSigns}: Birth Sign Data +-- @field [parent=#Player] #BirthSigns birthSigns + +--- +-- A read-only list of all @{#BirthSignRecord}s in the world database. +-- @field [parent=#BirthSigns] #list<#BirthSignRecord> records + +--- +-- Returns a read-only @{#BirthSignRecord} +-- @function [parent=#BirthSigns] record +-- @param #string recordId +-- @return #BirthSignRecord + +--- +-- Birth sign data record +-- @type BirthSignRecord +-- @field #string id Birth sign id +-- @field #string name Birth sign name +-- @field #string description Birth sign description +-- @field #string texture Birth sign texture +-- @field #list<#string> spells A read-only list containing the ids of all spells gained from this sign. + --- -- Send an event to menu scripts. -- @function [parent=#core] sendMenuEvent From f114d409c8ba855f6c01cbb4850c1f6922ab5a7a Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 7 Feb 2024 19:35:26 +0100 Subject: [PATCH 2/3] Add get and set birth sign --- apps/openmw/mwlua/types/player.cpp | 28 ++++++++++++++++++++++++++++ files/lua_api/openmw/types.lua | 11 +++++++++++ 2 files changed, 39 insertions(+) diff --git a/apps/openmw/mwlua/types/player.cpp b/apps/openmw/mwlua/types/player.cpp index 462bfa888e..c12f40e832 100644 --- a/apps/openmw/mwlua/types/player.cpp +++ b/apps/openmw/mwlua/types/player.cpp @@ -8,7 +8,11 @@ #include "apps/openmw/mwbase/world.hpp" #include "apps/openmw/mwmechanics/npcstats.hpp" #include "apps/openmw/mwworld/class.hpp" +#include "apps/openmw/mwworld/esmstore.hpp" #include "apps/openmw/mwworld/globals.hpp" +#include "apps/openmw/mwworld/player.hpp" + +#include namespace MWLua { @@ -35,6 +39,20 @@ namespace sol }; } +namespace +{ + ESM::RefId toBirthSignId(const sol::object& recordOrId) + { + if (recordOrId.is()) + return recordOrId.as()->mId; + std::string_view textId = LuaUtil::cast(recordOrId); + ESM::RefId id = ESM::RefId::deserializeText(textId); + if (!MWBase::Environment::get().getESMStore()->get().search(id)) + throw std::runtime_error("Failed to find birth sign: " + std::string(textId)); + return id; + } +} + namespace MWLua { static void verifyPlayer(const Object& player) @@ -173,5 +191,15 @@ namespace MWLua }; player["birthSigns"] = initCoreBirthSignBindings(context); + player["getBirthSign"] = [](const Object& player) -> std::string { + verifyPlayer(player); + return MWBase::Environment::get().getWorld()->getPlayer().getBirthSign().serializeText(); + }; + player["setBirthSign"] = [](const Object& player, const sol::object& recordOrId) { + verifyPlayer(player); + if (!dynamic_cast(&player)) + throw std::runtime_error("Only global scripts can change birth signs"); + MWBase::Environment::get().getWorld()->getPlayer().setBirthSign(toBirthSignId(recordOrId)); + }; } } diff --git a/files/lua_api/openmw/types.lua b/files/lua_api/openmw/types.lua index a14c44ebdb..edd2c1170f 100644 --- a/files/lua_api/openmw/types.lua +++ b/files/lua_api/openmw/types.lua @@ -1045,6 +1045,17 @@ -- Values that can be used with getControlSwitch/setControlSwitch. -- @field [parent=#Player] #CONTROL_SWITCH CONTROL_SWITCH +--- +-- @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 +-- @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 From 7586acc18bf2dbd05b65165c7f9b5118d25fb032 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Thu, 8 Feb 2024 16:53:48 +0100 Subject: [PATCH 3/3] Remove Core from functions that aren't in openmw.core --- apps/openmw/mwlua/birthsignbindings.cpp | 2 +- apps/openmw/mwlua/birthsignbindings.hpp | 2 +- apps/openmw/mwlua/classbindings.cpp | 2 +- apps/openmw/mwlua/classbindings.hpp | 2 +- apps/openmw/mwlua/types/npc.cpp | 2 +- apps/openmw/mwlua/types/player.cpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwlua/birthsignbindings.cpp b/apps/openmw/mwlua/birthsignbindings.cpp index 5592179fee..e569bc1b8f 100644 --- a/apps/openmw/mwlua/birthsignbindings.cpp +++ b/apps/openmw/mwlua/birthsignbindings.cpp @@ -25,7 +25,7 @@ namespace sol namespace MWLua { - sol::table initCoreBirthSignBindings(const Context& context) + sol::table initBirthSignRecordBindings(const Context& context) { sol::state_view& lua = context.mLua->sol(); sol::table birthSigns(context.mLua->sol(), sol::create); diff --git a/apps/openmw/mwlua/birthsignbindings.hpp b/apps/openmw/mwlua/birthsignbindings.hpp index 7c88b8cccb..bf41707d47 100644 --- a/apps/openmw/mwlua/birthsignbindings.hpp +++ b/apps/openmw/mwlua/birthsignbindings.hpp @@ -7,7 +7,7 @@ namespace MWLua { - sol::table initCoreBirthSignBindings(const Context& context); + sol::table initBirthSignRecordBindings(const Context& context); } #endif // MWLUA_BIRTHSIGNBINDINGS_H diff --git a/apps/openmw/mwlua/classbindings.cpp b/apps/openmw/mwlua/classbindings.cpp index 339b724f19..ea1ea8e7ef 100644 --- a/apps/openmw/mwlua/classbindings.cpp +++ b/apps/openmw/mwlua/classbindings.cpp @@ -25,7 +25,7 @@ namespace sol namespace MWLua { - sol::table initCoreClassBindings(const Context& context) + sol::table initClassRecordBindings(const Context& context) { sol::state_view& lua = context.mLua->sol(); sol::table classes(context.mLua->sol(), sol::create); diff --git a/apps/openmw/mwlua/classbindings.hpp b/apps/openmw/mwlua/classbindings.hpp index 9dd9befae4..1acb0a9ad3 100644 --- a/apps/openmw/mwlua/classbindings.hpp +++ b/apps/openmw/mwlua/classbindings.hpp @@ -7,7 +7,7 @@ namespace MWLua { - sol::table initCoreClassBindings(const Context& context); + sol::table initClassRecordBindings(const Context& context); } #endif // MWLUA_CLASSBINDINGS_H diff --git a/apps/openmw/mwlua/types/npc.cpp b/apps/openmw/mwlua/types/npc.cpp index b1ac3d994a..d7d459bb81 100644 --- a/apps/openmw/mwlua/types/npc.cpp +++ b/apps/openmw/mwlua/types/npc.cpp @@ -85,7 +85,7 @@ namespace MWLua record["baseGold"] = sol::readonly_property([](const ESM::NPC& rec) -> int { return rec.mNpdt.mGold; }); addActorServicesBindings(record, context); - npc["classes"] = initCoreClassBindings(context); + npc["classes"] = initClassRecordBindings(context); // This function is game-specific, in future we should replace it with something more universal. npc["isWerewolf"] = [](const Object& o) { diff --git a/apps/openmw/mwlua/types/player.cpp b/apps/openmw/mwlua/types/player.cpp index c12f40e832..130d3ded21 100644 --- a/apps/openmw/mwlua/types/player.cpp +++ b/apps/openmw/mwlua/types/player.cpp @@ -190,7 +190,7 @@ namespace MWLua return MWBase::Environment::get().getWorld()->getGlobalFloat(MWWorld::Globals::sCharGenState) == -1; }; - player["birthSigns"] = initCoreBirthSignBindings(context); + player["birthSigns"] = initBirthSignRecordBindings(context); player["getBirthSign"] = [](const Object& player) -> std::string { verifyPlayer(player); return MWBase::Environment::get().getWorld()->getPlayer().getBirthSign().serializeText();