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.
* ``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``
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.
* ``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)``
Searches for a general_ref with the given type.

@ -1572,6 +1572,7 @@ static const luaL_Reg dfhack_job_funcs[] = {
/***** Units module *****/
static const LuaWrapper::FunctionReg dfhack_units_module[] = {
WRAPM(Units, teleport),
WRAPM(Units, getGeneralRef),
WRAPM(Units, getSpecificRef),
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).
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::specific_ref *getSpecificRef(df::unit *unit, df::specific_ref_type type);

@ -71,6 +71,7 @@ using namespace std;
#include "df/job.h"
#include "df/nemesis_record.h"
#include "df/squad.h"
#include "df/tile_occupancy.h"
#include "df/ui.h"
#include "df/unit_inventory_item.h"
#include "df/unit_misc_trait.h"
@ -144,6 +145,49 @@ df::coord Units::getPosition(df::unit *unit)
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)
{
CHECK_NULL_POINTER(unit);

@ -54,7 +54,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
if (!Units::isCitizen(unit))
continue;
if (enable_teledwarf) do
if (enable_teledwarf)
{
// skip dwarves that are dragging creatures or being dragged
if ((unit->relationship_ids[df::unit_relationship_type::Draggee] != -1) ||
@ -74,44 +74,11 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
break;
}
// make sure source and dest map blocks are valid
auto old_occ = Maps::getTileOccupancy(unit->pos);
auto new_occ = Maps::getTileOccupancy(unit->path.dest);
if (!old_occ || !new_occ)
if (!Units::teleport(unit, unit->path.dest))
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();
//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)
{