From d9d2c7a60a3c2867ba06a9b68e7b57c89df3d626 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 6 Apr 2025 14:12:18 -0700 Subject: [PATCH 1/5] define -> operator for DF linked lists --- library/include/BitArray.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/library/include/BitArray.h b/library/include/BitArray.h index 3679323eb8..bad77d7935 100644 --- a/library/include/BitArray.h +++ b/library/include/BitArray.h @@ -318,6 +318,22 @@ namespace DFHack return cur->item; } + I * operator->() + { + CHECK_NULL_POINTER(root); + CHECK_NULL_POINTER(cur); + + return cur->item; + } + + I * operator->() const + { + CHECK_NULL_POINTER(root); + CHECK_NULL_POINTER(cur); + + return cur->item; + } + operator const_iterator() const { return const_iterator(*this); From 3565121aebe9376abff451cf013d9074ead321f8 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 6 Apr 2025 14:15:56 -0700 Subject: [PATCH 2/5] generalize linked_list_remove so it can take a predicate --- library/include/MiscUtils.h | 53 +++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h index 8568a55c0a..c916a6a9fb 100644 --- a/library/include/MiscUtils.h +++ b/library/include/MiscUtils.h @@ -309,24 +309,43 @@ Link *linked_list_insert_after(Link *pos, Link *link) } /** - * Returns true if the item with id idToRemove was found, deleted, and removed - * from the list. Otherwise returns false. + * Returns true if an item that matches the given function was found, deleted, + * and removed from the list. Otherwise returns false. Only removes the first + * match. + * + * Example usage: + * + * linked_list_remove(&world->projectiles.all, [&](df::projectile *proj) { + * if (proj->getType() != df::enums::projectile_type::Unit) + * return false; + * if (auto unit_proj = virtual_cast(proj)) + * return unit_proj->unit == unit; + * return false; + * }); */ -template -bool linked_list_remove(Link *head, int32_t idToRemove) -{ - for (Link *link = head; link; link = link->next) - { - if (!link->item || link->item->id != idToRemove) - continue; - - link->prev->next = link->next; - if (link->next) - link->next->prev = link->prev; - delete(link); - return true; - } - return false; +template F> +bool linked_list_remove(L *list, F matches) { + auto matches_wrapper = [&](L::iterator::value_type item) { + return item && matches(item); + }; + auto it = std::find_if(list->begin(), list->end(), matches_wrapper); + if (it == list->end()) + return false; + auto item = *it; + list->erase(it); + delete item; + return true; +} + +/** + * Returns true if the item with id idToRemove was found, deleted, and + * removed from the list. Otherwise returns false. + */ +template +bool linked_list_remove(L *list, int32_t idToRemove) { + return linked_list_remove(list, [&](L::iterator::value_type item) { + return item->id == idToRemove; + }); } template From 0b7c04bb156d835547405a5088d7ae06c01cf9bc Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 6 Apr 2025 14:16:17 -0700 Subject: [PATCH 3/5] remove projectile info for teleported units otherwise they will be teleported back to their next projectile targeted tile on the next tick --- docs/changelog.txt | 2 ++ library/modules/Units.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index cd43392b78..5d64c50a78 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -59,6 +59,7 @@ Template for new versions: - `stockpiles`: fix one-off error in item type when importing furniture stockpile settings - `dig-now`: fix cases where boulders/rough gems of incorrect material were being generated when digging through walls - `dig-now`: properly generate ice boulders when digging through ice walls +- `gui/teleport`: now properly handles teleporting units that are currently falling or being flung ## Misc Improvements - `spectate`: show dwarves' activities (like prayer) @@ -67,6 +68,7 @@ Template for new versions: ## API - ``Military`` module: added ``addToSquad`` function +- ``Units::teleport``: projectile information is now cleared for teleported units ## Lua - ``dfhack.military.addToSquad``: expose Military API function diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index 21f39932fe..e604562c77 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -67,6 +67,7 @@ distribution. #include "df/nemesis_record.h" #include "df/personality_goalst.h" #include "df/plotinfost.h" +#include "df/proj_unitst.h" #include "df/reputation_profilest.h" #include "df/syndrome.h" #include "df/tile_occupancy.h" @@ -773,6 +774,18 @@ bool Units::teleport(df::unit *unit, df::coord target_pos) else old_occ->bits.unit = false; + // Clear unit projectile info + if (unit->flags1.bits.projectile) { + unit->flags1.bits.projectile = false; + linked_list_remove(&world->projectiles.all, [&](df::projectile *proj) { + if (proj->getType() != df::enums::projectile_type::Unit) + return false; + if (auto unit_proj = virtual_cast(proj)) + return unit_proj->unit == unit; + return false; + }); + } + // 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 = true; From 3b9d731f71bd49123b09177f877fce99ccda6646 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 6 Apr 2025 14:31:21 -0700 Subject: [PATCH 4/5] don't show hover tooltip for hidden creatures --- docs/changelog.txt | 1 + plugins/lua/spectate.lua | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index cd43392b78..e311e6441d 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -56,6 +56,7 @@ Template for new versions: ## New Features ## Fixes +- `spectate`: don't show a hover tooltip for hidden units (e.g. invisible snatchers) - `stockpiles`: fix one-off error in item type when importing furniture stockpile settings - `dig-now`: fix cases where boulders/rough gems of incorrect material were being generated when digging through walls - `dig-now`: properly generate ice boulders when digging through ice walls diff --git a/plugins/lua/spectate.lua b/plugins/lua/spectate.lua index fd2f736d0e..8c7e653a7b 100644 --- a/plugins/lua/spectate.lua +++ b/plugins/lua/spectate.lua @@ -345,11 +345,15 @@ local function GetUnitInfoText(unit, settings_group_name) return txt end +local function unit_filter(unit) + return not dfhack.units.isHidden(unit) +end + local function GetHoverText(pos) if not pos then return end local txt = {} - local units = dfhack.units.getUnitsInBox(pos, pos) or {} -- todo: maybe (optionally) use filter parameter here? + local units = dfhack.units.getUnitsInBox(pos, pos, unit_filter) or {} for _,unit in ipairs(units) do local info = GetUnitInfoText(unit, 'hover') From 4f75aa4a6e59f37daff9b94f51f6a185b2dbc8c0 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 6 Apr 2025 14:36:09 -0700 Subject: [PATCH 5/5] try to make msvc happy --- library/include/MiscUtils.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h index c916a6a9fb..2b9426202d 100644 --- a/library/include/MiscUtils.h +++ b/library/include/MiscUtils.h @@ -328,8 +328,8 @@ bool linked_list_remove(L *list, F matches) { auto matches_wrapper = [&](L::iterator::value_type item) { return item && matches(item); }; - auto it = std::find_if(list->begin(), list->end(), matches_wrapper); - if (it == list->end()) + typename L::const_iterator it = std::find_if(list->cbegin(), list->cend(), matches_wrapper); + if (it == list->cend()) return false; auto item = *it; list->erase(it);