move fastdwarf's teleport code to Units module

and expose in Lua API
develop
myk002 2021-06-06 08:48:32 -07:00
parent 7d7d1feb4b
commit fc860478e4
No known key found for this signature in database
GPG Key ID: 8A39CA0FA0C16E78
5 changed files with 57 additions and 37 deletions

@ -1172,13 +1172,18 @@ Units module
Returns true *x,y,z* of the unit, or *nil* if invalid; may be not equal to unit.pos if caged. Returns true *x,y,z* of the unit, or *nil* if invalid; may be not equal to unit.pos if caged.
* ``dfhack.getUnitsInBox(x1,y1,z1,x2,y2,z2[,filter])`` * ``dfhack.units.getUnitsInBox(x1,y1,z1,x2,y2,z2[,filter])``
Returns a table of all units within the specified coordinates. If the ``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. 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 Note that ``pos2xyz()`` cannot currently be used to convert coordinate objects to
the arguments required by this function. the arguments required by this function.
* ``dfhack.units.teleport(unit, pos)``
Moves the specified unit and any riders to the target coordinates, setting
tile occupancy flags appropriately. Returns true if successful.
* ``dfhack.units.getGeneralRef(unit, type)`` * ``dfhack.units.getGeneralRef(unit, type)``
Searches for a general_ref with the given type. Searches for a general_ref with the given type.

@ -1572,6 +1572,7 @@ static const luaL_Reg dfhack_job_funcs[] = {
/***** Units module *****/ /***** Units module *****/
static const LuaWrapper::FunctionReg dfhack_units_module[] = { static const LuaWrapper::FunctionReg dfhack_units_module[] = {
WRAPM(Units, teleport),
WRAPM(Units, getGeneralRef), WRAPM(Units, getGeneralRef),
WRAPM(Units, getSpecificRef), WRAPM(Units, getSpecificRef),
WRAPM(Units, getContainer), WRAPM(Units, getContainer),

@ -82,6 +82,9 @@ DFHACK_EXPORT int32_t findIndexById(int32_t id);
/// Returns the true position of the unit (non-trivial in case of caged). /// Returns the true position of the unit (non-trivial in case of caged).
DFHACK_EXPORT df::coord getPosition(df::unit *unit); DFHACK_EXPORT df::coord getPosition(df::unit *unit);
// moves unit and any riders to the target coordinates
DFHACK_EXPORT bool teleport(df::unit *unit, df::coord target_pos);
DFHACK_EXPORT df::general_ref *getGeneralRef(df::unit *unit, df::general_ref_type type); DFHACK_EXPORT df::general_ref *getGeneralRef(df::unit *unit, df::general_ref_type type);
DFHACK_EXPORT df::specific_ref *getSpecificRef(df::unit *unit, df::specific_ref_type type); DFHACK_EXPORT df::specific_ref *getSpecificRef(df::unit *unit, df::specific_ref_type type);

@ -71,6 +71,7 @@ using namespace std;
#include "df/job.h" #include "df/job.h"
#include "df/nemesis_record.h" #include "df/nemesis_record.h"
#include "df/squad.h" #include "df/squad.h"
#include "df/tile_occupancy.h"
#include "df/ui.h" #include "df/ui.h"
#include "df/unit_inventory_item.h" #include "df/unit_inventory_item.h"
#include "df/unit_misc_trait.h" #include "df/unit_misc_trait.h"
@ -144,6 +145,49 @@ df::coord Units::getPosition(df::unit *unit)
return unit->pos; return unit->pos;
} }
bool Units::teleport(df::unit *unit, df::coord target_pos)
{
// make sure source and dest map blocks are valid
auto old_occ = Maps::getTileOccupancy(unit->pos);
auto new_occ = Maps::getTileOccupancy(target_pos);
if (!old_occ || !new_occ)
return false;
// clear appropriate occupancy flags at old tile
if (unit->flags1.bits.on_ground)
// this is potentially wrong, but the game will recompute this as needed
old_occ->bits.unit_grounded = 0;
else
old_occ->bits.unit = 0;
// if there's already somebody standing at the destination, then force the
// unit to lay down
if (new_occ->bits.unit)
unit->flags1.bits.on_ground = 1;
// set appropriate occupancy flags at new tile
if (unit->flags1.bits.on_ground)
new_occ->bits.unit_grounded = 1;
else
new_occ->bits.unit = 1;
// move unit to destination
unit->pos = target_pos;
// move unit's riders (including babies) to destination
if (unit->flags1.bits.ridden)
{
for (size_t j = 0; j < world->units.other[units_other_id::ANY_RIDER].size(); j++)
{
df::unit *rider = world->units.other[units_other_id::ANY_RIDER][j];
if (rider->relationship_ids[df::unit_relationship_type::RiderMount] == unit->id)
rider->pos = unit->pos;
}
}
return true;
}
df::general_ref *Units::getGeneralRef(df::unit *unit, df::general_ref_type type) df::general_ref *Units::getGeneralRef(df::unit *unit, df::general_ref_type type)
{ {
CHECK_NULL_POINTER(unit); CHECK_NULL_POINTER(unit);

@ -54,7 +54,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
if (!Units::isCitizen(unit)) if (!Units::isCitizen(unit))
continue; continue;
if (enable_teledwarf) do if (enable_teledwarf)
{ {
// skip dwarves that are dragging creatures or being dragged // skip dwarves that are dragging creatures or being dragged
if ((unit->relationship_ids[df::unit_relationship_type::Draggee] != -1) || if ((unit->relationship_ids[df::unit_relationship_type::Draggee] != -1) ||
@ -74,44 +74,11 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
break; break;
} }
// make sure source and dest map blocks are valid if (!Units::teleport(unit, unit->path.dest))
auto old_occ = Maps::getTileOccupancy(unit->pos);
auto new_occ = Maps::getTileOccupancy(unit->path.dest);
if (!old_occ || !new_occ)
break; break;
// clear appropriate occupancy flags at old tile
if (unit->flags1.bits.on_ground)
// this is technically wrong, but the game will recompute this as needed
old_occ->bits.unit_grounded = 0;
else
old_occ->bits.unit = 0;
// if there's already somebody standing at the destination, then force the unit to lay down
if (new_occ->bits.unit)
unit->flags1.bits.on_ground = 1;
// set appropriate occupancy flags at new tile
if (unit->flags1.bits.on_ground)
new_occ->bits.unit_grounded = 1;
else
new_occ->bits.unit = 1;
// move unit to destination
unit->pos = unit->path.dest;
unit->path.path.clear(); unit->path.path.clear();
//move unit's riders(including babies) to destination
if (unit->flags1.bits.ridden)
{
for (size_t j = 0; j < world->units.other[units_other_id::ANY_RIDER].size(); j++)
{
df::unit *rider = world->units.other[units_other_id::ANY_RIDER][j];
if (rider->relationship_ids[df::unit_relationship_type::RiderMount] == unit->id)
rider->pos = unit->pos;
}
} }
} while (0);
if (enable_fastdwarf) if (enable_fastdwarf)
{ {