From 73b5f0ced11d711f506e36f077689535c0d43ce1 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 10 Sep 2023 20:20:04 -0700 Subject: [PATCH] continue to highlight designations once they have become jobs --- plugins/pathable.cpp | 149 ++++++++++++++++++++++++++++++++----------- 1 file changed, 112 insertions(+), 37 deletions(-) diff --git a/plugins/pathable.cpp b/plugins/pathable.cpp index e93905a71..57f5a5853 100644 --- a/plugins/pathable.cpp +++ b/plugins/pathable.cpp @@ -3,15 +3,18 @@ #include "PluginManager.h" #include "TileTypes.h" +#include "modules/EventManager.h" #include "modules/Gui.h" #include "modules/Maps.h" #include "modules/Screen.h" #include "modules/Textures.h" +#include "df/block_square_event_designation_priorityst.h" #include "df/init.h" +#include "df/job_list_link.h" #include "df/map_block.h" #include "df/tile_designation.h" -#include "df/block_square_event_designation_priorityst.h" +#include "df/world.h" #include @@ -23,6 +26,7 @@ REQUIRE_GLOBAL(init); REQUIRE_GLOBAL(window_x); REQUIRE_GLOBAL(window_y); REQUIRE_GLOBAL(window_z); +REQUIRE_GLOBAL(world); namespace DFHack { DBG_DECLARE(pathable, log, DebugCategory::LINFO); @@ -211,58 +215,126 @@ static void paintScreenWarmDamp(bool show_hidden = false) { } } -static bool is_designated_for_smoothing(const df::coord &pos) { - auto des = Maps::getTileDesignation(pos); - if (!des) - return false; - return des->bits.smooth == 1; +struct designation{ + df::coord pos; + df::tile_designation td; + df::tile_occupancy to; + designation() = default; + designation(const df::coord &c, const df::tile_designation &td, const df::tile_occupancy &to) : pos(c), td(td), to(to) {} + + bool operator==(const designation &rhs) const { + return pos == rhs.pos; + } + + bool operator!=(const designation &rhs) const { + return !(rhs == *this); + } +}; + +namespace std { + template<> + struct hash { + std::size_t operator()(const designation &c) const { + std::hash hash_coord; + return hash_coord(c.pos); + } + }; } -static bool is_designated_for_engraving(const df::coord &pos) { - auto des = Maps::getTileDesignation(pos); - if (!des) - return false; - return des->bits.smooth == 2; +class Designations { +private: + std::unordered_map designations; +public: + Designations() { + df::job_list_link *link = world->jobs.list.next; + for (; link; link = link->next) { + df::job *job = link->item; + + if(!job || !Maps::isValidTilePos(job->pos)) + continue; + + df::tile_designation td; + df::tile_occupancy to; + switch (job->job_type) { + case df::job_type::SmoothWall: + case df::job_type::SmoothFloor: + case df::job_type::CarveFortification: + td.bits.smooth = 1; + break; + case df::job_type::DetailWall: + case df::job_type::DetailFloor: + td.bits.smooth = 2; + break; + case job_type::CarveTrack: + to.bits.carve_track_north = (job->item_category.whole >> 18) & 1; + to.bits.carve_track_south = (job->item_category.whole >> 19) & 1; + to.bits.carve_track_west = (job->item_category.whole >> 20) & 1; + to.bits.carve_track_east = (job->item_category.whole >> 21) & 1; + break; + default: + break; + } + designations.emplace(job->pos, designation(job->pos, td, to)); + } + } + + // get from job; if no job, then fall back to querying map + designation get(const df::coord &pos) const { + if (designations.count(pos)) { + return designations.at(pos); + } + auto pdes = Maps::getTileDesignation(pos); + auto pocc = Maps::getTileOccupancy(pos); + if (!pdes || !pocc) + return {}; + return designation(pos, *pdes, *pocc); + } +}; + +static bool is_designated_for_smoothing(const designation &designation) { + return designation.td.bits.smooth == 1; } -static bool is_designated_for_track_carving(const df::coord &pos) { - auto occ = Maps::getTileOccupancy(pos); - if (!occ) - return false; - return occ->bits.carve_track_east || occ->bits.carve_track_north || occ->bits.carve_track_south || occ->bits.carve_track_west; +static bool is_designated_for_engraving(const designation &designation) { + return designation.td.bits.smooth == 2; } -static char get_track_char(const df::coord &pos) { - auto occ = Maps::getTileOccupancy(pos); - if (occ->bits.carve_track_east && occ->bits.carve_track_north && occ->bits.carve_track_south && occ->bits.carve_track_west) +static bool is_designated_for_track_carving(const designation &designation) { + const df::tile_occupancy &occ = designation.to; + return occ.bits.carve_track_east || occ.bits.carve_track_north || occ.bits.carve_track_south || occ.bits.carve_track_west; +} + +static char get_track_char(const designation &designation) { + const df::tile_occupancy &occ = designation.to; + if (occ.bits.carve_track_east && occ.bits.carve_track_north && occ.bits.carve_track_south && occ.bits.carve_track_west) return (char)0xCE; // NSEW - if (occ->bits.carve_track_east && occ->bits.carve_track_north && occ->bits.carve_track_south) + if (occ.bits.carve_track_east && occ.bits.carve_track_north && occ.bits.carve_track_south) return (char)0xCC; // NSE - if (occ->bits.carve_track_east && occ->bits.carve_track_north && occ->bits.carve_track_west) + if (occ.bits.carve_track_east && occ.bits.carve_track_north && occ.bits.carve_track_west) return (char)0xCA; // NEW - if (occ->bits.carve_track_east && occ->bits.carve_track_south && occ->bits.carve_track_west) + if (occ.bits.carve_track_east && occ.bits.carve_track_south && occ.bits.carve_track_west) return (char)0xCB; // SEW - if (occ->bits.carve_track_north && occ->bits.carve_track_south && occ->bits.carve_track_west) + if (occ.bits.carve_track_north && occ.bits.carve_track_south && occ.bits.carve_track_west) return (char)0xB9; // NSW - if (occ->bits.carve_track_north && occ->bits.carve_track_south) + if (occ.bits.carve_track_north && occ.bits.carve_track_south) return (char)0xBA; // NS - if (occ->bits.carve_track_east && occ->bits.carve_track_west) + if (occ.bits.carve_track_east && occ.bits.carve_track_west) return (char)0xCD; // EW - if (occ->bits.carve_track_east && occ->bits.carve_track_north) + if (occ.bits.carve_track_east && occ.bits.carve_track_north) return (char)0xC8; // NE - if (occ->bits.carve_track_north && occ->bits.carve_track_west) + if (occ.bits.carve_track_north && occ.bits.carve_track_west) return (char)0xBC; // NW - if (occ->bits.carve_track_east && occ->bits.carve_track_south) + if (occ.bits.carve_track_east && occ.bits.carve_track_south) return (char)0xC9; // SE - if (occ->bits.carve_track_south && occ->bits.carve_track_west) + if (occ.bits.carve_track_south && occ.bits.carve_track_west) return (char)0xBB; // SW - if (occ->bits.carve_track_north) + if (occ.bits.carve_track_north) return (char)0xD0; // N - if (occ->bits.carve_track_south) + if (occ.bits.carve_track_south) return (char)0xD2; // S - if (occ->bits.carve_track_east) + if (occ.bits.carve_track_east) return (char)0xC6; // E - if (occ->bits.carve_track_west) + if (occ.bits.carve_track_west) return (char)0xB5; // W return (char)0xC5; // single line cross; should never happen } @@ -304,6 +376,7 @@ static void paintScreenCarve() { if (Screen::inGraphicsMode() || blink(500)) return; + Designations designations; bool draw_priority = blink(1000); auto dims = Gui::getDwarfmodeViewDims().map(); @@ -325,17 +398,19 @@ static void paintScreenCarve() { Screen::Pen cur_tile; cur_tile.fg = COLOR_DARKGREY; - if (is_designated_for_smoothing(map_pos)) { + auto des = designations.get(map_pos); + + if (is_designated_for_smoothing(des)) { if (is_smooth_wall(map_pos)) cur_tile.ch = get_tile_char(map_pos, (char)206, draw_priority); // hash, indicating a fortification designation else cur_tile.ch = get_tile_char(map_pos, (char)219, draw_priority); // solid block, indicating a smoothing designation } - else if (is_designated_for_engraving(map_pos)) { + else if (is_designated_for_engraving(des)) { cur_tile.ch = get_tile_char(map_pos, (char)10, draw_priority); // solid block with a circle on it } - else if (is_designated_for_track_carving(map_pos)) { - cur_tile.ch = get_tile_char(map_pos, get_track_char(map_pos), draw_priority); // directional track + else if (is_designated_for_track_carving(des)) { + cur_tile.ch = get_tile_char(map_pos, get_track_char(des), draw_priority); // directional track } else { TRACE(log).print("skipping tile with no carving designation\n");