diff --git a/3rdParty/Lua/CMakeLists.txt b/3rdParty/Lua/CMakeLists.txt new file mode 100644 index 000000000000..5a73b850cd25 --- /dev/null +++ b/3rdParty/Lua/CMakeLists.txt @@ -0,0 +1,11 @@ +include(functions/FetchContent_MakeAvailableExcludeFromAll) + +include(FetchContent) +FetchContent_Declare(Lua + URL https://github.com/walterschell/Lua/archive/88246d621abf7b6fba9332f49229d507f020e450.tar.gz + URL_HASH MD5=03b76927cb5341ffc53bea12c37ddcca +) +FetchContent_MakeAvailableExcludeFromAll(Lua) + +# 3DS, Switch, Vita, and Xbox do not appear to support 64bit types +target_compile_definitions(lua_static PRIVATE -DLUA_C89_NUMBERS=0) diff --git a/CMake/Dependencies.cmake b/CMake/Dependencies.cmake index da00a27b461e..9a48e11bb741 100644 --- a/CMake/Dependencies.cmake +++ b/CMake/Dependencies.cmake @@ -24,6 +24,8 @@ if(SUPPORTS_MPQ) endif() endif() +add_subdirectory(3rdParty/Lua) + if(SCREEN_READER_INTEGRATION) if(WIN32) add_subdirectory(3rdParty/tolk) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index a027ccdd3b69..4f670f81c3b6 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -159,6 +159,7 @@ set(libdevilutionx_SRCS utils/format_int.cpp utils/language.cpp utils/logged_fstream.cpp + utils/lua.cpp utils/paths.cpp utils/parse_int.cpp utils/pcx_to_clx.cpp @@ -287,6 +288,8 @@ if(DISCORD_INTEGRATION) target_link_libraries(libdevilutionx PRIVATE discord discord_game_sdk) endif() +target_link_libraries(libdevilutionx PRIVATE lua_static) + if(SCREEN_READER_INTEGRATION AND WIN32) target_compile_definitions(libdevilutionx PRIVATE Tolk) endif() diff --git a/Source/diablo.cpp b/Source/diablo.cpp index fc16323bc566..63920957b7f0 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -81,6 +81,7 @@ #include "utils/console.h" #include "utils/display.h" #include "utils/language.h" +#include "utils/lua.hpp" #include "utils/parse_int.hpp" #include "utils/paths.h" #include "utils/screen_reader.hpp" @@ -822,6 +823,7 @@ void RunGameLoop(interface_mode uMsg) nthread_ignore_mutex(false); discord_manager::StartGame(); + LuaEvent("GameStartedEvent"); #ifdef GPERF_HEAP_FIRST_GAME_ITERATION unsigned run_game_iteration = 0; #endif @@ -1230,6 +1232,7 @@ void DiabloDeinit() { FreeItemGFX(); + LuaShutdown(); ShutDownScreenReader(); if (gbSndInited) @@ -2449,6 +2452,7 @@ int DiabloMain(int argc, char **argv) LoadLanguageArchive(); ApplicationInit(); + LuaInitialize(); SaveOptions(); // Finally load game data diff --git a/Source/utils/lua.cpp b/Source/utils/lua.cpp new file mode 100644 index 000000000000..c0e0bfa62ce8 --- /dev/null +++ b/Source/utils/lua.cpp @@ -0,0 +1,51 @@ +#include "utils/lua.hpp" + +extern "C" { +#include +#include +#include +} + +#include "plrmsg.h" + +namespace devilution { + +lua_State *LuaState; + +int LuaPlayerMessage(lua_State *state) +{ + if (!lua_isstring(LuaState, 1)) + return 0; + + std::string msg = lua_tostring(state, 1); + EventPlrMsg(msg, UiFlags::ColorRed); + + return 1; +} + +void LuaInitialize() +{ + LuaState = luaL_newstate(); + lua_register(LuaState, "PlayerMessage", LuaPlayerMessage); + + int status = luaL_dofile(LuaState, "init.lua"); + if (status != LUA_OK) + SDL_Log("%s", lua_tostring(LuaState, -1)); +} + +void LuaShutdown() +{ + lua_close(LuaState); +} + +void LuaEvent(std::string name) +{ + lua_getglobal(LuaState, name.c_str()); + if (!lua_isfunction(LuaState, -1)) + return; + int status = lua_pcall(LuaState, 0, 0, 0); + if (status != LUA_OK) + SDL_Log("%s", lua_tostring(LuaState, -1)); +} + +} // namespace devilution diff --git a/Source/utils/lua.hpp b/Source/utils/lua.hpp new file mode 100644 index 000000000000..a66a5251f850 --- /dev/null +++ b/Source/utils/lua.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include + +namespace devilution { + +void LuaInitialize(); +void LuaShutdown(); +void LuaEvent(std::string name); + +} // namespace devilution