dfstatus: Allow sections and metal bars to be customized

develop
lethosor 2015-09-03 15:02:08 -04:00
parent 9eac4585b1
commit f1391b63e2
4 changed files with 207 additions and 67 deletions

@ -67,6 +67,7 @@ DFHack Future
- widgets' positions, formats, etc. are now customizable (see Readme) - widgets' positions, formats, etc. are now customizable (see Readme)
- weather display now separated from the date display - weather display now separated from the date display
- New mouse cursor widget - New mouse cursor widget
dfstatus: Can enable/disable individual categories and customize metal bar list
full-heal: "-r" option removes corpses full-heal: "-r" option removes corpses
gui/gm-editor gui/gm-editor
- Pointers can now be displaced - Pointers can now be displaced

@ -2365,6 +2365,7 @@ directory.
* gui/dfstatus * gui/dfstatus
Show a quick overview of critical stock quantities, including food, drinks, wood, and various bars. Show a quick overview of critical stock quantities, including food, drinks, wood, and various bars.
Sections can be enabled/disabled/configured by editing ``dfhack-config/dfstatus.lua``.
* gui/stockpiles * gui/stockpiles

@ -0,0 +1,28 @@
-- dfstatus config
-- the dfstatus script can be found in hack/scripts/gui/
--[[
The following variables can be set to true/false to enable/disable categories (all true by default)
* drink
* wood
* fuel
* prepared_meals
* tanned_hides
* cloth
* metals
Example:
drink = false
fuel = true
To add metals:
* metal 'IRON'
* metals "GOLD" 'SILVER'
* metal('COPPER')
* metals("BRONZE", 'HORN_SILVER')
Use '-' for a blank line:
* metal '-'
]]
metals 'IRON' 'PIG_IRON' 'STEEL'
metals '-'
metals 'GOLD' 'SILVER' 'COPPER'

@ -1,8 +1,87 @@
-- dfstatus 1.5 - a quick access status screen. -- a quick access status screen
-- originally written by enjia2000@gmail.com -- originally written by enjia2000@gmail.com (stolencatkarma)
local gui = require 'gui' local gui = require 'gui'
function warn(msg)
dfhack.color(COLOR_LIGHTRED)
print(msg)
dfhack.color(nil)
end
config = {
flags = {
drink = true,
wood = true,
fuel = true,
prepared_meals = true,
tanned_hides = true,
cloth = true,
metals = true,
},
metal_ids = {},
}
function parse_config()
local metal_map = {}
for id, raw in pairs(df.global.world.raws.inorganics) do
if raw.material.flags.IS_METAL then
metal_map[raw.id:upper()] = id
metal_map[id] = raw.id:upper()
end
end
local function add_metal(...)
for _, m in pairs({...}) do
id = metal_map[tostring(m):upper()]
if id ~= nil then
table.insert(config.metal_ids, id)
elseif m == '-' then
table.insert(config.metal_ids, '-')
else
warn('Invalid metal: ' .. tostring(m))
end
end
return add_metal
end
local env = {}
setmetatable(env, {
__index = function(_, k)
if k == 'metal' or k == 'metals' then
return add_metal
elseif k == 'flags' then
return config.flags
else
error('unknown name: ' .. k, 2)
end
end,
__newindex = function(_, k, v)
if config.flags[k] ~= nil then
if v ~= nil then
config.flags[k] = v
else
config.flags[k] = false
end
else
error('unknown flag: ' .. k, 2)
end
end,
})
local f, err = loadfile('dfhack-config/dfstatus.lua', 't', env)
if not f then
qerror('error loading config: ' .. err)
end
local ok, err = pcall(f)
if not ok then
qerror('error parsing config: ' .. err)
end
end
function getInorganicName(id)
return (df.inorganic_raw.find(id).material.state_name.Solid:gsub('^[a-z]', string.upper))
end
dfstatus = defclass(dfstatus, gui.FramedScreen) dfstatus = defclass(dfstatus, gui.FramedScreen)
dfstatus.ATTRS = { dfstatus.ATTRS = {
frame_style = gui.GREY_LINE_FRAME, frame_style = gui.GREY_LINE_FRAME,
@ -13,95 +92,126 @@ dfstatus.ATTRS = {
focus_path = 'dfstatus', focus_path = 'dfstatus',
} }
function dfstatus:onRenderBody(dc) function dfstatus:init()
self.text = {}
self.start = 1
local function write(line)
table.insert(self.text, line)
-- ensure that the window is wide enough for this line plus a scroll arrow
if #line + 1 > self.frame_width then
self.frame_width = #line + 1
end
end
local function newline() write('') end
local f = config.flags
local drink = 0 local drink = 0
local wood = 0 local wood = 0
--local meat = 0
--local raw_fish = 0
--local plants = 0
local prepared_meals = 0
local fuel = 0 local fuel = 0
local pigiron = 0
local iron = 0
local steel = 0
local silver = 0
local copper = 0
local gold = 0
local tannedhides = 0 local prepared_meals = 0
local tanned_hides = 0
local cloth = 0 local cloth = 0
local metals = {}
for _, id in pairs(config.metal_ids) do
metals[id] = 0
end
for _, item in ipairs(df.global.world.items.all) do for _, item in ipairs(df.global.world.items.all) do
if not item.flags.rotten and not item.flags.dump and not item.flags.forbid then if not item.flags.rotten and not item.flags.dump and not item.flags.forbid then
if (item:getType() == df.item_type.WOOD) then wood = wood + item:getStackSize() if item:getType() == df.item_type.WOOD then
elseif (item:getType() == df.item_type.DRINK) then drink = drink + item:getStackSize() wood = wood + item:getStackSize()
elseif (item:getType() == df.item_type.SKIN_TANNED) then tannedhides = tannedhides + item:getStackSize() elseif item:getType() == df.item_type.DRINK then
elseif (item:getType() == df.item_type.CLOTH) then cloth = cloth + item:getStackSize() drink = drink + item:getStackSize()
--elseif (item:getType() == df.item_type.MEAT) then meat = meat + item:getStackSize() elseif item:getType() == df.item_type.SKIN_TANNED then
--elseif (item:getType() == df.item_type.FISH_RAW) then raw_fish = raw_fish + item:getStackSize() tanned_hides = tanned_hides + item:getStackSize()
--elseif (item:getType() == df.item_type.PLANT) then plants = plants + item:getStackSize() elseif item:getType() == df.item_type.CLOTH then
elseif (item:getType() == df.item_type.FOOD) then prepared_meals = prepared_meals + item:getStackSize() cloth = cloth + item:getStackSize()
elseif (item:getType() == df.item_type.BAR) then elseif item:getType() == df.item_type.FOOD then
for token in string.gmatch(dfhack.items.getDescription(item,0),"[^%s]+") do prepared_meals = prepared_meals + item:getStackSize()
if (token == "silver") then silver = silver + item:getStackSize() elseif item:getType() == df.item_type.BAR then
elseif (token == "charcoal" or token == "coke") then fuel = fuel + item:getStackSize() if item:getMaterial() == df.builtin_mats.COAL then
elseif (token == "iron") then iron = iron + item:getStackSize() fuel = fuel + item:getStackSize()
elseif (token == "pig") then pigiron = pigiron + item:getStackSize() elseif item:getMaterial() == df.builtin_mats.INORGANIC then
elseif (token == "copper") then copper = copper + item:getStackSize() local mat_idx = item:getMaterialIndex()
elseif (token == "gold") then gold = gold + item:getStackSize() if metals[mat_idx] ~= nil then
elseif (token == "steel") then steel = steel + item:getStackSize() metals[mat_idx] = metals[mat_idx] + item:getStackSize()
end end
break -- only need to look at the 1st token of each item.
end end
end end
end end
end end
if f.drink then
write("Drinks: " .. drink)
end
if f.prepared_meals then
write("Meals: " .. prepared_meals)
end
if f.drink or f.prepared_meals then
newline()
end
if f.wood then
write("Wood: " .. wood)
end
if f.fuel then
write("Fuel: " .. fuel)
end
if f.wood or f.fuel then
newline()
end
if f.tanned_hides then
write("Hides: " .. tanned_hides)
end
if f.cloth then
write("Cloth: " .. cloth)
end
if f.tanned_hides or f.cloth then
newline()
end
if f.metals then
write("Metal bars:")
for _, id in pairs(config.metal_ids) do
if id == '-' then
newline()
else
write(' ' .. ('%-10s'):format(getInorganicName(id) .. ': ') .. metals[id])
end
end
end
self.start_min = 1
self.start_max = #self.text - self.frame_height + 1
end
function dfstatus:onRenderBody(dc)
dc:pen(COLOR_LIGHTGREEN) dc:pen(COLOR_LIGHTGREEN)
dc:string("Drinks: " .. drink) for id, line in pairs(self.text) do
dc:newline(0) if id >= self.start then
dc:string("Meals: " .. prepared_meals) dc:string(line):newline()
dc:newline(0) end
dc:newline(0) end
dc:string("Wood: " .. wood) dc:pen(COLOR_LIGHTCYAN)
dc:newline(0) if self.start > self.start_min then
dc:newline(0) dc:seek(self.frame_width - 1, 0):char(24)
dc:string("Hides: " .. tannedhides) end
dc:newline(0) if self.start < self.start_max then
dc:string("Cloth: " .. cloth) dc:seek(self.frame_width - 1, self.frame_height - 1):char(25)
dc:newline(0) end
-- dc:string("Raw Fish: ".. raw_fish)
-- dc:newline(0)
-- dc:string("Plants: ".. plants)
-- dc:newline(0)
dc:newline(0)
dc:string("Bars:")
dc:newline(1)
dc:string("Fuel: " .. fuel)
dc:newline(1)
dc:string("Pig Iron: " .. pigiron)
dc:newline(1)
dc:string("Steel: " .. steel)
dc:newline(1)
dc:string("Iron: " .. iron)
dc:newline(1)
dc:newline(1)
dc:string("Copper: " .. copper)
dc:newline(1)
dc:string("Silver: " .. silver)
dc:newline(1)
dc:string("Gold: " .. gold)
end end
function dfstatus:onInput(keys) function dfstatus:onInput(keys)
if keys.LEAVESCREEN or keys.SELECT then if keys.LEAVESCREEN or keys.SELECT then
self:dismiss() self:dismiss()
scr = nil scr = nil
elseif keys.STANDARDSCROLL_UP then
self.start = math.max(self.start - 1, self.start_min)
elseif keys.STANDARDSCROLL_DOWN then
self.start = math.min(self.start + 1, self.start_max)
end end
end end
if not scr then if not scr then
parse_config()
scr = dfstatus() scr = dfstatus()
scr:show() scr:show()
else else