|
|
|
@ -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 <functional>
|
|
|
|
|
|
|
|
|
@ -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<designation> {
|
|
|
|
|
std::size_t operator()(const designation &c) const {
|
|
|
|
|
std::hash<df::coord> 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<df::coord, designation> 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");
|
|
|
|
|