-
Notifications
You must be signed in to change notification settings - Fork 200
/
Copy pathtroubleshoot-item.lua
154 lines (143 loc) · 6 KB
/
troubleshoot-item.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
--@ module = true
local function coord_to_str(coord)
local out = {}
for k, v in pairs(coord) do
-- handle 2D and 3D coordinates
if k == 'x' then out[1] = v end
if k == 'y' then out[2] = v end
if k == 'z' then out[3] = v end
end
return '(' .. table.concat(out, ', ') .. ')'
end
function troubleshoot_item(item, out)
local outstr = nil --as:string
if out == nil then
outstr = ''
out = function(s, level) outstr = outstr .. s .. '\n' end
end
local function warn(s) out('WARNING: ' .. s) end
assert(df.item:is_instance(item), 'not an item')
if item.id < 0 then warn('Invalid ID: ' .. item.id) end
if not df.item.find(item.id) then warn('Could not locate item in item lists') end
-- Print the item name, and its ID as a header
out("Item details:")
out("Description: " .. dfhack.items.getDescription(item, item:getType(), false), 1)
out("ID: " .. item.id, 1)
if item.flags.forbid then out('Forbidden') end
if item.flags.melt then out('Melt-designated') end
if item.flags.dump then out('Dump-designated') end
if item.flags.hidden then out('Hidden') end
local unit_holder = dfhack.items.getGeneralRef(item, df.general_ref_type.UNIT_HOLDER)
if unit_holder then
if unit_holder.unit_id then
local unit = df.unit.find(unit_holder.unit_id)
if unit then
out('Held by unit: ' .. dfhack.units.getReadableName(unit))
else
warn('Could not find unit with unit_id: ' .. unit_holder.unit_id)
end
else
warn('Could not find unit_id in unit_holder')
end
end
local contained_in = dfhack.items.getGeneralRef(item, df.general_ref_type.CONTAINED_IN_ITEM)
if contained_in then
if contained_in.item_id then
local contained_in_item = df.item.find(contained_in.item_id)
if contained_in_item then
out('Stored in item of type: ' .. df.item_type[contained_in_item:getType()])
else
warn('Could not find item with item_id: ' .. contained_in.item_id)
end
else
warn('Could not find item_id in contained_in_item')
end
end
local building_holder = dfhack.items.getGeneralRef(item, df.general_ref_type.BUILDING_HOLDER)
if building_holder then
if building_holder.building_id then
local building = df.building.find(building_holder.building_id)
if building then
out('Inside building of type: ' .. df.building_type[building:getType()])
else
warn('Could not find building with building_id: ' .. building_holder.building_id)
end
else
warn('Could not find building_id in building_holder')
end
end
if item.flags.container then
local count = 0
local item_types = {}
for _, v in pairs(item.general_refs) do
if v:getType() == df.general_ref_type.CONTAINS_ITEM then
count = count + 1
local contained_item = df.item.find(v.item_id)
local item_desc = dfhack.items.getDescription(contained_item, contained_item:getType(), false)
item_types[item_desc] = item_types[item_desc] and item_types[item_desc] + 1 or 1
end
end
local item_string = count == 1 and 'item' or 'items'
if count > 0 then item_string = item_string .. ':' end
out(string.format('Is a container, holding %s %s', count, item_string))
for item_desc, item_count in pairs(item_types) do
out(string.format('%s : %s', item_desc, item_count), 1)
end
end
if item.flags.on_fire then out('On fire') end
if item.flags.rotten then out('Rotten') end
if item.flags.trader then out('Trade good') end
if item.flags.owned then out('Owned') end
if item.flags.foreign then out('Foreign') end
if item.flags.encased then out('Encased in ice') end
if item.flags.garbage_collect then warn('Marked for garbage collection') end
if item.flags.construction then out('Used for construction') end
if item.flags.in_building then out('Used for building') end
if item.flags.artifact then
out(item.flags.artifact_mood and "Artifact (from strange mood)" or "Artifact")
end
if item.flags.in_job then
out('In job')
local ref = dfhack.items.getSpecificRef(item, df.specific_ref_type.JOB)
if ref then
out('Job type: ' .. df.job_type[ref.data.job.job_type], 1)
out('Job position: ' .. coord_to_str(ref.data.job.pos), 1)
local found_job_item = false
for i, job_item_ref in pairs(ref.data.job.items) do
if item == job_item_ref.item then found_job_item = true end
end
if not found_job_item then warn('Item not attached to job') end
else
warn('No job specific_ref found')
end
end
for i, ref in pairs(item.specific_refs) do
if ref.type ~= df.specific_ref_type.JOB then
out('Unhandled specific_ref: ' .. df.specific_ref_type[ref.type])
end
end
if outstr then return outstr end
end
function main(args)
local item = dfhack.gui.getSelectedItem(true)
if item then
local out_table = {}
local out_function = function(s, level)
table.insert(out_table, {s, level and level or 0})
end
troubleshoot_item(item, out_function)
for _, row in pairs(out_table) do
local out_line = row[1]
local indent_amount = row[2]
local indent = ''
for i = 1, indent_amount do
indent = indent .. ' '
end
-- Output log lines, heading lines (indent_amount=0) are prefixed with '-', other lines are indented
print(dfhack.df2console(string.format("%s%s%s", indent_amount == 0 and '- ' or '', indent, out_line)))
end
else
qerror('No item found')
end
end
if not moduleMode then main({...}) end