From ebc1dcc32435a48a71c01de69434eea1071e31be Mon Sep 17 00:00:00 2001 From: Philip Lancaster Date: Sat, 26 Aug 2023 17:51:30 -0400 Subject: [PATCH 1/6] initial commit, most features implemented --- stocks2.lua | 718 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 718 insertions(+) create mode 100644 stocks2.lua diff --git a/stocks2.lua b/stocks2.lua new file mode 100644 index 0000000000..71e465fd35 --- /dev/null +++ b/stocks2.lua @@ -0,0 +1,718 @@ +-- a v50 script remake of the older stocks plugin +-- chawkzero, Aug 2023 + +local gui = require("gui") +local widgets = require("gui.widgets") +local utils = require("utils") + +local item_desc_width = 38 +local item_table = {} + +local current_search_query = "" +local filter_states = { + in_job = true, + rotten = true, + owned = true, + forbidden = true, + dump = true, + on_fire = true, + melt = true, + in_inv = true, + caged = true, + trade = true, + no_flags = true, +} + +local min_qual = 0 +local max_qual = 6 +local min_wear = 0 + +-- 0 = listed, 1 = selected +local apply_to_mode = 0 +local apply_to_labels = {"Listed", "Selected"} + +local stocks_window_width = 106 +local stocks_window_height = 50 + +StocksWindow = defclass(StocksWindow, widgets.Window) +StocksWindow.ATTRS({ + frame = {w = stocks_window_width, h = stocks_window_height}, + frame_title = "Stocks", + autoarrange_subviews = false, + autoarrange_gap = 0, +}) + +function StocksWindow:init() + --dfhack.printerr("StocksWindow:init() called!") + --[[ + COLOR_RESET, COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN, + COLOR_RED, COLOR_MAGENTA, COLOR_BROWN, COLOR_GREY, COLOR_DARKGREY, + COLOR_LIGHTBLUE, COLOR_LIGHTGREEN, COLOR_LIGHTCYAN, COLOR_LIGHTRED, + COLOR_LIGHTMAGENTA, COLOR_YELLOW, COLOR_WHITE + --]] + + self:addviews({ + widgets.Panel({ + view_id = "left_panel", + frame = {t = 0, b = 0, l = 0, r = stocks_window_width - 76}, + frame_style = gui.INTERIOR_FRAME, + subviews = { + widgets.EditField({ + view_id = "search_box", + frame = {t = 1, l = 0}, + label_text = "Search: ", + on_char = function(ch) return ch:match("[%l%s]") end, + on_change = function(new_text, old_text) + current_search_query = new_text + self:filter_list(current_search_query) + end, + }), + widgets.Label({ + text = {{text = "Items: ", pen = COLOR_LIGHTGREEN}}, + frame = {t = 3, l = 0}, + view_id = "item_count_label" + }), + widgets.List({ + view_id = "item_list", + --edit_below = false, + frame = {t = 4, b = 1, l = 1, r = 1}, + --not_found_label = "empty?", + text_pen = {fg = COLOR_GREY, bg = COLOR_BLACK}, + text_hpen = {fg = COLOR_BLACK, bg = COLOR_GREY}, + cursor_pen = {fg = COLOR_LIGHTGREEN, bg = COLOR_DARKGREY}, + }), + }, + }), + widgets.Panel({ + view_id = "right_panel", + frame = {t = 0, b = 0, r = 0, l = 72}, + frame_style = gui.INTERIOR_FRAME, + subviews = { + widgets.Label({ + text = "Filters (Alt+Key toggles)", + frame = {t = 0, l = 0}, + view_id = "filters_header_label", + }), + widgets.Label({ + text = "to be filled in...", + frame = {t = 1, l = 0}, + view_id = "filters_label", + }), + widgets.Label({ + text = { + {text = "Shift-C", pen = COLOR_LIGHTGREEN}, {text = ": Clear All", pen = COLOR_WHITE}, NEWLINE, + {text = "Shift-E", pen = COLOR_LIGHTGREEN}, {text = ": Enable All", pen = COLOR_WHITE}, NEWLINE, + {text = "Shift-G", pen = COLOR_LIGHTGREEN}, {text = ": Toggle Grouping", pen = COLOR_WHITE} + }, + frame = {t = 8, l = 0}, + view_id = "filters_label2", + }), + widgets.Label({ + text = { + {text = "-+", pen = COLOR_LIGHTGREEN}, {text = ": Min Qual: ", pen = COLOR_WHITE}, {text = "tbd", pen = COLOR_BROWN}, NEWLINE, + {text = "/*", pen = COLOR_LIGHTGREEN}, {text = ": Max Qual: ", pen = COLOR_WHITE}, {text = "tbd", pen = COLOR_BROWN}, NEWLINE, + {text = "Shift-W", pen = COLOR_LIGHTGREEN}, {text = ": Min Wear: ", pen = COLOR_WHITE}, {text = "tbd", pen = COLOR_BROWN} + }, + frame = {t = 12, l = 0}, + view_id = "filters_qual_wear", + }), + widgets.Label({ + text = { + {text = "Actions (", pen = COLOR_BROWN}, {text = "...", pen = COLOR_LIGHTGREEN}, {text = " Items)", pen = COLOR_BROWN} + }, + frame = {t = 16, l = 0}, + view_id = "actions_item_count_label", + }), + widgets.Label({ + text = { + {text = "Shift-Z", pen = COLOR_LIGHTGREEN}, {text = ": Zoom ", pen = COLOR_WHITE}, + {text = "-D", pen = COLOR_LIGHTGREEN}, {text = ": Dump", pen = COLOR_WHITE}, NEWLINE, + {text = "Shift-F", pen = COLOR_LIGHTGREEN}, {text = ": Forbid ", pen = COLOR_WHITE}, + {text = "-M", pen = COLOR_LIGHTGREEN}, {text = ": Melt", pen = COLOR_WHITE}, NEWLINE, + {text = "Shift-T", pen = COLOR_LIGHTGREEN}, {text = ": Mark for Trade", pen = COLOR_GREY}, + }, + frame = {t = 17, l = 0}, + view_id = "actions_label", + }), + widgets.Label({ + text = { + {text = "Shift-A", pen = COLOR_LIGHTGREEN}, {text = ": Apply to: ", pen = COLOR_WHITE}, + {text = apply_to_labels[apply_to_mode + 1], pen = COLOR_BROWN}, + }, + frame = {t = 20, l = 0}, + view_id = "apply_to_label", + }), + } + }), + }) + + self:populate_item_table() + self:filter_list(current_search_query) + self:show_filters() + self:show_qual_and_wear() +end + +function StocksWindow:populate_item_table() + -- retrieve all in-play items + local temp_table = {} + for i,v in ipairs(df.global.world.items.other[df.items_other_id.IN_PLAY]) do + local item_desc = dfhack.items.getDescription(v, v:getType()) + + -- store item description and an item ref + table.insert(temp_table, { desc = item_desc, ref = v }) + + --[[ + for i,g in pairs(v.general_refs) do + local t = g:getType() + + if t == df.general_ref_type.CONTAINED_IN_ITEM then + for i2,g2 in ipairs(g:getItem().general_refs) do + if g2:getType() == df.general_ref_type.UNIT_HOLDER then + dfhack.printerr(string.format("found a contained_in_item <-> unit_holder link! contained item: %s, container item: %s, ", item_desc, dfhack.items.getDescription(g:getItem(), g:getItem():getType()))) + end + end + end + end--]] + end + + -- sort alphabetically + local spec = { key = function(v) return v.desc end } + local order = utils.make_sort_order(temp_table, { spec }) + for i = 1, #order do item_table[i] = temp_table[order[i]] end +end + +function toggle_melt(item) + item.flags.melt = not item.flags.melt + + if item.flags.melt then + utils.insert_sorted(df.global.world.items.other.ANY_MELT_DESIGNATED, item, "id") + else + utils.erase_sorted(df.global.world.items.other.ANY_MELT_DESIGNATED, item, "id") + end +end + +function is_valid_melt_item(item) + local mat_info = dfhack.matinfo.decode(item) + if not mat_info then + return false + end + + -- must be a metal thing + if mat_info:getCraftClass() ~= df.craft_material_class.Metal then + return false + end + + -- must not be a metal bar + if item:getType() == df.item_type.BAR then + return false + end + + for i,g in ipairs(item.general_refs) do + local t = g:getType() + + -- don't be a holder of things + if t == df.general_ref_type.CONTAINS_ITEM or + t == df.general_ref_type.UNIT_HOLDER or + t == df.general_ref_type.CONTAINS_UNIT then + return false + end + + -- or be in something like a quiver, backpack, flask etc? + if t == df.general_ref_type.CONTAINED_IN_ITEM then + for i2, g2 in ipairs(g:getItem().general_refs) do + if g2:getType() == df.general_ref_type.UNIT_HOLDER then + return false + end + end + end + end + + -- lastly, don't melt masterworks + if item:getQuality() >= 5 then + return false + end + + return true +end + +function StocksWindow:onInput(keys) + --[[dfhack.printerr("window onInput called!") + for k,v in pairs(keys) do + dfhack.printerr(k) + dfhack.printerr(v) + end--]] + + -- JXOFDEMICT + --[[ + local filter_states = { + in_job = true, + rotten = true, + owned = true, + forbidden = true, + dump = true, + on_fire = true, + melt = true, + in_inv = true, + caged = true, + trade = true, + no_flags = true, +}--]] + + -- FILTERS ------------------- + local refresh_list = false + + if keys["CUSTOM_ALT_J"] then filter_states.in_job = not filter_states.in_job; refresh_list = true end + if keys["CUSTOM_ALT_X"] then filter_states.rotten = not filter_states.rotten; refresh_list = true end + if keys["CUSTOM_ALT_O"] then filter_states.owned = not filter_states.owned; refresh_list = true end + if keys["CUSTOM_ALT_F"] then filter_states.forbidden = not filter_states.forbidden; refresh_list = true end + if keys["CUSTOM_ALT_D"] then filter_states.dump = not filter_states.dump; refresh_list = true end + if keys["CUSTOM_ALT_E"] then filter_states.on_fire = not filter_states.on_fire; refresh_list = true end + if keys["CUSTOM_ALT_M"] then filter_states.melt = not filter_states.melt; refresh_list = true end + if keys["CUSTOM_ALT_I"] then filter_states.in_inv = not filter_states.in_inv; refresh_list = true end + if keys["CUSTOM_ALT_C"] then filter_states.caged = not filter_states.caged; refresh_list = true end + if keys["CUSTOM_ALT_T"] then filter_states.trade = not filter_states.trade; refresh_list = true end + if keys["CUSTOM_ALT_N"] then filter_states.no_flags = not filter_states.no_flags; refresh_list = true end + + if keys["CUSTOM_SHIFT_C"] then + for k,v in pairs(filter_states) do + filter_states[k] = false + end + refresh_list = true + end + + if keys["CUSTOM_SHIFT_E"] then + for k,v in pairs(filter_states) do + filter_states[k] = true + end + refresh_list = true + end + + -- QUALITY AND WEAR ------------------- + -- keypad minus? + if keys["STRING_A045"] then + local new_min_qual = min_qual - 1 + if new_min_qual < 0 then new_min_qual = 0 end + if new_min_qual ~= min_qual then + min_qual = new_min_qual + refresh_list = true + end + end + + -- keypad plus? + if keys["STRING_A043"] then + local new_min_qual = min_qual + 1 + if new_min_qual > max_qual then new_min_qual = max_qual end + if new_min_qual ~= min_qual then + min_qual = new_min_qual + refresh_list = true + end + end + + -- keypad forward slash? + if keys["STRING_A047"] then + local new_max_qual = max_qual - 1 + if new_max_qual < min_qual then new_max_qual = min_qual end + if new_max_qual ~= max_qual then + max_qual = new_max_qual + refresh_list = true + end + end + + -- keypad asterisk? + if keys["STRING_A042"] then + local new_max_qual = max_qual + 1 + if new_max_qual > 6 then new_max_qual = 6 end + if new_max_qual ~= max_qual then + max_qual = new_max_qual + refresh_list = true + end + end + + if keys["CUSTOM_SHIFT_W"] then + min_wear = (min_wear + 1) % 4 + refresh_list = true + end + + -- ACTIONS -------------------- + if keys["CUSTOM_SHIFT_D"] then + if apply_to_mode == 1 then --selected + _, choice = self.subviews.item_list:getSelected() + choice.ref.flags.dump = not choice.ref.flags.dump + else + for i,v in ipairs(self.subviews.item_list:getChoices()) do + v.ref.flags.dump = not v.ref.flags.dump + end + end + + refresh_list = true + end + + if keys["CUSTOM_SHIFT_F"] then + if apply_to_mode == 1 then --selected + _, choice = self.subviews.item_list:getSelected() + choice.ref.flags.forbid = not choice.ref.flags.forbid + else + for i,v in ipairs(self.subviews.item_list:getChoices()) do + v.ref.flags.forbid = not v.ref.flags.forbid + end + end + + refresh_list = true + end + + if keys["CUSTOM_SHIFT_M"] then + if apply_to_mode == 1 then --selected + _, choice = self.subviews.item_list:getSelected() + if is_valid_melt_item(choice.ref) then + toggle_melt(choice.ref) + end + else + for i,v in ipairs(self.subviews.item_list:getChoices()) do + toggle_melt(v.ref) + end + end + + refresh_list = true + end + + + + + if refresh_list then + self:filter_list(current_search_query) + end + + if keys["CUSTOM_SHIFT_A"] then + apply_to_mode = (apply_to_mode + 1) % 2 + self.subviews.apply_to_label:setText( + {{text = "Shift-A", pen = COLOR_LIGHTGREEN}, {text = ": Apply to: ", pen = COLOR_WHITE}, {text = apply_to_labels[apply_to_mode + 1], pen = COLOR_BROWN}, + }) + end + + self:show_filters() + self:show_qual_and_wear() + + return StocksWindow.super.onInput(self, keys) +end + +function StocksWindow:show_qual_and_wear() + local quality_labels = {"Ordinary", "WellCrafted", "FinelyCrafted", "Superior", "Exceptional", "Masterful", "Artifact"} + self.subviews.filters_qual_wear:setText( + { + { text = "-+", pen = COLOR_LIGHTGREEN}, { text = ": Min Qual: ", pen = COLOR_WHITE }, { text = quality_labels[min_qual + 1], pen = COLOR_BROWN }, NEWLINE, + { text = "/*", pen = COLOR_LIGHTGREEN}, { text = ": Max Qual: ", pen = COLOR_WHITE }, { text = quality_labels[max_qual + 1], pen = COLOR_BROWN }, NEWLINE, + { text = "Shift-W", pen = COLOR_LIGHTGREEN}, { text = ": Min Wear: ", pen = COLOR_WHITE }, { text = tostring(min_wear), pen = COLOR_BROWN } + } + ) +end + +function StocksWindow:show_filters() + + local function get_pen(state) + if state then + return COLOR_WHITE + else + return COLOR_GREY + end + end + + self.subviews.filters_label:setText( + { + { text = "J", pen = COLOR_LIGHTBLUE}, { text = ": In Job ", pen = get_pen(filter_states.in_job) }, + { text = "X", pen = COLOR_CYAN }, { text = ": Rotten", pen = get_pen(filter_states.rotten) }, NEWLINE, + { text = "O", pen = COLOR_GREEN}, { text = ": Owned ", pen = get_pen(filter_states.owned) }, + { text = "F", pen = COLOR_RED}, { text = ": Forbidden", pen = get_pen(filter_states.forbidden) }, NEWLINE, + { text = "D", pen = COLOR_MAGENTA}, { text = ": Dump ", pen = get_pen(filter_states.dump) }, + { text = "E", pen = COLOR_LIGHTRED}, { text = ": On Fire", pen = get_pen(filter_states.on_fire) }, NEWLINE, + { text = "M", pen = COLOR_BLUE}, { text = ": Melt ", pen = get_pen(filter_states.melt) }, + { text = "I", pen = COLOR_WHITE}, { text = ": In Inventory", pen = get_pen(filter_states.in_inv) }, NEWLINE, + { text = "C", pen = COLOR_LIGHTRED}, { text = ": Caged ", pen = get_pen(filter_states.caged) }, + { text = "T", pen = COLOR_LIGHTGREEN}, { text = ": Trade", pen = get_pen(filter_states.trade) }, NEWLINE, + { text = "N", pen = COLOR_GREY}, { text = ": No Flags", pen = get_pen(filter_states.no_flags) }, + } + ) +end + +function StocksWindow:filter_list(filter) + dfhack.printerr(string.format("filter_list() called with \"%s\"", filter)) + local list_contents = {} + local item_string + + local quality_labels = {"", "WellCrafted", "FinelyCrafted", "Superior", "Exceptional", "Masterful", "Artifact"} + local quality_pens = {COLOR_BLACK, COLOR_BROWN, COLOR_CYAN, COLOR_LIGHTBLUE, COLOR_GREEN, COLOR_LIGHTGREEN, COLOR_BLUE} + + for i,v in ipairs(item_table) do + local item = v.ref + local has_flags = false + + -- see if item is in job + local job_char + local ref = dfhack.items.getSpecificRef(item, df.specific_ref_type.JOB) + if ref and ref.data.job then + job_char = 'J' + has_flags = true + else + job_char = ' ' + end + if not filter_states.in_job and job_char == 'J' then goto continue end + + -- check various flags + local rotten_char + if item.flags.rotten then + rotten_char = 'X' + has_flags = true + else + rotten_char = ' ' + end + if not filter_states.rotten and item.flags.rotten then goto continue end + + local owned_char + if item.flags.owned then + owned_char = 'O' + has_flags = true + else + owned_char = ' ' + end + if not filter_states.owned and item.flags.owned then goto continue end + + local forbidden_char + if item.flags.forbid then + forbidden_char = 'F' + has_flags = true + else + forbidden_char = ' ' + end + if not filter_states.forbidden and item.flags.forbid then goto continue end + + local dump_char + if item.flags.dump then + dump_char = 'D' + has_flags = true + else + dump_char = ' ' + end + if not filter_states.dump and item.flags.dump then goto continue end + + local on_fire_char + if item.flags.on_fire then + on_fire_char = 'E' + has_flags = true + else + on_fire_char = ' ' + end + if not filter_states.on_fire and item.flags.on_fire then goto continue end + + local melt_char + if item.flags.melt then + melt_char = 'M' + has_flags = true + else + melt_char = ' ' + end + if not filter_states.melt and item.flags.melt then goto continue end + + local in_inv_char + if item.flags.in_inventory then + in_inv_char = 'I' + has_flags = true + else + in_inv_char = ' ' + end + if not filter_states.in_inv and item.flags.in_inventory then goto continue end + + -- skip if item has no flags and that filter is off! + if not filter_states.no_flags and has_flags == false then goto continue end + + -- check quality + local quality_label, quality_pen + quality_label = quality_labels[item:getQuality() + 1] + quality_pen = quality_pens[item:getQuality() + 1] + + -- skip by quality or wear + if item:getQuality() < min_qual or item:getQuality() > max_qual then goto continue end + if item:getWear() < min_wear then goto continue end + + local wear_tags = {"", "x", "X", "XX"} + --[[ + JXOFDEMICT + + J: in job lightblue + X: rotten cyan + O: owned green + F: forbidden red? + D: dump lightmagenta + E: on fire lightred? + M: melt blue + I: in inventory white + C: caged lightred + T: marked for trade lightgreen + --]] + if not filter or #filter < 1 or string.match(string.lower(v.desc), filter) then + local full_item_desc + if item:getWear() > 0 then + local wear_tag = wear_tags[item:getWear() + 1] + full_item_desc = wear_tag .. v.desc .. wear_tag + else + full_item_desc = v.desc + end + + table.insert(list_contents, { + text = { + {text = full_item_desc, width = item_desc_width, rjustify = false, pad_char = ' '}, ' ', + {text = job_char, width = 1, pen = COLOR_LIGHTBLUE}, + {text = rotten_char, width = 1, pen = COLOR_CYAN}, + {text = owned_char, width = 1, pen = COLOR_GREEN}, + {text = forbidden_char, width = 1, pen = COLOR_RED}, + {text = dump_char, width = 1, pen = COLOR_LIGHTMAGENTA}, + {text = on_fire_char, width = 1, pen = COLOR_LIGHTRED}, + {text = melt_char, width = 1, pen = COLOR_BLUE}, + {text = in_inv_char, width = 1, pen = COLOR_WHITE}, " ", + {text = quality_label, width = 13, rjustify = false, pad_char = ' ', pen = quality_pen}, + }, + ref = v.ref, + }) + end + + ::continue:: + end + + self.subviews.item_list:setChoices(list_contents) + self.subviews.item_count_label:setText(string.format("Items: %d", #list_contents)) + self.subviews.actions_item_count_label:setText({ + {text = "Actions (", pen = COLOR_BROWN}, {text = tostring(#list_contents), pen = COLOR_LIGHTGREEN}, {text = " Items)", pen = COLOR_BROWN} + }) + dfhack.printerr("done.") +end + +function StocksWindow:filter_list_old(filter) + dfhack.printerr(string.format("filter_list() called with \"%s\"", filter)) + local world = df.global.world + local list_contents = {} + local item_string + + local quality_labels = {"", "WellCrafted", "FinelyCrafted", "Superior", "Exceptional", "Masterful", "Artifact"} + local quality_pens = {COLOR_BLACK, COLOR_BROWN, COLOR_CYAN, COLOR_LIGHTBLUE, COLOR_GREEN, COLOR_LIGHTGREEN, COLOR_BLUE} + + dfhack.printerr("iterating over all world items...") + for k,v in pairs(world.items.other[df.items_other_id.IN_PLAY]) do repeat + local item_desc = dfhack.items.getDescription(v, v:getType()) + + -- JXOFDEMICT + --[[ + local filter_states = { + in_job = true, + rotten = true, + owned = true, + forbidden = true, + dump = true, + on_fire = true, + melt = true, + in_inv = true, + caged = true, + trade = true, + no_flags = true, + }--]] + + -- see if item is in job + local job_char + local ref = dfhack.items.getSpecificRef(v, df.specific_ref_type.JOB) + if ref and ref.data.job then job_char = 'J' else job_char = ' ' end + if not filter_states.in_job and job_char == 'J' then do break end end + + -- check various flags + local rotten_char + if v.flags.rotten then rotten_char = 'X' else rotten_char = ' ' end + if not filter_states.rotten and v.flags.rotten then do break end end + + local owned_char + if v.flags.owned then owned_char = 'O' else owned_char = ' ' end + if not filter_states.owned and v.flags.owned then do break end end + + local forbidden_char + if v.flags.forbid then forbidden_char = 'F' else forbidden_char = ' ' end + if not filter_states.forbidden and v.flags.forbid then do break end end + + local dump_char + if v.flags.dump then dump_char = 'D' else dump_char = ' ' end + if not filter_states.dump and v.flags.dump then do break end end + + local on_fire_char + if v.flags.on_fire then on_fire_char = 'E' else on_fire_char = ' ' end + if not filter_states.on_fire and v.flags.on_fire then do break end end + + local melt_char + if v.flags.melt then melt_char = 'M' else melt_char = ' ' end + if not filter_states.melt and v.flags.melt then do break end end + + local in_inv_char + if v.flags.in_inventory then in_inv_char = 'I' else in_inv_char = ' ' end + if not filter_states.in_inv and v.flags.in_inventory then do break end end + + -- check quality + local quality_label, quality_pen + quality_label = quality_labels[v:getQuality()] + quality_pen = quality_pens[v:getQuality()] + + --[[ + JXOFDEMICT + + J: in job lightblue + X: rotten cyan + O: owned green + F: forbidden red? + D: dump lightmagenta + E: on fire lightred? + M: melt blue + I: in inventory white + C: caged lightred + T: marked for trade lightgreen + --]] + if not filter or #filter < 1 or string.match(string.lower(item_desc), filter) then + table.insert(list_contents, { + text = { + {text = item_desc, width = item_desc_width, rjustify = false, pad_char = ' '}, ' ', + {text = job_char, width = 1, pen = COLOR_LIGHTBLUE}, + {text = rotten_char, width = 1, pen = COLOR_CYAN}, + {text = owned_char, width = 1, pen = COLOR_GREEN}, + {text = forbidden_char, width = 1, pen = COLOR_RED}, + {text = dump_char, width = 1, pen = COLOR_LIGHTMAGENTA}, + {text = on_fire_char, width = 1, pen = COLOR_LIGHTRED}, + {text = melt_char, width = 1, pen = COLOR_BLUE}, + {text = in_inv_char, width = 1, pen = COLOR_WHITE}, " ", + {text = quality_label, width = 13, rjustify = false, pad_char = ' ', pen = quality_pen}, + } + }) + end + until true end + + + local spec = { key = function(v) return v.text[1].text end } + local order = utils.make_sort_order(list_contents, { spec }) + local sorted_list_contents = {} + + for i = 1, #order do sorted_list_contents[i] = list_contents[order[i]] end + + --self.subviews.item_list:setChoices(list_contents) + self.subviews.item_list:setChoices(sorted_list_contents) + self.subviews.item_count_label:setText(string.format("Items: %d", #sorted_list_contents)) + dfhack.printerr("done.") +end + +StocksScreen = defclass(StocksScreen, gui.ZScreen) +StocksScreen.ATTRS({ + focus_path = "stocks2" +}) + +function StocksScreen:init() + self:addviews({StocksWindow{}}) +end + +function StocksScreen:onDismiss() + view = nil +end + +if dfhack_flags.module then + return +end + +view = view and view:raise() or StocksScreen{}:show() From fe9caad11d7a825eccf7a047ef6f7fd623c3d38d Mon Sep 17 00:00:00 2001 From: Philip Lancaster Date: Sat, 26 Aug 2023 17:55:14 -0400 Subject: [PATCH 2/6] removed old code and debug stuff --- stocks2.lua | 174 ---------------------------------------------------- 1 file changed, 174 deletions(-) diff --git a/stocks2.lua b/stocks2.lua index 71e465fd35..842bdb3ecb 100644 --- a/stocks2.lua +++ b/stocks2.lua @@ -43,14 +43,6 @@ StocksWindow.ATTRS({ }) function StocksWindow:init() - --dfhack.printerr("StocksWindow:init() called!") - --[[ - COLOR_RESET, COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN, - COLOR_RED, COLOR_MAGENTA, COLOR_BROWN, COLOR_GREY, COLOR_DARKGREY, - COLOR_LIGHTBLUE, COLOR_LIGHTGREEN, COLOR_LIGHTCYAN, COLOR_LIGHTRED, - COLOR_LIGHTMAGENTA, COLOR_YELLOW, COLOR_WHITE - --]] - self:addviews({ widgets.Panel({ view_id = "left_panel", @@ -74,9 +66,7 @@ function StocksWindow:init() }), widgets.List({ view_id = "item_list", - --edit_below = false, frame = {t = 4, b = 1, l = 1, r = 1}, - --not_found_label = "empty?", text_pen = {fg = COLOR_GREY, bg = COLOR_BLACK}, text_hpen = {fg = COLOR_BLACK, bg = COLOR_GREY}, cursor_pen = {fg = COLOR_LIGHTGREEN, bg = COLOR_DARKGREY}, @@ -160,19 +150,6 @@ function StocksWindow:populate_item_table() -- store item description and an item ref table.insert(temp_table, { desc = item_desc, ref = v }) - - --[[ - for i,g in pairs(v.general_refs) do - local t = g:getType() - - if t == df.general_ref_type.CONTAINED_IN_ITEM then - for i2,g2 in ipairs(g:getItem().general_refs) do - if g2:getType() == df.general_ref_type.UNIT_HOLDER then - dfhack.printerr(string.format("found a contained_in_item <-> unit_holder link! contained item: %s, container item: %s, ", item_desc, dfhack.items.getDescription(g:getItem(), g:getItem():getType()))) - end - end - end - end--]] end -- sort alphabetically @@ -236,28 +213,6 @@ function is_valid_melt_item(item) end function StocksWindow:onInput(keys) - --[[dfhack.printerr("window onInput called!") - for k,v in pairs(keys) do - dfhack.printerr(k) - dfhack.printerr(v) - end--]] - - -- JXOFDEMICT - --[[ - local filter_states = { - in_job = true, - rotten = true, - owned = true, - forbidden = true, - dump = true, - on_fire = true, - melt = true, - in_inv = true, - caged = true, - trade = true, - no_flags = true, -}--]] - -- FILTERS ------------------- local refresh_list = false @@ -376,8 +331,6 @@ function StocksWindow:onInput(keys) end - - if refresh_list then self:filter_list(current_search_query) end @@ -533,20 +486,7 @@ function StocksWindow:filter_list(filter) if item:getWear() < min_wear then goto continue end local wear_tags = {"", "x", "X", "XX"} - --[[ - JXOFDEMICT - J: in job lightblue - X: rotten cyan - O: owned green - F: forbidden red? - D: dump lightmagenta - E: on fire lightred? - M: melt blue - I: in inventory white - C: caged lightred - T: marked for trade lightgreen - --]] if not filter or #filter < 1 or string.match(string.lower(v.desc), filter) then local full_item_desc if item:getWear() > 0 then @@ -584,120 +524,6 @@ function StocksWindow:filter_list(filter) dfhack.printerr("done.") end -function StocksWindow:filter_list_old(filter) - dfhack.printerr(string.format("filter_list() called with \"%s\"", filter)) - local world = df.global.world - local list_contents = {} - local item_string - - local quality_labels = {"", "WellCrafted", "FinelyCrafted", "Superior", "Exceptional", "Masterful", "Artifact"} - local quality_pens = {COLOR_BLACK, COLOR_BROWN, COLOR_CYAN, COLOR_LIGHTBLUE, COLOR_GREEN, COLOR_LIGHTGREEN, COLOR_BLUE} - - dfhack.printerr("iterating over all world items...") - for k,v in pairs(world.items.other[df.items_other_id.IN_PLAY]) do repeat - local item_desc = dfhack.items.getDescription(v, v:getType()) - - -- JXOFDEMICT - --[[ - local filter_states = { - in_job = true, - rotten = true, - owned = true, - forbidden = true, - dump = true, - on_fire = true, - melt = true, - in_inv = true, - caged = true, - trade = true, - no_flags = true, - }--]] - - -- see if item is in job - local job_char - local ref = dfhack.items.getSpecificRef(v, df.specific_ref_type.JOB) - if ref and ref.data.job then job_char = 'J' else job_char = ' ' end - if not filter_states.in_job and job_char == 'J' then do break end end - - -- check various flags - local rotten_char - if v.flags.rotten then rotten_char = 'X' else rotten_char = ' ' end - if not filter_states.rotten and v.flags.rotten then do break end end - - local owned_char - if v.flags.owned then owned_char = 'O' else owned_char = ' ' end - if not filter_states.owned and v.flags.owned then do break end end - - local forbidden_char - if v.flags.forbid then forbidden_char = 'F' else forbidden_char = ' ' end - if not filter_states.forbidden and v.flags.forbid then do break end end - - local dump_char - if v.flags.dump then dump_char = 'D' else dump_char = ' ' end - if not filter_states.dump and v.flags.dump then do break end end - - local on_fire_char - if v.flags.on_fire then on_fire_char = 'E' else on_fire_char = ' ' end - if not filter_states.on_fire and v.flags.on_fire then do break end end - - local melt_char - if v.flags.melt then melt_char = 'M' else melt_char = ' ' end - if not filter_states.melt and v.flags.melt then do break end end - - local in_inv_char - if v.flags.in_inventory then in_inv_char = 'I' else in_inv_char = ' ' end - if not filter_states.in_inv and v.flags.in_inventory then do break end end - - -- check quality - local quality_label, quality_pen - quality_label = quality_labels[v:getQuality()] - quality_pen = quality_pens[v:getQuality()] - - --[[ - JXOFDEMICT - - J: in job lightblue - X: rotten cyan - O: owned green - F: forbidden red? - D: dump lightmagenta - E: on fire lightred? - M: melt blue - I: in inventory white - C: caged lightred - T: marked for trade lightgreen - --]] - if not filter or #filter < 1 or string.match(string.lower(item_desc), filter) then - table.insert(list_contents, { - text = { - {text = item_desc, width = item_desc_width, rjustify = false, pad_char = ' '}, ' ', - {text = job_char, width = 1, pen = COLOR_LIGHTBLUE}, - {text = rotten_char, width = 1, pen = COLOR_CYAN}, - {text = owned_char, width = 1, pen = COLOR_GREEN}, - {text = forbidden_char, width = 1, pen = COLOR_RED}, - {text = dump_char, width = 1, pen = COLOR_LIGHTMAGENTA}, - {text = on_fire_char, width = 1, pen = COLOR_LIGHTRED}, - {text = melt_char, width = 1, pen = COLOR_BLUE}, - {text = in_inv_char, width = 1, pen = COLOR_WHITE}, " ", - {text = quality_label, width = 13, rjustify = false, pad_char = ' ', pen = quality_pen}, - } - }) - end - until true end - - - local spec = { key = function(v) return v.text[1].text end } - local order = utils.make_sort_order(list_contents, { spec }) - local sorted_list_contents = {} - - for i = 1, #order do sorted_list_contents[i] = list_contents[order[i]] end - - --self.subviews.item_list:setChoices(list_contents) - self.subviews.item_list:setChoices(sorted_list_contents) - self.subviews.item_count_label:setText(string.format("Items: %d", #sorted_list_contents)) - dfhack.printerr("done.") -end - StocksScreen = defclass(StocksScreen, gui.ZScreen) StocksScreen.ATTRS({ focus_path = "stocks2" From 2e3ecc5ab36c5709baecab878f9a5a5ff3182368 Mon Sep 17 00:00:00 2001 From: Philip Lancaster Date: Sat, 26 Aug 2023 18:06:40 -0400 Subject: [PATCH 3/6] added .rst doc file --- docs/stocks2.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 docs/stocks2.rst diff --git a/docs/stocks2.rst b/docs/stocks2.rst new file mode 100644 index 0000000000..7503ecf387 --- /dev/null +++ b/docs/stocks2.rst @@ -0,0 +1,14 @@ +stocks2 +======== + +.. dfhack-tool:: + :summary: Alternative to the stocks screen based on the pre-v50 stocks plugin by Falconne. + :tags: stocks + +This script is a replica of the pre-v50 stocks plugin by Falconne and it offers an +alternative way to manage items in your game world. + +Usage +----- +``stocks2`` + Launch the stocks2 interface From 78e7c70d9fee83ae694728eea5abef7304857178 Mon Sep 17 00:00:00 2001 From: Philip Lancaster Date: Sat, 26 Aug 2023 18:12:37 -0400 Subject: [PATCH 4/6] removed some tabs --- stocks2.lua | 948 ++++++++++++++++++++++++++-------------------------- 1 file changed, 474 insertions(+), 474 deletions(-) diff --git a/stocks2.lua b/stocks2.lua index 842bdb3ecb..78647a7a50 100644 --- a/stocks2.lua +++ b/stocks2.lua @@ -10,17 +10,17 @@ local item_table = {} local current_search_query = "" local filter_states = { - in_job = true, - rotten = true, - owned = true, - forbidden = true, - dump = true, - on_fire = true, - melt = true, - in_inv = true, - caged = true, - trade = true, - no_flags = true, + in_job = true, + rotten = true, + owned = true, + forbidden = true, + dump = true, + on_fire = true, + melt = true, + in_inv = true, + caged = true, + trade = true, + no_flags = true, } local min_qual = 0 @@ -36,509 +36,509 @@ local stocks_window_height = 50 StocksWindow = defclass(StocksWindow, widgets.Window) StocksWindow.ATTRS({ - frame = {w = stocks_window_width, h = stocks_window_height}, - frame_title = "Stocks", - autoarrange_subviews = false, - autoarrange_gap = 0, + frame = {w = stocks_window_width, h = stocks_window_height}, + frame_title = "Stocks", + autoarrange_subviews = false, + autoarrange_gap = 0, }) function StocksWindow:init() - self:addviews({ - widgets.Panel({ - view_id = "left_panel", - frame = {t = 0, b = 0, l = 0, r = stocks_window_width - 76}, - frame_style = gui.INTERIOR_FRAME, - subviews = { - widgets.EditField({ - view_id = "search_box", - frame = {t = 1, l = 0}, - label_text = "Search: ", - on_char = function(ch) return ch:match("[%l%s]") end, - on_change = function(new_text, old_text) - current_search_query = new_text - self:filter_list(current_search_query) - end, - }), - widgets.Label({ - text = {{text = "Items: ", pen = COLOR_LIGHTGREEN}}, - frame = {t = 3, l = 0}, - view_id = "item_count_label" - }), - widgets.List({ - view_id = "item_list", - frame = {t = 4, b = 1, l = 1, r = 1}, - text_pen = {fg = COLOR_GREY, bg = COLOR_BLACK}, - text_hpen = {fg = COLOR_BLACK, bg = COLOR_GREY}, - cursor_pen = {fg = COLOR_LIGHTGREEN, bg = COLOR_DARKGREY}, - }), - }, - }), - widgets.Panel({ - view_id = "right_panel", - frame = {t = 0, b = 0, r = 0, l = 72}, - frame_style = gui.INTERIOR_FRAME, - subviews = { - widgets.Label({ - text = "Filters (Alt+Key toggles)", - frame = {t = 0, l = 0}, - view_id = "filters_header_label", - }), - widgets.Label({ - text = "to be filled in...", - frame = {t = 1, l = 0}, - view_id = "filters_label", - }), - widgets.Label({ - text = { - {text = "Shift-C", pen = COLOR_LIGHTGREEN}, {text = ": Clear All", pen = COLOR_WHITE}, NEWLINE, - {text = "Shift-E", pen = COLOR_LIGHTGREEN}, {text = ": Enable All", pen = COLOR_WHITE}, NEWLINE, - {text = "Shift-G", pen = COLOR_LIGHTGREEN}, {text = ": Toggle Grouping", pen = COLOR_WHITE} - }, - frame = {t = 8, l = 0}, - view_id = "filters_label2", - }), - widgets.Label({ - text = { - {text = "-+", pen = COLOR_LIGHTGREEN}, {text = ": Min Qual: ", pen = COLOR_WHITE}, {text = "tbd", pen = COLOR_BROWN}, NEWLINE, - {text = "/*", pen = COLOR_LIGHTGREEN}, {text = ": Max Qual: ", pen = COLOR_WHITE}, {text = "tbd", pen = COLOR_BROWN}, NEWLINE, - {text = "Shift-W", pen = COLOR_LIGHTGREEN}, {text = ": Min Wear: ", pen = COLOR_WHITE}, {text = "tbd", pen = COLOR_BROWN} - }, - frame = {t = 12, l = 0}, - view_id = "filters_qual_wear", - }), - widgets.Label({ - text = { - {text = "Actions (", pen = COLOR_BROWN}, {text = "...", pen = COLOR_LIGHTGREEN}, {text = " Items)", pen = COLOR_BROWN} - }, - frame = {t = 16, l = 0}, - view_id = "actions_item_count_label", - }), - widgets.Label({ - text = { - {text = "Shift-Z", pen = COLOR_LIGHTGREEN}, {text = ": Zoom ", pen = COLOR_WHITE}, - {text = "-D", pen = COLOR_LIGHTGREEN}, {text = ": Dump", pen = COLOR_WHITE}, NEWLINE, - {text = "Shift-F", pen = COLOR_LIGHTGREEN}, {text = ": Forbid ", pen = COLOR_WHITE}, - {text = "-M", pen = COLOR_LIGHTGREEN}, {text = ": Melt", pen = COLOR_WHITE}, NEWLINE, - {text = "Shift-T", pen = COLOR_LIGHTGREEN}, {text = ": Mark for Trade", pen = COLOR_GREY}, - }, - frame = {t = 17, l = 0}, - view_id = "actions_label", - }), - widgets.Label({ - text = { - {text = "Shift-A", pen = COLOR_LIGHTGREEN}, {text = ": Apply to: ", pen = COLOR_WHITE}, - {text = apply_to_labels[apply_to_mode + 1], pen = COLOR_BROWN}, - }, - frame = {t = 20, l = 0}, - view_id = "apply_to_label", - }), - } - }), - }) + self:addviews({ + widgets.Panel({ + view_id = "left_panel", + frame = {t = 0, b = 0, l = 0, r = stocks_window_width - 76}, + frame_style = gui.INTERIOR_FRAME, + subviews = { + widgets.EditField({ + view_id = "search_box", + frame = {t = 1, l = 0}, + label_text = "Search: ", + on_char = function(ch) return ch:match("[%l%s]") end, + on_change = function(new_text, old_text) + current_search_query = new_text + self:filter_list(current_search_query) + end, + }), + widgets.Label({ + text = {{text = "Items: ", pen = COLOR_LIGHTGREEN}}, + frame = {t = 3, l = 0}, + view_id = "item_count_label" + }), + widgets.List({ + view_id = "item_list", + frame = {t = 4, b = 1, l = 1, r = 1}, + text_pen = {fg = COLOR_GREY, bg = COLOR_BLACK}, + text_hpen = {fg = COLOR_BLACK, bg = COLOR_GREY}, + cursor_pen = {fg = COLOR_LIGHTGREEN, bg = COLOR_DARKGREY}, + }), + }, + }), + widgets.Panel({ + view_id = "right_panel", + frame = {t = 0, b = 0, r = 0, l = 72}, + frame_style = gui.INTERIOR_FRAME, + subviews = { + widgets.Label({ + text = "Filters (Alt+Key toggles)", + frame = {t = 0, l = 0}, + view_id = "filters_header_label", + }), + widgets.Label({ + text = "to be filled in...", + frame = {t = 1, l = 0}, + view_id = "filters_label", + }), + widgets.Label({ + text = { + {text = "Shift-C", pen = COLOR_LIGHTGREEN}, {text = ": Clear All", pen = COLOR_WHITE}, NEWLINE, + {text = "Shift-E", pen = COLOR_LIGHTGREEN}, {text = ": Enable All", pen = COLOR_WHITE}, NEWLINE, + {text = "Shift-G", pen = COLOR_LIGHTGREEN}, {text = ": Toggle Grouping", pen = COLOR_WHITE} + }, + frame = {t = 8, l = 0}, + view_id = "filters_label2", + }), + widgets.Label({ + text = { + {text = "-+", pen = COLOR_LIGHTGREEN}, {text = ": Min Qual: ", pen = COLOR_WHITE}, {text = "tbd", pen = COLOR_BROWN}, NEWLINE, + {text = "/*", pen = COLOR_LIGHTGREEN}, {text = ": Max Qual: ", pen = COLOR_WHITE}, {text = "tbd", pen = COLOR_BROWN}, NEWLINE, + {text = "Shift-W", pen = COLOR_LIGHTGREEN}, {text = ": Min Wear: ", pen = COLOR_WHITE}, {text = "tbd", pen = COLOR_BROWN} + }, + frame = {t = 12, l = 0}, + view_id = "filters_qual_wear", + }), + widgets.Label({ + text = { + {text = "Actions (", pen = COLOR_BROWN}, {text = "...", pen = COLOR_LIGHTGREEN}, {text = " Items)", pen = COLOR_BROWN} + }, + frame = {t = 16, l = 0}, + view_id = "actions_item_count_label", + }), + widgets.Label({ + text = { + {text = "Shift-Z", pen = COLOR_LIGHTGREEN}, {text = ": Zoom ", pen = COLOR_WHITE}, + {text = "-D", pen = COLOR_LIGHTGREEN}, {text = ": Dump", pen = COLOR_WHITE}, NEWLINE, + {text = "Shift-F", pen = COLOR_LIGHTGREEN}, {text = ": Forbid ", pen = COLOR_WHITE}, + {text = "-M", pen = COLOR_LIGHTGREEN}, {text = ": Melt", pen = COLOR_WHITE}, NEWLINE, + {text = "Shift-T", pen = COLOR_LIGHTGREEN}, {text = ": Mark for Trade", pen = COLOR_GREY}, + }, + frame = {t = 17, l = 0}, + view_id = "actions_label", + }), + widgets.Label({ + text = { + {text = "Shift-A", pen = COLOR_LIGHTGREEN}, {text = ": Apply to: ", pen = COLOR_WHITE}, + {text = apply_to_labels[apply_to_mode + 1], pen = COLOR_BROWN}, + }, + frame = {t = 20, l = 0}, + view_id = "apply_to_label", + }), + } + }), + }) - self:populate_item_table() - self:filter_list(current_search_query) - self:show_filters() - self:show_qual_and_wear() + self:populate_item_table() + self:filter_list(current_search_query) + self:show_filters() + self:show_qual_and_wear() end function StocksWindow:populate_item_table() - -- retrieve all in-play items - local temp_table = {} - for i,v in ipairs(df.global.world.items.other[df.items_other_id.IN_PLAY]) do - local item_desc = dfhack.items.getDescription(v, v:getType()) - - -- store item description and an item ref - table.insert(temp_table, { desc = item_desc, ref = v }) - end - - -- sort alphabetically - local spec = { key = function(v) return v.desc end } - local order = utils.make_sort_order(temp_table, { spec }) - for i = 1, #order do item_table[i] = temp_table[order[i]] end + -- retrieve all in-play items + local temp_table = {} + for i,v in ipairs(df.global.world.items.other[df.items_other_id.IN_PLAY]) do + local item_desc = dfhack.items.getDescription(v, v:getType()) + + -- store item description and an item ref + table.insert(temp_table, { desc = item_desc, ref = v }) + end + + -- sort alphabetically + local spec = { key = function(v) return v.desc end } + local order = utils.make_sort_order(temp_table, { spec }) + for i = 1, #order do item_table[i] = temp_table[order[i]] end end function toggle_melt(item) - item.flags.melt = not item.flags.melt - - if item.flags.melt then - utils.insert_sorted(df.global.world.items.other.ANY_MELT_DESIGNATED, item, "id") - else - utils.erase_sorted(df.global.world.items.other.ANY_MELT_DESIGNATED, item, "id") - end + item.flags.melt = not item.flags.melt + + if item.flags.melt then + utils.insert_sorted(df.global.world.items.other.ANY_MELT_DESIGNATED, item, "id") + else + utils.erase_sorted(df.global.world.items.other.ANY_MELT_DESIGNATED, item, "id") + end end function is_valid_melt_item(item) - local mat_info = dfhack.matinfo.decode(item) - if not mat_info then - return false - end - - -- must be a metal thing - if mat_info:getCraftClass() ~= df.craft_material_class.Metal then - return false - end - - -- must not be a metal bar - if item:getType() == df.item_type.BAR then - return false - end - - for i,g in ipairs(item.general_refs) do - local t = g:getType() - - -- don't be a holder of things - if t == df.general_ref_type.CONTAINS_ITEM or - t == df.general_ref_type.UNIT_HOLDER or - t == df.general_ref_type.CONTAINS_UNIT then - return false - end - - -- or be in something like a quiver, backpack, flask etc? - if t == df.general_ref_type.CONTAINED_IN_ITEM then - for i2, g2 in ipairs(g:getItem().general_refs) do - if g2:getType() == df.general_ref_type.UNIT_HOLDER then - return false - end - end - end - end - - -- lastly, don't melt masterworks - if item:getQuality() >= 5 then - return false - end - - return true + local mat_info = dfhack.matinfo.decode(item) + if not mat_info then + return false + end + + -- must be a metal thing + if mat_info:getCraftClass() ~= df.craft_material_class.Metal then + return false + end + + -- must not be a metal bar + if item:getType() == df.item_type.BAR then + return false + end + + for i,g in ipairs(item.general_refs) do + local t = g:getType() + + -- don't be a holder of things + if t == df.general_ref_type.CONTAINS_ITEM or + t == df.general_ref_type.UNIT_HOLDER or + t == df.general_ref_type.CONTAINS_UNIT then + return false + end + + -- or be in something like a quiver, backpack, flask etc? + if t == df.general_ref_type.CONTAINED_IN_ITEM then + for i2, g2 in ipairs(g:getItem().general_refs) do + if g2:getType() == df.general_ref_type.UNIT_HOLDER then + return false + end + end + end + end + + -- lastly, don't melt masterworks + if item:getQuality() >= 5 then + return false + end + + return true end function StocksWindow:onInput(keys) - -- FILTERS ------------------- - local refresh_list = false - - if keys["CUSTOM_ALT_J"] then filter_states.in_job = not filter_states.in_job; refresh_list = true end - if keys["CUSTOM_ALT_X"] then filter_states.rotten = not filter_states.rotten; refresh_list = true end - if keys["CUSTOM_ALT_O"] then filter_states.owned = not filter_states.owned; refresh_list = true end - if keys["CUSTOM_ALT_F"] then filter_states.forbidden = not filter_states.forbidden; refresh_list = true end - if keys["CUSTOM_ALT_D"] then filter_states.dump = not filter_states.dump; refresh_list = true end - if keys["CUSTOM_ALT_E"] then filter_states.on_fire = not filter_states.on_fire; refresh_list = true end - if keys["CUSTOM_ALT_M"] then filter_states.melt = not filter_states.melt; refresh_list = true end - if keys["CUSTOM_ALT_I"] then filter_states.in_inv = not filter_states.in_inv; refresh_list = true end - if keys["CUSTOM_ALT_C"] then filter_states.caged = not filter_states.caged; refresh_list = true end - if keys["CUSTOM_ALT_T"] then filter_states.trade = not filter_states.trade; refresh_list = true end - if keys["CUSTOM_ALT_N"] then filter_states.no_flags = not filter_states.no_flags; refresh_list = true end - - if keys["CUSTOM_SHIFT_C"] then - for k,v in pairs(filter_states) do - filter_states[k] = false - end - refresh_list = true - end - - if keys["CUSTOM_SHIFT_E"] then - for k,v in pairs(filter_states) do - filter_states[k] = true - end - refresh_list = true - end - - -- QUALITY AND WEAR ------------------- - -- keypad minus? - if keys["STRING_A045"] then - local new_min_qual = min_qual - 1 - if new_min_qual < 0 then new_min_qual = 0 end - if new_min_qual ~= min_qual then - min_qual = new_min_qual - refresh_list = true - end - end - - -- keypad plus? - if keys["STRING_A043"] then - local new_min_qual = min_qual + 1 - if new_min_qual > max_qual then new_min_qual = max_qual end - if new_min_qual ~= min_qual then - min_qual = new_min_qual - refresh_list = true - end - end - - -- keypad forward slash? - if keys["STRING_A047"] then - local new_max_qual = max_qual - 1 - if new_max_qual < min_qual then new_max_qual = min_qual end - if new_max_qual ~= max_qual then - max_qual = new_max_qual - refresh_list = true - end - end - - -- keypad asterisk? - if keys["STRING_A042"] then - local new_max_qual = max_qual + 1 - if new_max_qual > 6 then new_max_qual = 6 end - if new_max_qual ~= max_qual then - max_qual = new_max_qual - refresh_list = true - end - end - - if keys["CUSTOM_SHIFT_W"] then - min_wear = (min_wear + 1) % 4 - refresh_list = true - end - - -- ACTIONS -------------------- - if keys["CUSTOM_SHIFT_D"] then - if apply_to_mode == 1 then --selected - _, choice = self.subviews.item_list:getSelected() - choice.ref.flags.dump = not choice.ref.flags.dump - else - for i,v in ipairs(self.subviews.item_list:getChoices()) do - v.ref.flags.dump = not v.ref.flags.dump - end - end - - refresh_list = true - end - - if keys["CUSTOM_SHIFT_F"] then - if apply_to_mode == 1 then --selected - _, choice = self.subviews.item_list:getSelected() - choice.ref.flags.forbid = not choice.ref.flags.forbid - else - for i,v in ipairs(self.subviews.item_list:getChoices()) do - v.ref.flags.forbid = not v.ref.flags.forbid - end - end - - refresh_list = true - end - - if keys["CUSTOM_SHIFT_M"] then - if apply_to_mode == 1 then --selected - _, choice = self.subviews.item_list:getSelected() - if is_valid_melt_item(choice.ref) then - toggle_melt(choice.ref) - end - else - for i,v in ipairs(self.subviews.item_list:getChoices()) do - toggle_melt(v.ref) - end - end - - refresh_list = true - end - - - if refresh_list then - self:filter_list(current_search_query) - end - - if keys["CUSTOM_SHIFT_A"] then - apply_to_mode = (apply_to_mode + 1) % 2 - self.subviews.apply_to_label:setText( - {{text = "Shift-A", pen = COLOR_LIGHTGREEN}, {text = ": Apply to: ", pen = COLOR_WHITE}, {text = apply_to_labels[apply_to_mode + 1], pen = COLOR_BROWN}, - }) - end - - self:show_filters() - self:show_qual_and_wear() - - return StocksWindow.super.onInput(self, keys) + -- FILTERS ------------------- + local refresh_list = false + + if keys["CUSTOM_ALT_J"] then filter_states.in_job = not filter_states.in_job; refresh_list = true end + if keys["CUSTOM_ALT_X"] then filter_states.rotten = not filter_states.rotten; refresh_list = true end + if keys["CUSTOM_ALT_O"] then filter_states.owned = not filter_states.owned; refresh_list = true end + if keys["CUSTOM_ALT_F"] then filter_states.forbidden = not filter_states.forbidden; refresh_list = true end + if keys["CUSTOM_ALT_D"] then filter_states.dump = not filter_states.dump; refresh_list = true end + if keys["CUSTOM_ALT_E"] then filter_states.on_fire = not filter_states.on_fire; refresh_list = true end + if keys["CUSTOM_ALT_M"] then filter_states.melt = not filter_states.melt; refresh_list = true end + if keys["CUSTOM_ALT_I"] then filter_states.in_inv = not filter_states.in_inv; refresh_list = true end + if keys["CUSTOM_ALT_C"] then filter_states.caged = not filter_states.caged; refresh_list = true end + if keys["CUSTOM_ALT_T"] then filter_states.trade = not filter_states.trade; refresh_list = true end + if keys["CUSTOM_ALT_N"] then filter_states.no_flags = not filter_states.no_flags; refresh_list = true end + + if keys["CUSTOM_SHIFT_C"] then + for k,v in pairs(filter_states) do + filter_states[k] = false + end + refresh_list = true + end + + if keys["CUSTOM_SHIFT_E"] then + for k,v in pairs(filter_states) do + filter_states[k] = true + end + refresh_list = true + end + + -- QUALITY AND WEAR ------------------- + -- keypad minus? + if keys["STRING_A045"] then + local new_min_qual = min_qual - 1 + if new_min_qual < 0 then new_min_qual = 0 end + if new_min_qual ~= min_qual then + min_qual = new_min_qual + refresh_list = true + end + end + + -- keypad plus? + if keys["STRING_A043"] then + local new_min_qual = min_qual + 1 + if new_min_qual > max_qual then new_min_qual = max_qual end + if new_min_qual ~= min_qual then + min_qual = new_min_qual + refresh_list = true + end + end + + -- keypad forward slash? + if keys["STRING_A047"] then + local new_max_qual = max_qual - 1 + if new_max_qual < min_qual then new_max_qual = min_qual end + if new_max_qual ~= max_qual then + max_qual = new_max_qual + refresh_list = true + end + end + + -- keypad asterisk? + if keys["STRING_A042"] then + local new_max_qual = max_qual + 1 + if new_max_qual > 6 then new_max_qual = 6 end + if new_max_qual ~= max_qual then + max_qual = new_max_qual + refresh_list = true + end + end + + if keys["CUSTOM_SHIFT_W"] then + min_wear = (min_wear + 1) % 4 + refresh_list = true + end + + -- ACTIONS -------------------- + if keys["CUSTOM_SHIFT_D"] then + if apply_to_mode == 1 then --selected + _, choice = self.subviews.item_list:getSelected() + choice.ref.flags.dump = not choice.ref.flags.dump + else + for i,v in ipairs(self.subviews.item_list:getChoices()) do + v.ref.flags.dump = not v.ref.flags.dump + end + end + + refresh_list = true + end + + if keys["CUSTOM_SHIFT_F"] then + if apply_to_mode == 1 then --selected + _, choice = self.subviews.item_list:getSelected() + choice.ref.flags.forbid = not choice.ref.flags.forbid + else + for i,v in ipairs(self.subviews.item_list:getChoices()) do + v.ref.flags.forbid = not v.ref.flags.forbid + end + end + + refresh_list = true + end + + if keys["CUSTOM_SHIFT_M"] then + if apply_to_mode == 1 then --selected + _, choice = self.subviews.item_list:getSelected() + if is_valid_melt_item(choice.ref) then + toggle_melt(choice.ref) + end + else + for i,v in ipairs(self.subviews.item_list:getChoices()) do + toggle_melt(v.ref) + end + end + + refresh_list = true + end + + + if refresh_list then + self:filter_list(current_search_query) + end + + if keys["CUSTOM_SHIFT_A"] then + apply_to_mode = (apply_to_mode + 1) % 2 + self.subviews.apply_to_label:setText( + {{text = "Shift-A", pen = COLOR_LIGHTGREEN}, {text = ": Apply to: ", pen = COLOR_WHITE}, {text = apply_to_labels[apply_to_mode + 1], pen = COLOR_BROWN}, + }) + end + + self:show_filters() + self:show_qual_and_wear() + + return StocksWindow.super.onInput(self, keys) end function StocksWindow:show_qual_and_wear() - local quality_labels = {"Ordinary", "WellCrafted", "FinelyCrafted", "Superior", "Exceptional", "Masterful", "Artifact"} - self.subviews.filters_qual_wear:setText( - { - { text = "-+", pen = COLOR_LIGHTGREEN}, { text = ": Min Qual: ", pen = COLOR_WHITE }, { text = quality_labels[min_qual + 1], pen = COLOR_BROWN }, NEWLINE, - { text = "/*", pen = COLOR_LIGHTGREEN}, { text = ": Max Qual: ", pen = COLOR_WHITE }, { text = quality_labels[max_qual + 1], pen = COLOR_BROWN }, NEWLINE, - { text = "Shift-W", pen = COLOR_LIGHTGREEN}, { text = ": Min Wear: ", pen = COLOR_WHITE }, { text = tostring(min_wear), pen = COLOR_BROWN } - } - ) + local quality_labels = {"Ordinary", "WellCrafted", "FinelyCrafted", "Superior", "Exceptional", "Masterful", "Artifact"} + self.subviews.filters_qual_wear:setText( + { + { text = "-+", pen = COLOR_LIGHTGREEN}, { text = ": Min Qual: ", pen = COLOR_WHITE }, { text = quality_labels[min_qual + 1], pen = COLOR_BROWN }, NEWLINE, + { text = "/*", pen = COLOR_LIGHTGREEN}, { text = ": Max Qual: ", pen = COLOR_WHITE }, { text = quality_labels[max_qual + 1], pen = COLOR_BROWN }, NEWLINE, + { text = "Shift-W", pen = COLOR_LIGHTGREEN}, { text = ": Min Wear: ", pen = COLOR_WHITE }, { text = tostring(min_wear), pen = COLOR_BROWN } + } + ) end function StocksWindow:show_filters() - local function get_pen(state) - if state then - return COLOR_WHITE - else - return COLOR_GREY - end - end - - self.subviews.filters_label:setText( - { - { text = "J", pen = COLOR_LIGHTBLUE}, { text = ": In Job ", pen = get_pen(filter_states.in_job) }, - { text = "X", pen = COLOR_CYAN }, { text = ": Rotten", pen = get_pen(filter_states.rotten) }, NEWLINE, - { text = "O", pen = COLOR_GREEN}, { text = ": Owned ", pen = get_pen(filter_states.owned) }, - { text = "F", pen = COLOR_RED}, { text = ": Forbidden", pen = get_pen(filter_states.forbidden) }, NEWLINE, - { text = "D", pen = COLOR_MAGENTA}, { text = ": Dump ", pen = get_pen(filter_states.dump) }, - { text = "E", pen = COLOR_LIGHTRED}, { text = ": On Fire", pen = get_pen(filter_states.on_fire) }, NEWLINE, - { text = "M", pen = COLOR_BLUE}, { text = ": Melt ", pen = get_pen(filter_states.melt) }, - { text = "I", pen = COLOR_WHITE}, { text = ": In Inventory", pen = get_pen(filter_states.in_inv) }, NEWLINE, - { text = "C", pen = COLOR_LIGHTRED}, { text = ": Caged ", pen = get_pen(filter_states.caged) }, - { text = "T", pen = COLOR_LIGHTGREEN}, { text = ": Trade", pen = get_pen(filter_states.trade) }, NEWLINE, - { text = "N", pen = COLOR_GREY}, { text = ": No Flags", pen = get_pen(filter_states.no_flags) }, - } - ) + local function get_pen(state) + if state then + return COLOR_WHITE + else + return COLOR_GREY + end + end + + self.subviews.filters_label:setText( + { + { text = "J", pen = COLOR_LIGHTBLUE}, { text = ": In Job ", pen = get_pen(filter_states.in_job) }, + { text = "X", pen = COLOR_CYAN }, { text = ": Rotten", pen = get_pen(filter_states.rotten) }, NEWLINE, + { text = "O", pen = COLOR_GREEN}, { text = ": Owned ", pen = get_pen(filter_states.owned) }, + { text = "F", pen = COLOR_RED}, { text = ": Forbidden", pen = get_pen(filter_states.forbidden) }, NEWLINE, + { text = "D", pen = COLOR_MAGENTA}, { text = ": Dump ", pen = get_pen(filter_states.dump) }, + { text = "E", pen = COLOR_LIGHTRED}, { text = ": On Fire", pen = get_pen(filter_states.on_fire) }, NEWLINE, + { text = "M", pen = COLOR_BLUE}, { text = ": Melt ", pen = get_pen(filter_states.melt) }, + { text = "I", pen = COLOR_WHITE}, { text = ": In Inventory", pen = get_pen(filter_states.in_inv) }, NEWLINE, + { text = "C", pen = COLOR_LIGHTRED}, { text = ": Caged ", pen = get_pen(filter_states.caged) }, + { text = "T", pen = COLOR_LIGHTGREEN}, { text = ": Trade", pen = get_pen(filter_states.trade) }, NEWLINE, + { text = "N", pen = COLOR_GREY}, { text = ": No Flags", pen = get_pen(filter_states.no_flags) }, + } + ) end function StocksWindow:filter_list(filter) - dfhack.printerr(string.format("filter_list() called with \"%s\"", filter)) - local list_contents = {} - local item_string - - local quality_labels = {"", "WellCrafted", "FinelyCrafted", "Superior", "Exceptional", "Masterful", "Artifact"} - local quality_pens = {COLOR_BLACK, COLOR_BROWN, COLOR_CYAN, COLOR_LIGHTBLUE, COLOR_GREEN, COLOR_LIGHTGREEN, COLOR_BLUE} - - for i,v in ipairs(item_table) do - local item = v.ref - local has_flags = false - - -- see if item is in job - local job_char - local ref = dfhack.items.getSpecificRef(item, df.specific_ref_type.JOB) - if ref and ref.data.job then - job_char = 'J' - has_flags = true - else - job_char = ' ' - end - if not filter_states.in_job and job_char == 'J' then goto continue end - - -- check various flags - local rotten_char - if item.flags.rotten then - rotten_char = 'X' - has_flags = true - else - rotten_char = ' ' - end - if not filter_states.rotten and item.flags.rotten then goto continue end - - local owned_char - if item.flags.owned then - owned_char = 'O' - has_flags = true - else - owned_char = ' ' - end - if not filter_states.owned and item.flags.owned then goto continue end - - local forbidden_char - if item.flags.forbid then - forbidden_char = 'F' - has_flags = true - else - forbidden_char = ' ' - end - if not filter_states.forbidden and item.flags.forbid then goto continue end - - local dump_char - if item.flags.dump then - dump_char = 'D' - has_flags = true - else - dump_char = ' ' - end - if not filter_states.dump and item.flags.dump then goto continue end - - local on_fire_char - if item.flags.on_fire then - on_fire_char = 'E' - has_flags = true - else - on_fire_char = ' ' - end - if not filter_states.on_fire and item.flags.on_fire then goto continue end - - local melt_char - if item.flags.melt then - melt_char = 'M' - has_flags = true - else - melt_char = ' ' - end - if not filter_states.melt and item.flags.melt then goto continue end - - local in_inv_char - if item.flags.in_inventory then - in_inv_char = 'I' - has_flags = true - else - in_inv_char = ' ' - end - if not filter_states.in_inv and item.flags.in_inventory then goto continue end - - -- skip if item has no flags and that filter is off! - if not filter_states.no_flags and has_flags == false then goto continue end - - -- check quality - local quality_label, quality_pen - quality_label = quality_labels[item:getQuality() + 1] - quality_pen = quality_pens[item:getQuality() + 1] - - -- skip by quality or wear - if item:getQuality() < min_qual or item:getQuality() > max_qual then goto continue end - if item:getWear() < min_wear then goto continue end - - local wear_tags = {"", "x", "X", "XX"} + dfhack.printerr(string.format("filter_list() called with \"%s\"", filter)) + local list_contents = {} + local item_string + + local quality_labels = {"", "WellCrafted", "FinelyCrafted", "Superior", "Exceptional", "Masterful", "Artifact"} + local quality_pens = {COLOR_BLACK, COLOR_BROWN, COLOR_CYAN, COLOR_LIGHTBLUE, COLOR_GREEN, COLOR_LIGHTGREEN, COLOR_BLUE} + + for i,v in ipairs(item_table) do + local item = v.ref + local has_flags = false + + -- see if item is in job + local job_char + local ref = dfhack.items.getSpecificRef(item, df.specific_ref_type.JOB) + if ref and ref.data.job then + job_char = 'J' + has_flags = true + else + job_char = ' ' + end + if not filter_states.in_job and job_char == 'J' then goto continue end + + -- check various flags + local rotten_char + if item.flags.rotten then + rotten_char = 'X' + has_flags = true + else + rotten_char = ' ' + end + if not filter_states.rotten and item.flags.rotten then goto continue end + + local owned_char + if item.flags.owned then + owned_char = 'O' + has_flags = true + else + owned_char = ' ' + end + if not filter_states.owned and item.flags.owned then goto continue end + + local forbidden_char + if item.flags.forbid then + forbidden_char = 'F' + has_flags = true + else + forbidden_char = ' ' + end + if not filter_states.forbidden and item.flags.forbid then goto continue end + + local dump_char + if item.flags.dump then + dump_char = 'D' + has_flags = true + else + dump_char = ' ' + end + if not filter_states.dump and item.flags.dump then goto continue end + + local on_fire_char + if item.flags.on_fire then + on_fire_char = 'E' + has_flags = true + else + on_fire_char = ' ' + end + if not filter_states.on_fire and item.flags.on_fire then goto continue end + + local melt_char + if item.flags.melt then + melt_char = 'M' + has_flags = true + else + melt_char = ' ' + end + if not filter_states.melt and item.flags.melt then goto continue end + + local in_inv_char + if item.flags.in_inventory then + in_inv_char = 'I' + has_flags = true + else + in_inv_char = ' ' + end + if not filter_states.in_inv and item.flags.in_inventory then goto continue end + + -- skip if item has no flags and that filter is off! + if not filter_states.no_flags and has_flags == false then goto continue end + + -- check quality + local quality_label, quality_pen + quality_label = quality_labels[item:getQuality() + 1] + quality_pen = quality_pens[item:getQuality() + 1] + + -- skip by quality or wear + if item:getQuality() < min_qual or item:getQuality() > max_qual then goto continue end + if item:getWear() < min_wear then goto continue end + + local wear_tags = {"", "x", "X", "XX"} - if not filter or #filter < 1 or string.match(string.lower(v.desc), filter) then - local full_item_desc - if item:getWear() > 0 then - local wear_tag = wear_tags[item:getWear() + 1] - full_item_desc = wear_tag .. v.desc .. wear_tag - else - full_item_desc = v.desc - end - - table.insert(list_contents, { - text = { - {text = full_item_desc, width = item_desc_width, rjustify = false, pad_char = ' '}, ' ', - {text = job_char, width = 1, pen = COLOR_LIGHTBLUE}, - {text = rotten_char, width = 1, pen = COLOR_CYAN}, - {text = owned_char, width = 1, pen = COLOR_GREEN}, - {text = forbidden_char, width = 1, pen = COLOR_RED}, - {text = dump_char, width = 1, pen = COLOR_LIGHTMAGENTA}, - {text = on_fire_char, width = 1, pen = COLOR_LIGHTRED}, - {text = melt_char, width = 1, pen = COLOR_BLUE}, - {text = in_inv_char, width = 1, pen = COLOR_WHITE}, " ", - {text = quality_label, width = 13, rjustify = false, pad_char = ' ', pen = quality_pen}, - }, - ref = v.ref, - }) - end - - ::continue:: - end - - self.subviews.item_list:setChoices(list_contents) - self.subviews.item_count_label:setText(string.format("Items: %d", #list_contents)) - self.subviews.actions_item_count_label:setText({ - {text = "Actions (", pen = COLOR_BROWN}, {text = tostring(#list_contents), pen = COLOR_LIGHTGREEN}, {text = " Items)", pen = COLOR_BROWN} - }) - dfhack.printerr("done.") + if not filter or #filter < 1 or string.match(string.lower(v.desc), filter) then + local full_item_desc + if item:getWear() > 0 then + local wear_tag = wear_tags[item:getWear() + 1] + full_item_desc = wear_tag .. v.desc .. wear_tag + else + full_item_desc = v.desc + end + + table.insert(list_contents, { + text = { + {text = full_item_desc, width = item_desc_width, rjustify = false, pad_char = ' '}, ' ', + {text = job_char, width = 1, pen = COLOR_LIGHTBLUE}, + {text = rotten_char, width = 1, pen = COLOR_CYAN}, + {text = owned_char, width = 1, pen = COLOR_GREEN}, + {text = forbidden_char, width = 1, pen = COLOR_RED}, + {text = dump_char, width = 1, pen = COLOR_LIGHTMAGENTA}, + {text = on_fire_char, width = 1, pen = COLOR_LIGHTRED}, + {text = melt_char, width = 1, pen = COLOR_BLUE}, + {text = in_inv_char, width = 1, pen = COLOR_WHITE}, " ", + {text = quality_label, width = 13, rjustify = false, pad_char = ' ', pen = quality_pen}, + }, + ref = v.ref, + }) + end + + ::continue:: + end + + self.subviews.item_list:setChoices(list_contents) + self.subviews.item_count_label:setText(string.format("Items: %d", #list_contents)) + self.subviews.actions_item_count_label:setText({ + {text = "Actions (", pen = COLOR_BROWN}, {text = tostring(#list_contents), pen = COLOR_LIGHTGREEN}, {text = " Items)", pen = COLOR_BROWN} + }) + dfhack.printerr("done.") end StocksScreen = defclass(StocksScreen, gui.ZScreen) StocksScreen.ATTRS({ - focus_path = "stocks2" + focus_path = "stocks2" }) function StocksScreen:init() - self:addviews({StocksWindow{}}) + self:addviews({StocksWindow{}}) end function StocksScreen:onDismiss() - view = nil + view = nil end if dfhack_flags.module then - return + return end view = view and view:raise() or StocksScreen{}:show() From 57c2f7eadcde9e0f0f5890490506418d269f0c1a Mon Sep 17 00:00:00 2001 From: Philip Lancaster Date: Sat, 26 Aug 2023 18:13:23 -0400 Subject: [PATCH 5/6] trimmed trailing whitespace --- stocks2.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stocks2.lua b/stocks2.lua index 78647a7a50..eb59f79cdf 100644 --- a/stocks2.lua +++ b/stocks2.lua @@ -541,4 +541,4 @@ if dfhack_flags.module then return end -view = view and view:raise() or StocksScreen{}:show() +view = view and view:raise() or StocksScreen{}:show() \ No newline at end of file From bbd40e895d641f1eed5a153ae91b7034ce2707df Mon Sep 17 00:00:00 2001 From: Philip Lancaster Date: Sat, 26 Aug 2023 18:14:43 -0400 Subject: [PATCH 6/6] one more try --- stocks2.lua | 108 ++++++++++++++++++++++++++-------------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/stocks2.lua b/stocks2.lua index eb59f79cdf..87074a55d5 100644 --- a/stocks2.lua +++ b/stocks2.lua @@ -147,20 +147,20 @@ function StocksWindow:populate_item_table() local temp_table = {} for i,v in ipairs(df.global.world.items.other[df.items_other_id.IN_PLAY]) do local item_desc = dfhack.items.getDescription(v, v:getType()) - + -- store item description and an item ref table.insert(temp_table, { desc = item_desc, ref = v }) end - + -- sort alphabetically local spec = { key = function(v) return v.desc end } - local order = utils.make_sort_order(temp_table, { spec }) + local order = utils.make_sort_order(temp_table, { spec }) for i = 1, #order do item_table[i] = temp_table[order[i]] end end function toggle_melt(item) item.flags.melt = not item.flags.melt - + if item.flags.melt then utils.insert_sorted(df.global.world.items.other.ANY_MELT_DESIGNATED, item, "id") else @@ -171,29 +171,29 @@ end function is_valid_melt_item(item) local mat_info = dfhack.matinfo.decode(item) if not mat_info then - return false + return false end - + -- must be a metal thing if mat_info:getCraftClass() ~= df.craft_material_class.Metal then return false end - + -- must not be a metal bar if item:getType() == df.item_type.BAR then return false end - + for i,g in ipairs(item.general_refs) do local t = g:getType() - + -- don't be a holder of things if t == df.general_ref_type.CONTAINS_ITEM or t == df.general_ref_type.UNIT_HOLDER or t == df.general_ref_type.CONTAINS_UNIT then return false end - + -- or be in something like a quiver, backpack, flask etc? if t == df.general_ref_type.CONTAINED_IN_ITEM then for i2, g2 in ipairs(g:getItem().general_refs) do @@ -203,19 +203,19 @@ function is_valid_melt_item(item) end end end - + -- lastly, don't melt masterworks if item:getQuality() >= 5 then return false end - - return true + + return true end function StocksWindow:onInput(keys) -- FILTERS ------------------- local refresh_list = false - + if keys["CUSTOM_ALT_J"] then filter_states.in_job = not filter_states.in_job; refresh_list = true end if keys["CUSTOM_ALT_X"] then filter_states.rotten = not filter_states.rotten; refresh_list = true end if keys["CUSTOM_ALT_O"] then filter_states.owned = not filter_states.owned; refresh_list = true end @@ -227,21 +227,21 @@ function StocksWindow:onInput(keys) if keys["CUSTOM_ALT_C"] then filter_states.caged = not filter_states.caged; refresh_list = true end if keys["CUSTOM_ALT_T"] then filter_states.trade = not filter_states.trade; refresh_list = true end if keys["CUSTOM_ALT_N"] then filter_states.no_flags = not filter_states.no_flags; refresh_list = true end - + if keys["CUSTOM_SHIFT_C"] then for k,v in pairs(filter_states) do filter_states[k] = false end refresh_list = true end - + if keys["CUSTOM_SHIFT_E"] then for k,v in pairs(filter_states) do filter_states[k] = true end refresh_list = true end - + -- QUALITY AND WEAR ------------------- -- keypad minus? if keys["STRING_A045"] then @@ -252,7 +252,7 @@ function StocksWindow:onInput(keys) refresh_list = true end end - + -- keypad plus? if keys["STRING_A043"] then local new_min_qual = min_qual + 1 @@ -262,7 +262,7 @@ function StocksWindow:onInput(keys) refresh_list = true end end - + -- keypad forward slash? if keys["STRING_A047"] then local new_max_qual = max_qual - 1 @@ -272,7 +272,7 @@ function StocksWindow:onInput(keys) refresh_list = true end end - + -- keypad asterisk? if keys["STRING_A042"] then local new_max_qual = max_qual + 1 @@ -282,12 +282,12 @@ function StocksWindow:onInput(keys) refresh_list = true end end - + if keys["CUSTOM_SHIFT_W"] then min_wear = (min_wear + 1) % 4 refresh_list = true end - + -- ACTIONS -------------------- if keys["CUSTOM_SHIFT_D"] then if apply_to_mode == 1 then --selected @@ -298,10 +298,10 @@ function StocksWindow:onInput(keys) v.ref.flags.dump = not v.ref.flags.dump end end - + refresh_list = true end - + if keys["CUSTOM_SHIFT_F"] then if apply_to_mode == 1 then --selected _, choice = self.subviews.item_list:getSelected() @@ -311,10 +311,10 @@ function StocksWindow:onInput(keys) v.ref.flags.forbid = not v.ref.flags.forbid end end - + refresh_list = true end - + if keys["CUSTOM_SHIFT_M"] then if apply_to_mode == 1 then --selected _, choice = self.subviews.item_list:getSelected() @@ -326,25 +326,25 @@ function StocksWindow:onInput(keys) toggle_melt(v.ref) end end - + refresh_list = true end - - + + if refresh_list then self:filter_list(current_search_query) end - + if keys["CUSTOM_SHIFT_A"] then apply_to_mode = (apply_to_mode + 1) % 2 self.subviews.apply_to_label:setText( {{text = "Shift-A", pen = COLOR_LIGHTGREEN}, {text = ": Apply to: ", pen = COLOR_WHITE}, {text = apply_to_labels[apply_to_mode + 1], pen = COLOR_BROWN}, }) end - + self:show_filters() self:show_qual_and_wear() - + return StocksWindow.super.onInput(self, keys) end @@ -368,7 +368,7 @@ function StocksWindow:show_filters() return COLOR_GREY end end - + self.subviews.filters_label:setText( { { text = "J", pen = COLOR_LIGHTBLUE}, { text = ": In Job ", pen = get_pen(filter_states.in_job) }, @@ -383,21 +383,21 @@ function StocksWindow:show_filters() { text = "T", pen = COLOR_LIGHTGREEN}, { text = ": Trade", pen = get_pen(filter_states.trade) }, NEWLINE, { text = "N", pen = COLOR_GREY}, { text = ": No Flags", pen = get_pen(filter_states.no_flags) }, } - ) + ) end function StocksWindow:filter_list(filter) dfhack.printerr(string.format("filter_list() called with \"%s\"", filter)) local list_contents = {} local item_string - + local quality_labels = {"", "WellCrafted", "FinelyCrafted", "Superior", "Exceptional", "Masterful", "Artifact"} local quality_pens = {COLOR_BLACK, COLOR_BROWN, COLOR_CYAN, COLOR_LIGHTBLUE, COLOR_GREEN, COLOR_LIGHTGREEN, COLOR_BLUE} - + for i,v in ipairs(item_table) do - local item = v.ref + local item = v.ref local has_flags = false - + -- see if item is in job local job_char local ref = dfhack.items.getSpecificRef(item, df.specific_ref_type.JOB) @@ -408,7 +408,7 @@ function StocksWindow:filter_list(filter) job_char = ' ' end if not filter_states.in_job and job_char == 'J' then goto continue end - + -- check various flags local rotten_char if item.flags.rotten then @@ -418,7 +418,7 @@ function StocksWindow:filter_list(filter) rotten_char = ' ' end if not filter_states.rotten and item.flags.rotten then goto continue end - + local owned_char if item.flags.owned then owned_char = 'O' @@ -427,7 +427,7 @@ function StocksWindow:filter_list(filter) owned_char = ' ' end if not filter_states.owned and item.flags.owned then goto continue end - + local forbidden_char if item.flags.forbid then forbidden_char = 'F' @@ -436,7 +436,7 @@ function StocksWindow:filter_list(filter) forbidden_char = ' ' end if not filter_states.forbidden and item.flags.forbid then goto continue end - + local dump_char if item.flags.dump then dump_char = 'D' @@ -445,7 +445,7 @@ function StocksWindow:filter_list(filter) dump_char = ' ' end if not filter_states.dump and item.flags.dump then goto continue end - + local on_fire_char if item.flags.on_fire then on_fire_char = 'E' @@ -454,7 +454,7 @@ function StocksWindow:filter_list(filter) on_fire_char = ' ' end if not filter_states.on_fire and item.flags.on_fire then goto continue end - + local melt_char if item.flags.melt then melt_char = 'M' @@ -463,7 +463,7 @@ function StocksWindow:filter_list(filter) melt_char = ' ' end if not filter_states.melt and item.flags.melt then goto continue end - + local in_inv_char if item.flags.in_inventory then in_inv_char = 'I' @@ -472,19 +472,19 @@ function StocksWindow:filter_list(filter) in_inv_char = ' ' end if not filter_states.in_inv and item.flags.in_inventory then goto continue end - + -- skip if item has no flags and that filter is off! if not filter_states.no_flags and has_flags == false then goto continue end - - -- check quality + + -- check quality local quality_label, quality_pen quality_label = quality_labels[item:getQuality() + 1] quality_pen = quality_pens[item:getQuality() + 1] - + -- skip by quality or wear if item:getQuality() < min_qual or item:getQuality() > max_qual then goto continue end if item:getWear() < min_wear then goto continue end - + local wear_tags = {"", "x", "X", "XX"} if not filter or #filter < 1 or string.match(string.lower(v.desc), filter) then @@ -495,7 +495,7 @@ function StocksWindow:filter_list(filter) else full_item_desc = v.desc end - + table.insert(list_contents, { text = { {text = full_item_desc, width = item_desc_width, rjustify = false, pad_char = ' '}, ' ', @@ -512,10 +512,10 @@ function StocksWindow:filter_list(filter) ref = v.ref, }) end - + ::continue:: end - + self.subviews.item_list:setChoices(list_contents) self.subviews.item_count_label:setText(string.format("Items: %d", #list_contents)) self.subviews.actions_item_count_label:setText({ @@ -541,4 +541,4 @@ if dfhack_flags.module then return end -view = view and view:raise() or StocksScreen{}:show() \ No newline at end of file +view = view and view:raise() or StocksScreen{}:show()