diff --git a/SRB2.cbp b/SRB2.cbp index 99a71226467e07aeb3e6f01f01cb99608bea6cf7..f56a9a16039c4981e0633d7e83374975e438b0f2 100644 --- a/SRB2.cbp +++ b/SRB2.cbp @@ -2561,6 +2561,21 @@ HW3SOUND for 3D hardware sound support <Option target="Debug Mingw64/DirectX" /> <Option target="Release Mingw64/DirectX" /> </Unit> + <Unit filename="src/lua_blockmaplib.c"> + <Option compilerVar="CC" /> + <Option target="Debug Native/SDL" /> + <Option target="Release Native/SDL" /> + <Option target="Debug Mingw/SDL" /> + <Option target="Release Mingw/SDL" /> + <Option target="Debug Mingw/DirectX" /> + <Option target="Release Mingw/DirectX" /> + <Option target="Debug Linux/SDL" /> + <Option target="Release Linux/SDL" /> + <Option target="Debug Mingw64/SDL" /> + <Option target="Release Mingw64/SDL" /> + <Option target="Debug Mingw64/DirectX" /> + <Option target="Release Mingw64/DirectX" /> + </Unit> <Unit filename="src/lua_consolelib.c"> <Option compilerVar="CC" /> <Option target="Debug Native/SDL" /> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba354c2899870ccb7d4d850863b6a20ebd618110..cc728a61363ae095ee6746cc36811c1d7f981731 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -231,6 +231,7 @@ if(${SRB2_CONFIG_HAVE_BLUA}) add_definitions(-DHAVE_BLUA) set(SRB2_LUA_SOURCES lua_baselib.c + lua_blockmaplib.c lua_consolelib.c lua_hooklib.c lua_hudlib.c diff --git a/src/blua/Makefile.cfg b/src/blua/Makefile.cfg index e3fb3df4664e4943aff54361dd32be4500675bdd..8d2e7371428db75ced4042be0f33167a594d65f3 100644 --- a/src/blua/Makefile.cfg +++ b/src/blua/Makefile.cfg @@ -48,4 +48,5 @@ OBJS:=$(OBJS) \ $(OBJDIR)/lua_skinlib.o \ $(OBJDIR)/lua_thinkerlib.o \ $(OBJDIR)/lua_maplib.o \ + $(OBJDIR)/lua_blockmaplib.o \ $(OBJDIR)/lua_hudlib.o diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 9eec5bc6e7dd0a561a770c9ad0ecc1ed7486a5b1..78e42f7a42e00c476cb709204a00ea340eb56786 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -28,7 +28,8 @@ #define NOHUD if (hud_running) return luaL_error(L, "HUD rendering code should not call this function!"); // uncomment if you want to test - #define LUA_BLOCKMAP +// note: now outdated +//#define LUA_BLOCKMAP boolean luaL_checkboolean(lua_State *L, int narg) { luaL_checktype(L, narg, LUA_TBOOLEAN); diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c new file mode 100644 index 0000000000000000000000000000000000000000..f7ead76823873c73564f1ccbe804dfd85314af24 --- /dev/null +++ b/src/lua_blockmaplib.c @@ -0,0 +1,248 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2016 by Iestyn "Monster Iestyn" Jealous. +// Copyright (C) 2016 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file lua_blockmaplib.c +/// \brief blockmap library for Lua scripting + +#include "doomdef.h" +#ifdef HAVE_BLUA +#include "p_local.h" +#include "r_main.h" // validcount +#include "lua_script.h" +#include "lua_libs.h" +//#include "lua_hud.h" // hud_running errors + +static const char *const search_opt[] = { + "objects", + "lines", + NULL}; + +// a quickly-made function pointer typedef used by lib_searchBlockmap... +typedef boolean (*blockmap_func)(lua_State *, INT32, INT32, mobj_t *); + +static boolean blockfuncerror = false; // errors should only print once per search blockmap call + +// Helper function for "objects" search +static boolean lib_searchBlockmap_Objects(lua_State *L, INT32 x, INT32 y, mobj_t *thing) +{ + mobj_t *mobj, *bnext = NULL; + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + return true; + + // Check interaction with the objects in the blockmap. + for (mobj = blocklinks[y*bmapwidth + x]; mobj; mobj = bnext) + { + P_SetTarget(&bnext, mobj->bnext); // We want to note our reference to bnext here incase it is MF_NOTHINK and gets removed! + if (mobj == thing) + continue; // our thing just found itself, so move on + lua_pushvalue(L, 1); // push function + LUA_PushUserdata(L, thing, META_MOBJ); + LUA_PushUserdata(L, mobj, META_MOBJ); + if (lua_pcall(gL, 2, 1, 0)) { + if (!blockfuncerror || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + blockfuncerror = true; + return true; + } + if (!lua_isnil(gL, -1)) + { // if nil, continue + if (lua_toboolean(gL, -1)) + return false; + } + lua_pop(gL, 1); + if (P_MobjWasRemoved(thing) // func just popped our thing, cannot continue. + || (bnext && P_MobjWasRemoved(bnext))) // func just broke blockmap chain, cannot continue. + { + P_SetTarget(&bnext, NULL); + return true; + } + } + return true; +} + +// Helper function for "lines" search +static boolean lib_searchBlockmap_Lines(lua_State *L, INT32 x, INT32 y, mobj_t *thing) +{ + INT32 offset; + const INT32 *list; // Big blockmap +#ifdef POLYOBJECTS + polymaplink_t *plink; // haleyjd 02/22/06 +#endif + line_t *ld; + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + return true; + + offset = y*bmapwidth + x; + +#ifdef POLYOBJECTS + // haleyjd 02/22/06: consider polyobject lines + plink = polyblocklinks[offset]; + + while (plink) + { + polyobj_t *po = plink->po; + + if (po->validcount != validcount) // if polyobj hasn't been checked + { + size_t i; + po->validcount = validcount; + + for (i = 0; i < po->numLines; ++i) + { + if (po->lines[i]->validcount == validcount) // line has been checked + continue; + po->lines[i]->validcount = validcount; + + lua_pushvalue(L, 1); + LUA_PushUserdata(L, thing, META_MOBJ); + LUA_PushUserdata(L, po->lines[i], META_LINE); + if (lua_pcall(gL, 2, 1, 0)) { + if (!blockfuncerror || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + blockfuncerror = true; + return true; + } + if (!lua_isnil(gL, -1)) + { // if nil, continue + if (lua_toboolean(gL, -1)) + return false; + } + lua_pop(gL, 1); + if (P_MobjWasRemoved(thing)) + return true; + } + } + plink = (polymaplink_t *)(plink->link.next); + } +#endif + + offset = *(blockmap + offset); // offset = blockmap[y*bmapwidth+x]; + + // First index is really empty, so +1 it. + for (list = blockmaplump + offset + 1; *list != -1; list++) + { + ld = &lines[*list]; + + if (ld->validcount == validcount) + continue; // Line has already been checked. + + ld->validcount = validcount; + + lua_pushvalue(L, 1); + LUA_PushUserdata(L, thing, META_MOBJ); + LUA_PushUserdata(L, ld, META_LINE); + if (lua_pcall(gL, 2, 1, 0)) { + if (!blockfuncerror || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + blockfuncerror = true; + return true; + } + if (!lua_isnil(gL, -1)) + { // if nil, continue + if (lua_toboolean(gL, -1)) + return false; + } + lua_pop(gL, 1); + if (P_MobjWasRemoved(thing)) + return true; + } + return true; // Everything was checked. +} + +// The searchBlockmap function +// arguments: searchBlockmap(searchtype, function, mobj, [x1, x2, y1, y2]) +// return value: +// true = search completely uninteruppted, +// false = searching of at least one block stopped mid-way (doesn't stop the whole search though) +static int lib_searchBlockmap(lua_State *L) +{ + int searchtype = luaL_checkoption(L, 1, "objects", search_opt); + int n; + mobj_t *mobj; + INT32 xl, xh, yl, yh, bx, by; + fixed_t x1, x2, y1, y2; + boolean retval = true; + blockmap_func searchFunc; + + lua_remove(L, 1); // remove searchtype, stack is now function, mobj, [x1, x2, y1, y2] + luaL_checktype(L, 1, LUA_TFUNCTION); + + switch (searchtype) + { + case 0: // "objects" + default: + searchFunc = lib_searchBlockmap_Objects; + break; + case 1: // "lines" + searchFunc = lib_searchBlockmap_Lines; + break; + } + + // the mobj we are searching around, the "calling" mobj we could say + mobj = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + if (!mobj) + return LUA_ErrInvalid(L, "mobj_t"); + + n = lua_gettop(L); + + if (n > 2) // specific x/y ranges have been supplied + { + if (n < 6) + return luaL_error(L, "arguments 4 to 6 not all given (expected 4 fixed-point integers)"); + + x1 = luaL_checkfixed(L, 3); + x2 = luaL_checkfixed(L, 4); + y1 = luaL_checkfixed(L, 5); + y2 = luaL_checkfixed(L, 6); + } + else // mobj and function only - search around mobj's radius by default + { + fixed_t radius = mobj->radius + MAXRADIUS; + x1 = mobj->x - radius; + x2 = mobj->x + radius; + y1 = mobj->y - radius; + y2 = mobj->y + radius; + } + lua_settop(L, 2); // pop everything except function, mobj + + xl = (unsigned)(x1 - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(x2 - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(y1 - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(y2 - bmaporgy)>>MAPBLOCKSHIFT; + + BMBOUNDFIX(xl, xh, yl, yh); + + blockfuncerror = false; // reset + validcount++; + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + { + if (!searchFunc(L, bx, by, mobj)) + retval = false; + if (P_MobjWasRemoved(mobj)){ + lua_pushboolean(L, false); + return 1; + } + } + lua_pushboolean(L, retval); + return 1; +} + +int LUA_BlockmapLib(lua_State *L) +{ + lua_register(L, "searchBlockmap", lib_searchBlockmap); + return 0; +} + +#endif \ No newline at end of file diff --git a/src/lua_libs.h b/src/lua_libs.h index 8cca200861d890fa5fa18a190b15b77d670c40a5..fc8da25c11518e12513233b403ecfa4165861ae3 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -70,6 +70,7 @@ int LUA_PlayerLib(lua_State *L); int LUA_SkinLib(lua_State *L); int LUA_ThinkerLib(lua_State *L); int LUA_MapLib(lua_State *L); +int LUA_BlockmapLib(lua_State *L); int LUA_HudLib(lua_State *L); #endif diff --git a/src/lua_script.c b/src/lua_script.c index 35d3fd51f178c6bf0acb8296b6e5bcd54b600850..6252330a4f4615748f7fa78ec4da0c79a7b8b259 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -48,6 +48,7 @@ static lua_CFunction liblist[] = { LUA_SkinLib, // skin_t, skins[] LUA_ThinkerLib, // thinker_t LUA_MapLib, // line_t, side_t, sector_t, subsector_t + LUA_BlockmapLib, // blockmap stuff LUA_HudLib, // HUD stuff NULL }; diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index 820192649d981adeaa477f0791d200f46d3ddfe9..abf6d76d2935d7546f445cf9b53880963d0b1433 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -295,6 +295,7 @@ </ClCompile> <ClCompile Include="..\i_tcp.c" /> <ClCompile Include="..\lua_baselib.c" /> + <ClCompile Include="..\lua_blockmaplib.c" /> <ClCompile Include="..\lua_consolelib.c" /> <ClCompile Include="..\lua_hooklib.c" /> <ClCompile Include="..\lua_hudlib.c" /> diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index d04007dd77d026e48e8480bf93a54b86d279b7c5..bdb029cf9437e8c960a84a111bbcbfaf5dc9b82b 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -633,6 +633,9 @@ <ClCompile Include="..\lua_baselib.c"> <Filter>LUA</Filter> </ClCompile> + <ClCompile Include="..\lua_blockmaplib.c"> + <Filter>LUA</Filter> + </ClCompile> <ClCompile Include="..\lua_consolelib.c"> <Filter>LUA</Filter> </ClCompile> diff --git a/src/win32/Srb2win-vc10.vcxproj b/src/win32/Srb2win-vc10.vcxproj index 064f75d7d06cdee1aa62d70dda03e9e28d53e6f2..95f9c85f94aeb1e6b62b2ac9447402a01c811840 100644 --- a/src/win32/Srb2win-vc10.vcxproj +++ b/src/win32/Srb2win-vc10.vcxproj @@ -131,6 +131,7 @@ </ClCompile> <ClCompile Include="..\i_tcp.c" /> <ClCompile Include="..\lua_baselib.c" /> + <ClCompile Include="..\lua_blockmaplib.c" /> <ClCompile Include="..\lua_consolelib.c" /> <ClCompile Include="..\lua_hooklib.c" /> <ClCompile Include="..\lua_hudlib.c" /> diff --git a/src/win32/Srb2win-vc10.vcxproj.filters b/src/win32/Srb2win-vc10.vcxproj.filters index b2647ea1c21518389b7061276f6464d05998721b..cfd46f1f81d260f7f9645759f7601626c6a64dad 100644 --- a/src/win32/Srb2win-vc10.vcxproj.filters +++ b/src/win32/Srb2win-vc10.vcxproj.filters @@ -225,6 +225,9 @@ <ClCompile Include="..\lua_baselib.c"> <Filter>LUA</Filter> </ClCompile> + <ClCompile Include="..\lua_blockmaplib.c"> + <Filter>LUA</Filter> + </ClCompile> <ClCompile Include="..\lua_consolelib.c"> <Filter>LUA</Filter> </ClCompile>