From 91529fa5fcb6cd1da426e8e5a24169f25dd0edb7 Mon Sep 17 00:00:00 2001 From: yg-ong Date: Fri, 31 Jan 2025 15:59:07 +0800 Subject: [PATCH 01/29] Edit military module --- library/include/modules/Military.h | 1 + library/modules/Military.cpp | 101 +++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/library/include/modules/Military.h b/library/include/modules/Military.h index 013f804415..dc69dac52b 100644 --- a/library/include/modules/Military.h +++ b/library/include/modules/Military.h @@ -17,6 +17,7 @@ namespace Military DFHACK_EXPORT std::string getSquadName(int32_t squad_id); DFHACK_EXPORT df::squad* makeSquad(int32_t assignment_id); DFHACK_EXPORT void updateRoomAssignments(int32_t squad_id, int32_t civzone_id, df::squad_use_flags flags); +DFHACK_EXPORT bool removeFromSquad(int32_t unit_id); } } diff --git a/library/modules/Military.cpp b/library/modules/Military.cpp index 0477c366b0..23fc15a871 100644 --- a/library/modules/Military.cpp +++ b/library/modules/Military.cpp @@ -4,6 +4,7 @@ #include "MiscUtils.h" #include "modules/Military.h" #include "modules/Translation.h" +#include "modules/Units.h" #include "df/building.h" #include "df/building_civzonest.h" #include "df/historical_figure.h" @@ -289,3 +290,103 @@ void Military::updateRoomAssignments(int32_t squad_id, int32_t civzone_id, df::s } } } + +static bool remove_soldier_entity_link(df::historical_figure* hf, df::squad* squad) +{ + int32_t start_year = -1; + for (size_t i = 0; i < hf->entity_links.size(); i++) + { + auto link = strict_virtual_cast(hf->entity_links[i]); + if (link == nullptr) continue; + if (link->squad_id != squad->id) continue; + + hf->entity_links.erase(hf->entity_links.begin() + i); + delete link; + + start_year = link->start_year; + break; + } + if (start_year == -1) return false; + + auto former_squad = new df::histfig_entity_link_former_squadst(); + former_squad->squad_id = squad->id; + former_squad->entity_id = squad->entity_id; + former_squad->start_year = start_year; + former_squad->end_year = *df::global::cur_year; + former_squad->link_strength = 100; + + hf->entity_links.push_back(former_pos); + return true; +} + +static bool remove_captain_entity_link(df::historical_figure* hf, df::squad* squad) +{ + std::vector nps; + if (! Units::getNoblePositions(&nps, hf)) return false; + + int32_t assignment_id = -1; + for (auto& np : nps) + { + if (np.entity.id != squad->entity_id) continue; + if (np.assignment.squad_id != squad.id) continue; + + np.assignment->histfig = -1; + np.assignment->histfig2 = -1; + + assignment_id = np.assignment->id; + break; + } + if (assignment_id == -1) return false; + + int32_t start_year = -1; + for (size_t i = 0; i < hf->entity_links.size(); i++) + { + auto link = strict_virtual_cast(hf->entity_links[i]); + if (link == nullptr) continue; + if (link->assignment_id != assignment_id && link->entity_id != squad->entity_id) continue; + + hf->entity_links.erase(hf->entity_links.begin() + i); + delete link; + + start_year = link->start_year; + break; + } + if (start_year == -1) return false; + + auto former_pos = new df::histfig_entity_link_former_positionst(); + former_pos->assignment_id = assignment_id; + former_pos->entity_id = squad->entity_id; + former_pos->start_year = start_year; + former_pos->end_year = *df::global::cur_year; + former_pos->link_strength = 100; + + hf->entity_links.push_back(former_pos); + return true; +} + +bool Military::removeFromSquad(int32_t unit_id) +{ + df::unit* unit = df::unit::find(unit_id); + if (unit == nullptr) return false; + if (unit->military.squad_id == -1 || unit->military.squad_position == -1) return false; + + int32_t squad_id = unit->military.squad_id; + df::squad* squad = df::squad::find(squad_id); + if (squad == nullptr) return false; + + // remove from squad information + int32_t squad_pos = unit->military.squad_position; + df::squad_position* pos = squad->positions.at(squad_pos); + pos->occupant = -1; + + // remove from unit information + unit->military.squad_id = -1; + unit->military.squad_position = -1; + + df::historical_figure* hf = df::historical_figure::find(unit->hist_figure_id); + if (hf == nullptr) return false; + + return squad_pos == 0 // is unit a commander? + ? remove_captain_entity_link(hf, squad) + : remove_soldier_entity_link(hf, squad); +} From aa6fdb41fc4ee5330ba907a9960dde05cb34d2b1 Mon Sep 17 00:00:00 2001 From: Ying Gao Date: Fri, 7 Feb 2025 22:48:31 +0800 Subject: [PATCH 02/29] Add Military::removeFromSquad --- library/modules/Military.cpp | 64 ++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/library/modules/Military.cpp b/library/modules/Military.cpp index 23fc15a871..929285a761 100644 --- a/library/modules/Military.cpp +++ b/library/modules/Military.cpp @@ -7,6 +7,10 @@ #include "modules/Units.h" #include "df/building.h" #include "df/building_civzonest.h" +#include "df/histfig_entity_link_former_positionst.h" +#include "df/histfig_entity_link_former_squadst.h" +#include "df/histfig_entity_link_positionst.h" +#include "df/histfig_entity_link_squadst.h" #include "df/historical_figure.h" #include "df/historical_entity.h" #include "df/entity_position.h" @@ -17,6 +21,7 @@ #include "df/squad_schedule_order.h" #include "df/squad_order.h" #include "df/squad_order_trainst.h" +#include "df/unit.h" #include "df/world.h" using namespace DFHack; @@ -297,46 +302,51 @@ static bool remove_soldier_entity_link(df::historical_figure* hf, df::squad* squ for (size_t i = 0; i < hf->entity_links.size(); i++) { auto link = strict_virtual_cast(hf->entity_links[i]); - if (link == nullptr) continue; - if (link->squad_id != squad->id) continue; - + if (link == nullptr || link->squad_id != squad->id) + continue; + hf->entity_links.erase(hf->entity_links.begin() + i); - delete link; - start_year = link->start_year; + + delete link; break; } - if (start_year == -1) return false; + + if (start_year == -1) + return false; - auto former_squad = new df::histfig_entity_link_former_squadst(); + auto former_squad = df::allocate(); former_squad->squad_id = squad->id; former_squad->entity_id = squad->entity_id; former_squad->start_year = start_year; former_squad->end_year = *df::global::cur_year; former_squad->link_strength = 100; - hf->entity_links.push_back(former_pos); + hf->entity_links.push_back(former_squad); return true; } -static bool remove_captain_entity_link(df::historical_figure* hf, df::squad* squad) +static bool remove_officer_entity_link(df::historical_figure* hf, df::squad* squad) { std::vector nps; - if (! Units::getNoblePositions(&nps, hf)) return false; + if (! Units::getNoblePositions(&nps, hf)) + return false; int32_t assignment_id = -1; for (auto& np : nps) { - if (np.entity.id != squad->entity_id) continue; - if (np.assignment.squad_id != squad.id) continue; - + if (np.entity->id != squad->entity_id || np.assignment->squad_id != squad->id) + continue; + np.assignment->histfig = -1; np.assignment->histfig2 = -1; assignment_id = np.assignment->id; break; } - if (assignment_id == -1) return false; + + if (assignment_id == -1) + return false; int32_t start_year = -1; for (size_t i = 0; i < hf->entity_links.size(); i++) @@ -346,14 +356,16 @@ static bool remove_captain_entity_link(df::historical_figure* hf, df::squad* squ if (link->assignment_id != assignment_id && link->entity_id != squad->entity_id) continue; hf->entity_links.erase(hf->entity_links.begin() + i); - delete link; - start_year = link->start_year; + + delete link; break; } - if (start_year == -1) return false; + + if (start_year == -1) + return false; - auto former_pos = new df::histfig_entity_link_former_positionst(); + auto former_pos = df::allocate(); former_pos->assignment_id = assignment_id; former_pos->entity_id = squad->entity_id; former_pos->start_year = start_year; @@ -366,13 +378,16 @@ static bool remove_captain_entity_link(df::historical_figure* hf, df::squad* squ bool Military::removeFromSquad(int32_t unit_id) { - df::unit* unit = df::unit::find(unit_id); - if (unit == nullptr) return false; - if (unit->military.squad_id == -1 || unit->military.squad_position == -1) return false; + df::unit *unit = df::unit::find(unit_id); + if (unit == nullptr) + return false; + if (unit->military.squad_id == -1 || unit->military.squad_position == -1) + return false; int32_t squad_id = unit->military.squad_id; df::squad* squad = df::squad::find(squad_id); - if (squad == nullptr) return false; + if (squad == nullptr) + return false; // remove from squad information int32_t squad_pos = unit->military.squad_position; @@ -384,9 +399,10 @@ bool Military::removeFromSquad(int32_t unit_id) unit->military.squad_position = -1; df::historical_figure* hf = df::historical_figure::find(unit->hist_figure_id); - if (hf == nullptr) return false; + if (hf == nullptr) + return false; return squad_pos == 0 // is unit a commander? - ? remove_captain_entity_link(hf, squad) + ? remove_officer_entity_link(hf, squad) : remove_soldier_entity_link(hf, squad); } From 872cc7cba5a2e599c6e2f081b4ee2a8333d5d9ff Mon Sep 17 00:00:00 2001 From: Ying Gao Date: Fri, 7 Feb 2025 23:01:49 +0800 Subject: [PATCH 03/29] Fix style --- library/modules/Military.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/library/modules/Military.cpp b/library/modules/Military.cpp index 929285a761..d569250167 100644 --- a/library/modules/Military.cpp +++ b/library/modules/Military.cpp @@ -312,7 +312,7 @@ static bool remove_soldier_entity_link(df::historical_figure* hf, df::squad* squ break; } - if (start_year == -1) + if (start_year == -1) return false; auto former_squad = df::allocate(); @@ -335,7 +335,7 @@ static bool remove_officer_entity_link(df::historical_figure* hf, df::squad* squ int32_t assignment_id = -1; for (auto& np : nps) { - if (np.entity->id != squad->entity_id || np.assignment->squad_id != squad->id) + if (np.entity->id != squad->entity_id || np.assignment->squad_id != squad->id) continue; np.assignment->histfig = -1; @@ -352,8 +352,10 @@ static bool remove_officer_entity_link(df::historical_figure* hf, df::squad* squ for (size_t i = 0; i < hf->entity_links.size(); i++) { auto link = strict_virtual_cast(hf->entity_links[i]); - if (link == nullptr) continue; - if (link->assignment_id != assignment_id && link->entity_id != squad->entity_id) continue; + if (link == nullptr) + continue; + if (link->assignment_id != assignment_id && link->entity_id != squad->entity_id) + continue; hf->entity_links.erase(hf->entity_links.begin() + i); start_year = link->start_year; From 84370629900dcfca95a984cae8284d11e3d9678b Mon Sep 17 00:00:00 2001 From: Ying Gao Date: Fri, 7 Feb 2025 23:09:19 +0800 Subject: [PATCH 04/29] Attempt to fix trailing whitespace --- library/modules/Military.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/modules/Military.cpp b/library/modules/Military.cpp index d569250167..d1322735db 100644 --- a/library/modules/Military.cpp +++ b/library/modules/Military.cpp @@ -329,7 +329,7 @@ static bool remove_soldier_entity_link(df::historical_figure* hf, df::squad* squ static bool remove_officer_entity_link(df::historical_figure* hf, df::squad* squad) { std::vector nps; - if (! Units::getNoblePositions(&nps, hf)) + if (!Units::getNoblePositions(&nps, hf)) return false; int32_t assignment_id = -1; From 7eb27ef350963ebdac9a136bcc291ef989df99aa Mon Sep 17 00:00:00 2001 From: Ying Gao Date: Fri, 7 Feb 2025 23:12:44 +0800 Subject: [PATCH 05/29] Remove trailing whitespace --- library/modules/Military.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/modules/Military.cpp b/library/modules/Military.cpp index d1322735db..8292c6227b 100644 --- a/library/modules/Military.cpp +++ b/library/modules/Military.cpp @@ -304,14 +304,14 @@ static bool remove_soldier_entity_link(df::historical_figure* hf, df::squad* squ auto link = strict_virtual_cast(hf->entity_links[i]); if (link == nullptr || link->squad_id != squad->id) continue; - + hf->entity_links.erase(hf->entity_links.begin() + i); start_year = link->start_year; delete link; break; } - + if (start_year == -1) return false; @@ -337,14 +337,14 @@ static bool remove_officer_entity_link(df::historical_figure* hf, df::squad* squ { if (np.entity->id != squad->entity_id || np.assignment->squad_id != squad->id) continue; - + np.assignment->histfig = -1; np.assignment->histfig2 = -1; assignment_id = np.assignment->id; break; } - + if (assignment_id == -1) return false; @@ -359,11 +359,11 @@ static bool remove_officer_entity_link(df::historical_figure* hf, df::squad* squ hf->entity_links.erase(hf->entity_links.begin() + i); start_year = link->start_year; - + delete link; break; } - + if (start_year == -1) return false; From 9a06a27222538bf4cd7536453e0d9e851858a8c2 Mon Sep 17 00:00:00 2001 From: Ying Gao Date: Sat, 8 Feb 2025 02:43:23 +0800 Subject: [PATCH 06/29] Add Lua bindings --- docs/dev/Lua API.rst | 8 ++++++++ library/LuaApi.cpp | 1 + 2 files changed, 9 insertions(+) diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 000840c76b..4cc2c35d06 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -1986,6 +1986,14 @@ Military module Returns the name of a squad as a string. +* ``dfhack.military.removeFromSquad(unit_id)`` + + Removes a unit from its squad and returns true if successful. Unsets the unit's + military information (i.e., ``unit.military.squad_id`` and + ``unit.military.squad_pos``), the squad's position information (i.e., + ``squad.positions[squad_pos].occupant``), and modifies the unit's entity links + to indicate former squad membership or command. + Items module ------------ diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 4b82dddc17..6e251dbfcf 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -2341,6 +2341,7 @@ static const LuaWrapper::FunctionReg dfhack_military_module[] = { WRAPM(Military, makeSquad), WRAPM(Military, updateRoomAssignments), WRAPM(Military, getSquadName), + WRAPM(Military, removeFromSquad), { NULL, NULL } }; From c9e2dcc2812247cb4f9d1f3a4e3410f70d2172b3 Mon Sep 17 00:00:00 2001 From: Ying Gao Date: Sat, 8 Feb 2025 02:44:26 +0800 Subject: [PATCH 07/29] Modify Military.cpp --- library/modules/Military.cpp | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/library/modules/Military.cpp b/library/modules/Military.cpp index 8292c6227b..62d189c4d7 100644 --- a/library/modules/Military.cpp +++ b/library/modules/Military.cpp @@ -301,14 +301,18 @@ static bool remove_soldier_entity_link(df::historical_figure* hf, df::squad* squ int32_t start_year = -1; for (size_t i = 0; i < hf->entity_links.size(); i++) { - auto link = strict_virtual_cast(hf->entity_links[i]); - if (link == nullptr || link->squad_id != squad->id) + df::histfig_entity_link* link = hf->entity_links[i]; + if (link->getType() != df::enums::histfig_entity_link_type::SQUAD) + continue; + + auto squad_link = strict_virtual_cast(link); + if (squad_link == nullptr || squad_link->squad_id != squad->id) continue; hf->entity_links.erase(hf->entity_links.begin() + i); - start_year = link->start_year; + start_year = squad_link->start_year; - delete link; + delete squad_link; break; } @@ -351,16 +355,20 @@ static bool remove_officer_entity_link(df::historical_figure* hf, df::squad* squ int32_t start_year = -1; for (size_t i = 0; i < hf->entity_links.size(); i++) { - auto link = strict_virtual_cast(hf->entity_links[i]); - if (link == nullptr) + df::histfig_entity_link* link = hf->entity_links[i]; + if (link->getType() != df::enums::histfig_entity_link_type::POSITION) + continue; + + auto pos_link = strict_virtual_cast(link); + if (pos_link == nullptr) continue; - if (link->assignment_id != assignment_id && link->entity_id != squad->entity_id) + if (pos_link->assignment_id != assignment_id && pos_link->entity_id != squad->entity_id) continue; hf->entity_links.erase(hf->entity_links.begin() + i); - start_year = link->start_year; + start_year = pos_link->start_year; - delete link; + delete pos_link; break; } @@ -393,9 +401,12 @@ bool Military::removeFromSquad(int32_t unit_id) // remove from squad information int32_t squad_pos = unit->military.squad_position; - df::squad_position* pos = squad->positions.at(squad_pos); - pos->occupant = -1; + df::squad_position* pos = vector_get(squad->positions, squad_pos); + if (pos == nullptr) + return false; + // remove from squad information + pos->occupant = -1; // remove from unit information unit->military.squad_id = -1; unit->military.squad_position = -1; From cfe1dbb79b6b53e3d1f4e03bf92a6b2807b6a9de Mon Sep 17 00:00:00 2001 From: Ying Gao Date: Sat, 8 Feb 2025 03:14:43 +0800 Subject: [PATCH 08/29] Update changelog --- docs/changelog.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index b8d28decc8..e8340baeac 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -35,9 +35,11 @@ Template for new versions: ## Documentation ## API +- ``Military::removeFromSquad``: removes unit from any squad assignments ## Lua - ``dfhack.units.setAutomaticProfessions``: sets unit labors according to current work detail settings +- ``dfhack.military.removeFromSquad``: Lua API for ``Military::removeFromSquad`` ## Removed From 194bde01576571e023ea11255c3aa5a0f80a066a Mon Sep 17 00:00:00 2001 From: DFHack-Urist via GitHub Actions <63161697+DFHack-Urist@users.noreply.github.com> Date: Sat, 8 Feb 2025 07:15:59 +0000 Subject: [PATCH 09/29] Auto-update submodules scripts: master plugins/stonesense: master depends/dfhooks: main --- depends/dfhooks | 2 +- plugins/stonesense | 2 +- scripts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/depends/dfhooks b/depends/dfhooks index 5b70cd886f..5bd392890e 160000 --- a/depends/dfhooks +++ b/depends/dfhooks @@ -1 +1 @@ -Subproject commit 5b70cd886f619b503aa770008fb79aa39a3be6fa +Subproject commit 5bd392890e92a70622878c0513ef50e72e215435 diff --git a/plugins/stonesense b/plugins/stonesense index 9d851db080..1756e2f3f7 160000 --- a/plugins/stonesense +++ b/plugins/stonesense @@ -1 +1 @@ -Subproject commit 9d851db080012add38631af37ea5c5b60a893e79 +Subproject commit 1756e2f3f704a0d01b24feccd0089972c245c164 diff --git a/scripts b/scripts index ebb22f3adb..fc67fdc5b6 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit ebb22f3adb6070c931a82b5f6a1749e7bf3ced03 +Subproject commit fc67fdc5b67a25a776eebfa769b289801679e364 From 5a6de1fc928ecc067267064fab2fd443a36643c8 Mon Sep 17 00:00:00 2001 From: Ying Gao Date: Sat, 8 Feb 2025 19:15:03 +0800 Subject: [PATCH 10/29] Remove return val --- docs/dev/Lua API.rst | 2 +- library/include/modules/Military.h | 2 +- library/modules/Military.cpp | 35 ++++++++++++++---------------- 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 4cc2c35d06..66516642a9 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -1988,7 +1988,7 @@ Military module * ``dfhack.military.removeFromSquad(unit_id)`` - Removes a unit from its squad and returns true if successful. Unsets the unit's + Removes a unit from its squad. Unsets the unit's military information (i.e., ``unit.military.squad_id`` and ``unit.military.squad_pos``), the squad's position information (i.e., ``squad.positions[squad_pos].occupant``), and modifies the unit's entity links diff --git a/library/include/modules/Military.h b/library/include/modules/Military.h index dc69dac52b..37855d94db 100644 --- a/library/include/modules/Military.h +++ b/library/include/modules/Military.h @@ -17,7 +17,7 @@ namespace Military DFHACK_EXPORT std::string getSquadName(int32_t squad_id); DFHACK_EXPORT df::squad* makeSquad(int32_t assignment_id); DFHACK_EXPORT void updateRoomAssignments(int32_t squad_id, int32_t civzone_id, df::squad_use_flags flags); -DFHACK_EXPORT bool removeFromSquad(int32_t unit_id); +DFHACK_EXPORT void removeFromSquad(int32_t unit_id); } } diff --git a/library/modules/Military.cpp b/library/modules/Military.cpp index 62d189c4d7..9e507a99aa 100644 --- a/library/modules/Military.cpp +++ b/library/modules/Military.cpp @@ -296,7 +296,7 @@ void Military::updateRoomAssignments(int32_t squad_id, int32_t civzone_id, df::s } } -static bool remove_soldier_entity_link(df::historical_figure* hf, df::squad* squad) +static void remove_soldier_entity_link(df::historical_figure* hf, df::squad* squad) { int32_t start_year = -1; for (size_t i = 0; i < hf->entity_links.size(); i++) @@ -317,7 +317,7 @@ static bool remove_soldier_entity_link(df::historical_figure* hf, df::squad* squ } if (start_year == -1) - return false; + return; auto former_squad = df::allocate(); former_squad->squad_id = squad->id; @@ -327,14 +327,13 @@ static bool remove_soldier_entity_link(df::historical_figure* hf, df::squad* squ former_squad->link_strength = 100; hf->entity_links.push_back(former_squad); - return true; } -static bool remove_officer_entity_link(df::historical_figure* hf, df::squad* squad) +static void remove_officer_entity_link(df::historical_figure* hf, df::squad* squad) { std::vector nps; if (!Units::getNoblePositions(&nps, hf)) - return false; + return; int32_t assignment_id = -1; for (auto& np : nps) @@ -350,7 +349,7 @@ static bool remove_officer_entity_link(df::historical_figure* hf, df::squad* squ } if (assignment_id == -1) - return false; + return; int32_t start_year = -1; for (size_t i = 0; i < hf->entity_links.size(); i++) @@ -373,7 +372,7 @@ static bool remove_officer_entity_link(df::historical_figure* hf, df::squad* squ } if (start_year == -1) - return false; + return; auto former_pos = df::allocate(); former_pos->assignment_id = assignment_id; @@ -383,27 +382,24 @@ static bool remove_officer_entity_link(df::historical_figure* hf, df::squad* squ former_pos->link_strength = 100; hf->entity_links.push_back(former_pos); - return true; } -bool Military::removeFromSquad(int32_t unit_id) +void Military::removeFromSquad(int32_t unit_id) { df::unit *unit = df::unit::find(unit_id); - if (unit == nullptr) - return false; - if (unit->military.squad_id == -1 || unit->military.squad_position == -1) - return false; + if (unit == nullptr || unit->military.squad_id == -1 || unit->military.squad_position == -1) + return; int32_t squad_id = unit->military.squad_id; df::squad* squad = df::squad::find(squad_id); if (squad == nullptr) - return false; + return; // remove from squad information int32_t squad_pos = unit->military.squad_position; df::squad_position* pos = vector_get(squad->positions, squad_pos); if (pos == nullptr) - return false; + return; // remove from squad information pos->occupant = -1; @@ -413,9 +409,10 @@ bool Military::removeFromSquad(int32_t unit_id) df::historical_figure* hf = df::historical_figure::find(unit->hist_figure_id); if (hf == nullptr) - return false; + return;; - return squad_pos == 0 // is unit a commander? - ? remove_officer_entity_link(hf, squad) - : remove_soldier_entity_link(hf, squad); + if (squad_pos == 0) // is unit a commander? + remove_officer_entity_link(hf, squad); + else + remove_soldier_entity_link(hf, squad); } From 6d44e8f8f0e1eb0cd7b9a42c29dbfa8309d081f5 Mon Sep 17 00:00:00 2001 From: Ying Gao Date: Sun, 9 Feb 2025 12:51:12 +0800 Subject: [PATCH 11/29] Change return type of Military::removeFromSquad --- library/include/modules/Military.h | 2 +- library/modules/Military.cpp | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/library/include/modules/Military.h b/library/include/modules/Military.h index 37855d94db..dc69dac52b 100644 --- a/library/include/modules/Military.h +++ b/library/include/modules/Military.h @@ -17,7 +17,7 @@ namespace Military DFHACK_EXPORT std::string getSquadName(int32_t squad_id); DFHACK_EXPORT df::squad* makeSquad(int32_t assignment_id); DFHACK_EXPORT void updateRoomAssignments(int32_t squad_id, int32_t civzone_id, df::squad_use_flags flags); -DFHACK_EXPORT void removeFromSquad(int32_t unit_id); +DFHACK_EXPORT bool removeFromSquad(int32_t unit_id); } } diff --git a/library/modules/Military.cpp b/library/modules/Military.cpp index 9e507a99aa..3c5708d75e 100644 --- a/library/modules/Military.cpp +++ b/library/modules/Military.cpp @@ -384,22 +384,25 @@ static void remove_officer_entity_link(df::historical_figure* hf, df::squad* squ hf->entity_links.push_back(former_pos); } -void Military::removeFromSquad(int32_t unit_id) +bool Military::removeFromSquad(int32_t unit_id) { df::unit *unit = df::unit::find(unit_id); if (unit == nullptr || unit->military.squad_id == -1 || unit->military.squad_position == -1) - return; + return false; int32_t squad_id = unit->military.squad_id; df::squad* squad = df::squad::find(squad_id); if (squad == nullptr) - return; + return false; - // remove from squad information int32_t squad_pos = unit->military.squad_position; df::squad_position* pos = vector_get(squad->positions, squad_pos); if (pos == nullptr) - return; + return false; + + df::historical_figure* hf = df::historical_figure::find(unit->hist_figure_id); + if (hf == nullptr) + return false; // remove from squad information pos->occupant = -1; @@ -407,12 +410,10 @@ void Military::removeFromSquad(int32_t unit_id) unit->military.squad_id = -1; unit->military.squad_position = -1; - df::historical_figure* hf = df::historical_figure::find(unit->hist_figure_id); - if (hf == nullptr) - return;; - if (squad_pos == 0) // is unit a commander? remove_officer_entity_link(hf, squad); else remove_soldier_entity_link(hf, squad); + + return true; } From c21740929a56691be26401c56cf5ea0ba6df04a7 Mon Sep 17 00:00:00 2001 From: DFHack-Urist via GitHub Actions <63161697+DFHack-Urist@users.noreply.github.com> Date: Sun, 9 Feb 2025 07:15:07 +0000 Subject: [PATCH 12/29] Auto-update submodules plugins/stonesense: master --- plugins/stonesense | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/stonesense b/plugins/stonesense index 1756e2f3f7..92794aec77 160000 --- a/plugins/stonesense +++ b/plugins/stonesense @@ -1 +1 @@ -Subproject commit 1756e2f3f704a0d01b24feccd0089972c245c164 +Subproject commit 92794aec7768bdafd0f5fc23fed8b30655805b32 From 3844957820893c92bd1cf97cac617f7ef5e451bb Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 9 Feb 2025 00:55:35 -0800 Subject: [PATCH 13/29] refactor announcement settings logic --- plugins/spectate.cpp | 141 +++++++++++++++++++++++-------------------- 1 file changed, 77 insertions(+), 64 deletions(-) diff --git a/plugins/spectate.cpp b/plugins/spectate.cpp index ae33031b14..0871e4754c 100644 --- a/plugins/spectate.cpp +++ b/plugins/spectate.cpp @@ -33,42 +33,8 @@ namespace DFHack { } static uint32_t next_cycle_unpaused_ms = 0; // threshold for the next cycle -static bool was_in_settings = false; // whether we were in the vanilla settings screen last update -static const size_t announcement_flag_arr_size = sizeof(decltype(df::announcements::flags)) / sizeof(df::announcement_flags); -static std::unique_ptr saved_announcement_settings; - -static void save_announcement_settings(color_ostream &out) { - if (!saved_announcement_settings) - saved_announcement_settings = std::make_unique(new uint32_t[announcement_flag_arr_size]); - DEBUG(control,out).print("saving announcement settings\n"); - for (size_t i = 0; i < announcement_flag_arr_size; ++i) - (*saved_announcement_settings)[i] = d_init->announcements.flags[i].whole; -} - -static void restore_announcement_settings(color_ostream &out) { - if (!saved_announcement_settings) - return; - DEBUG(control,out).print("restoring saved announcement settings\n"); - for (size_t i = 0; i < announcement_flag_arr_size; ++i) - d_init->announcements.flags[i].whole = (*saved_announcement_settings)[i]; -} - -static void scrub_announcements(color_ostream &out) { - if (Gui::matchFocusString("dwarfmode/Settings")) { - DEBUG(control,out).print("not modifying announcement settings; vanilla settings screen is active\n"); - return; - } - - DEBUG(control,out).print("removing PAUSE from announcement settings\n"); - for (auto& flag : d_init->announcements.flags) { - flag.bits.DO_MEGA = false; - flag.bits.PAUSE = false; - flag.bits.RECENTER = false; - } -} - -struct Configuration { +static struct Configuration { bool auto_disengage; bool auto_unpause; bool cinematic_action; @@ -94,6 +60,75 @@ struct Configuration { } } config; +static class AnnouncementSettings { + bool was_in_settings = false; // whether we were in the vanilla settings screen last update + + const size_t announcement_flag_arr_size = sizeof(decltype(df::announcements::flags)) / sizeof(df::announcement_flags); + std::unique_ptr saved; + + void save_settings(color_ostream &out) { + if (!saved) + saved = std::make_unique(new uint32_t[announcement_flag_arr_size]); + DEBUG(control,out).print("saving announcement settings\n"); + for (size_t i = 0; i < announcement_flag_arr_size; ++i) + (*saved)[i] = d_init->announcements.flags[i].whole; + } + +public: + void reset(color_ostream &out, bool skip_restore = false) { + was_in_settings = false; + + if (saved) { + if (!skip_restore) + restore_settings(out); + delete[] *saved; + saved.reset(); + } + } + + void on_update(color_ostream &out) { + if (Gui::matchFocusString("dwarfmode/Settings")) { + if (!was_in_settings) { + DEBUG(cycle,out).print("settings screen active; restoring announcement settings\n"); + restore_settings(out); + was_in_settings = true; + } + } else if (was_in_settings) { + was_in_settings = false; + if (config.auto_unpause) { + DEBUG(cycle,out).print("settings screen now inactive; disabling announcement pausing\n"); + save_and_scrub_settings(out); + } + } + } + + void restore_settings(color_ostream &out) { + if (!saved || was_in_settings) + return; + DEBUG(control,out).print("restoring saved announcement settings\n"); + for (size_t i = 0; i < announcement_flag_arr_size; ++i) + d_init->announcements.flags[i].whole = (*saved)[i]; + } + + // remove pausing, popups, and recentering from all announcements + // saves first so the original settings can be restored + void save_and_scrub_settings(color_ostream &out) { + if (Gui::matchFocusString("dwarfmode/Settings")) { + DEBUG(control,out).print("not modifying announcement settings; vanilla settings screen is active\n"); + return; + } + + save_settings(out); + + DEBUG(control,out).print("scrubbing announcement settings\n"); + for (auto& flag : d_init->announcements.flags) { + flag.bits.DO_MEGA = false; + flag.bits.PAUSE = false; + flag.bits.RECENTER = false; + } + } +} announcement_settings; + static command_result do_command(color_ostream &out, vector ¶meters); static void follow_a_dwarf(color_ostream &out); @@ -108,14 +143,6 @@ DFhackCExport command_result plugin_init(color_ostream &out, std::vector follow_unit = -1; - cleanup(out); + announcement_settings.reset(out); } } else { DEBUG(control,out).print("%s from the API, but already %s; no action\n", @@ -148,7 +175,7 @@ DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) { DFhackCExport command_result plugin_shutdown (color_ostream &out) { DEBUG(control,out).print("shutting down %s\n", plugin_name); - cleanup(out); + announcement_settings.reset(out); return CR_OK; } @@ -162,7 +189,7 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan DEBUG(control,out).print("world unloaded; disabling %s\n", plugin_name); is_enabled = false; - cleanup(out); + announcement_settings.reset(out, true); } break; default: @@ -172,25 +199,12 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan } DFhackCExport command_result plugin_onupdate(color_ostream &out) { - if (Gui::matchFocusString("dwarfmode/Settings")) { - if (!was_in_settings) { - DEBUG(cycle,out).print("settings screen active; restoring announcement settings\n"); - restore_announcement_settings(out); - was_in_settings = true; - } - } else if (was_in_settings) { - was_in_settings = false; - if (config.auto_unpause) { - DEBUG(cycle,out).print("settings screen now inactive; disabling announcement pausing\n"); - save_announcement_settings(out); - scrub_announcements(out); - } - } + announcement_settings.on_update(out); if (config.auto_disengage && plotinfo->follow_unit < 0) { DEBUG(cycle,out).print("auto-disengage triggered\n"); is_enabled = false; - cleanup(out); + announcement_settings.reset(out); return CR_OK; } @@ -354,10 +368,9 @@ static void spectate_setSetting(color_ostream &out, string name, int val) { config.auto_disengage = val; } else if (name == "auto-unpause") { if (val && !config.auto_unpause) { - save_announcement_settings(out); - scrub_announcements(out); + announcement_settings.save_and_scrub_settings(out); } else if (!val && config.auto_unpause) { - restore_announcement_settings(out); + announcement_settings.restore_settings(out); } config.auto_unpause = val; } else if (name == "cinematic-action") { From 2daa28790b5b3dc3e7a052ec61d4768d5350c380 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 9 Feb 2025 02:28:45 -0800 Subject: [PATCH 14/29] implement follow history and zoom to/highlight unit when switching targets when paused --- plugins/spectate.cpp | 92 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 87 insertions(+), 5 deletions(-) diff --git a/plugins/spectate.cpp b/plugins/spectate.cpp index 0871e4754c..a3e3c86193 100644 --- a/plugins/spectate.cpp +++ b/plugins/spectate.cpp @@ -2,6 +2,7 @@ #include "LuaTools.h" #include "PluginLua.h" #include "PluginManager.h" +#include "VTableInterpose.h" #include "modules/Gui.h" #include "modules/Units.h" @@ -11,6 +12,7 @@ #include "df/d_init.h" #include "df/plotinfost.h" #include "df/unit.h" +#include "df/viewscreen_dwarfmodest.h" #include "df/world.h" #include @@ -34,6 +36,8 @@ namespace DFHack { static uint32_t next_cycle_unpaused_ms = 0; // threshold for the next cycle +static const size_t MAX_HISTORY = 200; + static struct Configuration { bool auto_disengage; bool auto_unpause; @@ -129,6 +133,77 @@ static class AnnouncementSettings { } } announcement_settings; +static void follow_a_dwarf(color_ostream &out); + +static class UnitHistory { + std::deque history; + size_t offset = 0; + +public: + void reset() { + history.clear(); + offset = 0; + } + + void add(color_ostream &out, df::unit *unit) { + int32_t id = unit->id; + DEBUG(cycle,out).print("now following unit %d: %s\n", id, DF2CONSOLE(Units::getReadableName(unit)).c_str()); + Gui::revealInDwarfmodeMap(Units::getPosition(unit), false, World::ReadPauseState()); + plotinfo->follow_unit = id; + if (offset > 0) { + DEBUG(cycle,out).print("trimming history forward of offset %zd\n", offset); + history.resize(history.size() - offset); + offset = 0; + } + history.push_back(id); + if (history.size() > MAX_HISTORY) { + DEBUG(cycle,out).print("history full, truncating\n"); + history.pop_front(); + } + DEBUG(cycle,out).print("history now has %zd entries\n", history.size()); + } + + void scan_back(color_ostream &out) { + if (history.empty() || offset >= history.size()-1) + return; + int unit_id = history[history.size() - (1 + ++offset)]; + DEBUG(cycle,out).print("scanning back to unit %d at offset %zd\n", unit_id, offset); + if (auto unit = df::unit::find(unit_id)) + Gui::revealInDwarfmodeMap(Units::getPosition(unit), false, World::ReadPauseState()); + plotinfo->follow_unit = unit_id; + } + + void scan_forward(color_ostream &out) { + if (history.empty() || offset == 0) { + DEBUG(cycle,out).print("already at most recent unit; following new unit\n"); + follow_a_dwarf(out); + return; + } + + int unit_id = history[history.size() - (1 + --offset)]; + DEBUG(cycle,out).print("scanning forward to unit %d at offset %zd\n", unit_id, offset); + if (auto unit = df::unit::find(unit_id)) + Gui::revealInDwarfmodeMap(Units::getPosition(unit), false, World::ReadPauseState()); + plotinfo->follow_unit = unit_id; + } +} unit_history; + +struct forward_back_interceptor : df::viewscreen_dwarfmodest { + typedef df::viewscreen_dwarfmodest interpose_base; + + DEFINE_VMETHOD_INTERPOSE(void, feed, (std::set *input)) { + bool is_at_default_view = Gui::matchFocusString("dwarfmode/Default", Gui::getDFViewscreen()); + if (is_at_default_view && input->count(df::interface_key::CUSTOM_LEFT)) + unit_history.scan_back(Core::getInstance().getConsole()); + else if (is_at_default_view && input->count(df::interface_key::CUSTOM_RIGHT)) + unit_history.scan_forward(Core::getInstance().getConsole()); + else { + INTERPOSE_NEXT(feed)(input); + } + } +}; +IMPLEMENT_VMETHOD_INTERPOSE(forward_back_interceptor, feed); + static command_result do_command(color_ostream &out, vector ¶meters); static void follow_a_dwarf(color_ostream &out); @@ -143,6 +218,11 @@ DFhackCExport command_result plugin_init(color_ostream &out, std::vector follow_unit = -1; - announcement_settings.reset(out); + on_disable(out); + // don't reset the unit history since we may want to re-enable } } else { DEBUG(control,out).print("%s from the API, but already %s; no action\n", @@ -175,7 +257,7 @@ DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) { DFhackCExport command_result plugin_shutdown (color_ostream &out) { DEBUG(control,out).print("shutting down %s\n", plugin_name); - announcement_settings.reset(out); + on_disable(out); return CR_OK; } @@ -190,6 +272,7 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan plugin_name); is_enabled = false; announcement_settings.reset(out, true); + unit_history.reset(); } break; default: @@ -204,7 +287,7 @@ DFhackCExport command_result plugin_onupdate(color_ostream &out) { if (config.auto_disengage && plotinfo->follow_unit < 0) { DEBUG(cycle,out).print("auto-disengage triggered\n"); is_enabled = false; - announcement_settings.reset(out); + on_disable(out); return CR_OK; } @@ -353,8 +436,7 @@ static void follow_a_dwarf(color_ostream &out) { DEBUG(cycle,out).print("selected unit idx %d\n", unit_idx); } - DEBUG(cycle,out).print("now following unit %d: %s\n", unit->id, Units::getReadableName(unit).c_str()); - plotinfo->follow_unit = unit->id; + unit_history.add(out, unit); } ///////////////////////////////////////////////////// From 82e014dd6791d2e8046ea9a15c84f258876a407b Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 9 Feb 2025 02:55:03 -0800 Subject: [PATCH 15/29] auto-disengage when the squads menu is opened --- docs/plugins/spectate.rst | 6 +++--- plugins/lua/spectate.lua | 15 +++++++++++++++ plugins/spectate.cpp | 23 +++++++++++++++++------ 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/docs/plugins/spectate.rst b/docs/plugins/spectate.rst index f49849c850..d0b5c8f04e 100644 --- a/docs/plugins/spectate.rst +++ b/docs/plugins/spectate.rst @@ -13,9 +13,9 @@ to following a different dwarf. It can also switch to following animals, hostiles, or visiting units. You can switch to the next target (or a previous target) immediately with the left/right arrow keys. -`spectate` will disengage and turn itself off when you move the map, just like -the vanilla follow mechanic. It will also disengage immediately if you open the -squads menu for military action. +By default, `spectate` will disengage and turn itself off when you move the +map, just like the vanilla follow mechanic. It will also disengage immediately +if you open the squads menu for military action. It can also annotate your dwarves on the map with their name, job, and other information, either as floating tooltips or in a panel that comes up when you diff --git a/plugins/lua/spectate.lua b/plugins/lua/spectate.lua index ba7e9ba7ba..e21016329f 100644 --- a/plugins/lua/spectate.lua +++ b/plugins/lua/spectate.lua @@ -1,6 +1,7 @@ local _ENV = mkmodule('plugins.spectate') local argparse = require('argparse') +local dlg = require('gui.dialogs') local json = require('json') local overlay = require('plugins.overlay') local utils = require('utils') @@ -55,6 +56,20 @@ function refresh_cpp_config() end end +function show_squads_warning() + local message = { + 'Cannot start spectate mode while auto-disengage is enabled and', + 'the squads panel is open. The auto-disengage feature automatically', + 'stops spectate mode when you open the squads panel.', + '', + 'Please either close the squads panel or disable auto-disengage by', + 'running the following command:', + '', + 'spectate set auto-disengage false', + } + dlg.showMessage("Spectate", table.concat(message, '\n')) +end + ----------------------------- -- commandline interface diff --git a/plugins/spectate.cpp b/plugins/spectate.cpp index a3e3c86193..67a841ed6a 100644 --- a/plugins/spectate.cpp +++ b/plugins/spectate.cpp @@ -79,7 +79,7 @@ static class AnnouncementSettings { } public: - void reset(color_ostream &out, bool skip_restore = false) { + void reset(color_ostream &out, bool skip_restore) { was_in_settings = false; if (saved) { @@ -218,9 +218,13 @@ DFhackCExport command_result plugin_init(color_ostream &out, std::vector follow_unit < 0) { + if (config.auto_disengage && (plotinfo->follow_unit < 0 || is_squads_open())) { DEBUG(cycle,out).print("auto-disengage triggered\n"); is_enabled = false; + plotinfo->follow_unit = -1; on_disable(out); return CR_OK; } From 8b28be61602c7c86baff4960024069253b9f2744 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 9 Feb 2025 03:29:50 -0800 Subject: [PATCH 16/29] first part of prefer recent units feature --- plugins/spectate.cpp | 80 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 10 deletions(-) diff --git a/plugins/spectate.cpp b/plugins/spectate.cpp index 67a841ed6a..c7f07b94ce 100644 --- a/plugins/spectate.cpp +++ b/plugins/spectate.cpp @@ -38,6 +38,17 @@ static uint32_t next_cycle_unpaused_ms = 0; // threshold for the next cycle static const size_t MAX_HISTORY = 200; +static const float ACTIVE_COMBAT_PREFERRED_WEIGHT = 25.0f; +static const float PASSIVE_COMBAT_PREFERRED_WEIGHT = 8.0f; +static const float JOB_WEIGHT = 3.0f; +static const float OTHER_WEIGHT = 1.0f; + +static const float RECENT_UNIT_MULTIPLIER = 2.0f; +static const int32_t RECENT_UNIT_MS = 15 * 60 * 1000; // 15 minutes + +///////////////////////////////////////////////////// +// Configuration + static struct Configuration { bool auto_disengage; bool auto_unpause; @@ -64,6 +75,9 @@ static struct Configuration { } } config; +///////////////////////////////////////////////////// +// AnnouncementSettings + static class AnnouncementSettings { bool was_in_settings = false; // whether we were in the vanilla settings screen last update @@ -133,6 +147,9 @@ static class AnnouncementSettings { } } announcement_settings; +///////////////////////////////////////////////////// +// UnitHistory + static void follow_a_dwarf(color_ostream &out); static class UnitHistory { @@ -204,6 +221,37 @@ struct forward_back_interceptor : df::viewscreen_dwarfmodest { }; IMPLEMENT_VMETHOD_INTERPOSE(forward_back_interceptor, feed); +///////////////////////////////////////////////////// +// RecentUnits + +static class RecentUnits { + std::unordered_map units; // unit id -> time seen +public: + void add(int32_t unit_id) { + units[unit_id] = Core::getInstance().getUnpausedMs(); + } + + bool contains(int32_t unit_id) { + return units.contains(unit_id); + } + + void trim() { + uint32_t unpaused_ms = Core::getInstance().getUnpausedMs(); + if (unpaused_ms < RECENT_UNIT_MS) + return; + uint32_t cutoff = unpaused_ms - RECENT_UNIT_MS; + for (auto it = units.begin(); it != units.end();) { + if (it->second < cutoff) + it = units.erase(it); + else + ++it; + } + } +} recent_units; + +///////////////////////////////////////////////////// +// plugin API + static command_result do_command(color_ostream &out, vector ¶meters); static void follow_a_dwarf(color_ostream &out); @@ -321,7 +369,6 @@ static command_result do_command(color_ostream &out, vector ¶meters) ///////////////////////////////////////////////////// // cycle logic -// static bool is_in_combat(df::unit *unit) { return false; @@ -370,17 +417,18 @@ static void get_dwarf_buckets(color_ostream &out, static std::default_random_engine rng; -static uint32_t get_next_cycle_unpaused_ms(bool has_active_combat) { +static uint32_t get_next_cycle_unpaused_ms(color_ostream &out, bool has_active_combat) { int32_t delay_ms = config.follow_ms; if (has_active_combat) { std::normal_distribution distribution(config.follow_ms / 2, config.follow_ms / 6); int32_t delay_ms = distribution(rng); delay_ms = std::min(config.follow_ms, std::max(1, delay_ms)); } + DEBUG(cycle,out).print("next cycle in %d ms\n", delay_ms); return Core::getInstance().getUnpausedMs() + delay_ms; } -static void add_bucket(const vector &bucket, vector &units, vector &intervals, vector &weights, float weight) { +static void add_bucket_to_vectors(const vector &bucket, vector &units, vector &intervals, vector &weights, float weight) { if (bucket.empty()) return; intervals.push_back(units.size() + bucket.size()); @@ -388,6 +436,24 @@ static void add_bucket(const vector &bucket, vector &units units.insert(units.end(), bucket.begin(), bucket.end()); } +static void add_bucket(const vector &bucket, vector &units, vector &intervals, vector &weights, float weight) { + if (bucket.empty()) + return; + if (config.prefer_new_arrivals) { + vector new_bucket, old_bucket; + for (auto unit : bucket) { + if (recent_units.contains(unit->id)) + new_bucket.push_back(unit); + else + old_bucket.push_back(unit); + } + add_bucket_to_vectors(new_bucket, units, intervals, weights, weight * RECENT_UNIT_MULTIPLIER); + add_bucket_to_vectors(old_bucket, units, intervals, weights, weight); + } else { + add_bucket_to_vectors(bucket, units, intervals, weights, weight); + } +} + #define DUMP_BUCKET(name) \ DEBUG(cycle,out).print("bucket: " #name ", size: %zd\n", name.size()); \ if (debug_cycle.isEnabled(DebugCategory::LTRACE)) { \ @@ -402,11 +468,6 @@ static void add_bucket(const vector &bucket, vector &units DEBUG(cycle,out).print(" %d\n", (int)f); \ } -static const float ACTIVE_COMBAT_PREFERRED_WEIGHT = 25.0f; -static const float PASSIVE_COMBAT_PREFERRED_WEIGHT = 8.0f; -static const float JOB_WEIGHT = 3.0f; -static const float OTHER_WEIGHT = 1.0f; - static void follow_a_dwarf(color_ostream &out) { DEBUG(cycle,out).print("choosing a unit to follow\n"); @@ -416,7 +477,7 @@ static void follow_a_dwarf(color_ostream &out) { vector other_units; get_dwarf_buckets(out, active_combat_units, passive_combat_units, job_units, other_units); - next_cycle_unpaused_ms = get_next_cycle_unpaused_ms(!active_combat_units.empty()); + next_cycle_unpaused_ms = get_next_cycle_unpaused_ms(out, !active_combat_units.empty()); // coalesce the buckets and add weights vector units; @@ -452,7 +513,6 @@ static void follow_a_dwarf(color_ostream &out) { ///////////////////////////////////////////////////// // Lua API -// static void spectate_setSetting(color_ostream &out, string name, int val) { DEBUG(control,out).print("entering spectate_setSetting %s = %d\n", name.c_str(), val); From ae305971aad0eba85af8f5760e1a39d8ab7c0e85 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 9 Feb 2025 03:31:04 -0800 Subject: [PATCH 17/29] only intercept arrow keys when the map has focus --- plugins/spectate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/spectate.cpp b/plugins/spectate.cpp index c7f07b94ce..94c5adb23f 100644 --- a/plugins/spectate.cpp +++ b/plugins/spectate.cpp @@ -209,7 +209,7 @@ struct forward_back_interceptor : df::viewscreen_dwarfmodest { typedef df::viewscreen_dwarfmodest interpose_base; DEFINE_VMETHOD_INTERPOSE(void, feed, (std::set *input)) { - bool is_at_default_view = Gui::matchFocusString("dwarfmode/Default", Gui::getDFViewscreen()); + bool is_at_default_view = Gui::matchFocusString("dwarfmode/Default"); if (is_at_default_view && input->count(df::interface_key::CUSTOM_LEFT)) unit_history.scan_back(Core::getInstance().getConsole()); else if (is_at_default_view && input->count(df::interface_key::CUSTOM_RIGHT)) From ea4b2a2e7a3fd498b986019ba21d219688328fe3 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 9 Feb 2025 03:39:55 -0800 Subject: [PATCH 18/29] collapse two overlays to one since we don't have a good method to control which one gets rendered first --- docs/plugins/spectate.rst | 43 ++++++++++++++++----------------------- plugins/lua/spectate.lua | 29 +++++++------------------- 2 files changed, 24 insertions(+), 48 deletions(-) diff --git a/docs/plugins/spectate.rst b/docs/plugins/spectate.rst index d0b5c8f04e..3d20b1e665 100644 --- a/docs/plugins/spectate.rst +++ b/docs/plugins/spectate.rst @@ -37,7 +37,7 @@ Usage spectate [status] spectate toggle spectate set - spectate overlay enable|disable + spectate overlay enable|disable Examples -------- @@ -59,8 +59,9 @@ Examples ``spectate set follow-seconds 30`` Configure `spectate` to switch targets every 30 seconds when in follow mode. -``spectate overlay follow enable`` - Show informative tooltips that follow each unit on the map. +``spectate overlay enable`` + Show informative tooltips that follow each unit on the map. Note that this + can be enabled independently of `spectate` itself. Settings -------- @@ -68,7 +69,8 @@ Settings ``auto-disengage`` (default: enabled) Toggle automatically disabling the plugin when the player moves the map or opens the squad panel. If this is disabled, you will need to manually - disable the plugin to turn off follow mode. + disable the plugin to turn off follow mode. You can still interact normally + with the DF UI. ``auto-unpause`` (default: disabled) Toggle auto-dismissal of announcements that pause the game, like sieges, @@ -102,47 +104,36 @@ Settings arrived on the map. ``tooltip-follow-job`` (default: enabled) - If the ``spectate.follow`` overlay is enabled, toggle whether to show the + If the ``spectate.tooltip`` overlay is enabled, toggle whether to show the job of the dwarf in the tooltip. ``tooltip-follow-name`` (default: enabled) - If the ``spectate.follow`` overlay is enabled, toggle whether to show the + If the ``spectate.tooltip`` overlay is enabled, toggle whether to show the name of the dwarf in the tooltip. ``tooltip-follow-stress`` (default: enabled) - If the ``spectate.follow`` overlay is enabled, toggle whether to show the + If the ``spectate.tooltip`` overlay is enabled, toggle whether to show the happiness level (stress) of the dwarf in the tooltip. ``tooltip-hover-job`` (default: enabled) - If the ``spectate.follow`` overlay is enabled, toggle whether to show the + If the ``spectate.tooltip`` overlay is enabled, toggle whether to show the job of the dwarf in the hover panel. ``tooltip-hover-name`` (default: enabled) - If the ``spectate.follow`` overlay is enabled, toggle whether to show the + If the ``spectate.tooltip`` overlay is enabled, toggle whether to show the name of the dwarf in the hover panel. ``tooltip-hover-stress`` (default: enabled) - If the ``spectate.follow`` overlay is enabled, toggle whether to show the + If the ``spectate.tooltip`` overlay is enabled, toggle whether to show the happiness level (stress) of the dwarf in the hover panel. Overlays -------- -``spectate`` provides two overlays via the `overlay` framework to add -information and functionality to the main map. These overlays can be controlled -via the ``spectate overlay`` command or the ``Overlays`` tab in -`gui/control-panel`. +``spectate.tooltip`` -The information displayed by these overlays can be configured via the -``spectate set`` command or the `gui/spectate` interface. +``spectate`` can show informative tooltips that follow each unit on the map +and/or a popup panel with information when your mouse cursor hovers over a unit. -``spectate.follow`` - Show informative tooltips that follow each unit on the map. You can enable - this overlay by running ``spectate overlay follow enable`` or, - equivalently, ``overlay enable spectate.follow``. - -``spectate.hover`` - Show a popup panel with selected information when your mouse cursor hovers - over a unit. You can enable this overlay by running - ``spectate overlay hover enable`` or, equivalently, - ``overlay enable spectate.hover``. +This overlay is managed via the `overlay` framework. It can be controlled via +the ``spectate overlay`` command or the ``Overlays`` tab in `gui/control-panel`. diff --git a/plugins/lua/spectate.lua b/plugins/lua/spectate.lua index e21016329f..d44957dcb1 100644 --- a/plugins/lua/spectate.lua +++ b/plugins/lua/spectate.lua @@ -109,15 +109,9 @@ local function set_setting(key, value) end end -local function set_overlay(name, value) - if not name:startswith('spectate.') then - name = 'spectate.' .. name - end - if name ~= 'spectate.follow' and name ~= 'spectate.hover' then - qerror('unknown overlay: ' .. name) - end +local function set_overlay(value) value = argparse.boolean(value, name) - dfhack.run_command('overlay', value and 'enable' or 'disable', name) + dfhack.run_command('overlay', value and 'enable' or 'disable', 'spectate.tooltip') end function parse_commandline(args) @@ -129,7 +123,7 @@ function parse_commandline(args) elseif command == 'set' then set_setting(args[1], args[2]) elseif command == 'overlay' then - set_overlay(args[1], args[2]) + set_overlay(args[1]) else return false end @@ -140,25 +134,16 @@ end ----------------------------- -- overlays -FollowOverlay = defclass(FollowOverlay, overlay.OverlayWidget) -FollowOverlay.ATTRS{ - desc='Adds info tooltips that follow units on the map.', - default_pos={x=1,y=1}, - fullscreen=true, - viewscreens='dwarfmode/Default', -} - -HoverOverlay = defclass(HoverOverlay, overlay.OverlayWidget) -HoverOverlay.ATTRS{ - desc='Shows info popup when hovering the mouse over units on the map.', +TooltipOverlay = defclass(TooltipOverlay, overlay.OverlayWidget) +TooltipOverlay.ATTRS{ + desc='Adds info tooltips that follow units or appear when you hover the mouse.', default_pos={x=1,y=1}, fullscreen=true, viewscreens='dwarfmode/Default', } OVERLAY_WIDGETS = { - follow=FollowOverlay, - hover=HoverOverlay, + tooltip=TooltipOverlay, } return _ENV From 77bbe8c87815e218d5f9bdc2f175572c9c27bc72 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 9 Feb 2025 03:59:30 -0800 Subject: [PATCH 19/29] implement recent units preference --- plugins/spectate.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/plugins/spectate.cpp b/plugins/spectate.cpp index 94c5adb23f..abe0fffaf1 100644 --- a/plugins/spectate.cpp +++ b/plugins/spectate.cpp @@ -4,6 +4,7 @@ #include "PluginManager.h" #include "VTableInterpose.h" +#include "modules/EventManager.h" #include "modules/Gui.h" #include "modules/Units.h" #include "modules/World.h" @@ -32,6 +33,7 @@ REQUIRE_GLOBAL(world); namespace DFHack { DBG_DECLARE(spectate, control, DebugCategory::LINFO); DBG_DECLARE(spectate, cycle, DebugCategory::LINFO); + DBG_DECLARE(spectate, event, DebugCategory::LINFO); } static uint32_t next_cycle_unpaused_ms = 0; // threshold for the next cycle @@ -43,6 +45,7 @@ static const float PASSIVE_COMBAT_PREFERRED_WEIGHT = 8.0f; static const float JOB_WEIGHT = 3.0f; static const float OTHER_WEIGHT = 1.0f; +static const int32_t RECENT_UNITS_SCAN_CYCLE = 51; static const float RECENT_UNIT_MULTIPLIER = 2.0f; static const int32_t RECENT_UNIT_MS = 15 * 60 * 1000; // 15 minutes @@ -226,7 +229,12 @@ IMPLEMENT_VMETHOD_INTERPOSE(forward_back_interceptor, feed); static class RecentUnits { std::unordered_map units; // unit id -> time seen + public: + void reset() { + units.clear(); + } + void add(int32_t unit_id) { units[unit_id] = Core::getInstance().getUnpausedMs(); } @@ -249,6 +257,14 @@ static class RecentUnits { } } recent_units; +static void on_new_active_unit(color_ostream& out, void* data) { + int32_t unit_id = reinterpret_cast(data); + DEBUG(event,out).print("unit %d has arrived on map\n", unit_id); + recent_units.add(unit_id); +} + +static EventManager::EventHandler new_unit_handler(plugin_self, on_new_active_unit, RECENT_UNITS_SCAN_CYCLE); + ///////////////////////////////////////////////////// // plugin API @@ -267,6 +283,7 @@ DFhackCExport command_result plugin_init(color_ostream &out, std::vector follow_unit < 0) || Core::getInstance().getUnpausedMs() >= next_cycle_unpaused_ms) + if ((!config.auto_disengage && plotinfo->follow_unit < 0) || Core::getInstance().getUnpausedMs() >= next_cycle_unpaused_ms) { + recent_units.trim(); follow_a_dwarf(out); + } return CR_OK; } From a8ebea3c96af3a4909b6a34e817cb01cedb6cf93 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 9 Feb 2025 04:43:10 -0800 Subject: [PATCH 20/29] implement conflict detection and cinematic camera --- plugins/spectate.cpp | 67 ++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/plugins/spectate.cpp b/plugins/spectate.cpp index abe0fffaf1..b27db51460 100644 --- a/plugins/spectate.cpp +++ b/plugins/spectate.cpp @@ -13,6 +13,7 @@ #include "df/d_init.h" #include "df/plotinfost.h" #include "df/unit.h" +#include "df/activity_entry.h" #include "df/viewscreen_dwarfmodest.h" #include "df/world.h" @@ -40,14 +41,22 @@ static uint32_t next_cycle_unpaused_ms = 0; // threshold for the next cycle static const size_t MAX_HISTORY = 200; -static const float ACTIVE_COMBAT_PREFERRED_WEIGHT = 25.0f; -static const float PASSIVE_COMBAT_PREFERRED_WEIGHT = 8.0f; -static const float JOB_WEIGHT = 3.0f; +static const float CITIZEN_COMBAT_PREFERRED_WEIGHT = 25.0f; +static const float OTHER_COMBAT_PREFERRED_WEIGHT = 10.0f; +static const float JOB_WEIGHT = 5.0f; static const float OTHER_WEIGHT = 1.0f; static const int32_t RECENT_UNITS_SCAN_CYCLE = 51; -static const float RECENT_UNIT_MULTIPLIER = 2.0f; -static const int32_t RECENT_UNIT_MS = 15 * 60 * 1000; // 15 minutes +static const float RECENT_UNIT_MULTIPLIER = 2.0f; // weight multiplier for recent units +static const int32_t RECENT_UNIT_MS = 15 * 60 * 1000; // 15 minutes + +// jobs that get "other" weight instad of "job" weight +static const std::unordered_set boring_jobs = { + df::job_type::Eat, + df::job_type::Drink, + df::job_type::Sleep, +}; + ///////////////////////////////////////////////////// // Configuration @@ -392,25 +401,22 @@ static command_result do_command(color_ostream &out, vector ¶meters) // cycle logic static bool is_in_combat(df::unit *unit) { - return false; -} - -static bool is_fleeing(df::unit *unit) { + if (Units::isCrazed(unit) || unit->mood == df::mood_type::Berserk) + return true; + for (auto activity_id : unit->activities) { + auto activity = df::activity_entry::find(activity_id); + if (activity && activity->type == df::activity_entry_type::Conflict) + return true; + } return false; } static void get_dwarf_buckets(color_ostream &out, - vector &active_combat_units, - vector &passive_combat_units, + vector &citizen_combat_units, + vector &other_combat_units, vector &job_units, vector &other_units) { - static const std::unordered_set boring_jobs = { - df::job_type::Eat, - df::job_type::Drink, - df::job_type::Sleep, - }; - for (auto unit : world->units.active) { if (Units::isDead(unit) || !Units::isActive(unit) || unit->flags1.bits.caged || unit->flags1.bits.chained || Units::isHidden(unit)) continue; @@ -424,10 +430,11 @@ static void get_dwarf_buckets(color_ostream &out, continue; if (is_in_combat(unit)) { - if (is_fleeing(unit)) - passive_combat_units.push_back(unit); + INFO(cycle).print("unit %d is in combat: %s\n", unit->id, DF2CONSOLE(Units::getReadableName(unit)).c_str()); + if (Units::isCitizen(unit, true) || Units::isResident(unit, true)) + citizen_combat_units.push_back(unit); else - active_combat_units.push_back(unit); + other_combat_units.push_back(unit); } else if (unit->job.current_job && !boring_jobs.contains(unit->job.current_job->job_type)) { job_units.push_back(unit); } else { @@ -440,9 +447,9 @@ static std::default_random_engine rng; static uint32_t get_next_cycle_unpaused_ms(color_ostream &out, bool has_active_combat) { int32_t delay_ms = config.follow_ms; - if (has_active_combat) { + if (config.cinematic_action && has_active_combat) { std::normal_distribution distribution(config.follow_ms / 2, config.follow_ms / 6); - int32_t delay_ms = distribution(rng); + delay_ms = distribution(rng); delay_ms = std::min(config.follow_ms, std::max(1, delay_ms)); } DEBUG(cycle,out).print("next cycle in %d ms\n", delay_ms); @@ -492,21 +499,21 @@ static void add_bucket(const vector &bucket, vector &units static void follow_a_dwarf(color_ostream &out) { DEBUG(cycle,out).print("choosing a unit to follow\n"); - vector active_combat_units; - vector passive_combat_units; + vector citizen_combat_units; + vector other_combat_units; vector job_units; vector other_units; - get_dwarf_buckets(out, active_combat_units, passive_combat_units, job_units, other_units); + get_dwarf_buckets(out, citizen_combat_units, other_combat_units, job_units, other_units); - next_cycle_unpaused_ms = get_next_cycle_unpaused_ms(out, !active_combat_units.empty()); + next_cycle_unpaused_ms = get_next_cycle_unpaused_ms(out, !citizen_combat_units.empty()); // coalesce the buckets and add weights vector units; vector intervals; vector weights; intervals.push_back(0); - add_bucket(active_combat_units, units, intervals, weights, config.prefer_conflict ? ACTIVE_COMBAT_PREFERRED_WEIGHT : JOB_WEIGHT); - add_bucket(passive_combat_units, units, intervals, weights, config.prefer_conflict ? PASSIVE_COMBAT_PREFERRED_WEIGHT : JOB_WEIGHT); + add_bucket(citizen_combat_units, units, intervals, weights, config.prefer_conflict ? CITIZEN_COMBAT_PREFERRED_WEIGHT : JOB_WEIGHT); + add_bucket(other_combat_units, units, intervals, weights, config.prefer_conflict ? OTHER_COMBAT_PREFERRED_WEIGHT : JOB_WEIGHT); add_bucket(job_units, units, intervals, weights, JOB_WEIGHT); add_bucket(other_units, units, intervals, weights, OTHER_WEIGHT); @@ -520,8 +527,8 @@ static void follow_a_dwarf(color_ostream &out) { df::unit *unit = units[unit_idx]; if (debug_cycle.isEnabled(DebugCategory::LDEBUG)) { - DUMP_BUCKET(active_combat_units); - DUMP_BUCKET(passive_combat_units); + DUMP_BUCKET(citizen_combat_units); + DUMP_BUCKET(other_combat_units); DUMP_BUCKET(job_units); DUMP_BUCKET(other_units); DUMP_FLOAT_VECTOR(intervals); From ab263e4755bd39aafa8ed5795860f689dd7f2e0f Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 9 Feb 2025 04:47:47 -0800 Subject: [PATCH 21/29] clarify function of include-animals setting --- docs/plugins/spectate.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/plugins/spectate.rst b/docs/plugins/spectate.rst index 3d20b1e665..b4d913d9e0 100644 --- a/docs/plugins/spectate.rst +++ b/docs/plugins/spectate.rst @@ -84,7 +84,7 @@ Settings include time that the game is paused. ``include-animals`` (default: disabled) - Toggle whether to sometimes follow fort animals. + Toggle whether to sometimes follow fort animals and wildlife. ``include-hostiles`` (default: disabled) Toggle whether to sometimes follow hostiles (eg. undead, titans, invaders, From fa8550427d3516bffe2f646c204938022db64326 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 9 Feb 2025 12:30:24 -0800 Subject: [PATCH 22/29] protect chained units from autobutcher --- docs/changelog.txt | 1 + docs/plugins/autobutcher.rst | 1 + plugins/autobutcher.cpp | 5 +++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index 36315052f7..3e5fa6ad90 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -67,6 +67,7 @@ Template for new versions: ## Misc Improvements - `spectate`: player-set configuration is now stored globally instead of per-fort +- `autobutcher`: treat animals on restraints as unavailable for slaughter ## Documentation - `stonesense-art-guide`: new guide for making sprite art for Stonesense diff --git a/docs/plugins/autobutcher.rst b/docs/plugins/autobutcher.rst index b429f57542..f7bea4d6d9 100644 --- a/docs/plugins/autobutcher.rst +++ b/docs/plugins/autobutcher.rst @@ -15,6 +15,7 @@ Units are protected from being automatically butchered if they are: * Untamed * Named or nicknamed * Caged, if and only if the cage is in a zone (to protect zoos) +* On a restraint * Trained for war or hunting * Females who are pregnant or brooding a clutch of fertile eggs diff --git a/plugins/autobutcher.cpp b/plugins/autobutcher.cpp index 9e93018cc9..8fde1cc347 100644 --- a/plugins/autobutcher.cpp +++ b/plugins/autobutcher.cpp @@ -666,9 +666,10 @@ static bool isProtectedUnit(df::unit *unit) { || Units::isHunter(unit) // ignore hunting dogs etc || Units::isMarkedForWarTraining(unit) // ignore units marked for any kind of training || Units::isMarkedForHuntTraining(unit) - // ignore creatures in built cages which are defined as rooms to leave zoos alone + || unit->flags1.bits.chained // ignore chained animals + // ignore creatures in built cages which are members of zones to leave zoos alone // (TODO: better solution would be to allow some kind of slaughter cages which you can place near the butcher) - || (isContainedInItem(unit) && isInBuiltCageRoom(unit)) // !!! see comments in isBuiltCageRoom() + || (isContainedInItem(unit) && isInBuiltCageRoom(unit)) || (unit->pregnancy_timer != 0) // do not butcher pregnant animals (which includes brooding female egglayers) || Units::isAvailableForAdoption(unit) || unit->name.has_name From eed96caeeea7f8ce1729c41ab7c3b4f89d1199f4 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sat, 8 Feb 2025 07:34:55 -0800 Subject: [PATCH 23/29] update to great reorg structures --- library/LuaApi.cpp | 5 +- library/RemoteTools.cpp | 2 +- .../df/custom/creature_handler.methods.inc | 2 +- library/include/modules/Buildings.h | 5 +- library/include/modules/Items.h | 2 +- library/include/modules/Job.h | 2 +- library/include/modules/MapCache.h | 2 +- library/modules/Buildings.cpp | 119 +++++++++--------- library/modules/Gui.cpp | 5 +- library/modules/Items.cpp | 21 ++-- library/modules/Job.cpp | 10 +- library/modules/Maps.cpp | 16 +-- library/modules/Materials.cpp | 18 +-- library/modules/Military.cpp | 35 +++--- library/modules/Units.cpp | 13 +- plugins/3dveins.cpp | 2 +- plugins/blueprint.cpp | 2 +- plugins/buildingplan/buildingplan.cpp | 4 +- plugins/buildingplan/buildingplan_cycle.cpp | 2 +- plugins/cursecheck.cpp | 1 - plugins/devel/eventExample.cpp | 1 + plugins/devel/stripcaged.cpp | 1 - plugins/dwarfmonitor.cpp | 3 +- plugins/embark-assistant/embark-assistant.cpp | 1 - plugins/embark-assistant/finder_ui.cpp | 2 - plugins/embark-assistant/matcher.cpp | 1 - plugins/embark-assistant/overlay.cpp | 1 - plugins/embark-assistant/survey.cpp | 2 - plugins/forceequip.cpp | 2 +- plugins/generated-creature-renamer.cpp | 1 - plugins/infinite-sky.cpp | 4 +- plugins/logistics.cpp | 1 + plugins/nestboxes.cpp | 1 + plugins/orders.cpp | 10 +- plugins/probe.cpp | 2 +- plugins/prospector.cpp | 14 ++- .../remotefortressreader/building_reader.cpp | 4 +- plugins/remotefortressreader/item_reader.cpp | 19 ++- .../remotefortressreader.cpp | 70 +++++------ plugins/stockpiles/OrganicMatLookup.cpp | 6 +- plugins/stockpiles/StockpileSerializer.cpp | 22 ++-- plugins/strangemood.cpp | 20 +-- plugins/tailor.cpp | 4 +- plugins/timestream.cpp | 5 +- 44 files changed, 236 insertions(+), 229 deletions(-) diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 6e251dbfcf..637df32211 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -99,6 +99,7 @@ distribution. #include "df/report_zoom_type.h" #include "df/specific_ref.h" #include "df/specific_ref_type.h" +#include "df/squad_use_flags.h" #include "df/squad.h" #include "df/unit.h" #include "df/unit_misc_trait.h" @@ -2443,7 +2444,7 @@ static int items_moveToBuilding(lua_State *state) static int items_moveToInventory(lua_State *state) { auto item = Lua::CheckDFObject(state, 1); auto unit = Lua::CheckDFObject(state, 2); - auto use_mode = (df::unit_inventory_item::T_mode)luaL_optint(state, 3, 0); + auto use_mode = (df::inv_item_role_type)luaL_optint(state, 3, 0); int body_part = luaL_optint(state, 4, -1); lua_pushboolean(state, Items::moveToInventory(item, unit, use_mode, body_part)); return 1; @@ -2816,7 +2817,7 @@ int buildings_setSize(lua_State *state) lua_pushinteger(state, size.x); lua_pushinteger(state, size.y); lua_pushinteger(state, area); - lua_pushinteger(state, Buildings::countExtentTiles(&bld->room, area)); + lua_pushinteger(state, Buildings::countExtentTiles(bld, area)); return 5; } else diff --git a/library/RemoteTools.cpp b/library/RemoteTools.cpp index fbace1ae2e..3df55b847a 100644 --- a/library/RemoteTools.cpp +++ b/library/RemoteTools.cpp @@ -458,7 +458,7 @@ static command_result ListEnums(color_ostream &stream, BITFIELD(cie_add_tag_mask1); BITFIELD(cie_add_tag_mask2); - describe_bitfield(out->mutable_death_info_flags()); + describe_bitfield(out->mutable_death_info_flags()); ENUM(profession); diff --git a/library/include/df/custom/creature_handler.methods.inc b/library/include/df/custom/creature_handler.methods.inc index 811128d058..14639bd889 100644 --- a/library/include/df/custom/creature_handler.methods.inc +++ b/library/include/df/custom/creature_handler.methods.inc @@ -1 +1 @@ -friend struct world_raws; +friend struct world; diff --git a/library/include/modules/Buildings.h b/library/include/modules/Buildings.h index ee7fcdf698..80fe443396 100644 --- a/library/include/modules/Buildings.h +++ b/library/include/modules/Buildings.h @@ -44,7 +44,6 @@ namespace df { struct building; struct building_cagest; struct building_civzonest; - struct building_extents; struct building_stockpilest; struct item; struct job_item; @@ -112,7 +111,7 @@ DFHACK_EXPORT bool getCorrectSize(df::coord2d &size, df::coord2d ¢er, * Checks if the tiles are free to be built upon. */ DFHACK_EXPORT bool checkFreeTiles(df::coord pos, df::coord2d size, - df::building_extents *ext = NULL, + df::building *bld, bool create_ext = false, bool allow_occupied = false, bool allow_wall = false, @@ -121,7 +120,7 @@ DFHACK_EXPORT bool checkFreeTiles(df::coord pos, df::coord2d size, /** * Returns the number of tiles included by the extent, or defval. */ -DFHACK_EXPORT int countExtentTiles(df::building_extents *ext, int defval = -1); +DFHACK_EXPORT int countExtentTiles(df::building *bld, int defval = -1); /** * Checks if the building contains the specified tile. If the building has diff --git a/library/include/modules/Items.h b/library/include/modules/Items.h index 79aed92c36..6d068e8786 100644 --- a/library/include/modules/Items.h +++ b/library/include/modules/Items.h @@ -157,7 +157,7 @@ DFHACK_EXPORT bool moveToContainer(df::item *item, df::item *container); DFHACK_EXPORT bool moveToBuilding(df::item *item, df::building_actual *building, df::building_item_role_type use_mode = df::building_item_role_type::TEMP, bool force_in_building = false); DFHACK_EXPORT bool moveToInventory(df::item *item, df::unit *unit, - df::unit_inventory_item::T_mode mode = df::unit_inventory_item::Hauled, int body_part = -1); + df::inv_item_role_type mode = df::inv_item_role_type::Hauled, int body_part = -1); /// Remove item from jobs and inventories, hide and forbid. /// Unless no_uncat, item is marked for garbage collection. diff --git a/library/include/modules/Job.h b/library/include/modules/Job.h index f0d3e89b97..a0754c4781 100644 --- a/library/include/modules/Job.h +++ b/library/include/modules/Job.h @@ -105,7 +105,7 @@ namespace DFHack DFHACK_EXPORT bool listNewlyCreated(std::vector *pvec, int *id_var); DFHACK_EXPORT bool attachJobItem(df::job *job, df::item *item, - df::job_item_ref::T_role role, + df::job_role_type role, int filter_idx = -1, int insert_idx = -1); DFHACK_EXPORT bool isSuitableItem(const df::job_item *item, df::item_type itype, int isubtype); diff --git a/library/include/modules/MapCache.h b/library/include/modules/MapCache.h index 04fddd38bd..0d63627389 100644 --- a/library/include/modules/MapCache.h +++ b/library/include/modules/MapCache.h @@ -84,7 +84,7 @@ class BlockInfo }; static GroundType getGroundType(int material); - typedef df::block_square_event_mineralst::T_flags DFVeinFlags; + typedef df::mineral_event_flag DFVeinFlags; t_veintype veintype; t_blockmaterials veinmats; diff --git a/library/modules/Buildings.cpp b/library/modules/Buildings.cpp index a560a6fc99..672464ceba 100644 --- a/library/modules/Buildings.cpp +++ b/library/modules/Buildings.cpp @@ -48,18 +48,21 @@ distribution. #include "df/building_coffinst.h" #include "df/building_def.h" #include "df/building_design.h" +#include "df/building_extents_type.h" #include "df/building_floodgatest.h" #include "df/building_furnacest.h" #include "df/building_grate_floorst.h" #include "df/building_grate_wallst.h" #include "df/building_rollersst.h" #include "df/building_screw_pumpst.h" +#include "df/building_squad_infost.h" #include "df/building_stockpilest.h" #include "df/building_trapst.h" #include "df/building_water_wheelst.h" #include "df/building_weaponst.h" #include "df/building_wellst.h" #include "df/building_workshopst.h" +#include "df/buildingitemst.h" #include "df/buildings_other_id.h" #include "df/d_init.h" #include "df/dfhack_room_quality_level.h" @@ -77,6 +80,7 @@ distribution. #include "df/plotinfost.h" #include "df/punishment.h" #include "df/squad.h" +#include "df/squad_barracks_infost.h" #include "df/unit.h" #include "df/unit_relationship_type.h" #include "df/world.h" @@ -112,15 +116,15 @@ struct CoordHash { static unordered_map locationToBuilding; -static df::building_extents_type *getExtentTile(df::building_extents &extent, df::coord2d tile) +static df::building_extents_type *getExtentTile(const df::building::T_room &room, df::coord2d tile) { - if (!extent.extents) + if (!room.extents) return NULL; - int dx = tile.x - extent.x; - int dy = tile.y - extent.y; - if (dx < 0 || dy < 0 || dx >= extent.width || dy >= extent.height) + int dx = tile.x - room.x; + int dy = tile.y - room.y; + if (dx < 0 || dy < 0 || dx >= room.width || dy >= room.height) return NULL; - return &extent.extents[dx + dy*extent.width]; + return &room.extents[dx + dy*room.width]; } /* @@ -162,14 +166,14 @@ void buildings_onUpdate(color_ostream &out) for (size_t i = 0; i < job->items.size(); i++) { df::job_item_ref *iref = job->items[i]; - if (iref->role != df::job_item_ref::Reagent) + if (iref->role != df::job_role_type::Reagent) continue; df::job_item *item = vector_get(job->job_items.elements, iref->job_item_idx); if (!item) continue; // Convert Reagent to Hauled, while decrementing quantity item->quantity = std::max(0, item->quantity-1); - iref->role = df::job_item_ref::Hauled; + iref->role = df::job_role_type::Hauled; iref->job_item_idx = -1; } } @@ -219,7 +223,7 @@ static void add_building_to_all_zones(df::building* bld) static void add_zone_to_all_buildings(df::building* zone_as_building) { - if (zone_as_building->getType() != building_type::Civzone) + if (zone_as_building->getType() != df::building_type::Civzone) return; auto zone = strict_virtual_cast(zone_as_building); @@ -259,7 +263,7 @@ static void remove_building_from_zone(df::building* bld, df::building_civzonest* static void remove_zone_from_all_buildings(df::building* zone_as_building) { - if (zone_as_building->getType() != building_type::Civzone) + if (zone_as_building->getType() != df::building_type::Civzone) return; auto zone = strict_virtual_cast(zone_as_building); @@ -478,19 +482,20 @@ df::building *Buildings::allocInstance(df::coord pos, df::building_type type, in // Type specific init switch (type) { - case building_type::Well: + using namespace df::enums::building_type; + case Well: { if (VIRTUAL_CAST_VAR(obj, df::building_wellst, bld)) obj->bucket_z = bld->z; break; } - case building_type::Workshop: + case Workshop: { if (VIRTUAL_CAST_VAR(obj, df::building_workshopst, bld)) obj->profile.max_general_orders = 5; break; } - case building_type::Furnace: + case Furnace: { if (VIRTUAL_CAST_VAR(obj, df::building_furnacest, bld)) { @@ -507,7 +512,7 @@ df::building *Buildings::allocInstance(df::coord pos, df::building_type type, in break; } */ - case building_type::Trap: + case Trap: { if (VIRTUAL_CAST_VAR(obj, df::building_trapst, bld)) { @@ -516,46 +521,46 @@ df::building *Buildings::allocInstance(df::coord pos, df::building_type type, in } break; } - case building_type::Floodgate: + case Floodgate: { if (VIRTUAL_CAST_VAR(obj, df::building_floodgatest, bld)) obj->gate_flags.bits.closed = true; break; } - case building_type::GrateWall: + case GrateWall: { if (VIRTUAL_CAST_VAR(obj, df::building_grate_wallst, bld)) obj->gate_flags.bits.closed = true; break; } - case building_type::GrateFloor: + case GrateFloor: { if (VIRTUAL_CAST_VAR(obj, df::building_grate_floorst, bld)) obj->gate_flags.bits.closed = true; break; } - case building_type::BarsVertical: + case BarsVertical: { if (VIRTUAL_CAST_VAR(obj, df::building_bars_verticalst, bld)) obj->gate_flags.bits.closed = true; break; } - case building_type::BarsFloor: + case BarsFloor: { if (VIRTUAL_CAST_VAR(obj, df::building_bars_floorst, bld)) obj->gate_flags.bits.closed = true; break; } - case building_type::Bridge: + case Bridge: { if (VIRTUAL_CAST_VAR(obj, df::building_bridgest, bld)) - obj->gate_flags.bits.closed = false; + obj->gate_flags.bits.raised = false; break; } - case building_type::Weapon: + case Weapon: { if (VIRTUAL_CAST_VAR(obj, df::building_weaponst, bld)) - obj->gate_flags.bits.closed = false; + obj->gate_flags.bits.retracted = false; break; } default: @@ -711,26 +716,29 @@ bool Buildings::getCorrectSize(df::coord2d &size, df::coord2d ¢er, } } -static void init_extents(df::building_extents *ext, const df::coord &pos, +static void init_extents(df::building::T_room &room, const df::coord &pos, const df::coord2d &size) { - ext->extents = new df::building_extents_type[size.x*size.y]; - ext->x = pos.x; - ext->y = pos.y; - ext->width = size.x; - ext->height = size.y; + room.extents = new df::building_extents_type[size.x*size.y]; + room.x = pos.x; + room.y = pos.y; + room.width = size.x; + room.height = size.y; - memset(ext->extents, 1, size.x*size.y); + memset(room.extents, 1, size.x*size.y); } bool Buildings::checkFreeTiles(df::coord pos, df::coord2d size, - df::building_extents *ext, + df::building *bld, bool create_ext, bool allow_occupied, bool allow_wall, bool allow_flow) { + CHECK_NULL_POINTER(bld); + bool found_any = false; + auto & room = bld->room; for (int dx = 0; dx < size.x; dx++) { @@ -740,9 +748,9 @@ bool Buildings::checkFreeTiles(df::coord pos, df::coord2d size, df::building_extents_type *etile = NULL; // Exclude using extents - if (ext && ext->extents) + if (room.extents) { - etile = getExtentTile(*ext, tile); + etile = getExtentTile(room, tile); if (!etile || !*etile) continue; } @@ -776,13 +784,13 @@ bool Buildings::checkFreeTiles(df::coord pos, df::coord2d size, found_any = true; else { - if (!ext || !create_ext) + if (!create_ext) return false; - if (!ext->extents) + if (!room.extents) { - init_extents(ext, pos, size); - etile = getExtentTile(*ext, tile); + init_extents(room, pos, size); + etile = getExtentTile(room, tile); } if (!etile) @@ -813,10 +821,10 @@ static bool checkBuildingTiles(df::building *bld, bool can_change, if (force_extents && !bld->room.extents) { // populate the room structure if it's not set already - init_extents(&bld->room, psize.first, psize.second); + init_extents(bld->room, psize.first, psize.second); } - return Buildings::checkFreeTiles(psize.first, psize.second, &bld->room, + return Buildings::checkFreeTiles(psize.first, psize.second, bld, can_change && bld->isExtentShaped(), !bld->isSettingOccupancy(), bld->getType() == @@ -824,14 +832,18 @@ static bool checkBuildingTiles(df::building *bld, bool can_change, !bld->isActual()); } -int Buildings::countExtentTiles(df::building_extents *ext, int defval) +int Buildings::countExtentTiles(df::building *bld, int defval) { - if (!ext || !ext->extents) + CHECK_NULL_POINTER(bld); + + auto & room = bld->room; + + if (!room.extents) return defval; int cnt = 0; - for (int i = 0; i < ext->width * ext->height; i++) - if (ext->extents[i]) + for (int i = 0; i < room.width * room.height; i++) + if (room.extents[i]) cnt++; return cnt; } @@ -881,7 +893,7 @@ static int computeMaterialAmount(df::building *bld) int cnt = size.x * size.y; if (bld->room.extents && bld->isExtentShaped()) - cnt = Buildings::countExtentTiles(&bld->room, cnt); + cnt = Buildings::countExtentTiles(bld, cnt); return cnt/4 + 1; } @@ -911,10 +923,9 @@ bool Buildings::setSize(df::building *bld, df::coord2d size, int direction) auto type = bld->getType(); - using namespace df::enums::building_type; - switch (type) { + using namespace df::enums::building_type; case WaterWheel: { auto obj = (df::building_water_wheelst*)bld; @@ -953,7 +964,7 @@ bool Buildings::setSize(df::building *bld, df::coord2d size, int direction) bool ok = checkBuildingTiles(bld, true); - if (type != Construction) + if (type != df::building_type::Construction) bld->setMaterialAmount(computeMaterialAmount(bld)); return ok; @@ -1158,7 +1169,7 @@ bool Buildings::constructWithItems(df::building *bld, std::vector ite for (size_t i = 0; i < items.size(); i++) { - Job::attachJobItem(job, items[i], df::job_item_ref::Hauled); + Job::attachJobItem(job, items[i], df::job_role_type::Hauled); if (items[i]->getType() == item_type::BOULDER) rough = true; @@ -1224,15 +1235,9 @@ bool Buildings::constructWithFilters(df::building *bld, std::vectorsquad_room_info) + for (auto room_info : zone->squad_room_info) { - int32_t squad_id = room_info->squad_id; - - df::squad* squad = df::squad::find(squad_id); - - //if this is null, something has gone just *terribly* wrong - if (squad) - { + if (auto squad = df::squad::find(room_info->squad_id)) { for (int i=(int)squad->rooms.size() - 1; i >= 0; i--) { if (squad->rooms[i]->building_id == zone->id) @@ -1406,7 +1411,7 @@ bool Buildings::deconstruct(df::building *bld) for (int i = ui_look_list->size()-1; i >= 0; --i) { auto item = (*ui_look_list)[i]; - if (item->type == df::lookinfost::Building && + if (item->type == df::look_info_type::Building && item->data.building.bld_id == id) { vector_erase_at(*ui_look_list, i); diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp index 951482d23f..853d42f3b8 100644 --- a/library/modules/Gui.cpp +++ b/library/modules/Gui.cpp @@ -84,7 +84,6 @@ distribution. #include "df/route_stockpile_link.h" #include "df/soundst.h" #include "df/stop_depart_condition.h" -#include "df/ui_unit_view_mode.h" #include "df/unit.h" #include "df/unit_inventory_item.h" #include "df/viewscreen_choose_start_sitest.h" @@ -1877,7 +1876,7 @@ DFHACK_EXPORT int Gui::makeAnnouncement(df::announcement_type type, df::announce new_report->text = message; new_report->color = color; new_report->bright = bright; - new_report->flags.whole = adv_unconscious ? df::report::T_flags::mask_unconscious : 0x0; + new_report->flags.whole = adv_unconscious ? df::announcement_flag::mask_unconscious : 0x0; new_report->pos = pos; new_report->id = world->status.next_report_id++; new_report->year = *df::global::cur_year; @@ -2197,7 +2196,7 @@ bool Gui::autoDFAnnouncement(df::announcement_infost info, string message) new_report->text = message; new_report->color = info.color; new_report->bright = info.bright; - new_report->flags.whole = adv_unconscious ? df::report::T_flags::mask_unconscious : 0x0; + new_report->flags.whole = adv_unconscious ? df::announcement_flag::mask_unconscious : 0x0; new_report->zoom_type = info.zoom_type; new_report->pos = info.pos; new_report->zoom_type2 = info.zoom_type2; diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index 47d68b1654..a99c2bb761 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -44,6 +44,7 @@ distribution. #include "df/building.h" #include "df/building_actual.h" #include "df/building_tradedepotst.h" +#include "df/buildingitemst.h" #include "df/builtin_mats.h" #include "df/caravan_state.h" #include "df/creature_raw.h" @@ -765,13 +766,13 @@ static bool removeItemOnGround(df::item *item) } static void resetUnitInvFlags(df::unit *unit, df::unit_inventory_item *inv_item) { - if (inv_item->mode == df::unit_inventory_item::Worn || - inv_item->mode == df::unit_inventory_item::WrappedAround) + if (inv_item->mode == df::inv_item_role_type::Worn || + inv_item->mode == df::inv_item_role_type::WrappedAround) { unit->flags2.bits.calculated_inventory = false; unit->flags2.bits.calculated_insulation = false; } - else if (inv_item->mode == df::unit_inventory_item::StuckIn) + else if (inv_item->mode == df::inv_item_role_type::StuckIn) unit->flags3.bits.stuck_weapon_computed = false; } @@ -815,7 +816,7 @@ static bool detachItem(df::item *item) } if (auto ref = virtual_cast(Items::getGeneralRef(item, general_ref_type::PROJECTILE))) - return linked_list_remove(&world->proj_list, ref->projectile_id) + return linked_list_remove(&world->projectiles.all, ref->projectile_id) && removeRef(item->general_refs, general_ref_type::PROJECTILE, ref->getID()); if (item->flags.bits.on_ground) { @@ -960,7 +961,7 @@ bool DFHack::Items::moveToBuilding(df::item *item, df::building_actual *building ref->building_id = building->id; item->general_refs.push_back(ref); - auto con = new df::building_actual::T_contained_items; + auto con = new df::buildingitemst; con->item = item; con->use_mode = use_mode; building->contained_items.push_back(con); @@ -969,7 +970,7 @@ bool DFHack::Items::moveToBuilding(df::item *item, df::building_actual *building } bool DFHack::Items::moveToInventory(df::item *item, df::unit *unit, - df::unit_inventory_item::T_mode mode, int body_part) + df::inv_item_role_type mode, int body_part) { CHECK_NULL_POINTER(item); CHECK_NULL_POINTER(unit); @@ -1063,7 +1064,7 @@ df::proj_itemst *Items::makeProjectile(df::item *item) ref->projectile_id = proj->id; item->general_refs.push_back(ref); - linked_list_append(&world->proj_list, proj->link); + linked_list_append(&world->projectiles.all, proj->link); return proj; } @@ -1799,8 +1800,8 @@ bool Items::createItem(vector &out_items, df::unit *unit, df::item_t bool Items::checkMandates(df::item *item) { CHECK_NULL_POINTER(item); - for (auto mandate : world->mandates) { - if ((mandate->mode == df::mandate::Export) && + for (auto mandate : world->mandates.all) { + if ((mandate->mode == df::mandate_type::Export) && (item->getType() == mandate->item_type) && (mandate->item_subtype == -1 || item->getSubtype() == mandate->item_subtype) && (mandate->mat_type == -1 || item->getMaterial() == mandate->mat_type) && @@ -1881,7 +1882,7 @@ bool Items::markForTrade(df::item *item, df::building_tradedepotst *depot) { job->pos = df::coord(depot->centerx, depot->centery, depot->z); // job <-> item link - if (!Job::attachJobItem(job, item, df::job_item_ref::Hauled)) { + if (!Job::attachJobItem(job, item, df::job_role_type::Hauled)) { delete job; delete href; return false; diff --git a/library/modules/Job.cpp b/library/modules/Job.cpp index 86809ba5ba..96344ddd6f 100644 --- a/library/modules/Job.cpp +++ b/library/modules/Job.cpp @@ -46,6 +46,8 @@ distribution. #include "df/job.h" #include "df/job_item.h" #include "df/job_list_link.h" +#include "df/job_postingst.h" +#include "df/job_restrictionst.h" #include "df/plotinfost.h" #include "df/specific_ref.h" #include "df/unit.h" @@ -323,11 +325,11 @@ void DFHack::Job::setJobCooldown(df::building *workshop, df::unit *worker, int c if (cooldown <= 0) return; - int idx = linear_index(workshop->job_claim_suppress, &df::building::T_job_claim_suppress::unit, worker); + int idx = linear_index(workshop->job_claim_suppress, &df::job_restrictionst::unit, worker); if (idx < 0) { - auto obj = new df::building::T_job_claim_suppress; + auto obj = new df::job_restrictionst; obj->unit = worker; obj->timer = cooldown; workshop->job_claim_suppress.push_back(obj); @@ -575,7 +577,7 @@ bool DFHack::Job::listNewlyCreated(std::vector *pvec, int *id_var) } bool DFHack::Job::attachJobItem(df::job *job, df::item *item, - df::job_item_ref::T_role role, + df::job_role_type role, int filter_idx, int insert_idx) { CHECK_NULL_POINTER(job); @@ -585,7 +587,7 @@ bool DFHack::Job::attachJobItem(df::job *job, df::item *item, * Functionality 100% reverse-engineered from DF code. */ - if (role != df::job_item_ref::TargetContainer) + if (role != df::job_role_type::TargetContainer) { if (item->flags.bits.in_job) return false; diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index c207360ac4..54fb43c810 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -47,6 +47,8 @@ distribution. #include "df/builtin_mats.h" #include "df/burrow.h" #include "df/feature_init.h" +#include "df/feature_map_shellst.h" +#include "df/feature_mapst.h" #include "df/flow_info.h" #include "df/map_block.h" #include "df/map_block_column.h" @@ -515,7 +517,7 @@ df::feature_init *Maps::getLocalInitFeature(df::coord2d rgn_pos, int32_t index) df::coord2d sub = rgn_pos & 15; - vector &features = fptr->feature_init[sub.x][sub.y]; + vector &features = fptr->feature_init[sub.x][sub.y]; return vector_get(features, index); } @@ -947,13 +949,13 @@ static int16_t basic_wet_dry_effect(int16_t region_y, int16_t rain) auto dimy = world->world_data->world_height; auto pole = world->world_data->flip_latitude; - if (dimy > 65 && pole != df::world_data::T_flip_latitude::None) + if (dimy > 65 && pole != df::pole_type::None) { // Medium and Large worlds with at least one pole auto latitude = region_y; - if (pole == df::world_data::T_flip_latitude::South) + if (pole == df::pole_type::South) latitude = dimy - region_y - 1; - else if (pole == df::world_data::T_flip_latitude::Both) + else if (pole == df::pole_type::Both) { if (region_y < dimy / 2) latitude = region_y * 2; @@ -993,7 +995,7 @@ df::enums::biome_type::biome_type Maps::getBiomeTypeWithRef(int16_t region_x, in bool tropical; // Determine tropicality - if (pole == df::world_data::T_flip_latitude::None) + if (pole == df::pole_type::None) { potential_tropical = region->temperature > 74; tropical = region->temperature > 84; @@ -1002,9 +1004,9 @@ df::enums::biome_type::biome_type Maps::getBiomeTypeWithRef(int16_t region_x, in { auto latitude = region_ref_y; // DF just uses region_y, but embark assistant needs region_ref_y - if (pole == df::world_data::T_flip_latitude::South) + if (pole == df::pole_type::South) latitude = dimy - region_ref_y - 1; - else if (pole == df::world_data::T_flip_latitude::Both) + else if (pole == df::pole_type::Both) { if (region_ref_y < dimy / 2) latitude = region_ref_y * 2; diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp index 341ddeabc4..18dd73b09a 100644 --- a/library/modules/Materials.cpp +++ b/library/modules/Materials.cpp @@ -99,7 +99,7 @@ bool MaterialInfo::decode(int16_t type, int32_t index) return false; } - df::world_raws &raws = world->raws; + auto &raws = world->raws; if (size_t(type) >= sizeof(raws.mat_table.builtin)/sizeof(void*)) return false; @@ -216,7 +216,7 @@ bool MaterialInfo::findBuiltin(const std::string &token) return true; } - df::world_raws &raws = world->raws; + auto &raws = world->raws; for (int i = 0; i < NUM_BUILTIN; i++) { auto obj = raws.mat_table.builtin[i]; @@ -236,10 +236,10 @@ bool MaterialInfo::findInorganic(const std::string &token) return true; } - df::world_raws &raws = world->raws; - for (size_t i = 0; i < raws.inorganics.size(); i++) + auto &raws = world->raws; + for (size_t i = 0; i < raws.inorganics.all.size(); i++) { - df::inorganic_raw *p = raws.inorganics[i]; + df::inorganic_raw *p = raws.inorganics.all[i]; if (p->id == token) return decode(0, i); } @@ -250,7 +250,7 @@ bool MaterialInfo::findPlant(const std::string &token, const std::string &subtok { if (token.empty()) return decode(-1); - df::world_raws &raws = world->raws; + auto &raws = world->raws; for (size_t i = 0; i < raws.plants.all.size(); i++) { df::plant_raw *p = raws.plants.all[i]; @@ -274,7 +274,7 @@ bool MaterialInfo::findCreature(const std::string &token, const std::string &sub { if (token.empty() || subtoken.empty()) return decode(-1); - df::world_raws &raws = world->raws; + auto &raws = world->raws; for (size_t i = 0; i < raws.creatures.all.size(); i++) { df::creature_raw *p = raws.creatures.all[i]; @@ -645,12 +645,12 @@ bool t_matglossInorganic::isGem() bool Materials::CopyInorganicMaterials (std::vector & inorganic) { - size_t size = world->raws.inorganics.size(); + size_t size = world->raws.inorganics.all.size(); inorganic.clear(); inorganic.reserve (size); for (size_t i = 0; i < size;i++) { - df::inorganic_raw *orig = world->raws.inorganics[i]; + df::inorganic_raw *orig = world->raws.inorganics.all[i]; t_matglossInorganic mat; mat.id = orig->id; mat.name = orig->material.stone_name; diff --git a/library/modules/Military.cpp b/library/modules/Military.cpp index 3c5708d75e..cbb4295562 100644 --- a/library/modules/Military.cpp +++ b/library/modules/Military.cpp @@ -7,6 +7,7 @@ #include "modules/Units.h" #include "df/building.h" #include "df/building_civzonest.h" +#include "df/building_squad_infost.h" #include "df/histfig_entity_link_former_positionst.h" #include "df/histfig_entity_link_former_squadst.h" #include "df/histfig_entity_link_positionst.h" @@ -16,11 +17,16 @@ #include "df/entity_position.h" #include "df/entity_position_assignment.h" #include "df/plotinfost.h" +#include "df/military_routinest.h" #include "df/squad.h" -#include "df/squad_position.h" -#include "df/squad_schedule_order.h" +#include "df/squad_barracks_infost.h" +#include "df/squad_month_positionst.h" #include "df/squad_order.h" #include "df/squad_order_trainst.h" +#include "df/squad_position.h" +#include "df/squad_routine_schedulest.h" +#include "df/squad_schedule_entry.h" +#include "df/squad_schedule_order.h" #include "df/unit.h" #include "df/world.h" @@ -96,7 +102,7 @@ df::squad* Military::makeSquad(int32_t assignment_id) result->id = *df::global::squad_next_id; result->uniform_priority = result->id + 1; //no idea why, but seems to hold result->supplies.carry_food = 2; - result->supplies.carry_water = df::squad::T_supplies::Water; + result->supplies.carry_water = df::squad_water_level_type::Water; result->entity_id = df::global::plotinfo->group_id; result->leader_position = corresponding_position->id; result->leader_assignment = found_assignment->id; @@ -116,7 +122,8 @@ df::squad* Military::makeSquad(int32_t assignment_id) for (const auto& routine : routines) { - df::squad_schedule_entry* asched = (df::squad_schedule_entry*)malloc(sizeof(df::squad_schedule_entry) * 12); + df::squad_routine_schedulest* schedule = new df::squad_routine_schedulest[12]; + auto &asched = schedule->month; for(int kk=0; kk < 12; kk++) { @@ -124,14 +131,14 @@ df::squad* Military::makeSquad(int32_t assignment_id) for(int jj=0; jj < squad_size; jj++) { - int32_t* order_assignments = new int32_t(); - *order_assignments = -1; + df::squad_month_positionst* order_assignments = new df::squad_month_positionst(); + order_assignments->assigned_order_idx = -1; asched[kk].order_assignments.push_back(order_assignments); } } - auto insert_training_order = [asched, squad_size](int month) + auto insert_training_order = [&](int month) { df::squad_schedule_order* order = new df::squad_schedule_order(); order->min_count = squad_size; @@ -212,7 +219,7 @@ df::squad* Military::makeSquad(int32_t assignment_id) } } - result->schedule.push_back(reinterpret_cast(asched)); + result->schedule.routine.push_back(schedule); } //Modify necessary world state @@ -234,8 +241,8 @@ void Military::updateRoomAssignments(int32_t squad_id, int32_t civzone_id, df::s if (squad == nullptr || zone == nullptr) return; - df::squad::T_rooms* room_from_squad = nullptr; - df::building_civzonest::T_squad_room_info* room_from_building = nullptr; + df::squad_barracks_infost* room_from_squad = nullptr; + df::building_squad_infost* room_from_building = nullptr; for (auto room : squad->rooms) { @@ -263,18 +270,18 @@ void Military::updateRoomAssignments(int32_t squad_id, int32_t civzone_id, df::s if (!avoiding_squad_roundtrip && room_from_squad == nullptr) { - room_from_squad = new df::squad::T_rooms(); + room_from_squad = new df::squad_barracks_infost(); room_from_squad->building_id = civzone_id; - insert_into_vector(squad->rooms, &df::squad::T_rooms::building_id, room_from_squad); + insert_into_vector(squad->rooms, &df::squad_barracks_infost::building_id, room_from_squad); } if (room_from_building == nullptr) { - room_from_building = new df::building_civzonest::T_squad_room_info(); + room_from_building = new df::building_squad_infost(); room_from_building->squad_id = squad_id; - insert_into_vector(zone->squad_room_info, &df::building_civzonest::T_squad_room_info::squad_id, room_from_building); + insert_into_vector(zone->squad_room_info, &df::building_squad_infost::squad_id, room_from_building); } if (room_from_squad) diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index 933ea53754..1af93c3b7d 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -61,16 +61,20 @@ distribution. #include "df/historical_kills.h" #include "df/history_event_hist_figure_diedst.h" #include "df/identity.h" +#include "df/interaction_profilest.h" #include "df/item.h" #include "df/job.h" #include "df/nemesis_record.h" +#include "df/personality_goalst.h" #include "df/plotinfost.h" +#include "df/reputation_profilest.h" #include "df/syndrome.h" #include "df/tile_occupancy.h" #include "df/training_assignment.h" #include "df/unit.h" #include "df/unit_action.h" #include "df/unit_action_type_group.h" +#include "df/unit_active_animationst.h" #include "df/unit_inventory_item.h" #include "df/unit_misc_trait.h" #include "df/unit_path_goal.h" @@ -79,6 +83,7 @@ distribution. #include "df/unit_soul.h" #include "df/unit_syndrome.h" #include "df/unit_wound.h" +#include "df/unit_wound_layerst.h" #include "df/world.h" #include "df/world_site.h" @@ -325,7 +330,7 @@ bool Units::isNaked(df::unit *unit, bool no_items) { for (auto inv_item : unit->inventory) { // TODO: Check for proper coverage (bad thought) - if (inv_item->mode == df::unit_inventory_item::Worn) + if (inv_item->mode == df::inv_item_role_type::Worn) return false; } return true; @@ -1247,7 +1252,7 @@ int Units::getEffectiveSkill(df::unit *unit, df::job_skill skill_id) { // This is 100% reverse-engineered from DF code int rating = getNominalSkill(unit, skill_id, true); // Apply special states - if (unit->counters.soldier_mood == df::unit::T_counters::None) { + if (unit->counters.soldier_mood == df::soldier_mood_type::None) { if (unit->counters.nausea > 0) rating >>= 1; if (unit->counters.winded > 0) @@ -1260,7 +1265,7 @@ int Units::getEffectiveSkill(df::unit *unit, df::job_skill skill_id) { rating >>= 1; } - if (unit->counters.soldier_mood != df::unit::T_counters::MartialTrance) { + if (unit->counters.soldier_mood != df::soldier_mood_type::MartialTrance) { if (!unit->flags3.bits.ghostly && !unit->flags3.bits.scuttle && !unit->flags2.bits.vision_good && !unit->flags2.bits.vision_damaged && !hasExtravision(unit)) @@ -1608,7 +1613,7 @@ float Units::computeSlowdownFactor(df::unit *unit) { if (!unit->flags1.bits.marauder && casteFlagSet(unit->race, unit->caste, caste_raw_flags::MEANDERER) && !(unit->following && isCitizen(unit)) && - linear_index(unit->inventory, &df::unit_inventory_item::mode, df::unit_inventory_item::Hauled) < 0) + linear_index(unit->inventory, &df::unit_inventory_item::mode, df::inv_item_role_type::Hauled) < 0) { coeff *= 4.0f; } diff --git a/plugins/3dveins.cpp b/plugins/3dveins.cpp index 3ed5455d0f..8f75e0549e 100644 --- a/plugins/3dveins.cpp +++ b/plugins/3dveins.cpp @@ -568,7 +568,7 @@ struct VeinGenerator bool VeinGenerator::init_biomes() { auto &mats = df::inorganic_raw::get_vector(); - materials.resize(world->raws.inorganics.size()); + materials.resize(world->raws.inorganics.all.size()); for (size_t i = 0; i < mats.size(); i++) { diff --git a/plugins/blueprint.cpp b/plugins/blueprint.cpp index c7ce4114e7..b82442a66d 100644 --- a/plugins/blueprint.cpp +++ b/plugins/blueprint.cpp @@ -679,7 +679,7 @@ static const char * if_pretty(const tile_context &ctx, const char *c) { } static bool is_rectangular(const df::building *bld) { - const df::building_extents &room = bld->room; + const df::building::T_room &room = bld->room; if (!room.extents) return true; for (int32_t y = 0; y < room.height; ++y) { diff --git a/plugins/buildingplan/buildingplan.cpp b/plugins/buildingplan/buildingplan.cpp index fe317e4705..64ddf89e34 100644 --- a/plugins/buildingplan/buildingplan.cpp +++ b/plugins/buildingplan/buildingplan.cpp @@ -166,12 +166,12 @@ static void load_organic_material_cache(df::organic_mat_category cat) { } static void load_material_cache() { - df::world_raws &raws = world->raws; + auto &raws = world->raws; for (int i = 1; i < DFHack::MaterialInfo::NUM_BUILTIN; ++i) if (raws.mat_table.builtin[i]) cache_matched(i, -1); - for (size_t i = 0; i < raws.inorganics.size(); i++) + for (size_t i = 0; i < raws.inorganics.all.size(); i++) cache_matched(0, i); load_organic_material_cache(df::organic_mat_category::Wood); diff --git a/plugins/buildingplan/buildingplan_cycle.cpp b/plugins/buildingplan/buildingplan_cycle.cpp index d55b5f5da4..1a97a801de 100644 --- a/plugins/buildingplan/buildingplan_cycle.cpp +++ b/plugins/buildingplan/buildingplan_cycle.cpp @@ -337,7 +337,7 @@ static void doVector(color_ostream &out, df::job_item_vector_id vector_id, } auto item = closest->second; // some item must be closest. - if (Job::attachJobItem(job, item, df::job_item_ref::Hauled, filter_idx)) { + if (Job::attachJobItem(job, item, df::job_role_type::Hauled, filter_idx)) { MaterialInfo material; material.decode(item); ItemTypeInfo item_type; diff --git a/plugins/cursecheck.cpp b/plugins/cursecheck.cpp index 9c41d73912..50b0c7f138 100644 --- a/plugins/cursecheck.cpp +++ b/plugins/cursecheck.cpp @@ -29,7 +29,6 @@ #include "df/unit_soul.h" #include "df/unit_syndrome.h" #include "df/world.h" -#include "df/world_raws.h" using std::vector; using std::string; diff --git a/plugins/devel/eventExample.cpp b/plugins/devel/eventExample.cpp index ceaec29921..c0944249f1 100644 --- a/plugins/devel/eventExample.cpp +++ b/plugins/devel/eventExample.cpp @@ -13,6 +13,7 @@ #include "df/job.h" #include "df/unit.h" #include "df/unit_wound.h" +#include "df/unit_wound_layerst.h" #include "df/world.h" #include diff --git a/plugins/devel/stripcaged.cpp b/plugins/devel/stripcaged.cpp index 14189bdc30..fdb11741ca 100644 --- a/plugins/devel/stripcaged.cpp +++ b/plugins/devel/stripcaged.cpp @@ -21,7 +21,6 @@ using namespace std; #include #include "df/world.h" -#include "df/world_raws.h" #include "df/building_def.h" #include "df/unit_inventory_item.h" #include diff --git a/plugins/dwarfmonitor.cpp b/plugins/dwarfmonitor.cpp index d4fddb4846..35f0238123 100644 --- a/plugins/dwarfmonitor.cpp +++ b/plugins/dwarfmonitor.cpp @@ -46,7 +46,6 @@ #include "df/unit_preference.h" #include "df/unit_soul.h" #include "df/viewscreen_unitst.h" -#include "df/world_raws.h" using std::deque; @@ -1184,7 +1183,7 @@ struct preference_map label = ""; typedef df::unit_preference::T_type T_type; - df::world_raws &raws = world->raws; + auto &raws = world->raws; switch (pref.type) { case (T_type::LikeCreature): diff --git a/plugins/embark-assistant/embark-assistant.cpp b/plugins/embark-assistant/embark-assistant.cpp index ee418363e7..db04308d0b 100644 --- a/plugins/embark-assistant/embark-assistant.cpp +++ b/plugins/embark-assistant/embark-assistant.cpp @@ -18,7 +18,6 @@ #include "df/world.h" #include "df/world_data.h" #include "df/world_geo_biome.h" -#include "df/world_raws.h" #include "defs.h" #include "embark-assistant.h" diff --git a/plugins/embark-assistant/finder_ui.cpp b/plugins/embark-assistant/finder_ui.cpp index b4c55dd823..bb90435343 100644 --- a/plugins/embark-assistant/finder_ui.cpp +++ b/plugins/embark-assistant/finder_ui.cpp @@ -14,9 +14,7 @@ #include "df/viewscreen_choose_start_sitest.h" #include "df/world.h" #include "df/world_data.h" -#include "df/world_raws.h" #include "df/world_region_type.h" -#include "df/world_raws.h" #include "embark-assistant.h" #include "finder_ui.h" diff --git a/plugins/embark-assistant/matcher.cpp b/plugins/embark-assistant/matcher.cpp index b540ae80b4..9f3900f0c9 100644 --- a/plugins/embark-assistant/matcher.cpp +++ b/plugins/embark-assistant/matcher.cpp @@ -10,7 +10,6 @@ #include "df/viewscreen_choose_start_sitest.h" #include "df/world.h" #include "df/world_data.h" -#include "df/world_raws.h" #include "df/world_region.h" #include "df/world_region_details.h" #include "df/world_region_type.h" diff --git a/plugins/embark-assistant/overlay.cpp b/plugins/embark-assistant/overlay.cpp index d5b50294a9..37130c6897 100644 --- a/plugins/embark-assistant/overlay.cpp +++ b/plugins/embark-assistant/overlay.cpp @@ -8,7 +8,6 @@ #include "df/viewscreen.h" #include "df/viewscreen_choose_start_sitest.h" #include "df/world.h" -#include "df/world_raws.h" #include "finder_ui.h" #include "help_ui.h" diff --git a/plugins/embark-assistant/survey.cpp b/plugins/embark-assistant/survey.cpp index 84994b2869..ddfc6d8d49 100644 --- a/plugins/embark-assistant/survey.cpp +++ b/plugins/embark-assistant/survey.cpp @@ -30,7 +30,6 @@ #include "df/interaction_source_type.h" #include "df/interaction_target.h" #include "df/interaction_target_materialst.h" -#include "df/material_common.h" #include "df/reaction.h" #include "df/reaction_product_itemst.h" #include "df/reaction_product_type.h" @@ -42,7 +41,6 @@ #include "df/world_data.h" #include "df/world_geo_biome.h" #include "df/world_geo_layer.h" -#include "df/world_raws.h" #include "df/world_region.h" #include "df/world_region_details.h" #include "df/world_region_feature.h" diff --git a/plugins/forceequip.cpp b/plugins/forceequip.cpp index df716831db..fa8cb8ef12 100644 --- a/plugins/forceequip.cpp +++ b/plugins/forceequip.cpp @@ -238,7 +238,7 @@ static bool moveToInventory(df::item *item, df::unit *unit, df::body_part_raw * return false; } - if (!Items::moveToInventory(item, unit, df::unit_inventory_item::Worn, bpIndex)) + if (!Items::moveToInventory(item, unit, df::inv_item_role_type::Worn, bpIndex)) { if (verbose) { WARN(log).print("\nEquipping failed - failed to retrieve item from its current location/container/inventory. Please move it to the ground and try again.\n"); } return false; diff --git a/plugins/generated-creature-renamer.cpp b/plugins/generated-creature-renamer.cpp index b0a00b3f21..0ea3227b1b 100644 --- a/plugins/generated-creature-renamer.cpp +++ b/plugins/generated-creature-renamer.cpp @@ -3,7 +3,6 @@ #include "Export.h" #include "PluginManager.h" #include "df/world.h" -#include "df/world_raws.h" #include "df/creature_raw.h" #include "df/caste_raw.h" #include "modules/World.h" diff --git a/plugins/infinite-sky.cpp b/plugins/infinite-sky.cpp index 9b41c2e2ca..ffa62ed830 100644 --- a/plugins/infinite-sky.cpp +++ b/plugins/infinite-sky.cpp @@ -8,6 +8,7 @@ #include "modules/Maps.h" #include "modules/World.h" +#include "df/block_column_print_infost.h" #include "df/construction.h" #include "df/map_block.h" #include "df/map_block_column.h" @@ -190,8 +191,7 @@ void doInfiniteSky(color_ostream& out, int32_t howMany) { __LINE__, bpos.x, bpos.y); continue; } - df::map_block_column::T_unmined_glyphs *glyphs = - new df::map_block_column::T_unmined_glyphs; + df::block_column_print_infost *glyphs = new df::block_column_print_infost; glyphs->x[0] = 0; glyphs->x[1] = 1; glyphs->x[2] = 2; diff --git a/plugins/logistics.cpp b/plugins/logistics.cpp index 52b9bf43a4..bcb59b7ad5 100644 --- a/plugins/logistics.cpp +++ b/plugins/logistics.cpp @@ -10,6 +10,7 @@ #include "modules/World.h" #include "df/building.h" +#include "df/buildingitemst.h" #include "df/building_stockpilest.h" #include "df/building_tradedepotst.h" #include "df/caravan_state.h" diff --git a/plugins/nestboxes.cpp b/plugins/nestboxes.cpp index 64cfcc301b..b935c34f81 100644 --- a/plugins/nestboxes.cpp +++ b/plugins/nestboxes.cpp @@ -6,6 +6,7 @@ #include "modules/Persistence.h" #include "modules/World.h" +#include "df/buildingitemst.h" #include "df/building_nest_boxst.h" #include "df/item.h" #include "df/item_eggst.h" diff --git a/plugins/orders.cpp b/plugins/orders.cpp index 89df783245..49558c1b88 100644 --- a/plugins/orders.cpp +++ b/plugins/orders.cpp @@ -765,8 +765,8 @@ static command_result orders_import(color_ostream &out, Json::Value &orders) if (it2.isMember("bearing")) { std::string bearing(it2["bearing"].asString()); - auto found = std::find_if(world->raws.inorganics.begin(), world->raws.inorganics.end(), [bearing](df::inorganic_raw *raw) -> bool { return raw->id == bearing; }); - if (found == world->raws.inorganics.end()) + auto found = std::find_if(world->raws.inorganics.all.begin(), world->raws.inorganics.all.end(), [bearing](df::inorganic_raw *raw) -> bool { return raw->id == bearing; }); + if (found == world->raws.inorganics.all.end()) { delete condition; @@ -774,7 +774,7 @@ static command_result orders_import(color_ostream &out, Json::Value &orders) continue; } - condition->metal_ore = found - world->raws.inorganics.begin(); + condition->metal_ore = found - world->raws.inorganics.all.begin(); } if (it2.isMember("reaction_class")) @@ -1008,8 +1008,8 @@ static bool orders_compare(df::manager_order *a, df::manager_order *b) return a->workshop_id >= 0; } - if (a->frequency == df::manager_order::T_frequency::OneTime - || b->frequency == df::manager_order::T_frequency::OneTime) + if (a->frequency == df::workquota_frequency_type::OneTime + || b->frequency == df::workquota_frequency_type::OneTime) return a->frequency < b->frequency; return a->frequency > b->frequency; } diff --git a/plugins/probe.cpp b/plugins/probe.cpp index 31c2df5edc..eff0c98c86 100644 --- a/plugins/probe.cpp +++ b/plugins/probe.cpp @@ -46,7 +46,7 @@ static command_result df_cprobe(color_ostream &out, vector & parameters) for (auto inv_item : unit->inventory) { df::item* item = inv_item->item; - if (inv_item->mode == df::unit_inventory_item::T_mode::Worn) { + if (inv_item->mode == df::inv_item_role_type::Worn) { out << " wears item: #" << item->id; if (item->flags.bits.owned) out << " (owned)"; diff --git a/plugins/prospector.cpp b/plugins/prospector.cpp index 159b557e4f..e8883fde59 100644 --- a/plugins/prospector.cpp +++ b/plugins/prospector.cpp @@ -223,9 +223,11 @@ void printVeins(color_ostream &con, MatMap &mat_map, MatMap gems; MatMap rest; + auto & inorganics = world->raws.inorganics.all; + for (const auto &kv : mat_map) { - df::inorganic_raw *gloss = vector_get(world->raws.inorganics, kv.first); + df::inorganic_raw *gloss = vector_get(inorganics, kv.first); if (!gloss) { con.printerr("invalid material gloss: %hi\n", kv.first); @@ -242,17 +244,17 @@ void printVeins(color_ostream &con, MatMap &mat_map, if (options.ores) { con << "Ores:" << std::endl; - printMats(con, ores, world->raws.inorganics, options); + printMats(con, ores, inorganics, options); } if (options.gems) { con << "Gems:" << std::endl; - printMats(con, gems, world->raws.inorganics, options); + printMats(con, gems, inorganics, options); } if (options.veins) { con << "Other vein stone:" << std::endl; - printMats(con, rest, world->raws.inorganics, options); + printMats(con, rest, inorganics, options); } } @@ -604,7 +606,7 @@ static command_result embark_prospector(color_ostream &out, // Print the report if (options.layers) { out << "Layer materials:" << std::endl; - printMats(out, layerMats, world->raws.inorganics, options); + printMats(out, layerMats, world->raws.inorganics.all, options); } if (options.hidden) { @@ -837,7 +839,7 @@ static command_result map_prospector(color_ostream &con, if (options.layers) { con << "Layer materials:" << std::endl; - printMats(con, layerMats, world->raws.inorganics, options); + printMats(con, layerMats, world->raws.inorganics.all, options); } if (options.features) { diff --git a/plugins/remotefortressreader/building_reader.cpp b/plugins/remotefortressreader/building_reader.cpp index 7cc715147b..ebf0359afd 100644 --- a/plugins/remotefortressreader/building_reader.cpp +++ b/plugins/remotefortressreader/building_reader.cpp @@ -529,7 +529,7 @@ void CopyBuilding(int buildingIndex, RemoteFortressReader::BuildingInstance * re default: break; } - if (actual->gate_flags.bits.closed) + if (actual->gate_flags.bits.raised) remote_build->set_active(1); else remote_build->set_active(0); @@ -671,7 +671,7 @@ void CopyBuilding(int buildingIndex, RemoteFortressReader::BuildingInstance * re auto actual = strict_virtual_cast(local_build); if (actual) { - if (actual->gate_flags.bits.closed) + if (actual->gate_flags.bits.retracted) remote_build->set_active(1); else remote_build->set_active(0); diff --git a/plugins/remotefortressreader/item_reader.cpp b/plugins/remotefortressreader/item_reader.cpp index 1353243b2b..58c84b9075 100644 --- a/plugins/remotefortressreader/item_reader.cpp +++ b/plugins/remotefortressreader/item_reader.cpp @@ -14,7 +14,6 @@ #include "df/art_image_property.h" #include "df/art_image_property_intransitive_verbst.h" #include "df/art_image_property_transitive_verbst.h" -#include "df/art_image_ref.h" #include "df/descriptor_shape.h" #include "df/instrument_piece.h" #include "df/instrument_register.h" @@ -240,19 +239,19 @@ void CopyItem(RemoteFortressReader::Item * NetItem, df::item * DfItem) GET_ART_IMAGE_CHUNK GetArtImageChunk = reinterpret_cast(Core::getInstance().vinfo->getAddress("get_art_image_chunk")); if (GetArtImageChunk) { - chunk = GetArtImageChunk(&(world->art_image_chunks), statue->image.id); + chunk = GetArtImageChunk(&(world->art_image_chunks.all), statue->image.id); } else { - for (size_t i = 0; i < world->art_image_chunks.size(); i++) + for (size_t i = 0; i < world->art_image_chunks.all.size(); i++) { - if (world->art_image_chunks[i]->id == statue->image.id) - chunk = world->art_image_chunks[i]; + if (world->art_image_chunks.all[i]->id == statue->image.id) + chunk = world->art_image_chunks.all[i]; } } - if (chunk && chunk->images[statue->image.subid]) + if (chunk && chunk->images[statue->image.subid].art_image) { - CopyImage(chunk->images[statue->image.subid], NetItem->mutable_image()); + CopyImage(chunk->images[statue->image.subid].art_image, NetItem->mutable_image()); } @@ -663,11 +662,11 @@ DFHack::command_result GetItemList(DFHack::color_ostream &stream, const DFHack:: { send_instrument->add_tuning_parm(*(instrument->tuning_parm[j])); } - for (size_t j = 0; j < instrument->registers.size(); j++) + for (size_t j = 0; j < instrument->timbre.registers.size(); j++) { auto reg = send_instrument->add_registers(); - reg->set_pitch_range_min(instrument->registers[j]->pitch_range_min); - reg->set_pitch_range_max(instrument->registers[j]->pitch_range_max); + reg->set_pitch_range_min(instrument->timbre.registers[j]->pitch_range_min); + reg->set_pitch_range_max(instrument->timbre.registers[j]->pitch_range_max); } send_instrument->set_description(DF2UTF(instrument->description)); } diff --git a/plugins/remotefortressreader/remotefortressreader.cpp b/plugins/remotefortressreader/remotefortressreader.cpp index ae6683dee9..697eb3fe92 100644 --- a/plugins/remotefortressreader/remotefortressreader.cpp +++ b/plugins/remotefortressreader/remotefortressreader.cpp @@ -42,6 +42,7 @@ #include "df/body_part_layer_raw.h" #include "df/body_part_raw.h" #include "df/bp_appearance_modifier.h" +#include "df/buildingitemst.h" #include "df/builtin_mats.h" #include "df/building_wellst.h" @@ -64,6 +65,7 @@ #include "df/inorganic_raw.h" #include "df/item.h" #include "df/job.h" +#include "df/job_postingst.h" #include "df/job_type.h" #include "df/job_item.h" #include "df/job_material_category.h" @@ -97,6 +99,7 @@ #include "df/unit.h" #include "df/unit_inventory_item.h" #include "df/unit_wound.h" +#include "df/unit_wound_layerst.h" #include "df/viewscreen_choose_start_sitest.h" #include "df/viewscreen_loadgamest.h" #include "df/viewscreen_savegamest.h" @@ -194,7 +197,6 @@ const char* growth_locations[] = { #include "df/art_image.h" #include "df/art_image_chunk.h" -#include "df/art_image_ref.h" command_result loadArtImageChunk(color_ostream &out, std::vector & parameters) { if (parameters.size() != 1) @@ -210,7 +212,7 @@ command_result loadArtImageChunk(color_ostream &out, std::vector & if (GetArtImageChunk) { int index = atoi(parameters[0].c_str()); - auto chunk = GetArtImageChunk(&(world->art_image_chunks), index); + auto chunk = GetArtImageChunk(&(world->art_image_chunks.all), index); out.print("Loaded chunk id: %d\n", chunk->id); } return CR_OK; @@ -809,10 +811,10 @@ static command_result GetMaterialList(color_ostream &stream, const EmptyMessage return CR_OK; } - df::world_raws *raws = &world->raws; + auto *raws = &world->raws; // df::world_history *history = &world->history; MaterialInfo mat; - for (size_t i = 0; i < raws->inorganics.size(); i++) + for (size_t i = 0; i < raws->inorganics.all.size(); i++) { mat.decode(0, i); MaterialDefinition *mat_def = out->add_material_list(); @@ -820,9 +822,9 @@ static command_result GetMaterialList(color_ostream &stream, const EmptyMessage mat_def->mutable_mat_pair()->set_mat_index(i); mat_def->set_id(mat.getToken()); mat_def->set_name(DF2UTF(mat.toString())); //find the name at cave temperature; - if (size_t(raws->inorganics[i]->material.state_color[GetState(&raws->inorganics[i]->material)]) < raws->descriptors.colors.size()) + if (size_t(raws->inorganics.all[i]->material.state_color[GetState(&raws->inorganics.all[i]->material)]) < raws->descriptors.colors.size()) { - ConvertDFColorDescriptor(raws->inorganics[i]->material.state_color[GetState(&raws->inorganics[i]->material)], mat_def->mutable_state_color()); + ConvertDFColorDescriptor(raws->inorganics.all[i]->material.state_color[GetState(&raws->inorganics.all[i]->material)], mat_def->mutable_state_color()); } } for (int i = 0; i < 19; i++) @@ -890,7 +892,7 @@ static command_result GetGrowthList(color_ostream &stream, const EmptyMessage *i - df::world_raws *raws = &world->raws; + auto *raws = &world->raws; if (!raws) return CR_OK;//'. @@ -1154,7 +1156,7 @@ void CopyDesignation(df::map_block * DfBlock, RemoteFortressReader::MapBlock * N void CopyProjectiles(RemoteFortressReader::MapBlock * NetBlock) { - for (auto proj = world->proj_list.next; proj != NULL; proj = proj->next) + for (auto proj = world->projectiles.all.next; proj != NULL; proj = proj->next) { STRICT_VIRTUAL_CAST_VAR(projectile, df::proj_itemst, proj->item); if (projectile == NULL) @@ -1187,7 +1189,7 @@ void CopyProjectiles(RemoteFortressReader::MapBlock * NetBlock) { bool isProj = false; auto vehicle = world->vehicles.active[i]; - for (auto proj = world->proj_list.next; proj != NULL; proj = proj->next) + for (auto proj = world->projectiles.all.next; proj != NULL; proj = proj->next) { STRICT_VIRTUAL_CAST_VAR(projectile, df::proj_itemst, proj->item); if (!projectile) @@ -1515,14 +1517,14 @@ static command_result GetBlockList(color_ostream &stream, const BlockRequest *in GET_ART_IMAGE_CHUNK GetArtImageChunk = reinterpret_cast(Core::getInstance().vinfo->getAddress("get_art_image_chunk")); if (GetArtImageChunk) { - chunk = GetArtImageChunk(&(world->art_image_chunks), engraving->art_id); + chunk = GetArtImageChunk(&(world->art_image_chunks.all), engraving->art_id); } else { - for (size_t i = 0; i < world->art_image_chunks.size(); i++) + for (size_t i = 0; i < world->art_image_chunks.all.size(); i++) { - if (world->art_image_chunks[i]->id == engraving->art_id) - chunk = world->art_image_chunks[i]; + if (world->art_image_chunks.all[i]->id == engraving->art_id) + chunk = world->art_image_chunks.all[i]; } } if (!chunk) @@ -1534,8 +1536,8 @@ static command_result GetBlockList(color_ostream &stream, const BlockRequest *in ConvertDFCoord(engraving->pos, netEngraving->mutable_pos()); netEngraving->set_quality(engraving->quality); netEngraving->set_tile(engraving->tile); - if (chunk->images[engraving->art_subid]) { - CopyImage(chunk->images[engraving->art_subid], netEngraving->mutable_image()); + if (chunk->images[engraving->art_subid].art_image) { + CopyImage(chunk->images[engraving->art_subid].art_image, netEngraving->mutable_image()); } netEngraving->set_floor(engraving->flags.bits.floor); netEngraving->set_west(engraving->flags.bits.west); @@ -1772,7 +1774,7 @@ static command_result GetUnitListInside(color_ostream &stream, const BlockReques if (unit->flags1.bits.projectile) { - for (auto proj = world->proj_list.next; proj != NULL; proj = proj->next) + for (auto proj = world->projectiles.all.next; proj != NULL; proj = proj->next) { STRICT_VIRTUAL_CAST_VAR(item, df::proj_unitst, proj->item); if (item == NULL) @@ -1985,27 +1987,23 @@ static command_result GetWorldMap(color_ostream &stream, const EmptyMessage *in, out->set_name(DF2UTF(Translation::translateName(&(data->name), false))); out->set_name_english(DF2UTF(Translation::translateName(&(data->name), true))); auto poles = data->flip_latitude; -#if DF_VERSION_INT > 34011 switch (poles) { - case df::world_data::None: + case df::pole_type::None: out->set_world_poles(WorldPoles::NO_POLES); break; - case df::world_data::North: + case df::pole_type::North: out->set_world_poles(WorldPoles::NORTH_POLE); break; - case df::world_data::South: + case df::pole_type::South: out->set_world_poles(WorldPoles::SOUTH_POLE); break; - case df::world_data::Both: + case df::pole_type::Both: out->set_world_poles(WorldPoles::BOTH_POLES); break; default: break; } -#else - out->set_world_poles(WorldPoles::NO_POLES); -#endif for (int yy = 0; yy < height; yy++) for (int xx = 0; xx < width; xx++) { @@ -2133,28 +2131,24 @@ static command_result GetWorldMapNew(color_ostream &stream, const EmptyMessage * out->set_world_height(height); out->set_name(DF2UTF(Translation::translateName(&(data->name), false))); out->set_name_english(DF2UTF(Translation::translateName(&(data->name), true))); -#if DF_VERSION_INT > 34011 auto poles = data->flip_latitude; switch (poles) { - case df::world_data::None: + case df::pole_type::None: out->set_world_poles(WorldPoles::NO_POLES); break; - case df::world_data::North: + case df::pole_type::North: out->set_world_poles(WorldPoles::NORTH_POLE); break; - case df::world_data::South: + case df::pole_type::South: out->set_world_poles(WorldPoles::SOUTH_POLE); break; - case df::world_data::Both: + case df::pole_type::Both: out->set_world_poles(WorldPoles::BOTH_POLES); break; default: break; } -#else - out->set_world_poles(WorldPoles::NO_POLES); -#endif for (int yy = 0; yy < height; yy++) for (int xx = 0; xx < width; xx++) { @@ -2272,28 +2266,24 @@ static void CopyLocalMap(df::world_data * worldData, df::world_region_details* w sprintf(name, "Region %d, %d", pos_x, pos_y); out->set_name_english(name); out->set_name(name); -#if DF_VERSION_INT > 34011 auto poles = worldData->flip_latitude; switch (poles) { - case df::world_data::None: + case df::pole_type::None: out->set_world_poles(WorldPoles::NO_POLES); break; - case df::world_data::North: + case df::pole_type::North: out->set_world_poles(WorldPoles::NORTH_POLE); break; - case df::world_data::South: + case df::pole_type::South: out->set_world_poles(WorldPoles::SOUTH_POLE); break; - case df::world_data::Both: + case df::pole_type::Both: out->set_world_poles(WorldPoles::BOTH_POLES); break; default: break; } -#else - out->set_world_poles(WorldPoles::NO_POLES); -#endif df::world_region_details * south = NULL; df::world_region_details * east = NULL; diff --git a/plugins/stockpiles/OrganicMatLookup.cpp b/plugins/stockpiles/OrganicMatLookup.cpp index 1efdd4df60..05cb776487 100644 --- a/plugins/stockpiles/OrganicMatLookup.cpp +++ b/plugins/stockpiles/OrganicMatLookup.cpp @@ -23,7 +23,7 @@ DBG_EXTERN(stockpiles, log); void OrganicMatLookup::food_mat_by_idx(color_ostream& out, organic_mat_category::organic_mat_category mat_category, std::vector::size_type food_idx, FoodMat& food_mat) { DEBUG(log, out).print("food_lookup: food_idx(%zd)\n", food_idx); - df::world_raws& raws = world->raws; + auto& raws = world->raws; df::special_mat_table table = raws.mat_table; int32_t main_idx = table.organic_indexes[mat_category][food_idx]; int16_t type = table.organic_types[mat_category][food_idx]; @@ -58,7 +58,7 @@ size_t OrganicMatLookup::food_max_size(organic_mat_category::organic_mat_categor void OrganicMatLookup::food_build_map() { if (index_built) return; - df::world_raws& raws = world->raws; + auto& raws = world->raws; df::special_mat_table table = raws.mat_table; using df::enums::organic_mat_category::organic_mat_category; using traits = df::enum_traits; @@ -73,7 +73,7 @@ void OrganicMatLookup::food_build_map() { } int16_t OrganicMatLookup::food_idx_by_token(color_ostream& out, organic_mat_category::organic_mat_category mat_category, const std::string& token) { - df::world_raws& raws = world->raws; + auto& raws = world->raws; df::special_mat_table table = raws.mat_table; DEBUG(log, out).print("food_idx_by_token:\n"); if (mat_category == organic_mat_category::Fish || diff --git a/plugins/stockpiles/StockpileSerializer.cpp b/plugins/stockpiles/StockpileSerializer.cpp index f315e7d674..1d11db41e5 100644 --- a/plugins/stockpiles/StockpileSerializer.cpp +++ b/plugins/stockpiles/StockpileSerializer.cpp @@ -566,7 +566,7 @@ static void unserialize_list_material(color_ostream& out, const char* subcat, bo vector& pile_list) { // we initialize all disallowed values to 1 // why? because that's how the memory is in DF before we muck with it. - size_t num_elems = world->raws.inorganics.size(); + size_t num_elems = world->raws.inorganics.all.size(); pile_list.resize(num_elems, 0); for (size_t i = 0; i < pile_list.size(); ++i) { MaterialInfo mi(0, i); @@ -814,9 +814,9 @@ void StockpileSerializer::read(color_ostream &out, DeserializeMode mode, const v void StockpileSerializer::write_containers(color_ostream& out) { DEBUG(log, out).print("writing container settings\n"); - mBuffer.set_max_bins(mPile->max_bins); - mBuffer.set_max_barrels(mPile->max_barrels); - mBuffer.set_max_wheelbarrows(mPile->max_wheelbarrows); + mBuffer.set_max_bins(mPile->storage.max_bins); + mBuffer.set_max_barrels(mPile->storage.max_barrels); + mBuffer.set_max_wheelbarrows(mPile->storage.max_wheelbarrows); } template @@ -869,21 +869,21 @@ void StockpileSerializer::read_containers(color_ostream& out, DeserializeMode mo read_elem(out, "max_bins", mode, std::bind(&StockpileSettings::has_max_bins, mBuffer), std::bind(&StockpileSettings::max_bins, mBuffer), - mPile->max_bins); + mPile->storage.max_bins); read_elem(out, "max_barrels", mode, std::bind(&StockpileSettings::has_max_barrels, mBuffer), std::bind(&StockpileSettings::max_barrels, mBuffer), - mPile->max_barrels); + mPile->storage.max_barrels); read_elem(out, "max_wheelbarrows", mode, std::bind(&StockpileSettings::has_max_wheelbarrows, mBuffer), std::bind(&StockpileSettings::max_wheelbarrows, mBuffer), - mPile->max_wheelbarrows); + mPile->storage.max_wheelbarrows); } void StockpileSettingsSerializer::write_general(color_ostream& out) { DEBUG(log, out).print("writing general settings\n"); - mBuffer.set_allow_inorganic(mSettings->allow_inorganic); - mBuffer.set_allow_organic(mSettings->allow_organic); + mBuffer.set_allow_inorganic(mSettings->misc.allow_inorganic); + mBuffer.set_allow_organic(mSettings->misc.allow_organic); } void StockpileSerializer::write_general(color_ostream& out) { @@ -895,11 +895,11 @@ void StockpileSettingsSerializer::read_general(color_ostream& out, DeserializeMo read_elem(out, "allow_inorganic", mode, std::bind(&StockpileSettings::has_allow_inorganic, mBuffer), std::bind(&StockpileSettings::allow_inorganic, mBuffer), - mSettings->allow_inorganic); + mSettings->misc.allow_inorganic); read_elem(out, "allow_organic", mode, std::bind(&StockpileSettings::has_allow_organic, mBuffer), std::bind(&StockpileSettings::allow_organic, mBuffer), - mSettings->allow_organic); + mSettings->misc.allow_organic); } void StockpileSerializer::read_general(color_ostream& out, DeserializeMode mode) { diff --git a/plugins/strangemood.cpp b/plugins/strangemood.cpp index 4955d49e96..98b8b4b725 100644 --- a/plugins/strangemood.cpp +++ b/plugins/strangemood.cpp @@ -644,8 +644,8 @@ command_result df_strangemood (color_ostream &out, vector & parameters) for (size_t i = 0; i < soul->preferences.size(); i++) { df::unit_preference *pref = soul->preferences[i]; - if (pref->active == 1 && - pref->type == df::unit_preference::T_type::LikeMaterial && + if (pref->flags.bits.visible && + pref->type == df::unitpref_type::LikeMaterial && pref->mattype == builtin_mats::INORGANIC) { item->mat_type = pref->mattype; @@ -722,8 +722,8 @@ command_result df_strangemood (color_ostream &out, vector & parameters) for (size_t i = 0; i < soul->preferences.size(); i++) { df::unit_preference *pref = soul->preferences[i]; - if (pref->active == 1 && - pref->type == df::unit_preference::T_type::LikeMaterial) + if (pref->flags.bits.visible && + pref->type == df::unitpref_type::LikeMaterial) { MaterialInfo mat(pref->mattype, pref->matindex); if (mat.material->flags.is_set(material_flags::SILK)) @@ -805,8 +805,8 @@ command_result df_strangemood (color_ostream &out, vector & parameters) for (size_t i = 0; i < soul->preferences.size(); i++) { df::unit_preference *pref = soul->preferences[i]; - if (pref->active == 1 && - pref->type == df::unit_preference::T_type::LikeMaterial && + if (pref->flags.bits.visible && + pref->type == df::unitpref_type::LikeMaterial && pref->mattype == 0 && getCreatedMetalBars(pref->matindex) > 0) mats.push_back(pref->matindex); } @@ -835,8 +835,8 @@ command_result df_strangemood (color_ostream &out, vector & parameters) for (size_t i = 0; i < soul->preferences.size(); i++) { df::unit_preference *pref = soul->preferences[i]; - if (pref->active == 1 && - pref->type == df::unit_preference::T_type::LikeMaterial && + if (pref->flags.bits.visible && + pref->type == df::unitpref_type::LikeMaterial && ((pref->mattype == builtin_mats::GLASS_GREEN) || (pref->mattype == builtin_mats::GLASS_CLEAR && have_glass[1]) || (pref->mattype == builtin_mats::GLASS_CRYSTAL && have_glass[2]))) @@ -867,8 +867,8 @@ command_result df_strangemood (color_ostream &out, vector & parameters) for (size_t i = 0; i < soul->preferences.size(); i++) { df::unit_preference *pref = soul->preferences[i]; - if (pref->active == 1 && - pref->type == df::unit_preference::T_type::LikeMaterial) + if (pref->flags.bits.visible && + pref->type == df::unitpref_type::LikeMaterial) { MaterialInfo mat(pref->mattype, pref->matindex); if (mat.material->flags.is_set(material_flags::BONE)) diff --git a/plugins/tailor.cpp b/plugins/tailor.cpp index ad96302887..ef9b77c67a 100644 --- a/plugins/tailor.cpp +++ b/plugins/tailor.cpp @@ -276,7 +276,7 @@ class Tailor { for (auto inv : u->inventory) { - if (inv->mode != df::unit_inventory_item::Worn) + if (inv->mode != df::inv_item_role_type::Worn) continue; // skip non-clothing if (!inv->item->isClothing()) @@ -456,7 +456,7 @@ class Tailor { order->mat_index == -1 && order->specdata.hist_figure_id == hfid && order->material_category.whole == mcat.whole && - order->frequency == df::manager_order::T_frequency::OneTime) + order->frequency == df::workquota_frequency_type::OneTime) return order; } return NULL; diff --git a/plugins/timestream.cpp b/plugins/timestream.cpp index a472c2efec..ea75ced359 100644 --- a/plugins/timestream.cpp +++ b/plugins/timestream.cpp @@ -32,6 +32,7 @@ #include "df/activity_event_worshipst.h" #include "df/building_nest_boxst.h" #include "df/building_trapst.h" +#include "df/buildingitemst.h" #include "df/init.h" #include "df/item_eggst.h" #include "df/unit.h" @@ -409,7 +410,9 @@ static void adjust_activities(color_ostream &out, int32_t timeskip) { for (auto act : world->activities.all) { for (auto ev : act->events) { switch (ev->getType()) { - using namespace df::enums::activity_event_type; + using namespace df::enums::activity_event_type; + case NONE: + break; case TrainingSession: // no counters From 3583334b7aa0039f78dd852f32c2482ec5886672 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sat, 8 Feb 2025 14:55:38 -0800 Subject: [PATCH 24/29] update core/plugin lua for great reorg --- library/lua/gui/dwarfmode.lua | 2 +- library/lua/syndrome-util.lua | 2 +- plugins/lua/buildingplan/planneroverlay.lua | 2 +- plugins/lua/sort/diplomacy.lua | 2 +- test/library/print.lua | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/lua/gui/dwarfmode.lua b/library/lua/gui/dwarfmode.lua index 793acbd520..61317f9ebc 100644 --- a/library/lua/gui/dwarfmode.lua +++ b/library/lua/gui/dwarfmode.lua @@ -249,7 +249,7 @@ end function get_hotkey_target(key) local hk = HOTKEY_KEYS[key] - if hk and hk.cmd == df.ui_hotkey.T_cmd.Zoom then + if hk and hk.cmd == df.hotkey_type.Zoom then return xyz2pos(hk.x, hk.y, hk.z) end end diff --git a/library/lua/syndrome-util.lua b/library/lua/syndrome-util.lua index efbaa5deaa..c0af9f8a72 100644 --- a/library/lua/syndrome-util.lua +++ b/library/lua/syndrome-util.lua @@ -98,7 +98,7 @@ function infectWithSyndrome(target,syndrome,resetPolicy) unitSyndrome.ticks = 0 unitSyndrome.wound_id = -1 for k,v in ipairs(syndrome.ce) do - local symptom = df.unit_syndrome.T_symptoms:new() + local symptom = df.active_creature_interaction_effectst:new() symptom.quantity = 0 symptom.delay = 0 symptom.ticks = 0 diff --git a/plugins/lua/buildingplan/planneroverlay.lua b/plugins/lua/buildingplan/planneroverlay.lua index 62e1a6c49c..f92dc95d84 100644 --- a/plugins/lua/buildingplan/planneroverlay.lua +++ b/plugins/lua/buildingplan/planneroverlay.lua @@ -1348,7 +1348,7 @@ function PlannerOverlay:place_building(placement_data, chosen_items) dfhack.printerr(('item no longer available: %d'):format(item_id)) break end - if not dfhack.job.attachJobItem(job, item, df.job_item_ref.T_role.Hauled, idx-1, -1) then + if not dfhack.job.attachJobItem(job, item, df.job_role_type.Hauled, idx-1, -1) then dfhack.printerr(('cannot attach item: %d'):format(item_id)) break end diff --git a/plugins/lua/sort/diplomacy.lua b/plugins/lua/sort/diplomacy.lua index c0ec818505..3e78593862 100644 --- a/plugins/lua/sort/diplomacy.lua +++ b/plugins/lua/sort/diplomacy.lua @@ -64,7 +64,7 @@ local function get_preferences(unit) if not unit then return {} end local preferences = {} for _, pref in ipairs(unit.status.current_soul.preferences) do - if pref.type == df.unit_preference.T_type.LikeItem and pref.active then + if pref.type == df.unitpref_type.LikeItem and pref.active then table.insert(preferences, make_item_description(pref.item_type, pref.item_subtype)) end end diff --git a/test/library/print.lua b/test/library/print.lua index 28a2e70370..79243d8989 100644 --- a/test/library/print.lua +++ b/test/library/print.lua @@ -47,7 +47,7 @@ end local function new_int_vector() -- create a vector of integers by cloning one from world. we do it this way -- because we can't allocate typed vectors from lua directly. - local vector = df.global.world.busy_buildings:new() + local vector = df.global.world.building_uses.buildings:new() vector:resize(0) return vector end From 17be93cb594379622ec8309ef1490c4d35ce2889 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sat, 8 Feb 2025 16:58:00 -0800 Subject: [PATCH 25/29] ignore missing viewscreens unused viewscreens are optimized out of windows builds but not linux builds, so this is necessary to get this test to pass on Windows --- test/structures/misc.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/structures/misc.lua b/test/structures/misc.lua index 13febff566..33d386b832 100644 --- a/test/structures/misc.lua +++ b/test/structures/misc.lua @@ -28,8 +28,10 @@ function test.viewscreenDtors() for name, type in pairs(df) do if name:startswith('viewscreen') then print('testing', name) - local v = type:new() - expect.true_(v:delete(), "destructor returned false: " .. name) + local ok, v = pcall(function() return type:new() end) + if ok then + expect.true_(v:delete(), "destructor returned false: " .. name) + end end end end From df46a55a523606ba005ac61639cbac3b31974989 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sat, 8 Feb 2025 23:13:44 -0800 Subject: [PATCH 26/29] add unit test for allocating and deallocating all types --- test/structures/misc.lua | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/test/structures/misc.lua b/test/structures/misc.lua index 33d386b832..ab58187b31 100644 --- a/test/structures/misc.lua +++ b/test/structures/misc.lua @@ -24,14 +24,39 @@ function test.overlappingGlobals() end end -function test.viewscreenDtors() +local known_bad_types = { + -- renderer base class has non-destructible padding declared + renderer_2d_base=true, + renderer_2d=true, + renderer_offscreen=true, + + -- abstract base classes that aren't instantiable + active_script_varst=true, + widget_sheet_button=true, +} + +if dfhack.getOSType() == 'linux' then + -- empty destructors are declared inline for these types, + -- and gcc appears to optimize them out + known_bad_types.mental_picture_propertyst = true + known_bad_types.region_block_eventst = true +end + +function test.destructors() + local count = 1 for name, type in pairs(df) do - if name:startswith('viewscreen') then - print('testing', name) - local ok, v = pcall(function() return type:new() end) - if ok then - expect.true_(v:delete(), "destructor returned false: " .. name) - end + if known_bad_types[name] then + goto continue + end + print(('testing constructor %5d: %s'):format(count, name)) + local ok, v = pcall(function() return type:new() end) + if not ok then + print(' constructor failed; skipping destructor test') + else + print(' destructor ok') + expect.true_(v:delete(), "destructor returned false: " .. name) end + count = count + 1 + ::continue:: end end From 6518abd6d6384105d5d534e3a56c464ddc0c03aa Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sat, 8 Feb 2025 07:34:29 -0800 Subject: [PATCH 27/29] update submodule refs --- library/xml | 2 +- plugins/stonesense | 2 +- scripts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/xml b/library/xml index b3202b06e0..2a84adf2fe 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit b3202b06e04c03433565e8248f2638dddde4ee22 +Subproject commit 2a84adf2fe1e76f5244f51cd4536442ebce10b5d diff --git a/plugins/stonesense b/plugins/stonesense index 92794aec77..8d445c72d5 160000 --- a/plugins/stonesense +++ b/plugins/stonesense @@ -1 +1 @@ -Subproject commit 92794aec7768bdafd0f5fc23fed8b30655805b32 +Subproject commit 8d445c72d5bc797bc2e8f6d0c42091fc068d0893 diff --git a/scripts b/scripts index fc67fdc5b6..fc3f7d044b 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit fc67fdc5b67a25a776eebfa769b289801679e364 +Subproject commit fc3f7d044b1b45f3ad7b9f7ba3bcc5a4bb24b09b From 47792ce67181d476c14123232e61d4de2192890a Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 9 Feb 2025 17:06:51 -0800 Subject: [PATCH 28/29] finish updating modules for the Great Reorg --- library/lua/custom-raw-tokens.lua | 2 +- library/lua/dfhack/workshops.lua | 2 +- library/lua/gui/materials.lua | 6 +++--- plugins/lua/sort.lua | 4 ++-- plugins/lua/stockflow.lua | 2 +- plugins/rendermax/rendermax.lua | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/library/lua/custom-raw-tokens.lua b/library/lua/custom-raw-tokens.lua index 6c19deb72a..7975ba5e39 100644 --- a/library/lua/custom-raw-tokens.lua +++ b/library/lua/custom-raw-tokens.lua @@ -300,7 +300,7 @@ local function getTokenArg1Else(userdata, token) elseif df.is_instance(df.building_workshopst, userdata) or df.is_instance(df.building_furnacest, userdata) then rawStruct = df.building_def.find(userdata.custom_type) elseif df.is_instance(df.interaction_instance, userdata) then - rawStruct = df.global.world.raws.interactions[userdata.interaction_id] + rawStruct = df.global.world.raws.interactions.all[userdata.interaction_id] else -- Assume raw struct *is* argument 1 rawStruct = userdata diff --git a/library/lua/dfhack/workshops.lua b/library/lua/dfhack/workshops.lua index a09849a57d..f43429642f 100644 --- a/library/lua/dfhack/workshops.lua +++ b/library/lua/dfhack/workshops.lua @@ -509,7 +509,7 @@ local function addReactionJobs(ret,bid,wid,cid) end local function scanRawsOres() local ret={} - for idx,ore in ipairs(df.global.world.raws.inorganics) do + for idx,ore in ipairs(df.global.world.raws.inorganics.all) do if #ore.metal_ore.mat_index~=0 then ret[idx]=ore end diff --git a/library/lua/gui/materials.lua b/library/lua/gui/materials.lua index d3a9408a51..7429a78237 100644 --- a/library/lua/gui/materials.lua +++ b/library/lua/gui/materials.lua @@ -116,7 +116,7 @@ end function MaterialDialog:initInorganicMode() local choices = {} - for i,mat in ipairs(df.global.world.raws.inorganics) do + for i,mat in ipairs(df.global.world.raws.inorganics.all) do self:addMaterial(choices, mat.material, 0, i, false, mat) end @@ -378,14 +378,14 @@ function ItemTraitsDialog(args) end -------------------------------------- local set_ore_ix = {} - for i, raw in ipairs(df.global.world.raws.inorganics) do + for i, raw in ipairs(df.global.world.raws.inorganics.all) do for _, ix in ipairs(raw.metal_ore.mat_index) do set_ore_ix[ix] = true end end local ores = {} for ix in pairs(set_ore_ix) do - local raw = df.global.world.raws.inorganics[ix] + local raw = df.global.world.raws.inorganics.all[ix] ores[#ores+1] = {mat_index = ix, name = raw.material.state_name.Solid} end table.sort(ores, function(a,b) return a.name < b.name end) diff --git a/plugins/lua/sort.lua b/plugins/lua/sort.lua index fe42cbb1ed..5777d2b174 100644 --- a/plugins/lua/sort.lua +++ b/plugins/lua/sort.lua @@ -43,7 +43,7 @@ local function get_active_idx_cache() end local function is_original_dwarf(unit) - return df.global.plotinfo.fortress_age == unit.curse.time_on_site // 10 + return df.global.plotinfo.fortress_age == unit.curse.interaction.time_on_site // 10 end local WAVE_END_GAP = 10000 @@ -53,7 +53,7 @@ local function get_most_recent_wave_oldest_active_idx(cache) for idx=#active_units-1,0,-1 do local unit = active_units[idx] if not dfhack.units.isCitizen(unit) then goto continue end - if oldest_unit and unit.curse.time_on_site - oldest_unit.curse.time_on_site > WAVE_END_GAP then + if oldest_unit and unit.curse.interaction.time_on_site - oldest_unit.curse.interaction.time_on_site > WAVE_END_GAP then return cache[oldest_unit.id] else oldest_unit = unit diff --git a/plugins/lua/stockflow.lua b/plugins/lua/stockflow.lua index 3b2b0fe669..dc44d23045 100644 --- a/plugins/lua/stockflow.lua +++ b/plugins/lua/stockflow.lua @@ -283,7 +283,7 @@ function collect_reactions() reaction_entry(result, job_types.CatchLiveFish) -- Cutting, encrusting, and metal extraction. - local rock_types = df.global.world.raws.inorganics + local rock_types = df.global.world.raws.inorganics.all for rock_id = #rock_types-1, 0, -1 do local material = rock_types[rock_id].material local rock_name = material.state_adj.Solid diff --git a/plugins/rendermax/rendermax.lua b/plugins/rendermax/rendermax.lua index f1cfa90203..6aacbde64f 100644 --- a/plugins/rendermax/rendermax.lua +++ b/plugins/rendermax/rendermax.lua @@ -164,7 +164,7 @@ function colorFrom16(col16) return {col[0],col[1],col[2]} end function addGems() - for k,v in pairs(df.global.world.raws.inorganics) do + for k,v in pairs(df.global.world.raws.inorganics.all) do if v.material.flags.IS_GEM then addMaterial("INORGANIC:"..v.id,colorFrom16(v.material.tile_color[0]+v.material.tile_color[2]*8)) end From 82c6551ebcb135f73ddb49e7d0d4533b2f794ccf Mon Sep 17 00:00:00 2001 From: DFHack-Urist via GitHub Actions <63161697+DFHack-Urist@users.noreply.github.com> Date: Mon, 10 Feb 2025 01:35:43 +0000 Subject: [PATCH 29/29] Auto-update submodules library/xml: master scripts: master plugins/stonesense: master --- library/xml | 2 +- plugins/stonesense | 2 +- scripts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/xml b/library/xml index 2a84adf2fe..9bf00722a7 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 2a84adf2fe1e76f5244f51cd4536442ebce10b5d +Subproject commit 9bf00722a739e6c00fd2a2c19ac7208e6f337ed3 diff --git a/plugins/stonesense b/plugins/stonesense index 8d445c72d5..9f5aa0f22e 160000 --- a/plugins/stonesense +++ b/plugins/stonesense @@ -1 +1 @@ -Subproject commit 8d445c72d5bc797bc2e8f6d0c42091fc068d0893 +Subproject commit 9f5aa0f22e70d3c9c0145fe2c4b4047a54dddca9 diff --git a/scripts b/scripts index fc3f7d044b..795cba2474 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit fc3f7d044b1b45f3ad7b9f7ba3bcc5a4bb24b09b +Subproject commit 795cba2474b928771cf59d6fc3690f4f5622bf99