From 04cc99cbdeb827e204fab71b4fa4522238f0650c Mon Sep 17 00:00:00 2001 From: Trihedraf Date: Mon, 2 Mar 2026 20:19:44 -0800 Subject: [PATCH] LuaEvent > lua:: named functions. +lua_event.cpp --- Source/CMakeLists.txt | 1 + Source/diablo.cpp | 3 +- Source/engine/render/scrollrt.cpp | 4 +- Source/lua/lua_event.cpp | 86 +++++++++++++++++++++++++++++++ Source/lua/lua_event.hpp | 29 ++++++++--- Source/lua/lua_global.cpp | 43 ++-------------- Source/lua/lua_global.hpp | 10 +--- Source/monster.cpp | 4 +- Source/player.cpp | 6 +-- Source/stores.cpp | 16 +++--- Source/tables/itemdat.cpp | 6 +-- Source/tables/monstdat.cpp | 6 +-- 12 files changed, 139 insertions(+), 75 deletions(-) create mode 100644 Source/lua/lua_event.cpp diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 4501d6cc9..2179dadf2 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -100,6 +100,7 @@ set(libdevilutionx_SRCS levels/trigs.cpp lua/autocomplete.cpp + lua/lua_event.cpp lua/lua_global.cpp lua/modules/audio.cpp lua/modules/hellfire.cpp diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 0339a9043..b14da41cb 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -72,6 +72,7 @@ #include "levels/trigs.h" #include "lighting.h" #include "loadsave.h" +#include "lua/lua_event.hpp" #include "lua/lua_global.hpp" #include "menu.h" #include "minitext.h" @@ -876,7 +877,7 @@ void RunGameLoop(interface_mode uMsg) nthread_ignore_mutex(false); discord_manager::StartGame(); - LuaEvent("GameStart"); + lua::GameStart(); #ifdef GPERF_HEAP_FIRST_GAME_ITERATION unsigned run_game_iteration = 0; #endif diff --git a/Source/engine/render/scrollrt.cpp b/Source/engine/render/scrollrt.cpp index a3c728f70..eab266304 100644 --- a/Source/engine/render/scrollrt.cpp +++ b/Source/engine/render/scrollrt.cpp @@ -48,7 +48,7 @@ #include "levels/gendung.h" #include "levels/tile_properties.hpp" #include "lighting.h" -#include "lua/lua_global.hpp" +#include "lua/lua_event.hpp" #include "minitext.h" #include "missiles.h" #include "nthread.h" @@ -1898,7 +1898,7 @@ void DrawAndBlit() DrawFPS(out); - LuaEvent("GameDrawComplete"); + lua::GameDrawComplete(); DrawMain(hgt, drawInfoBox, drawHealth, drawMana, drawBelt, drawControlButtons); diff --git a/Source/lua/lua_event.cpp b/Source/lua/lua_event.cpp new file mode 100644 index 000000000..d1eb38c7e --- /dev/null +++ b/Source/lua/lua_event.cpp @@ -0,0 +1,86 @@ +#include "lua/lua_event.hpp" + +#include +#include +#include + +#include + +#include "lua/lua_global.hpp" +#include "monster.h" +#include "player.h" +#include "utils/log.hpp" + +namespace devilution { + +namespace lua { + +template +void CallLuaEvent(std::string_view name, Args &&...args) +{ + sol::table *events = GetLuaEvents(); + if (events == nullptr) { + return; + } + + const auto trigger = events->traverse_get>(name, "trigger"); + if (!trigger.has_value() || !trigger->is()) { + LogError("events.{}.trigger is not a function", name); + return; + } + const sol::protected_function fn = trigger->as(); + SafeCallResult(fn(std::forward(args)...), /*optional=*/true); +} + +void MonsterDataLoaded() +{ + CallLuaEvent("MonsterDataLoaded"); +} +void UniqueMonsterDataLoaded() +{ + CallLuaEvent("UniqueMonsterDataLoaded"); +} +void ItemDataLoaded() +{ + CallLuaEvent("ItemDataLoaded"); +} +void UniqueItemDataLoaded() +{ + CallLuaEvent("UniqueItemDataLoaded"); +} + +void StoreOpened(std::string_view name) +{ + CallLuaEvent("StoreOpened", name); +} + +void OnMonsterTakeDamage(const Monster *monster, int damage, int damageType) +{ + CallLuaEvent("OnMonsterTakeDamage", monster, damage, damageType); +} + +void OnPlayerGainExperience(const Player *player, uint32_t exp) +{ + CallLuaEvent("OnPlayerGainExperience", player, exp); +} +void OnPlayerTakeDamage(const Player *player, int damage, int damageType) +{ + CallLuaEvent("OnPlayerTakeDamage", player, damage, damageType); +} + +void LoadModsComplete() +{ + CallLuaEvent("LoadModsComplete"); +} +void GameDrawComplete() +{ + CallLuaEvent("GameDrawComplete"); +} +void GameStart() +{ + CallLuaEvent("GameStart"); +} + +} // namespace lua + +} // namespace devilution diff --git a/Source/lua/lua_event.hpp b/Source/lua/lua_event.hpp index b7c016107..f8f54d91e 100644 --- a/Source/lua/lua_event.hpp +++ b/Source/lua/lua_event.hpp @@ -1,14 +1,31 @@ #pragma once +#include #include namespace devilution { -/** - * @brief Triggers a Lua event by name. - * This is a minimal header for code that only needs to trigger events. - */ -void LuaEvent(std::string_view name); -void LuaEvent(std::string_view name, std::string_view arg); +struct Player; +struct Monster; + +namespace lua { + +void MonsterDataLoaded(); +void UniqueMonsterDataLoaded(); +void ItemDataLoaded(); +void UniqueItemDataLoaded(); + +void StoreOpened(std::string_view name); + +void OnMonsterTakeDamage(const Monster *monster, int damage, int damageType); + +void OnPlayerGainExperience(const Player *player, uint32_t exp); +void OnPlayerTakeDamage(const Player *player, int damage, int damageType); + +void LoadModsComplete(); +void GameDrawComplete(); +void GameStart(); + +} // namespace lua } // namespace devilution diff --git a/Source/lua/lua_global.cpp b/Source/lua/lua_global.cpp index af030f25c..8e2d7007b 100644 --- a/Source/lua/lua_global.cpp +++ b/Source/lua/lua_global.cpp @@ -12,6 +12,7 @@ #include "appfat.h" #include "effects.h" #include "engine/assets.hpp" +#include "lua/lua_event.hpp" #include "lua/modules/audio.hpp" #include "lua/modules/floatingnumbers.hpp" #include "lua/modules/hellfire.hpp" @@ -254,7 +255,7 @@ void LuaReloadActiveMods() LoadObjectData(); LoadQuestData(); - LuaEvent("LoadModsComplete"); + lua::LoadModsComplete(); } void LuaInitialize() @@ -314,45 +315,9 @@ void LuaShutdown() CurrentLuaState = std::nullopt; } -template -void CallLuaEvent(std::string_view name, Args &&...args) +sol::table *GetLuaEvents() { - if (!CurrentLuaState.has_value()) { - return; - } - - const auto trigger = CurrentLuaState->events.traverse_get>(name, "trigger"); - if (!trigger.has_value() || !trigger->is()) { - LogError("events.{}.trigger is not a function", name); - return; - } - const sol::protected_function fn = trigger->as(); - SafeCallResult(fn(std::forward(args)...), /*optional=*/true); -} - -void LuaEvent(std::string_view name) -{ - CallLuaEvent(name); -} - -void LuaEvent(std::string_view name, std::string_view arg) -{ - CallLuaEvent(name, arg); -} - -void LuaEvent(std::string_view name, const Player *player, int arg1, int arg2) -{ - CallLuaEvent(name, player, arg1, arg2); -} - -void LuaEvent(std::string_view name, const Monster *monster, int arg1, int arg2) -{ - CallLuaEvent(name, monster, arg1, arg2); -} - -void LuaEvent(std::string_view name, const Player *player, uint32_t arg1) -{ - CallLuaEvent(name, player, arg1); + return CurrentLuaState ? &CurrentLuaState->events : nullptr; } sol::state &GetLuaState() diff --git a/Source/lua/lua_global.hpp b/Source/lua/lua_global.hpp index 24f70901e..d7812f1a7 100644 --- a/Source/lua/lua_global.hpp +++ b/Source/lua/lua_global.hpp @@ -8,20 +8,14 @@ namespace devilution { -struct Player; -struct Monster; - void LuaInitialize(); void LuaReloadActiveMods(); void LuaShutdown(); -void LuaEvent(std::string_view name); -void LuaEvent(std::string_view name, std::string_view arg); -void LuaEvent(std::string_view name, const Player *player, int arg1, int arg2); -void LuaEvent(std::string_view name, const Monster *monster, int arg1, int arg2); -void LuaEvent(std::string_view name, const Player *player, uint32_t arg1); + sol::state &GetLuaState(); sol::environment CreateLuaSandbox(); sol::object SafeCallResult(sol::protected_function_result result, bool optional); +sol::table *GetLuaEvents(); /** Adds a handler to be called when mods status changes after the initial startup. */ void AddModsChangedHandler(tl::function_ref callback); diff --git a/Source/monster.cpp b/Source/monster.cpp index f6e86adc0..e8905a23d 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -70,7 +70,7 @@ #include "levels/tile_properties.hpp" #include "levels/trigs.h" #include "lighting.h" -#include "lua/lua_global.hpp" +#include "lua/lua_event.hpp" #include "minitext.h" #include "missiles.h" #include "movie.h" @@ -3868,7 +3868,7 @@ void AddDoppelganger(Monster &monster) void ApplyMonsterDamage(DamageType damageType, Monster &monster, int damage) { - LuaEvent("OnMonsterTakeDamage", &monster, damage, static_cast(damageType)); + lua::OnMonsterTakeDamage(&monster, damage, static_cast(damageType)); monster.hitPoints -= damage; diff --git a/Source/player.cpp b/Source/player.cpp index b0e9a7222..1b6f14096 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -41,7 +41,7 @@ #include "levels/trigs.h" #include "lighting.h" #include "loadsave.h" -#include "lua/lua_global.hpp" +#include "lua/lua_event.hpp" #include "minitext.h" #include "missiles.h" #include "monster.h" @@ -2442,7 +2442,7 @@ void Player::_addExperience(uint32_t experience, int levelDelta) clampedExp = std::min({ clampedExp, /* level 1-5: */ getNextExperienceThreshold() / 20U, /* level 6-50: */ 200U * getCharacterLevel() }); } - LuaEvent("OnPlayerGainExperience", this, clampedExp); + lua::OnPlayerGainExperience(this, clampedExp); const uint32_t maxExperience = GetNextExperienceThresholdForLevel(getMaxCharacterLevel()); @@ -2824,7 +2824,7 @@ void ApplyPlrDamage(DamageType damageType, Player &player, int dam, int minHP /* { int totalDamage = (dam << 6) + frac; if (&player == MyPlayer && !player.hasNoLife()) { - LuaEvent("OnPlayerTakeDamage", &player, totalDamage, static_cast(damageType)); + lua::OnPlayerTakeDamage(&player, totalDamage, static_cast(damageType)); } if (totalDamage > 0 && player.pManaShield && HasNoneOf(player._pIFlags, ItemSpecialEffect::NoMana)) { const uint8_t manaShieldLevel = player._pSplLvl[static_cast(SpellID::ManaShield)]; diff --git a/Source/stores.cpp b/Source/stores.cpp index 70c468f7c..bd5cb919f 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -2204,28 +2204,28 @@ void StartStore(TalkID s) // Fire StoreOpened Lua event for main store entries switch (s) { case TalkID::Smith: - LuaEvent("StoreOpened", "griswold"); + lua::StoreOpened("griswold"); break; case TalkID::Witch: - LuaEvent("StoreOpened", "adria"); + lua::StoreOpened("adria"); break; case TalkID::Boy: - LuaEvent("StoreOpened", "wirt"); + lua::StoreOpened("wirt"); break; case TalkID::Healer: - LuaEvent("StoreOpened", "pepin"); + lua::StoreOpened("pepin"); break; case TalkID::Storyteller: - LuaEvent("StoreOpened", "cain"); + lua::StoreOpened("cain"); break; case TalkID::Tavern: - LuaEvent("StoreOpened", "ogden"); + lua::StoreOpened("ogden"); break; case TalkID::Drunk: - LuaEvent("StoreOpened", "farnham"); + lua::StoreOpened("farnham"); break; case TalkID::Barmaid: - LuaEvent("StoreOpened", "gillian"); + lua::StoreOpened("gillian"); break; default: break; diff --git a/Source/tables/itemdat.cpp b/Source/tables/itemdat.cpp index 8c26c7b4d..1ec2da413 100644 --- a/Source/tables/itemdat.cpp +++ b/Source/tables/itemdat.cpp @@ -14,7 +14,7 @@ #include "data/file.hpp" #include "data/iterators.hpp" #include "data/record_reader.hpp" -#include "lua/lua_global.hpp" +#include "lua/lua_event.hpp" #include "tables/spelldat.h" #include "utils/str_cat.hpp" @@ -619,7 +619,7 @@ void LoadItemDat() ItemMappingIdsToIndices.clear(); LoadItemDatFromFile(dataFile, filename, 0); - LuaEvent("ItemDataLoaded"); + lua::ItemDataLoaded(); } void ReadItemPower(RecordReader &reader, std::string_view fieldName, ItemPower &power) @@ -676,7 +676,7 @@ void LoadUniqueItemDat() UniqueItemMappingIdsToIndices.clear(); LoadUniqueItemDatFromFile(dataFile, filename, 0); - LuaEvent("UniqueItemDataLoaded"); + lua::UniqueItemDataLoaded(); } void LoadItemAffixesDat(std::string_view filename, std::vector &out) diff --git a/Source/tables/monstdat.cpp b/Source/tables/monstdat.cpp index 1eadd020e..f81313d38 100644 --- a/Source/tables/monstdat.cpp +++ b/Source/tables/monstdat.cpp @@ -24,7 +24,7 @@ #include "data/iterators.hpp" #include "data/record_reader.hpp" #include "items.h" -#include "lua/lua_global.hpp" +#include "lua/lua_event.hpp" #include "monster.h" #include "tables/textdat.h" #include "utils/language.h" @@ -413,7 +413,7 @@ void LoadMonstDat() MonstersData.resize(NUM_DEFAULT_MTYPES); // ensure the hardcoded monster type slots are filled LoadMonstDatFromFile(dataFile, filename, false); - LuaEvent("MonsterDataLoaded"); + lua::MonsterDataLoaded(); MonstersData.shrink_to_fit(); } @@ -462,7 +462,7 @@ void LoadUniqueMonstDat() UniqueMonstersData.clear(); LoadUniqueMonstDatFromFile(dataFile, filename); - LuaEvent("UniqueMonsterDataLoaded"); + lua::UniqueMonsterDataLoaded(); UniqueMonstersData.shrink_to_fit(); }