-
Notifications
You must be signed in to change notification settings - Fork 200
/
Copy pathdfstatus.lua
228 lines (210 loc) · 6.24 KB
/
dfstatus.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
-- a quick access status screen
-- originally written by enjia2000@gmail.com (stolencatkarma)
--[====[
gui/dfstatus
============
Show a quick overview of critical stock quantities, including food, drinks, wood, and various bars.
Sections can be enabled/disabled/configured by editing :file:`dfhack-config/dfstatus.lua`.
]====]
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.ATTRS = {
frame_style = gui.GREY_LINE_FRAME,
frame_title = 'dfstatus',
frame_width = 16,
frame_height = 17,
frame_inset = 1,
focus_path = 'dfstatus',
}
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 wood = 0
local fuel = 0
local prepared_meals = 0
local tanned_hides = 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
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()
elseif item:getType() == df.item_type.DRINK then
drink = drink + item:getStackSize()
elseif item:getType() == df.item_type.SKIN_TANNED then
tanned_hides = tanned_hides + item:getStackSize()
elseif item:getType() == df.item_type.CLOTH then
cloth = cloth + item:getStackSize()
elseif item:getType() == df.item_type.FOOD then
prepared_meals = prepared_meals + item:getStackSize()
elseif item:getType() == df.item_type.BAR then
if item:getMaterial() == df.builtin_mats.COAL then
fuel = fuel + item:getStackSize()
elseif item:getMaterial() == df.builtin_mats.INORGANIC then
local mat_idx = item:getMaterialIndex()
if metals[mat_idx] ~= nil then
metals[mat_idx] = metals[mat_idx] + item:getStackSize()
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)
for id, line in pairs(self.text) do
if id >= self.start then
dc:string(line):newline()
end
end
dc:pen(COLOR_LIGHTCYAN)
if self.start > self.start_min then
dc:seek(self.frame_width - 1, 0):char(24)
end
if self.start < self.start_max then
dc:seek(self.frame_width - 1, self.frame_height - 1):char(25)
end
end
function dfstatus:onInput(keys)
if keys.LEAVESCREEN or keys.SELECT then
self:dismiss()
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
if not scr then
parse_config()
scr = dfstatus()
scr:show()
else
scr:dismiss()
scr = nil
end