diff --git a/docs/warn-stranded.rst b/docs/warn-stranded.rst index b5db2dd496..6242068f87 100644 --- a/docs/warn-stranded.rst +++ b/docs/warn-stranded.rst @@ -11,17 +11,24 @@ they get overly stressed or start starving. You can enable ``warn-stranded`` notifications in `gui/control-panel` on the "Maintenance" tab. +If you ignore a unit, either call ``warn-stranded clear`` in the dfhack console or if you have multiple +stranded you can toggle/clear all units in the warning dialog. + Usage ----- :: - warn-stranded + warn-stranded [clear] Examples -------- -``warn-stranded`` +``warn-stranded clear`` + Clear all ignored units and then check for ones that are stranded. Options ------- + +``clear`` + Will clear all ignored units so that warnings will be displayed again. diff --git a/warn-stranded.lua b/warn-stranded.lua index b08b0be080..0c11b9442d 100644 --- a/warn-stranded.lua +++ b/warn-stranded.lua @@ -1,6 +1,7 @@ -- Detects and alerts when a citizen is stranded -- by Azrazalea --- Heavily based off of warn-starving +-- Logic heavily based off of warn-starving +-- GUI heavily based off of autobutcher -- Thanks myk002 for telling me about pathability groups! --@ module = true @@ -8,6 +9,16 @@ local gui = require 'gui' local utils = require 'utils' local widgets = require 'gui.widgets' +local function clear() + dfhack.persistent.delete('warnStrandedIgnore') +end + +local args = utils.invert({...}) +if args.clear then + clear() +end + + warning = defclass(warning, gui.ZScreen) warning.ATTRS = { focus_path='warn-stranded', @@ -16,24 +27,35 @@ warning.ATTRS = { } function warning:init(info) - local main = widgets.Window{ - frame={w=80, h=18}, - frame_title='Stranded Citizen Warning', - resizable=true, - autoarrange_subviews=true - } - - main:addviews{ - widgets.WrappedLabel{ - text_to_wrap=table.concat(info.messages, NEWLINE), - } + self:addviews{ + widgets.Window{ + view_id = 'main', + frame={w=80, h=18}, + frame_title='Stranded Citizen Warning', + resizable=true, + subviews = { + widgets.Label{ + frame = { l = 0, t = 0}, + text_pen = COLOR_CYAN, + text = 'Number Stranded: '..#info.units, + }, + widgets.List{ + view_id = 'list', + frame = { t = 3, b = 5 }, + text_pen = { fg = COLOR_GREY, bg = COLOR_BLACK }, + cursor_pen = { fg = COLOR_BLACK, bg = COLOR_GREEN }, + }, + widgets.Label{ + view_id = 'bottom_ui', + frame = { b = 0, h = 1 }, + text = 'filled by updateBottom()' + } + } + } } - self:addviews{main} -end - -function warning:onDismiss() - view = nil + self:initListChoices(info.units) + self:updateBottom() end local function getSexString(sex) @@ -44,6 +66,101 @@ local function getSexString(sex) return "("..sym..")" end +local function getUnitDescription(unit) + return '['..dfhack.units.getProfessionName(unit)..'] '..dfhack.TranslateName(dfhack.units.getVisibleName(unit)).. + ' '..getSexString(unit.sex)..' Stress category: '..dfhack.units.getStressCategory(unit) +end + + +local function unitIgnored(unit) + local currentIgnore = dfhack.persistent.get('warnStrandedIgnore') + if currentIgnore == nil then return false end + + for index, id in pairs(currentIgnore['ints']) do + if id == unit.id then + print(id) + print(unit.id) + print('Unit Ignored') + return true, index + end + end + + return false +end + +local function toggleUnitIgnore(unit) + local currentIgnore = dfhack.persistent.get('warnStrandedIgnore') + + if currentIgnore == nil then + currentIgnore = { key = 'warnStrandedIgnore', value = 'warnStrandedIgnore', ints = {} } + dfhack.printerr('nil, creating') + table.insert(currentIgnore['ints'], unit.id) + end + + local ignored, index = unitIgnored(unit) + + if ignored then + dfhack.printerr('toggle remove') + table.remove(currentIgnore['ints'], unit.id) + else + dfhack.printerr('toggle insert') + table.insert(currentIgnore['ints'], unit.id) + end + + dfhack.persistent.save(currentIgnore) +end + +function warning:initListChoices(units) + local choices = {} + for _, unit in pairs(units) do + table.insert(choices, { text = getUnitDescription(unit), unit = unit }) + end + local list = self.subviews.list + list:setChoices(choices, 1) +end + +function warning:updateBottom() + self.subviews.bottom_ui:setText( + { + { key = 'SELECT', text = ': Toggle ignore unit', on_activate = self:callback('onIgnore') }, ' ', + { key = 'CUSTOM_SHIFT_I', text = ': Ignore all', on_activate = self:callback('onIgnoreAll') }, ' ', + { key = 'CUSTOM_SHIFT_C', text = ': Clear all ignored', on_activate = self:callback('onClear') }, + } + ) +end + +function warning:onIgnore() + local index, choice = self.subviews.list:getSelected() + local unit = choice.unit + + toggleUnitIgnore(unit) +end + +function warning:onIgnoreAll() + local currentIgnore = dfhack.persistent.get('warnStrandedIgnore') + local choices = self.subviews.list.getChoices() + + if currentIgnore == nil then + currentIgnore = { key = 'warnStrandedIgnore', value = 'warnStrandedIgnore', ints = {} } + end + + for _, choice in choices do + if not unitIgnored(unit) then + table.insert(currentIgnore['ints'], unit.id) + end + end + + dfhack.persistent.save(currentIgnore) +end + +function warning:onClear() + clear() +end + +function warning:onDismiss() + view = nil +end + function doCheck() local grouped = {} local citizens = dfhack.units.getCitizens() @@ -66,26 +183,13 @@ function doCheck() for _, units in pairs(grouped) do - if #units == 1 then + if #units == 1 and not unitIgnored(units[1]) then table.insert(strandedUnits, units[1]) end end if #strandedUnits > 0 then - dfhack.color(COLOR_LIGHTMAGENTA) - - local messages = {} - local preface = "Number of stranded: "..#strandedUnits - print(dfhack.df2console(preface)) - table.insert(messages, preface) - for _, unit in pairs(strandedUnits) do - local unitString = '['..dfhack.units.getProfessionName(unit)..'] '..dfhack.TranslateName(dfhack.units.getVisibleName(unit))..' '..getSexString(unit.sex)..' Stress category: '..dfhack.units.getStressCategory(unit) - print(dfhack.df2console(unitString)) - table.insert(messages, unitString) - end - - dfhack.color() - return warning{messages=messages}:show() + return warning{units=strandedUnits}:show() end end