Adds isUnitInBox to Units module

develop
Josh Cooper 2022-11-12 14:42:41 -08:00
parent 34de030ba9
commit ebd450af0e
5 changed files with 30 additions and 12 deletions

@ -1192,6 +1192,10 @@ Units module
Returns true *x,y,z* of the unit, or *nil* if invalid; may be not equal to unit.pos if caged.
* ``dfhack.units.isUnitInBox(unit,x1,y1,z1,x2,y2,z2)``
Returns true if the unit is within the specified coordinates.
* ``dfhack.units.getUnitsInBox(x1,y1,z1,x2,y2,z2[,filter])``
Returns a table of all units within the specified coordinates. If the ``filter``

@ -73,6 +73,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
- ``Lua::PushInterfaceKeys()``: transforms viewscreen ``feed()`` keys into something that can be interpreted by lua-based widgets
- ``Lua::Push()``: now handles maps with otherwise supported keys and values
- Units module: added new checks
- ``isUnitInBox()``
- ``isAnimal()``
- ``isVisiting()`` any visiting unit (diplomat, merchant, visitor)
- ``isVisitor()`` ie. not merchants or diplomats

@ -1559,6 +1559,7 @@ static const luaL_Reg dfhack_job_funcs[] = {
/***** Units module *****/
static const LuaWrapper::FunctionReg dfhack_units_module[] = {
WRAPM(Units, isUnitInBox),
WRAPM(Units, teleport),
WRAPM(Units, getGeneralRef),
WRAPM(Units, getSpecificRef),
@ -1716,6 +1717,8 @@ static int units_getUnitsInBox(lua_State *state)
{
luaL_checktype(state, 7, LUA_TFUNCTION);
units.erase(std::remove_if(units.begin(), units.end(), [&state](df::unit *unit) -> bool {
// todo: merging this filter into the base function would be welcomed by plugins
// (it would also be faster, and less obfuscated than this [ie. erase(remove_if)])
lua_dup(state); // copy function
Lua::PushDFObject(state, unit);
lua_call(state, 1, 1);

@ -73,6 +73,9 @@ static const int MAX_COLORS = 15;
// found. Call repeatedly do get all units in a specified box (uses tile coords)
DFHACK_EXPORT int32_t getNumUnits();
DFHACK_EXPORT df::unit *getUnit(const int32_t index);
DFHACK_EXPORT bool isUnitInBox(df::unit* u,
int16_t x1, int16_t y1, int16_t z1,
int16_t x2, int16_t y2, int16_t z2);
DFHACK_EXPORT bool getUnitsInBox(std::vector<df::unit*> &units,
int16_t x1, int16_t y1, int16_t z1,
int16_t x2, int16_t y2, int16_t z2);

@ -98,6 +98,23 @@ df::unit *Units::getUnit (const int32_t index)
return vector_get(world->units.all, index);
}
bool Units::isUnitInBox(df::unit* u,
int16_t x1, int16_t y1, int16_t z1,
int16_t x2, int16_t y2, int16_t z2) {
if (x1 > x2) swap(x1, x2);
if (y1 > y2) swap(y1, y2);
if (z1 > z2) swap(z1, z2);
if (u->pos.x >= x1 && u->pos.x <= x2) {
if (u->pos.y >= y1 && u->pos.y <= y2) {
if (u->pos.z >= z1 && u->pos.z <= z2) {
return true;
}
}
}
return false;
}
// returns index of creature actually read or -1 if no creature can be found
bool Units::getUnitsInBox (std::vector<df::unit*> &units,
int16_t x1, int16_t y1, int16_t z1,
@ -106,22 +123,12 @@ bool Units::getUnitsInBox (std::vector<df::unit*> &units,
if (!world)
return false;
if (x1 > x2) swap(x1, x2);
if (y1 > y2) swap(y1, y2);
if (z1 > z2) swap(z1, z2);
units.clear();
for (df::unit *u : world->units.all)
{
if (u->pos.x >= x1 && u->pos.x <= x2)
if (isUnitInBox(u, x1, y1, z1, x2, y2, z2))
{
if (u->pos.y >= y1 && u->pos.y <= y2)
{
if (u->pos.z >= z1 && u->pos.z <= z2)
{
units.push_back(u);
}
}
units.push_back(u);
}
}
return true;