Skip to content

Commit 23a32fa

Browse files
committed
upstream
1 parent 87bf5d8 commit 23a32fa

File tree

3 files changed

+230
-3
lines changed

3 files changed

+230
-3
lines changed

docs/dev/Lua API.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3549,6 +3549,13 @@ parameters.
35493549
``tonumber(arg)``. If ``arg_name`` is specified, it is used to make error
35503550
messages more useful.
35513551

3552+
* ``argparse.boolean(arg, arg_name)``
3553+
3554+
Converts ``string.lower(arg)`` from "yes/no/on/off/true/false/etc..." to a lua
3555+
boolean. Throws if the value can't be converted, otherwise returns
3556+
``true``/``false``. If ``arg_name`` is specified, it is used to make error
3557+
messages more useful.
3558+
35523559
dumper
35533560
======
35543561

library/LuaApi.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,8 +1368,8 @@ static CommandHistory * ensureCommandHistory(std::string id,
13681368

13691369
static int getCommandHistory(lua_State *state)
13701370
{
1371-
std::string id = lua_tostring(state, 1);
1372-
std::string src_file = lua_tostring(state, 2);
1371+
std::string id = luaL_checkstring(state, 1);
1372+
std::string src_file = luaL_checkstring(state, 2);
13731373
std::vector<std::string> entries;
13741374
ensureCommandHistory(id, src_file)->getEntries(entries);
13751375
Lua::PushVector(state, entries);
@@ -2033,7 +2033,7 @@ static int units_getCitizens(lua_State *L) {
20332033
}
20342034

20352035
static int units_getUnitsByNobleRole(lua_State *L) {
2036-
std::string role_name = lua_tostring(L, -1);
2036+
std::string role_name = luaL_checkstring(L, -1);
20372037
std::vector<df::unit *> units;
20382038
Units::getUnitsByNobleRole(units, role_name);
20392039
Lua::PushVector(L, units);

plugins/pathable.cpp

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
#include "Debug.h"
2+
#include "MemAccess.h"
23
#include "PluginManager.h"
34
#include "TileTypes.h"
45

6+
#include "modules/EventManager.h"
57
#include "modules/Gui.h"
8+
#include "modules/Job.h"
69
#include "modules/Maps.h"
710
#include "modules/Screen.h"
811
#include "modules/Textures.h"
912

13+
#include "df/block_square_event_designation_priorityst.h"
1014
#include "df/init.h"
15+
#include "df/job_list_link.h"
1116
#include "df/map_block.h"
1217
#include "df/tile_designation.h"
18+
#include "df/world.h"
1319

1420
#include <functional>
1521

@@ -21,6 +27,7 @@ REQUIRE_GLOBAL(init);
2127
REQUIRE_GLOBAL(window_x);
2228
REQUIRE_GLOBAL(window_y);
2329
REQUIRE_GLOBAL(window_z);
30+
REQUIRE_GLOBAL(world);
2431

2532
namespace DFHack {
2633
DBG_DECLARE(pathable, log, DebugCategory::LINFO);
@@ -209,8 +216,221 @@ static void paintScreenWarmDamp(bool show_hidden = false) {
209216
}
210217
}
211218

219+
struct designation{
220+
df::coord pos;
221+
df::tile_designation td;
222+
df::tile_occupancy to;
223+
designation() = default;
224+
designation(const df::coord &c, const df::tile_designation &td, const df::tile_occupancy &to) : pos(c), td(td), to(to) {}
225+
226+
bool operator==(const designation &rhs) const {
227+
return pos == rhs.pos;
228+
}
229+
230+
bool operator!=(const designation &rhs) const {
231+
return !(rhs == *this);
232+
}
233+
};
234+
235+
namespace std {
236+
template<>
237+
struct hash<designation> {
238+
std::size_t operator()(const designation &c) const {
239+
std::hash<df::coord> hash_coord;
240+
return hash_coord(c.pos);
241+
}
242+
};
243+
}
244+
245+
class Designations {
246+
private:
247+
std::unordered_map<df::coord, designation> designations;
248+
public:
249+
Designations() {
250+
df::job_list_link *link = world->jobs.list.next;
251+
for (; link; link = link->next) {
252+
df::job *job = link->item;
253+
254+
if(!job || !Maps::isValidTilePos(job->pos))
255+
continue;
256+
257+
df::tile_designation td;
258+
df::tile_occupancy to;
259+
bool keep_if_taken = false;
260+
261+
switch (job->job_type) {
262+
case df::job_type::SmoothWall:
263+
case df::job_type::SmoothFloor:
264+
keep_if_taken = true;
265+
// fallthrough
266+
case df::job_type::CarveFortification:
267+
td.bits.smooth = 1;
268+
break;
269+
case df::job_type::DetailWall:
270+
case df::job_type::DetailFloor:
271+
td.bits.smooth = 2;
272+
break;
273+
case job_type::CarveTrack:
274+
to.bits.carve_track_north = (job->item_category.whole >> 18) & 1;
275+
to.bits.carve_track_south = (job->item_category.whole >> 19) & 1;
276+
to.bits.carve_track_west = (job->item_category.whole >> 20) & 1;
277+
to.bits.carve_track_east = (job->item_category.whole >> 21) & 1;
278+
break;
279+
default:
280+
continue;
281+
}
282+
if (keep_if_taken || !Job::getWorker(job))
283+
designations.emplace(job->pos, designation(job->pos, td, to));
284+
}
285+
}
286+
287+
// get from job; if no job, then fall back to querying map
288+
designation get(const df::coord &pos) const {
289+
if (designations.count(pos)) {
290+
return designations.at(pos);
291+
}
292+
auto pdes = Maps::getTileDesignation(pos);
293+
auto pocc = Maps::getTileOccupancy(pos);
294+
if (!pdes || !pocc)
295+
return {};
296+
return designation(pos, *pdes, *pocc);
297+
}
298+
};
299+
300+
static bool is_designated_for_smoothing(const designation &designation) {
301+
return designation.td.bits.smooth == 1;
302+
}
303+
304+
static bool is_designated_for_engraving(const designation &designation) {
305+
return designation.td.bits.smooth == 2;
306+
}
307+
308+
static bool is_designated_for_track_carving(const designation &designation) {
309+
const df::tile_occupancy &occ = designation.to;
310+
return occ.bits.carve_track_east || occ.bits.carve_track_north || occ.bits.carve_track_south || occ.bits.carve_track_west;
311+
}
312+
313+
static char get_track_char(const designation &designation) {
314+
const df::tile_occupancy &occ = designation.to;
315+
if (occ.bits.carve_track_east && occ.bits.carve_track_north && occ.bits.carve_track_south && occ.bits.carve_track_west)
316+
return (char)0xCE; // NSEW
317+
if (occ.bits.carve_track_east && occ.bits.carve_track_north && occ.bits.carve_track_south)
318+
return (char)0xCC; // NSE
319+
if (occ.bits.carve_track_east && occ.bits.carve_track_north && occ.bits.carve_track_west)
320+
return (char)0xCA; // NEW
321+
if (occ.bits.carve_track_east && occ.bits.carve_track_south && occ.bits.carve_track_west)
322+
return (char)0xCB; // SEW
323+
if (occ.bits.carve_track_north && occ.bits.carve_track_south && occ.bits.carve_track_west)
324+
return (char)0xB9; // NSW
325+
if (occ.bits.carve_track_north && occ.bits.carve_track_south)
326+
return (char)0xBA; // NS
327+
if (occ.bits.carve_track_east && occ.bits.carve_track_west)
328+
return (char)0xCD; // EW
329+
if (occ.bits.carve_track_east && occ.bits.carve_track_north)
330+
return (char)0xC8; // NE
331+
if (occ.bits.carve_track_north && occ.bits.carve_track_west)
332+
return (char)0xBC; // NW
333+
if (occ.bits.carve_track_east && occ.bits.carve_track_south)
334+
return (char)0xC9; // SE
335+
if (occ.bits.carve_track_south && occ.bits.carve_track_west)
336+
return (char)0xBB; // SW
337+
if (occ.bits.carve_track_north)
338+
return (char)0xD0; // N
339+
if (occ.bits.carve_track_south)
340+
return (char)0xD2; // S
341+
if (occ.bits.carve_track_east)
342+
return (char)0xC6; // E
343+
if (occ.bits.carve_track_west)
344+
return (char)0xB5; // W
345+
return (char)0xC5; // single line cross; should never happen
346+
}
347+
348+
static bool is_smooth_wall(const df::coord &pos) {
349+
df::tiletype *tt = Maps::getTileType(pos);
350+
return tt && tileSpecial(*tt) == df::tiletype_special::SMOOTH
351+
&& tileShape(*tt) == df::tiletype_shape::WALL;
352+
}
353+
354+
static bool blink(int delay) {
355+
return (Core::getInstance().p->getTickCount()/delay) % 2 == 0;
356+
}
357+
358+
static char get_tile_char(const df::coord &pos, char desig_char, bool draw_priority) {
359+
if (!draw_priority)
360+
return desig_char;
361+
362+
std::vector<df::block_square_event_designation_priorityst *> priorities;
363+
Maps::SortBlockEvents(Maps::getTileBlock(pos), NULL, NULL, NULL, NULL, NULL, NULL, NULL, &priorities);
364+
if (priorities.empty())
365+
return desig_char;
366+
switch (priorities[0]->priority[pos.x % 16][pos.y % 16] / 1000) {
367+
case 1: return '1';
368+
case 2: return '2';
369+
case 3: return '3';
370+
case 4: return '4';
371+
case 5: return '5';
372+
case 6: return '6';
373+
case 7: return '7';
374+
default:
375+
return '4';
376+
}
377+
}
378+
379+
static void paintScreenCarve() {
380+
DEBUG(log).print("entering paintScreenCarve\n");
381+
382+
if (Screen::inGraphicsMode() || blink(500))
383+
return;
384+
385+
Designations designations;
386+
bool draw_priority = blink(1000);
387+
388+
auto dims = Gui::getDwarfmodeViewDims().map();
389+
for (int y = dims.first.y; y <= dims.second.y; ++y) {
390+
for (int x = dims.first.x; x <= dims.second.x; ++x) {
391+
df::coord map_pos(*window_x + x, *window_y + y, *window_z);
392+
393+
if (!Maps::isValidTilePos(map_pos))
394+
continue;
395+
396+
if (!Maps::isTileVisible(map_pos)) {
397+
TRACE(log).print("skipping hidden tile\n");
398+
continue;
399+
}
400+
401+
TRACE(log).print("scanning map tile at (%d, %d, %d) screen offset (%d, %d)\n",
402+
map_pos.x, map_pos.y, map_pos.z, x, y);
403+
404+
Screen::Pen cur_tile;
405+
cur_tile.fg = COLOR_DARKGREY;
406+
407+
auto des = designations.get(map_pos);
408+
409+
if (is_designated_for_smoothing(des)) {
410+
if (is_smooth_wall(map_pos))
411+
cur_tile.ch = get_tile_char(map_pos, (char)206, draw_priority); // hash, indicating a fortification designation
412+
else
413+
cur_tile.ch = get_tile_char(map_pos, (char)219, draw_priority); // solid block, indicating a smoothing designation
414+
}
415+
else if (is_designated_for_engraving(des)) {
416+
cur_tile.ch = get_tile_char(map_pos, (char)10, draw_priority); // solid block with a circle on it
417+
}
418+
else if (is_designated_for_track_carving(des)) {
419+
cur_tile.ch = get_tile_char(map_pos, get_track_char(des), draw_priority); // directional track
420+
}
421+
else {
422+
TRACE(log).print("skipping tile with no carving designation\n");
423+
continue;
424+
}
425+
426+
Screen::paintTile(cur_tile, x, y, true);
427+
}
428+
}
429+
}
430+
212431
DFHACK_PLUGIN_LUA_FUNCTIONS {
213432
DFHACK_LUA_FUNCTION(paintScreenPathable),
214433
DFHACK_LUA_FUNCTION(paintScreenWarmDamp),
434+
DFHACK_LUA_FUNCTION(paintScreenCarve),
215435
DFHACK_LUA_END
216436
};

0 commit comments

Comments
 (0)