diff --git a/docs/changelog.txt b/docs/changelog.txt index a1335786d4..ee69fa5fa5 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -69,8 +69,10 @@ Template for new versions: ## Documentation ## API +- ``Units::isUnitInBox``, ``Units::getUnitsInBox``: add versions accepting pos arguments ## Lua +- ``dfhack.units.isUnitInBox``, ``dfhack.units.getUnitsInBox``: add versions accepting pos arguments ## Removed diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 96f3cd2593..5933f57367 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -1610,18 +1610,18 @@ Units module The unit is of Great Danger. This includes megabeasts, titans, forgotten beasts, and demons. +* ``dfhack.units.isUnitInBox(unit, pos1, pos2)`` * ``dfhack.units.isUnitInBox(unit,x1,y1,z1,x2,y2,z2)`` Returns true if the unit is within a box defined by the specified coordinates. +``dfhack.units.getUnitsInBox(pos1, pos2[, filter])`` * ``dfhack.units.getUnitsInBox(x1,y1,z1,x2,y2,z2[,filter])`` Returns a table of all units within the specified coordinates. If the ``filter`` argument is given, only units where ``filter(unit)`` - returns true will be included. Note that ``pos2xyz()`` cannot currently - be used to convert coordinate objects to the arguments required by - this function. + returns true will be included. * ``dfhack.units.getUnitByNobleRole(role_name)`` diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index eb639631ad..a5225c57c8 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -2162,32 +2162,55 @@ static int units_getNoblePositions(lua_State *L) { static int units_isUnitInBox(lua_State *state) { auto u = Lua::CheckDFObject(state, 1); - int x1 = luaL_checkint(state, 2); - int y1 = luaL_checkint(state, 3); - int z1 = luaL_checkint(state, 4); - int x2 = luaL_checkint(state, 5); - int y2 = luaL_checkint(state, 6); - int z2 = luaL_checkint(state, 7); - - lua_pushboolean(state, Units::isUnitInBox(u, x1, y1, z1, x2, y2, z2)); + if (lua_gettop(state) > 3) { + int x1 = luaL_checkint(state, 2); + int y1 = luaL_checkint(state, 3); + int z1 = luaL_checkint(state, 4); + int x2 = luaL_checkint(state, 5); + int y2 = luaL_checkint(state, 6); + int z2 = luaL_checkint(state, 7); + lua_pushboolean(state, Units::isUnitInBox(u, x1, y1, z1, x2, y2, z2)); + } + else { + df::coord pos1, pos2; + Lua::CheckDFAssign(state, &pos1, 2); + Lua::CheckDFAssign(state, &pos2, 3); + lua_pushboolean(state, Units::isUnitInBox(u, pos1, pos2)); + } return 1; } static int units_getUnitsInBox(lua_State *state) { vector units; - int x1 = luaL_checkint(state, 1); - int y1 = luaL_checkint(state, 2); - int z1 = luaL_checkint(state, 3); - int x2 = luaL_checkint(state, 4); - int y2 = luaL_checkint(state, 5); - int z2 = luaL_checkint(state, 6); + cuboid box; + + int max_arg = lua_gettop(state); + if (max_arg > 3) { + int x1 = luaL_checkint(state, 1); + int y1 = luaL_checkint(state, 2); + int z1 = luaL_checkint(state, 3); + int x2 = luaL_checkint(state, 4); + int y2 = luaL_checkint(state, 5); + int z2 = luaL_checkint(state, 6); + box = cuboid(x1,y1,z1,x2,y2,z2); + } + else { + df::coord pos1, pos2; + Lua::CheckDFAssign(state, &pos1, 1); + Lua::CheckDFAssign(state, &pos2, 2); + box = cuboid(pos1, pos2); + } + int fn_arg = max_arg > 3 ? 7 : 3; bool ok = false; - if (lua_gettop(state) < 7 || lua_isnil(state, 7)) // Default filter - ok = Units::getUnitsInBox(units, x1, y1, z1, x2, y2, z2); + if (max_arg < fn_arg || lua_isnil(state, fn_arg)) // Default filter + ok = Units::getUnitsInBox(units, box); else { - luaL_checktype(state, 7, LUA_TFUNCTION); - ok = Units::getUnitsInBox(units, x1, y1, z1, x2, y2, z2, [&state](df::unit *unit) { + luaL_checktype(state, fn_arg, LUA_TFUNCTION); + if (max_arg > fn_arg) // Something after filter on stack + luaL_argerror(state, fn_arg+1, "too many arguments!"); + + ok = Units::getUnitsInBox(units, box, [&state](df::unit *unit) { lua_dup(state); // Copy function Lua::PushDFObject(state, unit); lua_call(state, 1, 1); diff --git a/library/include/modules/Units.h b/library/include/modules/Units.h index f398d135f8..2e0f188b5c 100644 --- a/library/include/modules/Units.h +++ b/library/include/modules/Units.h @@ -179,6 +179,7 @@ DFHACK_EXPORT bool isGreatDanger(df::unit *unit); DFHACK_EXPORT bool isUnitInBox(df::unit *u, const cuboid &box); DFHACK_EXPORT inline bool isUnitInBox(df::unit *u, int16_t x1, int16_t y1, int16_t z1, int16_t x2, int16_t y2, int16_t z2) { return isUnitInBox(u, cuboid(x1, y1, z1, x2, y2, z2)); } +DFHACK_EXPORT inline bool isUnitInBox(df::unit *u, df::coord pos1, df::coord pos2) { return isUnitInBox(u, cuboid(pos1, pos2)); } // Fill vector with units in box matching filter. DFHACK_EXPORT bool getUnitsInBox(std::vector &units, const cuboid &box, @@ -186,6 +187,9 @@ DFHACK_EXPORT bool getUnitsInBox(std::vector &units, const cuboid &b DFHACK_EXPORT inline bool getUnitsInBox(std::vector &units, int16_t x1, int16_t y1, int16_t z1, int16_t x2, int16_t y2, int16_t z2, std::function filter = [](df::unit *u) { return true; }) { return getUnitsInBox(units, cuboid(x1, y1, z1, x2, y2, z2), filter); } +DFHACK_EXPORT inline bool getUnitsInBox(std::vector &units, df::coord pos1, df::coord pos2, + std::function filter = [](df::unit *u) { return true; }) + { return getUnitsInBox(units, cuboid(pos1, pos2), filter); } // Noble string must be in form "CAPTAIN_OF_THE_GUARD", etc. DFHACK_EXPORT bool getUnitsByNobleRole(std::vector &units, std::string noble);