From 0e3c7edebfce7ec8d10e921d694816415fc752bd Mon Sep 17 00:00:00 2001 From: SilasD Date: Tue, 26 Aug 2025 12:18:07 -0700 Subject: [PATCH 1/7] =?UTF-8?q?internal/caravan/*=20allow=20searching=20fo?= =?UTF-8?q?r=20items=20with=20CP417=20names.=20Such=20as:=20=20=20hyena=20?= =?UTF-8?q?bone=20figurine=20of=20B=C3=ABr=C3=BBl=20Saviorstockade=20=20?= =?UTF-8?q?=20L=C3=A2ven=20=C3=B4sed,=20The=20Prairie=20of=20Mazes=20(Shie?= =?UTF-8?q?ld)=20=20=20(+=C2=ABgrown=20pear=20wood=20=C3=AD=C3=BF=C3=ADmo?= =?UTF-8?q?=C2=BB+)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog.txt | 1 + internal/caravan/common.lua | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 5ecf8024e1..e694a6371a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -33,6 +33,7 @@ Template for new versions: ## Fixes ## Misc Improvements +- `caravan`: the ``Bring goods to depot``, ``Trade``, and ``Assign items for display`` screens now allow searching for items with non-ASCII characters in their description ## Removed diff --git a/internal/caravan/common.lua b/internal/caravan/common.lua index 996a616562..f3ba1fa9ca 100644 --- a/internal/caravan/common.lua +++ b/internal/caravan/common.lua @@ -15,8 +15,8 @@ SOME_PEN = to_pen{ch=':', fg=COLOR_YELLOW} ALL_PEN = to_pen{ch=string.char(251), fg=COLOR_LIGHTGREEN} function add_words(words, str) - for word in str:gmatch("[%w]+") do - table.insert(words, word:lower()) + for word in dfhack.toSearchNormalized(str):gmatch("[%w]+") do + table.insert(words, word) end end From dbd125b3bb16022e40222587098e0f603a71d621 Mon Sep 17 00:00:00 2001 From: SilasD Date: Tue, 26 Aug 2025 14:20:10 -0700 Subject: [PATCH 2/7] internal/caravan/common.lua obfuscate_value() API change An optional parameter `threshold` was added to allow the caller to pass in that value instead of recalculating it on each call. `get_broker_skill()` is slow, and `obfuscate_value()` is typically called 1000s of times, so passing `threshold` improves performance. This API change maintains backwards compatiblity. In addition, `get_broker_skill()` and `get_threshold()` were exposed to scripts that use this module. Also minor code cleanup: * An alias was only used twice, right after it was defined. The code is better off written without the alias. * Integers should ideally be compared with integers. No user-visible changes. --- internal/caravan/common.lua | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/internal/caravan/common.lua b/internal/caravan/common.lua index f3ba1fa9ca..8f22306261 100644 --- a/internal/caravan/common.lua +++ b/internal/caravan/common.lua @@ -10,9 +10,8 @@ CH_DN = string.char(31) CH_MONEY = string.char(15) CH_EXCEPTIONAL = string.char(240) -local to_pen = dfhack.pen.parse -SOME_PEN = to_pen{ch=':', fg=COLOR_YELLOW} -ALL_PEN = to_pen{ch=string.char(251), fg=COLOR_LIGHTGREEN} +SOME_PEN = dfhack.pen.parse{ch=':', fg=COLOR_YELLOW} +ALL_PEN = dfhack.pen.parse{ch=string.char(251), fg=COLOR_LIGHTGREEN} function add_words(words, str) for word in dfhack.toSearchNormalized(str):gmatch("[%w]+") do @@ -35,7 +34,7 @@ function make_container_search_key(item, desc) return table.concat(words, ' ') end -local function get_broker_skill() +function get_broker_skill() local broker = dfhack.units.getUnitByNobleRole('broker') if not broker then return 0 end for _,skill in ipairs(broker.status.current_soul.skills) do @@ -46,7 +45,7 @@ local function get_broker_skill() return 0 end -local function get_threshold(broker_skill) +function get_threshold(broker_skill) if broker_skill <= df.skill_rating.Dabbling then return 0 end if broker_skill <= df.skill_rating.Novice then return 10 end if broker_skill <= df.skill_rating.Adequate then return 25 end @@ -62,7 +61,7 @@ local function get_threshold(broker_skill) if broker_skill <= df.skill_rating.Master then return 4000 end if broker_skill <= df.skill_rating.HighMaster then return 5000 end if broker_skill <= df.skill_rating.GrandMaster then return 10000 end - return math.huge + return math.maxinteger end local function estimate(value, round_base, granularity) @@ -76,8 +75,8 @@ end -- Otherwise, if it's less than or equal to [threshold + 50] * 3, it will round to the nearest multiple of 100 -- Otherwise, if it's less than or equal to [threshold + 50] * 30, it will round to the nearest multiple of 1000 -- Otherwise, it will display a guess equal to [threshold + 50] * 30 rounded up to the nearest multiple of 1000. -function obfuscate_value(value) - local threshold = get_threshold(get_broker_skill()) +function obfuscate_value(value, threshold) + threshold = threshold or get_threshold(get_broker_skill()) if value < threshold then return dfhack.formatInt(value) end threshold = threshold + 50 if value <= threshold then return ('~%s'):format(estimate(value, 5, 10)) end @@ -267,7 +266,7 @@ function get_slider_widgets(self, suffix) {label='100'..CH_MONEY, value={index=4, value=100}, pen=COLOR_BROWN}, {label='500'..CH_MONEY, value={index=5, value=500}, pen=COLOR_BROWN}, {label='1000'..CH_MONEY, value={index=6, value=1000}, pen=COLOR_BROWN}, - {label='Max', value={index=7, value=math.huge}, pen=COLOR_GREEN}, + {label='Max', value={index=7, value=math.maxinteger}, pen=COLOR_GREEN}, }, initial_option=7, on_change=function(val) From 761a677c9843f0450e349b20a69483c79257bf29 Mon Sep 17 00:00:00 2001 From: SilasD Date: Tue, 26 Aug 2025 18:48:38 -0700 Subject: [PATCH 3/7] internal/caravan/movegoods.lua use new obfuscate_value() API Verified that this gives identical results to the unmodified code, with the exception of some icon closures that could not be verified. --- internal/caravan/movegoods.lua | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/internal/caravan/movegoods.lua b/internal/caravan/movegoods.lua index df90d7f886..77e8222979 100644 --- a/internal/caravan/movegoods.lua +++ b/internal/caravan/movegoods.lua @@ -399,10 +399,10 @@ local function get_entry_icon(data, item_id) return common.SOME_PEN end -local function make_choice_text(at_depot, dist, value, quantity, desc) +local function make_choice_text(at_depot, dist, value, quantity, desc, cache_threshold) return { {width=DIST_COL_WIDTH-2, rjustify=true, text=at_depot and 'depot' or tostring(dist)}, - {gap=2, width=VALUE_COL_WIDTH, rjustify=true, text=common.obfuscate_value(value)}, + {gap=2, width=VALUE_COL_WIDTH, rjustify=true, text=common.obfuscate_value(value, cache_threshold)}, {gap=2, width=QTY_COL_WIDTH, rjustify=true, text=quantity}, {gap=2, text=desc}, } @@ -559,18 +559,20 @@ function MoveGoods:cache_choices() end local group_choices, nogroup_choices = {}, {} + local cache_threshold = common.get_threshold(common.get_broker_skill()) for _, group in pairs(groups) do local data = group.data for item_id, item_data in pairs(data.items) do local nogroup_choice = copyall(group) nogroup_choice.icon = curry(get_entry_icon, data, item_id) nogroup_choice.text = make_choice_text(item_data.item.flags.in_building, - data.dist, data.per_item_value, 1, data.desc) + data.dist, data.per_item_value, 1, data.desc, cache_threshold) nogroup_choice.item_id = item_id table.insert(nogroup_choices, nogroup_choice) end data.total_value = data.per_item_value * data.quantity - group.text = make_choice_text(data.num_at_depot == data.quantity, data.dist, data.total_value, data.quantity, data.desc) + group.text = make_choice_text(data.num_at_depot == data.quantity, data.dist, + data.total_value, data.quantity, data.desc, cache_threshold) table.insert(group_choices, group) self.value_pending = self.value_pending + (data.per_item_value * data.selected) end From de12a181b1cd4bb96d0403423dd499c7461d80fd Mon Sep 17 00:00:00 2001 From: SilasD Date: Tue, 26 Aug 2025 21:18:22 -0700 Subject: [PATCH 4/7] internal/caravan/pedestal.lua use new obfuscate_value() API Verified that this gives identical results to the unmodified code. --- internal/caravan/pedestal.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/internal/caravan/pedestal.lua b/internal/caravan/pedestal.lua index dab100ef48..1184a85c3e 100644 --- a/internal/caravan/pedestal.lua +++ b/internal/caravan/pedestal.lua @@ -503,10 +503,10 @@ local function get_status(item, display_bld) return STATUS.AVAILABLE.value end -local function make_choice_text(data) +local function make_choice_text(data, threshold) return { {width=STATUS_COL_WIDTH, text=function() return STATUS[STATUS_REVMAP[data.status]].label end}, - {gap=2, width=VALUE_COL_WIDTH, rjustify=true, text=common.obfuscate_value(data.value)}, + {gap=2, width=VALUE_COL_WIDTH, rjustify=true, text=common.obfuscate_value(data.value, threshold)}, {gap=2, text=data.desc}, } end @@ -530,6 +530,7 @@ end function AssignItems:cache_choices(inside_containers, display_bld) if self.choices_cache[inside_containers] then return self.choices_cache[inside_containers] end + local cache_threshold = common.get_threshold(common.get_broker_skill()) local choices = {} for _, item in ipairs(df.global.world.items.other.IN_PLAY) do if not is_displayable_item(item) then goto continue end @@ -559,7 +560,7 @@ function AssignItems:cache_choices(inside_containers, display_bld) end local entry = { search_key=search_key, - text=make_choice_text(data), + text=make_choice_text(data, cache_threshold), data=data, } table.insert(choices, entry) From 76b0f7e4e029613da49f0994b712a00e479c9a6b Mon Sep 17 00:00:00 2001 From: SilasD Date: Wed, 27 Aug 2025 07:44:12 -0700 Subject: [PATCH 5/7] internal/caravan/trade.lua use new obfuscate_value() API Verified that this gives identical results to the unmodified code. --- internal/caravan/trade.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/internal/caravan/trade.lua b/internal/caravan/trade.lua index f27e949ea5..f78bc75c05 100644 --- a/internal/caravan/trade.lua +++ b/internal/caravan/trade.lua @@ -315,9 +315,9 @@ local function is_ethical_product(item, animal_ethics, wood_ethics) (not wood_ethics or not common.has_wood(item)) end -local function make_choice_text(value, desc) +local function make_choice_text(value, threshold, desc) return { - {width=STATUS_COL_WIDTH+VALUE_COL_WIDTH, rjustify=true, text=common.obfuscate_value(value)}, + {width=STATUS_COL_WIDTH+VALUE_COL_WIDTH, rjustify=true, text=common.obfuscate_value(value, threshold)}, {gap=2, text=desc}, } end @@ -328,6 +328,7 @@ function Trade:cache_choices(list_idx, trade_bins) local goodflags = trade.goodflag[list_idx] local trade_bins_choices, notrade_bins_choices = {}, {} local parent_data + local cache_threshold = common.get_threshold(common.get_broker_skill()) for item_idx, item in ipairs(trade.good[list_idx]) do local goodflag = goodflags[item_idx] if not goodflag.contained then @@ -374,7 +375,7 @@ function Trade:cache_choices(list_idx, trade_bins) search_key=search_key, icon=curry(get_entry_icon, data), data=data, - text=make_choice_text(data.value, desc), + text=make_choice_text(data.value, cache_threshold, desc), } if not data.update_container_fn then table.insert(trade_bins_choices, choice) From 4e93bee0647c5b3ce121d6b716824896adee713e Mon Sep 17 00:00:00 2001 From: SilasD Date: Thu, 28 Aug 2025 09:59:51 -0700 Subject: [PATCH 6/7] internal/caravan/common.lua use trader over broker When doing trading (i.e. the DF Trade window is open showing the two columns), it *can* happen that you *have* a broker, but you actually *trade* using a different unit. This can be triggered by opening the depot building view and choosing `Anyone requested at trade`, repeating this until some unit that is not the broker shows up to do the trading. When this happens, the DFHack `Select trade goods` overlay shows different obfuscated values than the DF Trade window. This patch fixes that case by using the trader's appraisal skill if trading is active. --- internal/caravan/common.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/caravan/common.lua b/internal/caravan/common.lua index 8f22306261..9fffefe4c6 100644 --- a/internal/caravan/common.lua +++ b/internal/caravan/common.lua @@ -36,6 +36,13 @@ end function get_broker_skill() local broker = dfhack.units.getUnitByNobleRole('broker') + local interface_trade = df.global.game.main_interface.trade + if interface_trade.open == true + and interface_trade.choosing_merchant == false + and interface_trade.fortress_trader ~= nil + then + broker = interface_trade.fortress_trader + end if not broker then return 0 end for _,skill in ipairs(broker.status.current_soul.skills) do if skill.id == df.job_skill.APPRAISAL then From a5c1294cb22470d1b7876b336b4ec01a28265e3f Mon Sep 17 00:00:00 2001 From: SilasD Date: Wed, 17 Sep 2025 15:11:50 -0700 Subject: [PATCH 7/7] update changelog I guess these are misc improvements, not fixes? I'm not quite sure. --- changelog.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index e694a6371a..18afcc1b4c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -33,7 +33,8 @@ Template for new versions: ## Fixes ## Misc Improvements -- `caravan`: the ``Bring goods to depot``, ``Trade``, and ``Assign items for display`` screens now allow searching for items with non-ASCII characters in their description +- `caravan`: the ``Bring goods to depot``, ``Trade``, and ``Assign items for display`` overlays now allow searching for items with non-ASCII characters in their description +- `caravan`: the ``Trade`` overlay will use the trader's appraisal skill instead of the broker's to round/obfuscate the value of items ## Removed