diff --git a/data/art/dfhack.png b/data/art/dfhack.png index 17719f084..133dc5aaf 100644 Binary files a/data/art/dfhack.png and b/data/art/dfhack.png differ diff --git a/data/orders/military.json b/data/orders/military.json index 5b7604dac..0e53747b6 100644 --- a/data/orders/military.json +++ b/data/orders/military.json @@ -1138,42 +1138,6 @@ "job" : "MakeWeapon", "material" : "INORGANIC:SILVER" }, - { - "amount_left" : 1, - "amount_total" : 1, - "frequency" : "Daily", - "id" : 64, - "is_active" : false, - "is_validated" : false, - "item_conditions" : - [ - { - "condition" : "AtLeast", - "item_type" : "BAR", - "material" : "INORGANIC:SILVER", - "value" : 20 - }, - { - "condition" : "AtLeast", - "item_type" : "BAR", - "material" : "COAL", - "value" : 100 - }, - { - "condition" : "AtMost", - "flags" : - [ - "metal" - ], - "item_subtype" : "ITEM_WEAPON_CROSSBOW", - "item_type" : "WEAPON", - "value" : 10 - } - ], - "item_subtype" : "ITEM_WEAPON_CROSSBOW", - "job" : "MakeWeapon", - "material" : "INORGANIC:SILVER" - }, { "amount_left" : 1, "amount_total" : 1, @@ -1656,12 +1620,6 @@ "item_type" : "WEAPON", "material" : "INORGANIC:STEEL", "value" : 10 - }, - { - "condition" : "LessThan", - "item_type" : "BAR", - "material" : "INORGANIC:SILVER", - "value" : 5 } ], "item_subtype" : "ITEM_WEAPON_CROSSBOW", @@ -2357,12 +2315,6 @@ "material" : "INORGANIC:STEEL", "value" : 30 }, - { - "condition" : "LessThan", - "item_type" : "BAR", - "material" : "INORGANIC:SILVER", - "value" : 5 - }, { "condition" : "AtMost", "flags" : @@ -3068,12 +3020,6 @@ "material" : "INORGANIC:STEEL", "value" : 30 }, - { - "condition" : "LessThan", - "item_type" : "BAR", - "material" : "INORGANIC:SILVER", - "value" : 5 - }, { "condition" : "AtMost", "flags" : @@ -3856,12 +3802,6 @@ "material" : "INORGANIC:STEEL", "value" : 30 }, - { - "condition" : "LessThan", - "item_type" : "BAR", - "material" : "INORGANIC:SILVER", - "value" : 5 - }, { "condition" : "AtMost", "flags" : @@ -4734,12 +4674,6 @@ "material" : "INORGANIC:STEEL", "value" : 30 }, - { - "condition" : "LessThan", - "item_type" : "BAR", - "material" : "INORGANIC:SILVER", - "value" : 5 - }, { "condition" : "AtMost", "flags" : diff --git a/docs/changelog.txt b/docs/changelog.txt index ece6f04e1..daf0e8e1d 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -39,6 +39,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - ``Units::isFortControlled``: Account for agitated wildlife - Fix right click sometimes closing both a DFHack window and a vanilla panel - Fixed issue with scrollable lists having some data off-screen if they were scrolled before being made visible +- `channel-safely`: fixed bug resulting in marker mode never being set for any designation ## Misc Improvements - `automelt`: is now more resistent to savegame corruption @@ -49,6 +50,8 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - `clean`: new hotkey for `spotclean`: Ctrl-C - `autobutcher`: changed defaults from 5 females / 1 male to 4 females / 2 males so a single unfortunate accident doesn't leave players without a mating pair - `autobutcher`: now immediately loads races available at game start into the watchlist +- replaced DFHack logo used for the hover hotspot with a crisper image +- `orders`: recipe for silver crossbows removed from ``library/military`` as it is not a vanilla recipe, but is available in ``library/military_include_artifact_materials`` ## Documentation @@ -57,6 +60,9 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ## Lua - `overlay`: overlay widgets can now specify focus paths for the viewscreens they attach to so they only appear in specific contexts. see `overlay-dev-guide` for details. - ``widgets.CycleHotkeyLabel``: Added ``key_back`` optional parameter to cycle backwards. +- ``widgets.HotkeyLabel``: Added ``setLabel`` method to allow easily updating the label text without mangling the keyboard shortcut. +- ``widgets.HotkeyLabel``: Added ``setOnActivate`` method to allow easily updating the ``on_activate`` callback. +- ``widgets.FilteredList``: Added ``case_sensitive`` optional paramter to determine if filtering is case sensitive. ## Removed diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 503f4bece..4e900bea5 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -4808,6 +4808,16 @@ It has the following attributes: :on_activate: If specified, it is the callback that will be called whenever the hotkey is pressed or the label is clicked. +The HotkeyLabel widget implements the following methods: + +* ``hotkeylabel:setLabel(label)`` + + Updates the label without altering the hotkey text. + +* ``hotkeylabel:setOnActivate(on_activate)`` + + Updates the on_activate callback. + CycleHotkeyLabel class ---------------------- @@ -4958,6 +4968,7 @@ construction that allows filtering the list by subwords of its items. In addition to passing through all attributes supported by List, it supports: +:case_sensitive: If true, matching is case sensitive. Defaults to true. :edit_pen: If specified, used instead of ``cursor_pen`` for the edit field. :edit_below: If true, the edit field is placed below the list instead of above. :edit_key: If specified, the edit field is disabled until this key is pressed. diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 45ea7d84d..69d43821e 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -478,7 +478,7 @@ static void OpenPersistent(lua_State *state) static int DFHACK_MATINFO_TOKEN = 0; -void Lua::Push(lua_State *state, MaterialInfo &info) +void Lua::Push(lua_State *state, const MaterialInfo &info) { if (!info.isValid()) { diff --git a/library/LuaTools.cpp b/library/LuaTools.cpp index b4d009c7b..ed0b0699d 100644 --- a/library/LuaTools.cpp +++ b/library/LuaTools.cpp @@ -101,7 +101,7 @@ void DFHack::Lua::Push(lua_State *state, const Units::NoblePosition &pos) lua_setfield(state, -2, "position"); } -void DFHack::Lua::Push(lua_State *state, df::coord pos) +void DFHack::Lua::Push(lua_State *state, const df::coord &pos) { lua_createtable(state, 0, 3); lua_pushinteger(state, pos.x); @@ -112,7 +112,7 @@ void DFHack::Lua::Push(lua_State *state, df::coord pos) lua_setfield(state, -2, "z"); } -void DFHack::Lua::Push(lua_State *state, df::coord2d pos) +void DFHack::Lua::Push(lua_State *state, const df::coord2d &pos) { lua_createtable(state, 0, 2); lua_pushinteger(state, pos.x); @@ -191,7 +191,7 @@ void DFHack::Lua::PushInterfaceKeys(lua_State *L, } } -int DFHack::Lua::PushPosXYZ(lua_State *state, df::coord pos) +int DFHack::Lua::PushPosXYZ(lua_State *state, const df::coord &pos) { if (!pos.isValid()) { @@ -207,7 +207,7 @@ int DFHack::Lua::PushPosXYZ(lua_State *state, df::coord pos) } } -int DFHack::Lua::PushPosXY(lua_State *state, df::coord2d pos) +int DFHack::Lua::PushPosXY(lua_State *state, const df::coord2d &pos) { if (!pos.isValid()) { diff --git a/library/include/LuaTools.h b/library/include/LuaTools.h index ca9aac788..86d3d0c7e 100644 --- a/library/include/LuaTools.h +++ b/library/include/LuaTools.h @@ -325,10 +325,10 @@ namespace DFHack {namespace Lua { inline void Push(lua_State *state, const std::string &str) { lua_pushlstring(state, str.data(), str.size()); } - DFHACK_EXPORT void Push(lua_State *state, df::coord obj); - DFHACK_EXPORT void Push(lua_State *state, df::coord2d obj); + DFHACK_EXPORT void Push(lua_State *state, const df::coord &obj); + DFHACK_EXPORT void Push(lua_State *state, const df::coord2d &obj); void Push(lua_State *state, const Units::NoblePosition &pos); - DFHACK_EXPORT void Push(lua_State *state, MaterialInfo &info); + DFHACK_EXPORT void Push(lua_State *state, const MaterialInfo &info); DFHACK_EXPORT void Push(lua_State *state, const Screen::Pen &info); template inline void Push(lua_State *state, T *ptr) { PushDFObject(state, ptr); @@ -361,29 +361,34 @@ namespace DFHack {namespace Lua { DFHACK_EXPORT void GetVector(lua_State *state, std::vector &pvec); - DFHACK_EXPORT int PushPosXYZ(lua_State *state, df::coord pos); - DFHACK_EXPORT int PushPosXY(lua_State *state, df::coord2d pos); - - template - inline void TableInsert(lua_State *state, T_Key key, T_Value value) - { - Lua::Push(state, key); - Lua::Push(state, value); - lua_settable(state, -3); - } + DFHACK_EXPORT int PushPosXYZ(lua_State *state, const df::coord &pos); + DFHACK_EXPORT int PushPosXY(lua_State *state, const df::coord2d &pos); template void Push(lua_State *L, const std::map &pmap) { lua_createtable(L, 0, pmap.size()); - for (auto &entry : pmap) - TableInsert(L, entry.first, entry.second); + for (auto &entry : pmap) { + Lua::Push(L, entry.first); + Lua::Push(L, entry.second); + lua_settable(L, -3); + } } template void Push(lua_State *L, const std::unordered_map &pmap) { lua_createtable(L, 0, pmap.size()); - for (auto &entry : pmap) - TableInsert(L, entry.first, entry.second); + for (auto &entry : pmap) { + Lua::Push(L, entry.first); + Lua::Push(L, entry.second); + lua_settable(L, -3); + } + } + + template + inline void TableInsert(lua_State *state, const T_Key &key, const T_Value &value) { + Lua::Push(state, key); + Lua::Push(state, value); + lua_settable(state, -3); } DFHACK_EXPORT void CheckPen(lua_State *L, Screen::Pen *pen, int index, bool allow_nil = false, bool allow_color = true); diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index dfc584fff..a5840a1b1 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -1419,6 +1419,20 @@ HotkeyLabel.ATTRS{ } function HotkeyLabel:init() + self:initializeLabel() +end + +function HotkeyLabel:setOnActivate(on_activate) + self.on_activate = on_activate + self:initializeLabel() +end + +function HotkeyLabel:setLabel(label) + self.label = label + self:initializeLabel() +end + +function HotkeyLabel:initializeLabel() self:setText{{key=self.key, key_sep=self.key_sep, text=self.label, on_activate=self.on_activate}} end @@ -1868,6 +1882,7 @@ end FilteredList = defclass(FilteredList, Widget) FilteredList.ATTRS { + case_sensitive = true, edit_below = false, edit_key = DEFAULT_NIL, edit_ignore_keys = DEFAULT_NIL, @@ -2028,11 +2043,17 @@ function FilteredList:setFilter(filter, pos) -- start matches at non-space or non-punctuation. this allows -- punctuation itself to be matched if that is useful (e.g. -- filenames or parameter names) - if key ~= '' and - not search_key:match('%f[^%p\x00]'..key) and + if key ~= '' then + if not self.case_sensitive then + search_key = string.lower(search_key) + key = string.lower(key) + end + + if not search_key:match('%f[^%p\x00]'..key) and not search_key:match('%f[^%s\x00]'..key) then - ok = false - break + ok = false + break + end end end if ok then diff --git a/plugins/channel-safely/channel-manager.cpp b/plugins/channel-safely/channel-manager.cpp index c22bd8a8e..aa7a24461 100644 --- a/plugins/channel-safely/channel-manager.cpp +++ b/plugins/channel-safely/channel-manager.cpp @@ -5,7 +5,17 @@ #include //hash function for df::coord #include +#define NUMARGS(...) std::tuple_size::value +#define d_assert(condition, ...) \ + static_assert(NUMARGS(__VA_ARGS__) >= 1, "d_assert(condition, format, ...) requires at least up to format as arguments"); \ + if (!condition) { \ + DFHack::Core::getInstance().getConsole().printerr(__VA_ARGS__); \ + assert(0); \ + } + + df::unit* find_dwarf(const df::coord &map_pos) { + df::unit* nearest = nullptr; uint32_t distance; for (auto unit : df::global::world->units.active) { @@ -57,6 +67,7 @@ void ChannelManager::manage_group(const Group &group, bool set_marker_mode, bool // cavein prevention bool cavein_possible = false; uint8_t least_access = 100; + std::unordered_map cavein_candidates; if (!marker_mode) { /* To prevent cave-ins we're looking at accessibility of tiles with open space below them @@ -111,7 +122,7 @@ void ChannelManager::manage_group(const Group &group, bool set_marker_mode, bool // if no cave-in is possible [or we don't check for], we'll just execute normally and move on if (!cavein_possible) { TRACE(manager).print("cave-in evaluated false\n"); - assert(manage_one(pos, true, marker_mode)); + d_assert(manage_one(pos, true, marker_mode), "manage_one() is failing under !cavein"); continue; } // cavein is only possible if marker_mode is false @@ -136,16 +147,16 @@ void ChannelManager::manage_group(const Group &group, bool set_marker_mode, bool evT->priority[Coord(local)] = v; } } - assert(manage_one(pos, true, false)); + d_assert(manage_one(pos, true, false), "manage_one() is failing for cavein "); continue; } // cavein possible, but we failed to meet the criteria for activation if (cavein_candidates.count(pos)) { - DEBUG(manager).print("cave-in evaluated true and no dignow and (%d > %d)\n", cavein_candidates[pos], least_access+OFFSET); + DEBUG(manager).print("cave-in evaluated true and the cavein candidate's accessibility check was made as (%d <= %d)\n", cavein_candidates[pos], least_access+OFFSET); } else { - DEBUG(manager).print("cave-in evaluated true and no dignow and pos is not a candidate\n"); + DEBUG(manager).print("cave-in evaluated true and the position was not a candidate, nor was it set for dignow\n"); } - assert(manage_one(pos, true, true)); + d_assert(manage_one(pos, true, true), "manage_one() is failing to set a cave-in causing designation to marker mode"); } INFO(manager).print("manage_group() is done\n"); }