From 8e6026766f9975d9fdfc001dcf63e443dd770864 Mon Sep 17 00:00:00 2001 From: SilasD Date: Wed, 21 Oct 2026 15:43:08 -0700 Subject: [PATCH 01/10] Units.cpp: mothers now have flags4.bits.carrying_somebody flags --- library/modules/Units.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index a5472b4e95..d661f8b3ab 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -860,7 +860,7 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) unit->idle_area = target_pos; // Move unit's riders (including babies) to destination - if (unit->flags1.bits.ridden) + if (unit->flags1.bits.ridden || unit->flags4.bits.carrying_somebody) for (auto rider : world->units.other[units_other_id::ANY_RIDER]) if (rider->relationship_ids[unit_relationship_type::RiderMount] == unit->id) rider->pos = unit->pos; From 9c779a04656b59b16ee667499f39bf9243d62c38 Mon Sep 17 00:00:00 2001 From: SilasD Date: Wed, 28 Oct 2026 07:48:57 -0700 Subject: [PATCH 02/10] Units.cpp add special handling for wagon riders. wagon riders do not ride the center tile of the wagon, and the draft animals are not even in the wagon's extent. I like being able to do math on coords. --- library/modules/Units.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index d661f8b3ab..3d1a903797 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -31,6 +31,7 @@ distribution. #include "VersionInfo.h" #include "modules/Items.h" +#include "modules/Job.h" #include "modules/Maps.h" #include "modules/Materials.h" #include "modules/Translation.h" @@ -863,7 +864,14 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) if (unit->flags1.bits.ridden || unit->flags4.bits.carrying_somebody) for (auto rider : world->units.other[units_other_id::ANY_RIDER]) if (rider->relationship_ids[unit_relationship_type::RiderMount] == unit->id) - rider->pos = unit->pos; + // Wagon riders need special handling -- they are not at the center of the wagon, + // and the draft animal riders are not even in the extent of the wagon. + if (auto craw = df::creature_raw::find(unit->race); craw && + craw->flags.is_set(df::creature_raw_flags::EQUIPMENT_WAGON)) + Units::teleport(rider, (rider->pos - src_pos) + unit->pos); + else + rider->pos = unit->pos; + return true; } From 75031341942d174132ef923f653f88f33bd96967 Mon Sep 17 00:00:00 2001 From: SilasD Date: Wed, 28 Oct 2026 15:51:35 -0700 Subject: [PATCH 03/10] Units.cpp teleport -- break links to cages and chains. --- library/modules/Units.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index 3d1a903797..9a88a2d000 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -39,6 +39,8 @@ distribution. #include "modules/World.h" #include "df/activity_entry.h" +#include "df/building_cagest.h" +#include "df/building_chainst.h" #include "df/burrow.h" #include "df/caste_raw.h" #include "df/creature_interaction_effect_display_namest.h" @@ -872,6 +874,38 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) else rider->pos = unit->pos; + // If the unit was teleported out of a cage, break those links. + if (auto cage = Units::getContainer(unit)) + { + for (auto job: strict_virtual_cast(Items::getHolderBuilding(cage))->jobs) + if (job->job_type == df::job_type::ReleaseLargeCreature || job->job_type == df::job_type::ReleasePet) + if (auto gref = findRef(job->general_refs, df::general_ref_type::UNIT_CAGEE); + gref && gref->getID() == unit->id) + Job::removeJob(job); + if (auto bld = strict_virtual_cast(Items::getHolderBuilding(cage))) + std::erase(bld->assigned_units, unit->id); + removeRef(cage->general_refs, df::general_ref_type::CONTAINS_UNIT, unit->id); + removeRef(unit->general_refs, df::general_ref_type::CONTAINED_IN_ITEM, cage->id); + unit->flags1.bits.caged = false; + } + + // If the unit was teleported out of a chain, break those links. + if (auto bld = strict_virtual_cast + (findBuildingRef(unit->general_refs, df::general_ref_type::BUILDING_CHAIN))) + { + for (auto job: bld->jobs) + if (auto gref = findRef(job->general_refs, df::general_ref_type::UNIT_CAGEE); + (job->job_type == df::job_type::UnchainAnimal || job->job_type == df::job_type::UnchainPet) + && gref && gref->getID() == unit->id) + Job::removeJob(job); + if (bld->chained == unit) + bld->chained = NULL; + if (bld->assigned == unit) + bld->assigned = NULL; + removeRef(unit->general_refs, df::general_ref_type::BUILDING_CHAIN, bld->id); + unit->flags1.bits.chained = false; + } + return true; } From 0fd30f69375300efee5180a388808aa72e643dd0 Mon Sep 17 00:00:00 2001 From: SilasD Date: Thu, 29 Oct 2026 17:55:51 -0700 Subject: [PATCH 04/10] Units.cpp if teleporting a rider, unlink from mount. --- library/modules/Units.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index 9a88a2d000..8addee7e43 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -874,6 +874,26 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) else rider->pos = unit->pos; + // if the unit itself was a rider, break that link. + if (unit->flags1.bits.rider) + { + auto mount = df::unit::find(unit->relationship_ids[df::unit_relationship_type::RiderMount]); + unit->flags1.bits.rider = false; + unit->relationship_ids[df::unit_relationship_type::RiderMount] = -1; + if (mount) + { + mount->flags1.bits.ridden = false; + mount->flags4.bits.carrying_somebody = false; + // rebuild the ridden flags; mothers can carry more than one baby. + for (auto rider : world->units.other[units_other_id::ANY_RIDER]) + if (rider->relationship_ids[unit_relationship_type::RiderMount] == mount->id) + if (rider->profession == df::profession::BABY) + mount->flags4.bits.carrying_somebody = true; + else + mount->flags1.bits.ridden = true; + } + } + // If the unit was teleported out of a cage, break those links. if (auto cage = Units::getContainer(unit)) { From a863ed7695c50f200fcfd8392f0a1aad2db2f89a Mon Sep 17 00:00:00 2001 From: SilasD Date: Thu, 29 Oct 2026 19:37:05 -0700 Subject: [PATCH 05/10] Units.cpp teleport: don't break link between wagons and riders. also pull out "is a wagon" tests into predicates. --- library/modules/Units.cpp | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index 8addee7e43..1a41b1b307 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -788,14 +788,25 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) if (!old_occ || !new_occ) return false; + auto is_wagon = [](df::unit *unit) { + if (!unit) + return false; + auto craw = df::creature_raw::find(unit->race); + return craw && craw->flags.is_set(df::creature_raw_flags::EQUIPMENT_WAGON); + }; + + auto uid_is_wagon = [&](int32_t unit_id) { + return is_wagon(df::unit::find(unit_id)); + }; + // EQUIPMENT units (e.g. wagons) occupy a 3x3 footprint centered on their // position; all other units occupy just their position tile - auto unit_extent = [](df::unit *u) { - if (auto craw = df::creature_raw::find(u->race); craw && - craw->flags.is_set(df::creature_raw_flags::EQUIPMENT_WAGON)) + auto unit_extent = [&](df::unit *unit) { + if (is_wagon(unit)) return 1; return 0; }; + const int extent = unit_extent(unit); auto for_each_occupied_tile = [&](df::coord center, auto &&fn) { @@ -868,20 +879,19 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) if (rider->relationship_ids[unit_relationship_type::RiderMount] == unit->id) // Wagon riders need special handling -- they are not at the center of the wagon, // and the draft animal riders are not even in the extent of the wagon. - if (auto craw = df::creature_raw::find(unit->race); craw && - craw->flags.is_set(df::creature_raw_flags::EQUIPMENT_WAGON)) + if (is_wagon(unit)) Units::teleport(rider, (rider->pos - src_pos) + unit->pos); else rider->pos = unit->pos; - // if the unit itself was a rider, break that link. + // if the unit itself was a rider, break that link (except do nothing to wagon-riders). if (unit->flags1.bits.rider) { auto mount = df::unit::find(unit->relationship_ids[df::unit_relationship_type::RiderMount]); - unit->flags1.bits.rider = false; - unit->relationship_ids[df::unit_relationship_type::RiderMount] = -1; - if (mount) + if (mount && !is_wagon(mount)) { + unit->flags1.bits.rider = false; + unit->relationship_ids[df::unit_relationship_type::RiderMount] = -1; mount->flags1.bits.ridden = false; mount->flags4.bits.carrying_somebody = false; // rebuild the ridden flags; mothers can carry more than one baby. From 29fe02c5685a0a7160621f1eeac819294401931d Mon Sep 17 00:00:00 2001 From: SilasD Date: Sun, 1 Nov 2026 16:04:46 -0800 Subject: [PATCH 06/10] Units.cpp teleport deal with dragged units, pull delete-cage/chained jobs into a predicate, don't break links between wagons and riders, teleport wagon riders with wagons even though they are not on the wagon's tile (although the game seems to tolerate and fix this), RescueWounded jobs set flags4.carrying_somebody not flags1.ridden, remove some redundant namespace specifiers, try to maintain a consistant brace style. --- library/modules/Units.cpp | 108 ++++++++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 35 deletions(-) diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index 1a41b1b307..3470df9b0c 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -41,6 +41,7 @@ distribution. #include "df/activity_entry.h" #include "df/building_cagest.h" #include "df/building_chainst.h" +#include "df/buildingitemst.h" #include "df/burrow.h" #include "df/caste_raw.h" #include "df/creature_interaction_effect_display_namest.h" @@ -795,10 +796,6 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) return craw && craw->flags.is_set(df::creature_raw_flags::EQUIPMENT_WAGON); }; - auto uid_is_wagon = [&](int32_t unit_id) { - return is_wagon(df::unit::find(unit_id)); - }; - // EQUIPMENT units (e.g. wagons) occupy a 3x3 footprint centered on their // position; all other units occupy just their position tile auto unit_extent = [&](df::unit *unit) { @@ -874,67 +871,108 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) unit->idle_area = target_pos; // Move unit's riders (including babies) to destination - if (unit->flags1.bits.ridden || unit->flags4.bits.carrying_somebody) + if (unit->flags1.bits.ridden || unit->flags4.bits.carrying_somebody) { for (auto rider : world->units.other[units_other_id::ANY_RIDER]) if (rider->relationship_ids[unit_relationship_type::RiderMount] == unit->id) // Wagon riders need special handling -- they are not at the center of the wagon, // and the draft animal riders are not even in the extent of the wagon. - if (is_wagon(unit)) - Units::teleport(rider, (rider->pos - src_pos) + unit->pos); - else - rider->pos = unit->pos; + // Unified this case with the normal case by maintaining the rider's delta-pos from + // the mount, and recursively teleporting instead of just setting the rider's pos. + Units::teleport(rider, (rider->pos - src_pos) + unit->pos); + } - // if the unit itself was a rider, break that link (except do nothing to wagon-riders). - if (unit->flags1.bits.rider) - { - auto mount = df::unit::find(unit->relationship_ids[df::unit_relationship_type::RiderMount]); - if (mount && !is_wagon(mount)) - { + // if the unit itself was a rider and it is not on the same tile as its mount, break that link. + // (except do nothing to wagon-riders). + if (unit->flags1.bits.rider) { + auto mount = df::unit::find(unit->relationship_ids[unit_relationship_type::RiderMount]); + if (mount && unit->pos != mount->pos && !is_wagon(mount)) { unit->flags1.bits.rider = false; - unit->relationship_ids[df::unit_relationship_type::RiderMount] = -1; + unit->relationship_ids[unit_relationship_type::RiderMount] = -1; mount->flags1.bits.ridden = false; mount->flags4.bits.carrying_somebody = false; // rebuild the ridden flags; mothers can carry more than one baby. - for (auto rider : world->units.other[units_other_id::ANY_RIDER]) - if (rider->relationship_ids[unit_relationship_type::RiderMount] == mount->id) - if (rider->profession == df::profession::BABY) + for (auto rider : world->units.other[units_other_id::ANY_RIDER]) { + if (rider->relationship_ids[unit_relationship_type::RiderMount] == mount->id) { + // notes on the recover wounded job: + // the wounded unit has .rider and .move_state true, no relevant refs, + // no job, relationship_ids.RiderMount set, mount_type == 1 Carried, + // health.flags.should_not_move true, a misc_trait of RequestRescueCooldown, + // and an entry in world.units.other.ANY_RIDER. + // the rescuing unit has .carrying_somebody and .move_state true, + // no relevant refs, and a job of type 164 RecoverWounded. + if (rider->profession == df::profession::BABY || (mount->job.current_job + && mount->job.current_job->job_type == job_type::RecoverWounded)) mount->flags4.bits.carrying_somebody = true; else mount->flags1.bits.ridden = true; + } + } } } + // removes jobs related to caging/uncaging/chaining/unchaining the teleported unit. + auto delete_cagee_jobs = [](df::unit* unit, df::building* bld) { + std::vector jobs_to_delete; + for (auto job: bld->jobs) + if (findUnitRef(job->general_refs, df::general_ref_type::UNIT_CAGEE) == unit) + jobs_to_delete.push_back(job); + for (auto job: jobs_to_delete) + Job::removeJob(job); + }; + // If the unit was teleported out of a cage, break those links. - if (auto cage = Units::getContainer(unit)) - { - for (auto job: strict_virtual_cast(Items::getHolderBuilding(cage))->jobs) - if (job->job_type == df::job_type::ReleaseLargeCreature || job->job_type == df::job_type::ReleasePet) - if (auto gref = findRef(job->general_refs, df::general_ref_type::UNIT_CAGEE); - gref && gref->getID() == unit->id) - Job::removeJob(job); - if (auto bld = strict_virtual_cast(Items::getHolderBuilding(cage))) + if (auto cage = getContainer(unit)) { + auto bld = strict_virtual_cast(Items::getHolderBuilding(cage)); + if (bld && bld->contained_items.size() > 0 && bld->contained_items[0]->item == cage) { + delete_cagee_jobs(unit, bld); std::erase(bld->assigned_units, unit->id); + bld->cage_flags.bits.check_occupants = true; + } removeRef(cage->general_refs, df::general_ref_type::CONTAINS_UNIT, unit->id); removeRef(unit->general_refs, df::general_ref_type::CONTAINED_IN_ITEM, cage->id); unit->flags1.bits.caged = false; + // unit->idle_area_type of caged units is set to -1, but that will be corrected by the game soon enough. } // If the unit was teleported out of a chain, break those links. if (auto bld = strict_virtual_cast (findBuildingRef(unit->general_refs, df::general_ref_type::BUILDING_CHAIN))) { - for (auto job: bld->jobs) - if (auto gref = findRef(job->general_refs, df::general_ref_type::UNIT_CAGEE); - (job->job_type == df::job_type::UnchainAnimal || job->job_type == df::job_type::UnchainPet) - && gref && gref->getID() == unit->id) - Job::removeJob(job); + delete_cagee_jobs(unit, bld); if (bld->chained == unit) - bld->chained = NULL; + bld->chained = nullptr; if (bld->assigned == unit) - bld->assigned = NULL; + bld->assigned = nullptr; removeRef(unit->general_refs, df::general_ref_type::BUILDING_CHAIN, bld->id); unit->flags1.bits.chained = false; - } + // unit->idle_area_type of chained units is set to 17 ChainedAnimal, but that will be corrected by the game soon enough. + } + + // removes dragger/draggee links and any dragger job, which is assumed to be related to the dragging. + auto break_dragging_links = [&target_pos](df::unit* dragger, df::unit* draggee) { + if (!dragger || !draggee) + return; + if (dragger->flags1.bits.merchant && draggee->flags1.bits.merchant) { + // this cannot infinite-recurse because at least one of the units is already at target_pos. + if (dragger->pos != target_pos) + Units::teleport(dragger, target_pos); + if (draggee->pos != target_pos) + Units::teleport(draggee, target_pos); + } + if ((isCitizen(dragger, false) || isResident(dragger, false)) && dragger->job.current_job != NULL) + Job::removeJob(dragger->job.current_job); + dragger->relationship_ids[unit_relationship_type::Draggee] = -1; + draggee->relationship_ids[unit_relationship_type::Dragger] = -1; + // draggees have flag1 move_state false, but the game cleans that up during the next tick. + }; + + // If the unit was dragging another unit, break those links. + if (auto draggee = df::unit::find(unit->relationship_ids[unit_relationship_type::Draggee])) + break_dragging_links(unit, draggee); + + // If the unit was being dragged by another unit, break those links. + if (auto dragger = df::unit::find(unit->relationship_ids[unit_relationship_type::Dragger])) + break_dragging_links(dragger, unit); return true; } From 378163cd5a9273670f4ed0d0d98f99371913ea74 Mon Sep 17 00:00:00 2001 From: SilasD Date: Mon, 2 Nov 2026 12:55:25 -0800 Subject: [PATCH 07/10] Units.cpp teleport remove no-longer-riders from ANY_RIDER, riders never are on_ground, fix bug in merchant dragging. --- library/modules/Units.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index 3470df9b0c..e59274a39c 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -855,7 +855,8 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) } // If there's already somebody standing at the destination, then force the unit to lay down - if (new_occ->bits.unit) + // (except riders never lay down) + if (new_occ->bits.unit && !unit->flags1.bits.rider) unit->flags1.bits.on_ground = true; // Set appropriate occupancy flags at new tile @@ -870,7 +871,7 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) unit->pos = target_pos; unit->idle_area = target_pos; - // Move unit's riders (including babies) to destination + // Move unit's riders (including babies and wounded) to destination if (unit->flags1.bits.ridden || unit->flags4.bits.carrying_somebody) { for (auto rider : world->units.other[units_other_id::ANY_RIDER]) if (rider->relationship_ids[unit_relationship_type::RiderMount] == unit->id) @@ -888,6 +889,8 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) if (mount && unit->pos != mount->pos && !is_wagon(mount)) { unit->flags1.bits.rider = false; unit->relationship_ids[unit_relationship_type::RiderMount] = -1; + // units.other.* are not sorted; do not use erase_from_vector. + std::erase(world->units.other[units_other_id::ANY_RIDER], unit); mount->flags1.bits.ridden = false; mount->flags4.bits.carrying_somebody = false; // rebuild the ridden flags; mothers can carry more than one baby. @@ -958,6 +961,7 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) Units::teleport(dragger, target_pos); if (draggee->pos != target_pos) Units::teleport(draggee, target_pos); + return; } if ((isCitizen(dragger, false) || isResident(dragger, false)) && dragger->job.current_job != NULL) Job::removeJob(dragger->job.current_job); From 7c97e51939d3514bf2b8d0cef6cc94d8248a9ace Mon Sep 17 00:00:00 2001 From: SilasD Date: Mon, 2 Nov 2026 14:36:22 -0800 Subject: [PATCH 08/10] Units.cpp teleport don't teleport into walls or impassible building tiles, don't teleport to or from hidden tiles. --- library/modules/Units.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index e59274a39c..54ae5a3300 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -27,6 +27,7 @@ distribution. #include "Internal.h" #include "MemAccess.h" #include "MiscUtils.h" +#include "Tiletypes.h" #include "Types.h" #include "VersionInfo.h" @@ -789,6 +790,23 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) if (!old_occ || !new_occ) return false; + if (!unit->flags3.bits.ghostly) { + auto new_tt = Maps::getTileType(target_pos); + if (tileShapeBasic(tileShape(*new_tt)) == df::tiletype_shape_basic::Wall) + return false; + + using namespace df::enums::tile_building_occ; + if (auto b = new_occ->bits.building; + b == Obstacle || b == Well || b == Impassable || b == Dynamic) + return false; + } + + // these won't return nullptr because we already got occupancies from these coords. + if (Maps::getTileDesignation(src_pos)->bits.hidden) + return false; + if (Maps::getTileDesignation(target_pos)->bits.hidden) + return false; + auto is_wagon = [](df::unit *unit) { if (!unit) return false; From 8563e1a5fa94dda7978bf6fc7a844cd8910b018c Mon Sep 17 00:00:00 2001 From: SilasD Date: Mon, 2 Nov 2026 15:28:08 -0800 Subject: [PATCH 09/10] Units.cpp teleport update documentation, changelog --- docs/changelog.txt | 6 ++++++ docs/dev/Lua API.rst | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index c2470dbe87..ba6a2a75b3 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -60,8 +60,14 @@ Template for new versions: ## New Features ## Fixes +- ``Units::teleport`` don't teleport units (except ghosts) into walls or impassable parts of buildings; don't teleport into or out of hidden tiles. +- ``Units::teleport`` teleport babies along with their mothers, teleport merchant wagon-riders with their wagons. don't break links between wagons & their riders. +- ``Units::teleport`` when using teleport to separate a rider/carried unit from its mount/carrying unit, clean up the links between the two. +- ``Units::teleport`` when using teleport to separate a dragged unit from a dragger unit, clean up the links between the two. ## Misc Improvements +- ``Units::teleport`` can now remove units from cages & chains, and will cancel any associated uncage/unchain jobs. +- ``Units::teleport`` when teleporting a merchant dragging a pack animal, also teleport the animal. ## Documentation - ``export-world-map``: added more format conversion examples. diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 2f55e17184..823db24607 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -1808,6 +1808,11 @@ Units module Moves the specified unit and any riders to the target coordinates, setting tile occupancy flags appropriately. Returns true if successful. + This function correctly removes units from cages and chains, and correctly + removes the links between one unit dragging another unit. As a special + case, teleporting a merchant that is dragging a pack animal will also + teleport the pack animal. + * ``dfhack.units.getGeneralRef(unit, type)`` Searches for a ``general_ref`` with the given type. From 20024afcd8101a695a80e22012e075b1a42e5603 Mon Sep 17 00:00:00 2001 From: SilasD Date: Mon, 2 Nov 2026 15:32:09 -0800 Subject: [PATCH 10/10] Units.cpp #include filenames are case-sensitive. --- library/modules/Units.cpp | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index 54ae5a3300..4c382266c3 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -27,7 +27,7 @@ distribution. #include "Internal.h" #include "MemAccess.h" #include "MiscUtils.h" -#include "Tiletypes.h" +#include "TileTypes.h" #include "Types.h" #include "VersionInfo.h" @@ -907,20 +907,13 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) if (mount && unit->pos != mount->pos && !is_wagon(mount)) { unit->flags1.bits.rider = false; unit->relationship_ids[unit_relationship_type::RiderMount] = -1; - // units.other.* are not sorted; do not use erase_from_vector. + // units.other.* are not sorted; do not use erase_from_vector(). std::erase(world->units.other[units_other_id::ANY_RIDER], unit); mount->flags1.bits.ridden = false; mount->flags4.bits.carrying_somebody = false; // rebuild the ridden flags; mothers can carry more than one baby. for (auto rider : world->units.other[units_other_id::ANY_RIDER]) { if (rider->relationship_ids[unit_relationship_type::RiderMount] == mount->id) { - // notes on the recover wounded job: - // the wounded unit has .rider and .move_state true, no relevant refs, - // no job, relationship_ids.RiderMount set, mount_type == 1 Carried, - // health.flags.should_not_move true, a misc_trait of RequestRescueCooldown, - // and an entry in world.units.other.ANY_RIDER. - // the rescuing unit has .carrying_somebody and .move_state true, - // no relevant refs, and a job of type 164 RecoverWounded. if (rider->profession == df::profession::BABY || (mount->job.current_job && mount->job.current_job->job_type == job_type::RecoverWounded)) mount->flags4.bits.carrying_somebody = true; @@ -931,7 +924,6 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) } } - // removes jobs related to caging/uncaging/chaining/unchaining the teleported unit. auto delete_cagee_jobs = [](df::unit* unit, df::building* bld) { std::vector jobs_to_delete; for (auto job: bld->jobs) @@ -941,7 +933,6 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) Job::removeJob(job); }; - // If the unit was teleported out of a cage, break those links. if (auto cage = getContainer(unit)) { auto bld = strict_virtual_cast(Items::getHolderBuilding(cage)); if (bld && bld->contained_items.size() > 0 && bld->contained_items[0]->item == cage) { @@ -952,10 +943,8 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) removeRef(cage->general_refs, df::general_ref_type::CONTAINS_UNIT, unit->id); removeRef(unit->general_refs, df::general_ref_type::CONTAINED_IN_ITEM, cage->id); unit->flags1.bits.caged = false; - // unit->idle_area_type of caged units is set to -1, but that will be corrected by the game soon enough. } - // If the unit was teleported out of a chain, break those links. if (auto bld = strict_virtual_cast (findBuildingRef(unit->general_refs, df::general_ref_type::BUILDING_CHAIN))) { @@ -966,10 +955,8 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) bld->assigned = nullptr; removeRef(unit->general_refs, df::general_ref_type::BUILDING_CHAIN, bld->id); unit->flags1.bits.chained = false; - // unit->idle_area_type of chained units is set to 17 ChainedAnimal, but that will be corrected by the game soon enough. } - // removes dragger/draggee links and any dragger job, which is assumed to be related to the dragging. auto break_dragging_links = [&target_pos](df::unit* dragger, df::unit* draggee) { if (!dragger || !draggee) return; @@ -985,14 +972,10 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) Job::removeJob(dragger->job.current_job); dragger->relationship_ids[unit_relationship_type::Draggee] = -1; draggee->relationship_ids[unit_relationship_type::Dragger] = -1; - // draggees have flag1 move_state false, but the game cleans that up during the next tick. }; - // If the unit was dragging another unit, break those links. if (auto draggee = df::unit::find(unit->relationship_ids[unit_relationship_type::Draggee])) break_dragging_links(unit, draggee); - - // If the unit was being dragged by another unit, break those links. if (auto dragger = df::unit::find(unit->relationship_ids[unit_relationship_type::Dragger])) break_dragging_links(dragger, unit);