From 3a250e073503e19e33ad96de3f55011b39e389fe Mon Sep 17 00:00:00 2001 From: Alistair-Afton Date: Wed, 16 Sep 2026 15:58:22 +0200 Subject: [PATCH 1/2] Units::teleport: update occupancy for the full EQUIPMENT footprint EQUIPMENT units (wagons) occupy a 3x3 footprint centered on their position, but teleport only cleared and set the unit occupancy bits on the center tile. Teleported wagons left stale unit flags on the eight surrounding source tiles and arrived with none set on the destination footprint, leaving the map occupancy inconsistent until something recomputed it (issue #5797). The footprint extent now comes from the race's EQUIPMENT_WAGON flag, so ordinary units keep the existing single-tile behavior. --- docs/changelog.txt | 1 + library/modules/Units.cpp | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index e078c870da..9bd3d5aba0 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -73,6 +73,7 @@ Template for new versions: - `buildingplan`: fix "Unlink all" only unlinking some mechanisms (or crashing) when freeing mechanisms from the building - `timestream`: deal properly with units who have breathing difficulties - `stocks`: overlay now resets scroll position when collapsing categories so the item list is no longer left blank and unscrollable +- ``Units::teleport``: update unit occupancy on the full 3x3 footprint of EQUIPMENT units (e.g. wagons) instead of only their center tile ## Misc Improvements - Added ``Coord2d`` and ``Coord3d`` C++ templates, providing a standard set operations for 2-tuples and 3-tuples of any numeric type diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index 33553f2874..b188992b64 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -42,6 +42,7 @@ distribution. #include "df/caste_raw.h" #include "df/creature_interaction_effect_display_namest.h" #include "df/creature_raw.h" +#include "df/creature_raw_flags.h" #include "df/curse_attr_change.h" #include "df/entity_position.h" #include "df/entity_position_assignment.h" @@ -777,12 +778,28 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) if (!old_occ || !new_occ) return false; + // EQUIPMENT units (e.g. wagons) occupy a 3x3 footprint centered on their + // position; all other units occupy just their position tile + int extent = 0; + if (auto craw = df::creature_raw::find(unit->race); craw && + craw->flags.is_set(df::creature_raw_flags::EQUIPMENT_WAGON)) + extent = 1; + + auto for_each_occupied_tile = [&](df::coord center, auto &&fn) { + for (int dy = -extent; dy <= extent; ++dy) + for (int dx = -extent; dx <= extent; ++dx) + if (auto occ = Maps::getTileOccupancy(center.x+dx, center.y+dy, center.z)) + fn(*occ); + }; + // 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 = false; - else - old_occ->bits.unit = false; + for_each_occupied_tile(unit->pos, [&](df::tile_occupancy &occ) { + if (unit->flags1.bits.on_ground) + // This is potentially wrong, but the game will recompute this as needed + occ.bits.unit_grounded = false; + else + occ.bits.unit = false; + }); // Clear unit projectile info if (unit->flags1.bits.projectile) { @@ -801,10 +818,12 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) unit->flags1.bits.on_ground = true; // Set appropriate occupancy flags at new tile - if (unit->flags1.bits.on_ground) - new_occ->bits.unit_grounded = true; - else - new_occ->bits.unit = true; + for_each_occupied_tile(target_pos, [&](df::tile_occupancy &occ) { + if (unit->flags1.bits.on_ground) + occ.bits.unit_grounded = true; + else + occ.bits.unit = true; + }); // Move unit to destination unit->pos = target_pos; From c73f088d1c8b4db0e6c8dc13f940bdc50e81a294 Mon Sep 17 00:00:00 2001 From: Kelly Kinkade Date: Thu, 17 Sep 2026 10:07:43 -0500 Subject: [PATCH 2/2] reorder changelog.txt --- docs/changelog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index 9bd3d5aba0..8f14eb8e40 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -67,13 +67,13 @@ Template for new versions: - Fixed a possible hang or assertion failure when pressing a hotkey while a DFHack GUI window was open but unfocused - In ``Screen`` module, Fix out-of-bounds color table access when Lua pens use ``COLOR_RESET`` - rename the ``stockpiles`` tool tag to ``stockpile`` so it no longer collides with the `stockpiles` plugin in `gui/launcher` +- ``Units::teleport``: update unit occupancy on the full 3x3 footprint of EQUIPMENT units (e.g. wagons) instead of only their center tile - `3dveins`: fix failure on embarks that cross midmap tiles - `aquifer`: make ``--skip-top`` and top-relative ``--levels`` take effect for the ``drain``, ``convert``, and ``add`` actions instead of being silently ignored - `autodump`: ``destroy`` no longer leaves the contents of destroyed containers in limbo or crashes when destroying unit-held items - `buildingplan`: fix "Unlink all" only unlinking some mechanisms (or crashing) when freeing mechanisms from the building - `timestream`: deal properly with units who have breathing difficulties - `stocks`: overlay now resets scroll position when collapsing categories so the item list is no longer left blank and unscrollable -- ``Units::teleport``: update unit occupancy on the full 3x3 footprint of EQUIPMENT units (e.g. wagons) instead of only their center tile ## Misc Improvements - Added ``Coord2d`` and ``Coord3d`` C++ templates, providing a standard set operations for 2-tuples and 3-tuples of any numeric type