From f73d52c917ab7d03380c61f4ec051f4dd49bbecd Mon Sep 17 00:00:00 2001 From: Alex Noir Date: Fri, 14 Jun 2024 00:09:27 +0300 Subject: [PATCH] Add paintTileMapPort to support world map tile painting (no getTileMapPort yet) --- library/LuaApi.cpp | 29 ++++++++++++++++++++++++++ library/include/modules/Screen.h | 9 ++++++++ library/modules/Screen.cpp | 35 ++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index acbd1cb8d5..01b5ff5e76 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -2860,6 +2860,34 @@ static int screen_readTile(lua_State *L) return 1; } +static int screen_paintTileMapPort(lua_State *L) +{ + Pen pen; + Lua::CheckPen(L, &pen, 1); + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); + if (lua_gettop(L) >= 4 && !lua_isnil(L, 4)) + { + if (lua_type(L, 4) == LUA_TSTRING) + pen.ch = lua_tostring(L, 4)[0]; + else + pen.ch = luaL_checkint(L, 4); + } + if (lua_gettop(L) >= 5 && !lua_isnil(L, 5)) + pen.tile = luaL_checkint(L, 5); + lua_pushboolean(L, Screen::paintTileMapPort(pen, x, y)); + return 1; +} + +// static int screen_readTileMapPort(lua_State *L) +// { +// int x = luaL_checkint(L, 1); +// int y = luaL_checkint(L, 2); +// Pen pen = Screen::readTileMapPort(x, y); +// Lua::Push(L, pen); +// return 1; +// } + static int screen_paintString(lua_State *L) { Pen pen; @@ -3047,6 +3075,7 @@ static const luaL_Reg dfhack_screen_funcs[] = { { "getWindowSize", screen_getWindowSize }, { "paintTile", screen_paintTile }, { "readTile", screen_readTile }, + { "paintTileMapPort", screen_paintTileMapPort }, { "paintString", screen_paintString }, { "fillRect", screen_fillRect }, { "findGraphicsTile", screen_findGraphicsTile }, diff --git a/library/include/modules/Screen.h b/library/include/modules/Screen.h index f2078e663d..1c60638dce 100644 --- a/library/include/modules/Screen.h +++ b/library/include/modules/Screen.h @@ -35,6 +35,7 @@ distribution. #include "df/viewscreen.h" #include "df/graphic_viewportst.h" +#include "df/graphic_map_portst.h" #include #include @@ -203,6 +204,12 @@ namespace DFHack /// Retrieves one screen tile from the buffer DFHACK_EXPORT Pen readTile(int x, int y, bool map = false, int32_t * df::graphic_viewportst::*texpos_field = NULL); + /// Paint one world map tile with the given pen + DFHACK_EXPORT bool paintTileMapPort(const Pen &pen, int x, int y, int32_t * df::graphic_map_portst::*texpos_field = NULL); + + /// Retrieves one world map tile from the buffer + // DFHACK_EXPORT Pen readTile(int x, int y, int32_t * df::graphic_map_portst::*texpos_field = NULL); + /// Paint a string onto the screen. Ignores ch and tile of pen. DFHACK_EXPORT bool paintString(const Pen &pen, int x, int y, const std::string &text, bool map = false); @@ -315,6 +322,8 @@ namespace DFHack namespace Hooks { GUI_HOOK_DECLARE(get_tile, Pen, (int x, int y, bool map, int32_t * df::graphic_viewportst::*texpos_field)); GUI_HOOK_DECLARE(set_tile, bool, (const Pen &pen, int x, int y, bool map, int32_t * df::graphic_viewportst::*texpos_field)); + // GUI_HOOK_DECLARE(get_tile_map_port, Pen, (int x, int y, int32_t * df::graphic_map_portst::*texpos_field)); + GUI_HOOK_DECLARE(set_tile_map_port, bool, (const Pen &pen, int x, int y, int32_t * df::graphic_map_portst::*texpos_field)); } //! Temporary hide a screen until destructor is called diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index 8c3745e22f..161b61cc7a 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -365,6 +365,41 @@ Pen Screen::readTile(int x, int y, bool map, int32_t * df::graphic_viewportst::* return doGetTile(x, y, map, texpos_field); } +static bool doSetTile_map_port(const Pen &pen, int x, int y, int32_t * df::graphic_map_portst::*texpos_field) { + auto &vp = gps->main_map_port; + if (!texpos_field) + texpos_field = &df::graphic_map_portst::screentexpos_interface; + + if (x < 0 || x >= vp->dim_x || y < 0 || y >= vp->dim_y) + return false; + + size_t max_index = vp->dim_y * vp->dim_x - 1; + size_t index = (y * vp->dim_x) + x; + + if (index > max_index) + return false; + + long texpos = pen.tile; + if (!texpos && pen.ch) + texpos = init->font.large_font_texpos[(uint8_t)pen.ch]; + (vp->*texpos_field)[index] = texpos; + return true; +} + +GUI_HOOK_DEFINE(Screen::Hooks::set_tile_map_port, doSetTile_map_port); +static bool doSetTileMapPort(const Pen &pen, int x, int y, int32_t * df::graphic_map_portst::*texpos_field = NULL) +{ + return GUI_HOOK_TOP(Screen::Hooks::set_tile_map_port)(pen, x, y, texpos_field); +} + +bool Screen::paintTileMapPort(const Pen &pen, int x, int y, int32_t * df::graphic_map_portst::*texpos_field) +{ + if (!gps || !pen.valid()) return false; + + doSetTileMapPort(pen, x, y, texpos_field); + return true; +} + bool Screen::paintString(const Pen &pen, int x, int y, const std::string &text, bool map) { auto dim = getWindowSize();