From e353f5f03ea9f68be9b5947e29f939dd3e3193f3 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sat, 27 Oct 2012 20:16:27 +0400 Subject: [PATCH] Add a script to complement the weapon rack binary patch. --- NEWS | 1 + dfhack.init-example | 6 ++ library/lua/class.lua | 10 +- library/lua/gui/widgets.lua | 17 +-- scripts/gui/assign-rack.lua | 202 ++++++++++++++++++++++++++++++++++++ 5 files changed, 226 insertions(+), 10 deletions(-) create mode 100644 scripts/gui/assign-rack.lua diff --git a/NEWS b/NEWS index 6b87a52b8..5103cf921 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,7 @@ DFHack future - gui/guide-path: displays the cached path for minecart Guide orders. - gui/workshop-job: displays inputs of a workshop job and allows tweaking them. - gui/workflow: a front-end for the workflow plugin. + - gui/assign-rack: works together with a binary patch to fix weapon racks. Workflow plugin: - properly considers minecarts assigned to routes busy. - code for deducing job outputs rewritten in lua for flexibility. diff --git a/dfhack.init-example b/dfhack.init-example index 2cdb114be..7dfa86016 100644 --- a/dfhack.init-example +++ b/dfhack.init-example @@ -81,6 +81,9 @@ keybinding add Alt-A@dwarfmode/QueryBuilding/Some/Workshop/Job gui/workshop-job # workflow front-end keybinding add Alt-W@dwarfmode/QueryBuilding/Some/Workshop/Job gui/workflow +# assign weapon racks to squads so that they can be used +keybinding add P@dwarfmode/QueryBuilding/Some/Weaponrack gui/assign-rack + ############################ # UI and game logic tweaks # ############################ @@ -118,3 +121,6 @@ tweak fast-trade tweak military-stable-assign # in same list, color units already assigned to squads in brown & green tweak military-color-assigned + +# stop squad equpment stored on weapon racks and armor stands from being stockpiled +tweak armory diff --git a/library/lua/class.lua b/library/lua/class.lua index bcfff13e2..e18bad9a9 100644 --- a/library/lua/class.lua +++ b/library/lua/class.lua @@ -65,10 +65,14 @@ end local function apply_attrs(obj, attrs, init_table) for k,v in pairs(attrs) do - if v == DEFAULT_NIL then - v = nil + local init_v = init_table[k] + if init_v ~= nil then + obj[k] = init_v + elseif v == DEFAULT_NIL then + obj[k] = nil + else + obj[k] = v end - obj[k] = init_table[k] or v end end diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index e526408fb..e731af068 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -501,14 +501,17 @@ function List:onRenderBody(dc) local y = (i - top)*self.row_height if iw and obj.icon then - dc:seek(0, y) - if type(obj.icon) == 'table' then - dc:char(nil,obj.icon) - else - if current then - dc:string(obj.icon, obj.icon_pen or cur_pen) + local icon = getval(obj.icon) + if icon then + dc:seek(0, y) + if type(icon) == 'table' then + dc:char(nil,icon) else - dc:string(obj.icon, obj.icon_pen or cur_dpen) + if current then + dc:string(icon, obj.icon_pen or self.icon_pen or cur_pen) + else + dc:string(icon, obj.icon_pen or self.icon_pen or cur_dpen) + end end end end diff --git a/scripts/gui/assign-rack.lua b/scripts/gui/assign-rack.lua new file mode 100644 index 000000000..d358dfff1 --- /dev/null +++ b/scripts/gui/assign-rack.lua @@ -0,0 +1,202 @@ +-- Assign weapon racks to squads. Requires patch from bug 1445. + +--[[ + + Required patches: + + v0.34.11 linux: http://pastebin.com/mt5EUgFZ + v0.34.11 windows: http://pastebin.com/09nRCybe + +]] + +local utils = require 'utils' +local gui = require 'gui' +local guidm = require 'gui.dwarfmode' +local widgets = require 'gui.widgets' +local dlg = require 'gui.dialogs' + +AssignRack = defclass(AssignRack, guidm.MenuOverlay) + +AssignRack.focus_path = 'assign-rack' + +AssignRack.ATTRS { + building = DEFAULT_NIL, + frame_inset = 1, + frame_background = COLOR_BLACK, +} + +function list_squads(building,squad_table,squad_list) + local sqlist = building:getSquads() + if not sqlist then + return + end + + for i,v in ipairs(sqlist) do + local obj = df.squad.find(v.squad_id) + if obj then + if not squad_table[v.squad_id] then + squad_table[v.squad_id] = { id = v.squad_id, obj = obj } + table.insert(squad_list, squad_table[v.squad_id]) + end + + -- Set specific use flags + for n,ok in pairs(v.mode) do + if ok then + squad_table[v.squad_id][n] = true + end + end + + -- Check if any use is possible + local btype = building:getType() + if btype == df.building_type.Bed then + if v.mode.sleep then + squad_table[v.squad_id].any = true + end + elseif btype == df.building.Weaponrack then + if v.mode.train or v.mode.indiv_eq then + squad_table[v.squad_id].any = true + end + else + if v.mode.indiv_eq then + squad_table[v.squad_id].any = true + end + end + end + end + + for i,v in ipairs(building.parents) do + list_squads(v, squad_table, squad_list) + end +end + +function filter_invalid(list, id) + for i=#list-1,0,-1 do + local bld = df.building.find(list[i]) + if not bld or bld:getSpecificSquad() ~= id then + list:erase(i) + end + end +end + +function AssignRack:init(args) + self.squad_table = {} + self.squad_list = {} + list_squads(self.building, self.squad_table, self.squad_list) + table.sort(self.squad_list, function(a,b) return a.id < b.id end) + + self.choices = {} + for i,v in ipairs(self.squad_list) do + if v.any and (v.train or v.indiv_eq) then + local name = v.obj.alias + if name == '' then + name = dfhack.TranslateName(v.obj.name, true) + end + + filter_invalid(v.obj.rack_combat, v.id) + filter_invalid(v.obj.rack_training, v.id) + + table.insert(self.choices, { + icon = self:callback('isSelected', v), + icon_pen = COLOR_LIGHTGREEN, + obj = v, + text = { + name, NEWLINE, ' ', + { text = function() + return string.format('%d combat, %d training', #v.obj.rack_combat, #v.obj.rack_training) + end } + } + }) + end + end + + self:addviews{ + widgets.Label{ + frame = { l = 0, t = 0 }, + text = { + 'Assign Weapon Rack' + } + }, + widgets.List{ + view_id = 'list', + frame = { t = 2, b = 2 }, + icon_width = 2, row_height = 2, + scroll_keys = widgets.SECONDSCROLL, + choices = self.choices, + on_submit = self:callback('onSubmit'), + }, + widgets.Label{ + frame = { l = 0, t = 2 }, + text_pen = COLOR_LIGHTRED, + text = 'No appropriate barracks\n\nNote: weapon racks use the\nIndividual equipment flag', + visible = (#self.choices == 0), + }, + widgets.Label{ + frame = { l = 0, b = 0 }, + text = { + { key = 'LEAVESCREEN', text = ': Back', + on_activate = self:callback('dismiss') } + } + }, + } +end + +function AssignRack:isSelected(info) + if self.building.specific_squad == info.id then + return '\xfb' + else + return nil + end +end + +function AssignRack:onSubmit(idx, choice) + local rid = self.building.id + local curid = self.building.specific_squad + + local cur = df.squad.find(curid) + if cur then + utils.erase_sorted(cur.rack_combat, rid) + utils.erase_sorted(cur.rack_training, rid) + end + + self.building.specific_squad = -1 + df.global.ui.equipment.update.buildings = true + + local new = df.squad.find(choice.obj.id) + if new and choice.obj.id ~= curid then + self.building.specific_squad = choice.obj.id + + if choice.obj.indiv_eq then + utils.insert_sorted(new.rack_combat, rid) + end + if choice.obj.train then + utils.insert_sorted(new.rack_training, rid) + end + end +end + +function AssignRack:onInput(keys) + if self:propagateMoveKeys(keys) then + if df.global.world.selected_building ~= self.building then + self:dismiss() + end + else + AssignRack.super.onInput(self, keys) + end +end + +if dfhack.gui.getCurFocus() ~= 'dwarfmode/QueryBuilding/Some/Weaponrack' then + qerror("This script requires a weapon rack selected in the 'q' mode") +end + +AssignRack{ building = dfhack.gui.getSelectedBuilding() }:show() + +if not already_warned then + already_warned = true + dlg.showMessage( + 'BUG ALERT', + { 'This script requires a binary patch from', NEWLINE, + 'bug 1445 on the tracker. Otherwise the game', NEWLINE, + 'will lose your settings due to a bug.' }, + COLOR_YELLOW + ) +end