From c239a71ffe395c3bab79b8418279c3433e6b6adb Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 25 May 2016 16:34:09 +0100 Subject: [PATCH 01/21] Add P_PointOnLineSide to Lua --- src/lua_baselib.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 1bacf9102..e083530a9 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -205,6 +205,16 @@ static int lib_pClosestPointOnLine(lua_State *L) return 2; } +static int lib_pPointOnLineSide(lua_State *L) +{ + fixed_t x = luaL_checkfixed(L, 1); + fixed_t y = luaL_checkfixed(L, 2); + line_t *line = *((line_t **)luaL_checkudata(L, 3, META_LINE)); + //HUDSAFE + lua_pushinteger(L, P_PointOnLineSide(x, y, line)); + return 1; +} + // P_ENEMY ///////////// @@ -1981,6 +1991,7 @@ static luaL_Reg lib[] = { // p_maputil {"P_AproxDistance",lib_pAproxDistance}, {"P_ClosestPointOnLine",lib_pClosestPointOnLine}, + {"P_PointOnLineSide",lib_pPointOnLineSide}, // p_enemy {"P_CheckMeleeRange", lib_pCheckMeleeRange}, From 8211e89aec537ff6179330a30c42f31a36ecee9e Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 25 May 2016 17:15:44 +0100 Subject: [PATCH 02/21] Add seg_t to Lua, may be of use to Nev3r (and possibly others, I guess) segs[i] is the segs table, "for seg in segs.iterate" iterates through segs, you know the drill by now I hope --- src/lua_libs.h | 1 + src/lua_maplib.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++ src/lua_script.c | 16 ++++++ 3 files changed, 164 insertions(+) diff --git a/src/lua_libs.h b/src/lua_libs.h index 931cf62d0..6c9524dea 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -38,6 +38,7 @@ extern lua_State *gL; #define META_SUBSECTOR "SUBSECTOR_T*" #define META_SECTOR "SECTOR_T*" #define META_FFLOOR "FFLOOR_T*" +#define META_SEG "SEG_T*" #define META_MAPHEADER "MAPHEADER_T*" #define META_CVAR "CONSVAR_T*" diff --git a/src/lua_maplib.c b/src/lua_maplib.c index c512bf3c5..28561f34e 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -185,6 +185,32 @@ static const char *const ffloor_opt[] = { "alpha", NULL}; +enum seg_e { + seg_valid = 0, + seg_v1, + seg_v2, + seg_side, + seg_offset, + seg_angle, + seg_sidedef, + seg_linedef, + seg_frontsector, + seg_backsector, +}; + +static const char *const seg_opt[] = { + "valid", + "v1", + "v2", + "side", + "offset", + "angle", + "sidedef", + "linedef", + "frontsector", + "backsector", + NULL}; + static const char *const array_opt[] ={"iterate",NULL}; static const char *const valid_opt[] ={"valid",NULL}; @@ -818,6 +844,63 @@ static int vertex_num(lua_State *L) return 1; } +static int seg_get(lua_State *L) +{ + seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG)); + enum seg_e field = luaL_checkoption(L, 2, seg_opt[0], seg_opt); + + if (!seg) + { + if (field == seg_valid) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed seg_t doesn't exist anymore."); + } + + switch(field) + { + case seg_valid: // valid + lua_pushboolean(L, 1); + return 1; + case seg_v1: + LUA_PushUserdata(L, seg->v1, META_VERTEX); + return 1; + case seg_v2: + LUA_PushUserdata(L, seg->v2, META_VERTEX); + return 1; + case seg_side: + lua_pushinteger(L, seg->side); + return 1; + case seg_offset: + lua_pushfixed(L, seg->offset); + return 1; + case seg_angle: + lua_pushangle(L, seg->angle); + return 1; + case seg_sidedef: + LUA_PushUserdata(L, seg->sidedef, META_SIDE); + return 1; + case seg_linedef: + LUA_PushUserdata(L, seg->linedef, META_LINE); + return 1; + case seg_frontsector: + LUA_PushUserdata(L, seg->frontsector, META_SECTOR); + return 1; + case seg_backsector: + LUA_PushUserdata(L, seg->backsector, META_SECTOR); + return 1; + } + return 0; +} + +static int seg_num(lua_State *L) +{ + seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG)); + lua_pushinteger(L, seg-segs); + return 1; +} + static int lib_iterateSectors(lua_State *L) { size_t i = 0; @@ -1048,6 +1131,52 @@ static int lib_numvertexes(lua_State *L) return 1; } +static int lib_iterateSegs(lua_State *L) +{ + size_t i = 0; + if (lua_gettop(L) < 2) + return luaL_error(L, "Don't call segs.iterate() directly, use it as 'for seg in segs.iterate do end'."); + lua_settop(L, 2); + lua_remove(L, 1); // state is unused. + if (!lua_isnil(L, 1)) + i = (size_t)(*((seg_t **)luaL_checkudata(L, 1, META_SEG)) - segs)+1; + if (i < numsegs) + { + LUA_PushUserdata(L, &segs[i], META_SEG); + return 1; + } + return 0; +} + +static int lib_getSeg(lua_State *L) +{ + int field; + lua_settop(L, 2); + lua_remove(L, 1); // dummy userdata table is unused. + if (lua_isnumber(L, 1)) + { + size_t i = lua_tointeger(L, 1); + if (i >= numsegs) + return 0; + LUA_PushUserdata(L, &segs[i], META_SEG); + return 1; + } + field = luaL_checkoption(L, 1, NULL, array_opt); + switch(field) + { + case 0: // iterate + lua_pushcfunction(L, lib_iterateSegs); + return 1; + } + return 0; +} + +static int lib_numsegs(lua_State *L) +{ + lua_pushinteger(L, numsegs); + return 1; +} + static int ffloor_get(lua_State *L) { ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR)); @@ -1367,6 +1496,14 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L, 1); + luaL_newmetatable(L, META_SEG); + lua_pushcfunction(L, seg_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, seg_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + luaL_newmetatable(L, META_MAPHEADER); lua_pushcfunction(L, mapheaderinfo_get); lua_setfield(L, -2, "__index"); @@ -1425,6 +1562,16 @@ int LUA_MapLib(lua_State *L) lua_setmetatable(L, -2); lua_setglobal(L, "vertexes"); + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getSeg); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_numsegs); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "segs"); + lua_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_pushcfunction(L, lib_getMapheaderinfo); diff --git a/src/lua_script.c b/src/lua_script.c index acb306827..621b7dfe4 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -455,6 +455,7 @@ enum ARCH_SIDE, ARCH_SUBSECTOR, ARCH_SECTOR, + ARCH_SEG, ARCH_MAPHEADER, ARCH_TEND=0xFF, @@ -474,6 +475,7 @@ static const struct { {META_SIDE, ARCH_SIDE}, {META_SUBSECTOR,ARCH_SUBSECTOR}, {META_SECTOR, ARCH_SECTOR}, + {META_SEG, ARCH_SEG}, {META_MAPHEADER, ARCH_MAPHEADER}, {NULL, ARCH_NULL} }; @@ -664,6 +666,17 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) } break; } + case ARCH_SEG: + { + seg_t *seg = *((seg_t **)lua_touserdata(gL, myindex)); + if (!seg) + WRITEUINT8(save_p, ARCH_NULL); + else { + WRITEUINT8(save_p, ARCH_SEG); + WRITEUINT16(save_p, seg - segs); + } + break; + } case ARCH_MAPHEADER: { mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex)); @@ -842,6 +855,9 @@ static UINT8 UnArchiveValue(int TABLESINDEX) case ARCH_SECTOR: LUA_PushUserdata(gL, §ors[READUINT16(save_p)], META_SECTOR); break; + case ARCH_SEG: + LUA_PushUserdata(gL, &segs[READUINT16(save_p)], META_SEG); + break; case ARCH_MAPHEADER: LUA_PushUserdata(gL, §ors[READUINT16(save_p)], META_MAPHEADER); break; From 88a805b3313e6a47afa4423889254095c4091e04 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 24 Jun 2016 19:17:35 +0100 Subject: [PATCH 03/21] Using colormap[n] on colormap userdata from v.getColormap (e.g. colormap[0] or colormap[255]) now gives you the palette color replacing that index --- src/lua_hudlib.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 31549afa7..86784293e 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -223,7 +223,12 @@ static int hudinfo_num(lua_State *L) static int colormap_get(lua_State *L) { - return luaL_error(L, "colormap is not a struct."); + const UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP)); + UINT32 i = luaL_checkinteger(L, 2); + if (i >= 256) + return luaL_error(L, "colormap index %d out of range (0 - %d)", i, 255); + lua_pushinteger(L, colormap[i]); + return 1; } static int patch_get(lua_State *L) From 4c723d05ac49692ee839ea7f95b3fd6e088e9d3a Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 8 Jul 2016 20:05:54 +0100 Subject: [PATCH 04/21] Added node_t and nodes[] to Lua Still some issues with node.bbox, but the rest seems to work --- src/lua_libs.h | 5 + src/lua_maplib.c | 238 +++++++++++++++++++++++++++++++++++++++++++++++ src/lua_script.c | 16 ++++ 3 files changed, 259 insertions(+) diff --git a/src/lua_libs.h b/src/lua_libs.h index 6c9524dea..8cca20086 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -39,12 +39,17 @@ extern lua_State *gL; #define META_SECTOR "SECTOR_T*" #define META_FFLOOR "FFLOOR_T*" #define META_SEG "SEG_T*" +#define META_NODE "NODE_T*" #define META_MAPHEADER "MAPHEADER_T*" #define META_CVAR "CONSVAR_T*" #define META_SECTORLINES "SECTOR_T*LINES" #define META_SIDENUM "LINE_T*SIDENUM" +#define META_NODEBBOX "NODE_T*BBOX" +#define META_NODECHILDREN "NODE_T*CHILDREN" + +#define META_BBOX "BOUNDING_BOX" #define META_HUDINFO "HUDINFO_T*" #define META_PATCH "PATCH_T*" diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 28561f34e..d9fdc1274 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -211,6 +211,26 @@ static const char *const seg_opt[] = { "backsector", NULL}; +enum node_e { + node_valid = 0, + node_x, + node_y, + node_dx, + node_dy, + node_bbox, + node_children, +}; + +static const char *const node_opt[] = { + "valid", + "x", + "y", + "dx", + "dy", + "bbox", + "children", + NULL}; + static const char *const array_opt[] ={"iterate",NULL}; static const char *const valid_opt[] ={"valid",NULL}; @@ -901,6 +921,145 @@ static int seg_num(lua_State *L) return 1; } +static int node_get(lua_State *L) +{ + node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE)); + enum node_e field = luaL_checkoption(L, 2, node_opt[0], node_opt); + + if (!node) + { + if (field == node_valid) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed node_t doesn't exist anymore."); + } + + switch(field) + { + case node_valid: // valid + lua_pushboolean(L, 1); + return 1; + case node_x: + lua_pushfixed(L, node->x); + return 1; + case node_y: + lua_pushfixed(L, node->y); + return 1; + case node_dx: + lua_pushfixed(L, node->x); + return 1; + case node_dy: + lua_pushfixed(L, node->x); + return 1; + case node_bbox: + LUA_PushUserdata(L, node->bbox, META_NODEBBOX); + return 1; + case node_children: + LUA_PushUserdata(L, node->children, META_NODECHILDREN); + return 1; + } + return 0; +} + +static int node_num(lua_State *L) +{ + node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE)); + lua_pushinteger(L, node-nodes); + return 1; +} + +// node.bbox[i][j]: i = 0 or 1, j = 0 1 2 or 3 +// NOTE: 2D arrays are NOT double pointers, +// the second bbox will be directly after the first in memory (hence the way the bbox is pushed here) +// this function handles the [i] part, bbox_get handles the [j] part +static int nodebbox_get(lua_State *L) +{ + fixed_t *bbox = *((fixed_t **)luaL_checkudata(L, 1, META_NODEBBOX)); + int i; + lua_settop(L, 2); + if (!lua_isnumber(L, 2)) + { + int field = luaL_checkoption(L, 2, NULL, valid_opt); + if (!bbox) + { + if (field == 0) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed node_t doesn't exist anymore."); + } else if (field == 0) { + lua_pushboolean(L, 1); + return 1; + } + } + + i = lua_tointeger(L, 2); + if (i < 0 || i > 1) + return 0; + LUA_PushUserdata(L, bbox + i*4*sizeof(fixed_t), META_BBOX); + return 1; +} + +// node.children[i]: i = 0 or 1 +static int nodechildren_get(lua_State *L) +{ + UINT16 *children = *((UINT16 **)luaL_checkudata(L, 1, META_NODECHILDREN)); + int i; + lua_settop(L, 2); + if (!lua_isnumber(L, 2)) + { + int field = luaL_checkoption(L, 2, NULL, valid_opt); + if (!children) + { + if (field == 0) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed node_t doesn't exist anymore."); + } else if (field == 0) { + lua_pushboolean(L, 1); + return 1; + } + } + + i = lua_tointeger(L, 2); + if (i < 0 || i > 1) + return 0; + lua_pushinteger(L, children[i]); + return 1; +} + +// bounding box (aka fixed_t array with four elements) +// NOTE: may be useful for polyobjects or other things later +static int bbox_get(lua_State *L) +{ + fixed_t *bbox = *((fixed_t **)luaL_checkudata(L, 1, META_BBOX)); + int i; + lua_settop(L, 2); + if (!lua_isnumber(L, 2)) + { + int field = luaL_checkoption(L, 2, NULL, valid_opt); + if (!bbox) + { + if (field == 0) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed node_t doesn't exist anymore."); + } else if (field == 0) { + lua_pushboolean(L, 1); + return 1; + } + } + + i = lua_tointeger(L, 2); + if (i < 0 || i > 3) + return 0; + lua_pushinteger(L, bbox[i]); + return 1; +} + static int lib_iterateSectors(lua_State *L) { size_t i = 0; @@ -1177,6 +1336,52 @@ static int lib_numsegs(lua_State *L) return 1; } +static int lib_iterateNodes(lua_State *L) +{ + size_t i = 0; + if (lua_gettop(L) < 2) + return luaL_error(L, "Don't call nodes.iterate() directly, use it as 'for node in nodes.iterate do end'."); + lua_settop(L, 2); + lua_remove(L, 1); // state is unused. + if (!lua_isnil(L, 1)) + i = (size_t)(*((node_t **)luaL_checkudata(L, 1, META_NODE)) - nodes)+1; + if (i < numsegs) + { + LUA_PushUserdata(L, &nodes[i], META_NODE); + return 1; + } + return 0; +} + +static int lib_getNode(lua_State *L) +{ + int field; + lua_settop(L, 2); + lua_remove(L, 1); // dummy userdata table is unused. + if (lua_isnumber(L, 1)) + { + size_t i = lua_tointeger(L, 1); + if (i >= numnodes) + return 0; + LUA_PushUserdata(L, &nodes[i], META_NODE); + return 1; + } + field = luaL_checkoption(L, 1, NULL, array_opt); + switch(field) + { + case 0: // iterate + lua_pushcfunction(L, lib_iterateNodes); + return 1; + } + return 0; +} + +static int lib_numnodes(lua_State *L) +{ + lua_pushinteger(L, numnodes); + return 1; +} + static int ffloor_get(lua_State *L) { ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR)); @@ -1504,6 +1709,29 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + luaL_newmetatable(L, META_NODE); + lua_pushcfunction(L, node_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, node_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_NODEBBOX); + lua_pushcfunction(L, nodebbox_get); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_NODECHILDREN); + lua_pushcfunction(L, nodechildren_get); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_BBOX); + lua_pushcfunction(L, bbox_get); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); + luaL_newmetatable(L, META_MAPHEADER); lua_pushcfunction(L, mapheaderinfo_get); lua_setfield(L, -2, "__index"); @@ -1572,6 +1800,16 @@ int LUA_MapLib(lua_State *L) lua_setmetatable(L, -2); lua_setglobal(L, "segs"); + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getNode); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_numnodes); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "nodes"); + lua_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_pushcfunction(L, lib_getMapheaderinfo); diff --git a/src/lua_script.c b/src/lua_script.c index 621b7dfe4..6274baa73 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -456,6 +456,7 @@ enum ARCH_SUBSECTOR, ARCH_SECTOR, ARCH_SEG, + ARCH_NODE, ARCH_MAPHEADER, ARCH_TEND=0xFF, @@ -476,6 +477,7 @@ static const struct { {META_SUBSECTOR,ARCH_SUBSECTOR}, {META_SECTOR, ARCH_SECTOR}, {META_SEG, ARCH_SEG}, + {META_NODE, ARCH_NODE}, {META_MAPHEADER, ARCH_MAPHEADER}, {NULL, ARCH_NULL} }; @@ -677,6 +679,17 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) } break; } + case ARCH_NODE: + { + node_t *node = *((node_t **)lua_touserdata(gL, myindex)); + if (!node) + WRITEUINT8(save_p, ARCH_NULL); + else { + WRITEUINT8(save_p, ARCH_NODE); + WRITEUINT16(save_p, node - nodes); + } + break; + } case ARCH_MAPHEADER: { mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex)); @@ -858,6 +871,9 @@ static UINT8 UnArchiveValue(int TABLESINDEX) case ARCH_SEG: LUA_PushUserdata(gL, &segs[READUINT16(save_p)], META_SEG); break; + case ARCH_NODE: + LUA_PushUserdata(gL, &nodes[READUINT16(save_p)], META_NODE); + break; case ARCH_MAPHEADER: LUA_PushUserdata(gL, §ors[READUINT16(save_p)], META_MAPHEADER); break; From f2b3640c6ab42d771d3561dde640f245c92df29d Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 8 Jul 2016 20:43:02 +0100 Subject: [PATCH 05/21] Make sure seg/node arrays are invalidated in LUA_InvalidateLevel (I'll fix sector.lines and ffloors and other things I missed in the public repo) --- src/lua_script.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lua_script.c b/src/lua_script.c index 6274baa73..9d1eb8918 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -416,6 +416,14 @@ void LUA_InvalidateLevel(void) LUA_InvalidateUserdata(&sides[i]); for (i = 0; i < numvertexes; i++) LUA_InvalidateUserdata(&vertexes[i]); + for (i = 0; i < numsegs; i++) + LUA_InvalidateUserdata(&segs[i]); + for (i = 0; i < numnodes; i++) + { + LUA_InvalidateUserdata(&nodes[i]); + LUA_InvalidateUserdata(nodes[i].bbox); + LUA_InvalidateUserdata(nodes[i].children); + } } void LUA_InvalidateMapthings(void) From 61304dd833e4c8bdb33298a644bb4a760822d6b0 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 8 Jul 2016 22:58:09 +0100 Subject: [PATCH 06/21] Added NF_SUBSECTOR to dehacked.c lists --- src/dehacked.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index 75235e054..5dd9c532c 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7270,6 +7270,9 @@ struct { {"FF_COLORMAPONLY",FF_COLORMAPONLY}, ///< Only copy the colormap, not the lightlevel {"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop. + // Node flags + {"NF_SUBSECTOR",NF_SUBSECTOR}, // Indicate a leaf. + // Angles {"ANG1",ANG1}, {"ANG2",ANG2}, From c8a2eaf8a6387aa9ab0f7e927afc7b13561c5435 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 10 Jul 2016 17:35:05 +0100 Subject: [PATCH 07/21] Make sure to invalidate sector.lines and all ffloors for the previous map's sectors as well (yes, I changed my mind about doing it in public repo, probably too much hassle if we want 2.1.16 out soon) --- src/lua_script.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lua_script.c b/src/lua_script.c index 9d1eb8918..5f2aab088 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -395,6 +395,7 @@ void LUA_InvalidateLevel(void) { thinker_t *th; size_t i; + ffloor_t *rover = NULL; if (!gL) return; @@ -406,7 +407,15 @@ void LUA_InvalidateLevel(void) for (i = 0; i < numsubsectors; i++) LUA_InvalidateUserdata(&subsectors[i]); for (i = 0; i < numsectors; i++) + { LUA_InvalidateUserdata(§ors[i]); + LUA_InvalidateUserdata(sectors[i].lines); + if (sectors[i].ffloors) + { + for (rover = sectors[i].ffloors; rover; rover = rover->next) + LUA_InvalidateUserdata(rover); + } + } for (i = 0; i < numlines; i++) { LUA_InvalidateUserdata(&lines[i]); From 3fba690d0a34da125e3c7a1f16b4284087595ef9 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 10 Jul 2016 17:58:54 +0100 Subject: [PATCH 08/21] Allow $$$.sav to archive and read ffloor_t userdata Lua extvars Oh, and P_GetFFloorByID is now a thing, to assist with the above. Also added a suitable description for P_GetFFloorBySec --- src/lua_script.c | 37 +++++++++++++++++++++++++++++++++++++ src/p_spec.c | 29 +++++++++++++++++++++++++++++ src/p_spec.h | 2 ++ 3 files changed, 68 insertions(+) diff --git a/src/lua_script.c b/src/lua_script.c index 5f2aab088..158b1bc4b 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -474,6 +474,7 @@ enum ARCH_SECTOR, ARCH_SEG, ARCH_NODE, + ARCH_FFLOOR, ARCH_MAPHEADER, ARCH_TEND=0xFF, @@ -495,6 +496,7 @@ static const struct { {META_SECTOR, ARCH_SECTOR}, {META_SEG, ARCH_SEG}, {META_NODE, ARCH_NODE}, + {META_FFLOOR, ARCH_FFLOOR}, {META_MAPHEADER, ARCH_MAPHEADER}, {NULL, ARCH_NULL} }; @@ -707,6 +709,32 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) } break; } + case ARCH_FFLOOR: + { + ffloor_t *rover = *((ffloor_t **)lua_touserdata(gL, myindex)); + if (!rover) + WRITEUINT8(save_p, ARCH_NULL); + else { + ffloor_t *r2 = NULL; + UINT16 i = 0; + // search for id + for (r2 = rover->target->ffloors; r2; r2 = r2->next); + { + if (r2 == rover) + break; + i++; + } + if (!r2) + WRITEUINT8(save_p, ARCH_NULL); + else + { + WRITEUINT8(save_p, ARCH_FFLOOR); + WRITEUINT16(save_p, rover->target - sectors); + WRITEUINT16(save_p, i); + } + } + break; + } case ARCH_MAPHEADER: { mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex)); @@ -891,6 +919,15 @@ static UINT8 UnArchiveValue(int TABLESINDEX) case ARCH_NODE: LUA_PushUserdata(gL, &nodes[READUINT16(save_p)], META_NODE); break; + case ARCH_FFLOOR: + { + sector_t *sector = §ors[READUINT16(save_p)]; + UINT16 id = READUINT16(save_p); + ffloor_t *rover = P_GetFFloorByID(sector, id); + if (rover) + LUA_PushUserdata(gL, rover, META_FFLOOR); + break; + } case ARCH_MAPHEADER: LUA_PushUserdata(gL, §ors[READUINT16(save_p)], META_MAPHEADER); break; diff --git a/src/p_spec.c b/src/p_spec.c index 3ca697295..51c2d03d8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4708,6 +4708,13 @@ void P_UpdateSpecials(void) } } +/** Gets a 3Dfloor by control sector. + * + * \param sec Target sector. + * \param sec2 Control sector. + * \return Pointer to found 3Dfloor, or NULL. + * \sa P_GetFFloorByID + */ static inline ffloor_t *P_GetFFloorBySec(sector_t *sec, sector_t *sec2) { ffloor_t *rover; @@ -4720,6 +4727,28 @@ static inline ffloor_t *P_GetFFloorBySec(sector_t *sec, sector_t *sec2) return NULL; } +/** Gets a 3Dfloor by ID number. + * + * \param sec Target sector. + * \param id ID of 3Dfloor in target sector. Can be a number from 0 to sec->numattached-1. + * \return Pointer to found 3Dfloor, or NULL. + * \sa P_GetFFloorBySec + */ +ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id) +{ + ffloor_t *rover; + UINT16 i = 0; + + if (!sec->ffloors) + return NULL; + if (id >= sec->numattached) + return NULL; // ID out of range + for (rover = sec->ffloors; rover; rover = rover->next) + if (i++ == id) + return rover; + return NULL; +} + /** Adds a newly formed 3Dfloor structure to a sector's ffloors list. * * \param sec Target sector. diff --git a/src/p_spec.h b/src/p_spec.h index a8f9ac492..23e4cfdf9 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -64,6 +64,8 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller); void P_ChangeSectorTag(UINT32 sector, INT16 newtag); +ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id); + // // P_LIGHTS // From e3ab77ef2158f3d07e109826daf879bbbcc56dbf Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 4 Aug 2016 18:54:29 +0100 Subject: [PATCH 09/21] node.bbox now works with the format node.bbox(child, bboxcoord) child can be 0 or 1 (or "right" and "left", alternatively) bbox coord can be 0,1,2 or 3 (or "top", "bottom", "left" and "right", alternatively) Also added some support for bbox userdata taking "top" "bottom" "left" "right" fields. Not that there's any use for non-node bbox userdata just yet... --- src/lua_maplib.c | 106 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 95 insertions(+), 11 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index d9fdc1274..0aea4acf7 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -231,6 +231,34 @@ static const char *const node_opt[] = { "children", NULL}; +enum nodechild_e { + nodechild_valid = 0, + nodechild_right, + nodechild_left, +}; + +static const char *const nodechild_opt[] = { + "valid", + "right", + "left", + NULL}; + +enum bbox_e { + bbox_valid = 0, + bbox_top, + bbox_bottom, + bbox_left, + bbox_right, +}; + +static const char *const bbox_opt[] = { + "valid", + "top", + "bottom", + "left", + "right", + NULL}; + static const char *const array_opt[] ={"iterate",NULL}; static const char *const valid_opt[] ={"valid",NULL}; @@ -968,7 +996,7 @@ static int node_num(lua_State *L) lua_pushinteger(L, node-nodes); return 1; } - +/* // node.bbox[i][j]: i = 0 or 1, j = 0 1 2 or 3 // NOTE: 2D arrays are NOT double pointers, // the second bbox will be directly after the first in memory (hence the way the bbox is pushed here) @@ -1000,6 +1028,52 @@ static int nodebbox_get(lua_State *L) LUA_PushUserdata(L, bbox + i*4*sizeof(fixed_t), META_BBOX); return 1; } +*/ +static int nodebbox_call(lua_State *L) +{ + fixed_t *bbox = *((fixed_t **)luaL_checkudata(L, 1, META_NODEBBOX)); + int i, j; + int n = lua_gettop(L); + + if (!bbox) + return luaL_error(L, "accessed node bbox doesn't exist anymore."); + if (n < 3) + return luaL_error(L, "arguments 2 and/or 3 not given (expected node.bbox(child, coord))"); + // get child + if (!lua_isnumber(L, 2)) { + enum nodechild_e field = luaL_checkoption(L, 2, nodechild_opt[0], nodechild_opt); + switch (field) { + case nodechild_right: i = 0; break; + case nodechild_left: i = 1; break; + default: + return luaL_error(L, "invalid node child \"%s\".", lua_tostring(L, 2)); + } + } + else { + i = lua_tointeger(L, 2); + if (i < 0 || i > 1) + return 0; + } + // get bbox coord + if (!lua_isnumber(L, 3)) { + enum bbox_e field = luaL_checkoption(L, 3, bbox_opt[0], bbox_opt); + switch (field) { + case bbox_top: j = BOXTOP; break; + case bbox_bottom: j = BOXBOTTOM; break; + case bbox_left: j = BOXLEFT; break; + case bbox_right: j = BOXRIGHT; break; + default: + return luaL_error(L, "invalid bbox coordinate \"%s\".", lua_tostring(L, 3)); + } + } + else { + j = lua_tointeger(L, 3); + if (j < 0 || j > 3) + return 0; + } + lua_pushinteger(L, bbox[i*4 + j]); + return 1; +} // node.children[i]: i = 0 or 1 static int nodechildren_get(lua_State *L) @@ -1039,23 +1113,31 @@ static int bbox_get(lua_State *L) lua_settop(L, 2); if (!lua_isnumber(L, 2)) { - int field = luaL_checkoption(L, 2, NULL, valid_opt); + enum bbox_e field = luaL_checkoption(L, 2, bbox_opt[0], bbox_opt); if (!bbox) { - if (field == 0) { + if (field == bbox_valid) { lua_pushboolean(L, 0); return 1; } - return luaL_error(L, "accessed node_t doesn't exist anymore."); - } else if (field == 0) { + return luaL_error(L, "accessed bbox doesn't exist anymore."); + } else if (field == bbox_valid) { lua_pushboolean(L, 1); return 1; } + else switch (field) { + case bbox_top: i = BOXTOP; break; + case bbox_bottom: i = BOXBOTTOM; break; + case bbox_left: i = BOXLEFT; break; + case bbox_right: i = BOXRIGHT; break; + default: return 0; + } + } + else { + i = lua_tointeger(L, 2); + if (i < 0 || i > 3) + return 0; } - - i = lua_tointeger(L, 2); - if (i < 0 || i > 3) - return 0; lua_pushinteger(L, bbox[i]); return 1; } @@ -1718,8 +1800,10 @@ int LUA_MapLib(lua_State *L) lua_pop(L, 1); luaL_newmetatable(L, META_NODEBBOX); - lua_pushcfunction(L, nodebbox_get); - lua_setfield(L, -2, "__index"); + //lua_pushcfunction(L, nodebbox_get); + //lua_setfield(L, -2, "__index"); + lua_pushcfunction(L, nodebbox_call); + lua_setfield(L, -2, "__call"); lua_pop(L, 1); luaL_newmetatable(L, META_NODECHILDREN); From ebb1fd14701bcfff2b19fe0106e25626388064d0 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 4 Aug 2016 19:20:34 +0100 Subject: [PATCH 10/21] node.children now also takes "right" and "left" as fields, as alternatives to integers 0 and 1 in other words node.children[0] == node.children.right and node.children[1] == node.children.left --- src/lua_maplib.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 0aea4acf7..2679e4ba9 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1083,23 +1083,28 @@ static int nodechildren_get(lua_State *L) lua_settop(L, 2); if (!lua_isnumber(L, 2)) { - int field = luaL_checkoption(L, 2, NULL, valid_opt); + enum nodechild_e field = luaL_checkoption(L, 2, nodechild_opt[0], nodechild_opt); if (!children) { - if (field == 0) { + if (field == nodechild_valid) { lua_pushboolean(L, 0); return 1; } return luaL_error(L, "accessed node_t doesn't exist anymore."); - } else if (field == 0) { + } else if (field == nodechild_valid) { lua_pushboolean(L, 1); return 1; + } else switch (field) { + case nodechild_right: i = 0; break; + case nodechild_left: i = 1; break; + default: return 0; } } - - i = lua_tointeger(L, 2); - if (i < 0 || i > 1) - return 0; + else { + i = lua_tointeger(L, 2); + if (i < 0 || i > 1) + return 0; + } lua_pushinteger(L, children[i]); return 1; } @@ -1124,8 +1129,7 @@ static int bbox_get(lua_State *L) } else if (field == bbox_valid) { lua_pushboolean(L, 1); return 1; - } - else switch (field) { + } else switch (field) { case bbox_top: i = BOXTOP; break; case bbox_bottom: i = BOXBOTTOM; break; case bbox_left: i = BOXLEFT; break; From 5787817662a5d1433949439f5ff4be61c86d3743 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 23 Oct 2016 23:13:11 +0100 Subject: [PATCH 11/21] Committing my work on P_SearchBlockmap_Objects so far, no idea if it's even functional yet so I've commented it out for now --- src/lua_baselib.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 48b095e08..f6933cd3a 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -27,6 +27,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 boolean luaL_checkboolean(lua_State *L, int narg) { luaL_checktype(L, narg, LUA_TBOOLEAN); @@ -215,6 +217,103 @@ static int lib_pPointOnLineSide(lua_State *L) return 1; } +#ifdef LUA_BLOCKMAP +// auxillary function for lib_pSearchBlockmap_Objects +static boolean lib_pSearchBlockmap_Objects_aux(lua_State *L, INT32 x, INT32 y, mobj_t *thing, int funcarg) +{ + 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! + lua_pushvalue(L, funcarg); + LUA_PushUserdata(L, thing, META_MOBJ); + LUA_PushUserdata(L, mobj, META_MOBJ); + if (lua_pcall(gL, 2, 1, 0)) { + if (cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + return false; + } + if (!lua_isnil(gL, -1)) + { // if nil, continue + if (lua_toboolean(gL, -1)) + return false; + } + 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; +} + +// P_SearchBlockmap_Objects +// Lua-exclusive, but it kind of needs to be for best results +static int lib_pSearchBlockmap_Objects(lua_State *L) +{ + int n = lua_gettop(L); + mobj_t *mobj; + INT32 xl, xh, yl, yh, bx, by; + fixed_t x1, x2, y1, y2; + int funcarg; + + // the mobj we are searching around + mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + if (!mobj) + return LUA_ErrInvalid(L, "mobj_t"); + + if (n > 2) // specific x/y ranges have been supplied + { + if (n < 6) + return luaL_error(L, "arguments 2 to 5 not all given (expected 4 fixed-point integers)"); + + x1 = luaL_checkfixed(L, 2); + x2 = luaL_checkfixed(L, 3); + y1 = luaL_checkfixed(L, 4); + y2 = luaL_checkfixed(L, 5); + funcarg = 6; + } + else // mobj and function only - search around mobj's radius by default + { + x1 = mobj->x - mobj->radius; + x2 = mobj->x + mobj->radius; + y1 = mobj->y - mobj->radius; + y2 = mobj->y + mobj->radius; + funcarg = 2; + } + luaL_checktype(L, funcarg, LUA_TFUNCTION); + + xl = (unsigned)(x1 - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; + xh = (unsigned)(x2 - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; + yl = (unsigned)(y1 - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; + yh = (unsigned)(y2 - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; + + BMBOUNDFIX(xl, xh, yl, yh); + + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + { + if (!lib_pSearchBlockmap_Objects_aux(L, bx, by, mobj, funcarg)){ + lua_pushboolean(L, false); + return 1; + } + if (P_MobjWasRemoved(mobj)){ + lua_pushboolean(L, false); + return 1; + } + } + lua_pushboolean(L, true); + return 1; +} +#endif + // P_ENEMY ///////////// @@ -2002,6 +2101,9 @@ static luaL_Reg lib[] = { {"P_AproxDistance",lib_pAproxDistance}, {"P_ClosestPointOnLine",lib_pClosestPointOnLine}, {"P_PointOnLineSide",lib_pPointOnLineSide}, +#ifdef LUA_BLOCKMAP + {"P_SearchBlockmap_Objects",lib_pSearchBlockmap_Objects}, +#endif // p_enemy {"P_CheckMeleeRange", lib_pCheckMeleeRange}, From 36b7156ff7601fbc01ce718e86aa8317ee969365 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 24 Oct 2016 23:11:41 +0100 Subject: [PATCH 12/21] Turns out it does work yay, just had to make some tweaks really Next question: should the calling mo be able to find itself in the blockmap, or should it skip itself? --- src/lua_baselib.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index f6933cd3a..8c0d3ff19 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -28,7 +28,7 @@ #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 + #define LUA_BLOCKMAP boolean luaL_checkboolean(lua_State *L, int narg) { luaL_checktype(L, narg, LUA_TBOOLEAN); @@ -218,6 +218,7 @@ static int lib_pPointOnLineSide(lua_State *L) } #ifdef LUA_BLOCKMAP +static boolean blockfuncerror = false; // auxillary function for lib_pSearchBlockmap_Objects static boolean lib_pSearchBlockmap_Objects_aux(lua_State *L, INT32 x, INT32 y, mobj_t *thing, int funcarg) { @@ -234,10 +235,11 @@ static boolean lib_pSearchBlockmap_Objects_aux(lua_State *L, INT32 x, INT32 y, m LUA_PushUserdata(L, thing, META_MOBJ); LUA_PushUserdata(L, mobj, META_MOBJ); if (lua_pcall(gL, 2, 1, 0)) { - if (cv_debug & DBG_LUA) + if (!blockfuncerror || cv_debug & DBG_LUA) CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); - return false; + blockfuncerror = true; + return true; } if (!lua_isnil(gL, -1)) { // if nil, continue @@ -263,9 +265,10 @@ static int lib_pSearchBlockmap_Objects(lua_State *L) INT32 xl, xh, yl, yh, bx, by; fixed_t x1, x2, y1, y2; int funcarg; + boolean retval = true; // the mobj we are searching around - mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); @@ -297,19 +300,18 @@ static int lib_pSearchBlockmap_Objects(lua_State *L) BMBOUNDFIX(xl, xh, yl, yh); + blockfuncerror = false; // reset for (bx = xl; bx <= xh; bx++) for (by = yl; by <= yh; by++) { - if (!lib_pSearchBlockmap_Objects_aux(L, bx, by, mobj, funcarg)){ - lua_pushboolean(L, false); - return 1; - } + if (!lib_pSearchBlockmap_Objects_aux(L, bx, by, mobj, funcarg)) + retval = false; if (P_MobjWasRemoved(mobj)){ lua_pushboolean(L, false); - return 1; + return 1; } } - lua_pushboolean(L, true); + lua_pushboolean(L, retval); return 1; } #endif From 98e43ac0d94b5813fb2abcfb9f73842f8df0f116 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 25 Oct 2016 16:15:17 +0100 Subject: [PATCH 13/21] Fixed ffloor_t Lua variables not actually saving to $$$.sav Stupid overlooked semicolons --- src/lua_script.c | 4 ++-- src/p_spec.c | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/lua_script.c b/src/lua_script.c index 158b1bc4b..35d3fd51f 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -715,10 +715,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) if (!rover) WRITEUINT8(save_p, ARCH_NULL); else { - ffloor_t *r2 = NULL; + ffloor_t *r2; UINT16 i = 0; // search for id - for (r2 = rover->target->ffloors; r2; r2 = r2->next); + for (r2 = rover->target->ffloors; r2; r2 = r2->next) { if (r2 == rover) break; diff --git a/src/p_spec.c b/src/p_spec.c index 2b02cc6ca..31203165d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4753,7 +4753,7 @@ static inline ffloor_t *P_GetFFloorBySec(sector_t *sec, sector_t *sec2) /** Gets a 3Dfloor by ID number. * * \param sec Target sector. - * \param id ID of 3Dfloor in target sector. Can be a number from 0 to sec->numattached-1. + * \param id ID of 3Dfloor in target sector. Note that the first FOF's ID is 0. * \return Pointer to found 3Dfloor, or NULL. * \sa P_GetFFloorBySec */ @@ -4764,8 +4764,6 @@ ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id) if (!sec->ffloors) return NULL; - if (id >= sec->numattached) - return NULL; // ID out of range for (rover = sec->ffloors; rover; rover = rover->next) if (i++ == id) return rover; From 60dcfd1021a58cef8a3f5a3fac10c7d5a7b13dd2 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 25 Oct 2016 22:39:27 +0100 Subject: [PATCH 14/21] Pop result of P_SearchBlockmap_Objects's function arg Also P_SearchBlockmap_Lines is a thing now too --- src/lua_baselib.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 8c0d3ff19..9eec5bc6e 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -246,6 +246,7 @@ static boolean lib_pSearchBlockmap_Objects_aux(lua_State *L, INT32 x, INT32 y, m 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. { @@ -314,6 +315,158 @@ static int lib_pSearchBlockmap_Objects(lua_State *L) lua_pushboolean(L, retval); return 1; } + +// auxillary function for lib_pSearchBlockmap_Objects +static boolean lib_pSearchBlockmap_Lines_aux(lua_State *L, INT32 x, INT32 y, mobj_t *thing, int funcarg) +{ + 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, funcarg); + 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, funcarg); + 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. +} + +// P_SearchBlockmap_Lines +// same deal as the _Objects version +static int lib_pSearchBlockmap_Lines(lua_State *L) +{ + int n = lua_gettop(L); + mobj_t *mobj; + INT32 xl, xh, yl, yh, bx, by; + fixed_t x1, x2, y1, y2; + int funcarg; + boolean retval = true; + + // the mobj we are searching around + mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + if (!mobj) + return LUA_ErrInvalid(L, "mobj_t"); + + if (n > 2) // specific x/y ranges have been supplied + { + if (n < 6) + return luaL_error(L, "arguments 2 to 5 not all given (expected 4 fixed-point integers)"); + + x1 = luaL_checkfixed(L, 2); + x2 = luaL_checkfixed(L, 3); + y1 = luaL_checkfixed(L, 4); + y2 = luaL_checkfixed(L, 5); + funcarg = 6; + } + else // mobj and function only - search around mobj's radius by default + { + x1 = mobj->x - mobj->radius; + x2 = mobj->x + mobj->radius; + y1 = mobj->y - mobj->radius; + y2 = mobj->y + mobj->radius; + funcarg = 2; + } + luaL_checktype(L, funcarg, LUA_TFUNCTION); + + xl = (unsigned)(x1 - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; + xh = (unsigned)(x2 - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; + yl = (unsigned)(y1 - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; + yh = (unsigned)(y2 - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; + + BMBOUNDFIX(xl, xh, yl, yh); + + blockfuncerror = false; // reset + validcount++; + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + { + if (!lib_pSearchBlockmap_Lines_aux(L, bx, by, mobj, funcarg)) + retval = false; + if (P_MobjWasRemoved(mobj)){ + lua_pushboolean(L, false); + return 1; + } + } + lua_pushboolean(L, retval); + return 1; +} #endif // P_ENEMY @@ -2105,6 +2258,7 @@ static luaL_Reg lib[] = { {"P_PointOnLineSide",lib_pPointOnLineSide}, #ifdef LUA_BLOCKMAP {"P_SearchBlockmap_Objects",lib_pSearchBlockmap_Objects}, + {"P_SearchBlockmap_Lines",lib_pSearchBlockmap_Lines}, #endif // p_enemy From dc1e7165f7938812f6e0c825b45923bd825c50a2 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 27 Oct 2016 18:10:30 +0100 Subject: [PATCH 15/21] Created lua_blockmaplib.c, for Lua's blockmap library my P_SearchBlockmap_* functions are now a single searchBlockmap function, you can choose between "objects" and "lines" with the first arg to decide what to iterate through. I also rearranged the argument order a bit for easy stack cleanup etc I'll remove the old stuff later, don't worry, it's disabled for now --- SRB2.cbp | 15 ++ src/CMakeLists.txt | 1 + src/blua/Makefile.cfg | 1 + src/lua_baselib.c | 3 +- src/lua_blockmaplib.c | 248 +++++++++++++++++++++++++ src/lua_libs.h | 1 + src/lua_script.c | 1 + src/sdl/Srb2SDL-vc10.vcxproj | 1 + src/sdl/Srb2SDL-vc10.vcxproj.filters | 3 + src/win32/Srb2win-vc10.vcxproj | 1 + src/win32/Srb2win-vc10.vcxproj.filters | 3 + 11 files changed, 277 insertions(+), 1 deletion(-) create mode 100644 src/lua_blockmaplib.c diff --git a/SRB2.cbp b/SRB2.cbp index 99a712264..f56a9a160 100644 --- a/SRB2.cbp +++ b/SRB2.cbp @@ -2561,6 +2561,21 @@ HW3SOUND for 3D hardware sound support