Skip to content

Commit 4365c86

Browse files
authored
Merge pull request #1502 from SilasD/uniform-unstick-fix
Minor fixes to uniform-unstick
2 parents 2f285b0 + 1989990 commit 4365c86

File tree

2 files changed

+55
-49
lines changed

2 files changed

+55
-49
lines changed

changelog.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ Template for new versions:
3232
## New Features
3333

3434
## Fixes
35+
- `uniform-unstick`: added quivers, backpacks, and flasks/waterskins to uniform analysis
36+
- `uniform-unstick`: the ``--drop`` option now only evaluates clothing as possible items to drop
37+
- `uniform-unstick`: the ``--free`` option no longer redundantly reports an improperly assigned item when that item is removed from a uniform
38+
- `uniform-unstick`: the ``--drop`` and ``--free`` options now only drop items which are actually in a unit's inventory
39+
- `uniform-unstick`: the ``--all`` and ``--drop`` options, when used together, now print the separator line between each unit's report in the proper place
3540

3641
## Misc Improvements
3742

uniform-unstick.lua

Lines changed: 50 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -62,38 +62,20 @@ local function bodyparts_that_can_wear(unit, item)
6262
local bodyparts = {}
6363
local unitparts = dfhack.units.getCasteRaw(unit).body_info.body_parts
6464

65-
if item._type == df.item_helmst then
66-
for index, part in ipairs(unitparts) do
67-
if part.flags.HEAD then
68-
table.insert(bodyparts, index)
69-
end
70-
end
71-
elseif item._type == df.item_armorst then
72-
for index, part in ipairs(unitparts) do
73-
if part.flags.UPPERBODY then
74-
table.insert(bodyparts, index)
75-
end
76-
end
77-
elseif item._type == df.item_glovesst then
78-
for index, part in ipairs(unitparts) do
79-
if part.flags.GRASP then
80-
table.insert(bodyparts, index)
81-
end
82-
end
83-
elseif item._type == df.item_pantsst then
84-
for index, part in ipairs(unitparts) do
85-
if part.flags.LOWERBODY then
86-
table.insert(bodyparts, index)
87-
end
88-
end
89-
elseif item._type == df.item_shoesst then
90-
for index, part in ipairs(unitparts) do
91-
if part.flags.STANCE then
92-
table.insert(bodyparts, index)
65+
for bodypart_flag, item_type in pairs({
66+
HEAD = df.item_helmst,
67+
UPPERBODY = df.item_armorst,
68+
GRASP = df.item_glovesst,
69+
LOWERBODY = df.item_pantsst,
70+
STANCE = df.item_shoesst,
71+
}) do
72+
if item._type == item_type then
73+
for index, part in ipairs(unitparts) do
74+
if part.flags[bodypart_flag] then
75+
table.insert(bodyparts, index)
76+
end
9377
end
9478
end
95-
else
96-
-- print("Ignoring item type for "..item_description(item) )
9779
end
9880

9981
return bodyparts
@@ -109,6 +91,7 @@ end
10991
-- @param squad_position df.squad_position
11092
-- @param item_id number
11193
local function remove_item_from_position(squad_position, item_id)
94+
utils.erase_sorted(squad_position.equipment.assigned_items, item_id)
11295
for _, uniform_slot_specs in ipairs(squad_position.equipment.uniform) do
11396
for _, uniform_spec in ipairs(uniform_slot_specs) do
11497
for idx, assigned_item_id in ipairs(uniform_spec.assigned) do
@@ -119,9 +102,16 @@ local function remove_item_from_position(squad_position, item_id)
119102
end
120103
end
121104
end
105+
for _, special_case in ipairs({"quiver", "backpack", "flask"}) do
106+
if squad_position.equipment[special_case] == item_id then
107+
squad_position.equipment[special_case] = -1
108+
return
109+
end
110+
end
122111
end
123112

124113
-- Will figure out which items need to be moved to the floor, returns an item_id:item map
114+
-- and a flag that indicates whether a separator line needs to be printed
125115
local function process(unit, args)
126116
local silent = args.all -- Don't print details if we're iterating through all dwarves
127117
local unit_name = dfhack.df2console(dfhack.units.getReadableName(unit))
@@ -164,7 +154,8 @@ local function process(unit, args)
164154
-- Include weapons so we can check we have them later
165155
if inv_item.mode == df.inv_item_role_type.Worn or
166156
inv_item.mode == df.inv_item_role_type.Weapon or
167-
inv_item.mode == df.inv_item_role_type.Strapped
157+
inv_item.mode == df.inv_item_role_type.Strapped or
158+
inv_item.mode == df.inv_item_role_type.Flask
168159
then
169160
worn_items[item.id] = item
170161
worn_parts[item.id] = inv_item.body_part_id
@@ -181,6 +172,12 @@ local function process(unit, args)
181172
end
182173
end
183174
end
175+
for _, special_case in ipairs({"quiver", "backpack", "flask"}) do
176+
local assigned_item_id = squad_position.equipment[special_case]
177+
if assigned_item_id ~= -1 then
178+
uniform_assigned_items[assigned_item_id] = df.item.find(assigned_item_id)
179+
end
180+
end
184181

185182
-- Figure out which assigned items are currently not being worn
186183
-- and if some other unit is carrying the item, unassign it from this unit's uniform
@@ -215,13 +212,7 @@ local function process(unit, args)
215212
-- Make the equipment.assigned_items list consistent with what is present in equipment.uniform
216213
for i=#(squad_position.equipment.assigned_items)-1,0,-1 do
217214
local assigned_item_id = squad_position.equipment.assigned_items[i]
218-
-- Quiver, backpack, and flask are assigned in their own locations rather than in equipment.uniform, and thus need their own checks
219-
-- If more separately-assigned items are added in the future, this handling will need to be updated accordingly
220-
if uniform_assigned_items[assigned_item_id] == nil and
221-
assigned_item_id ~= squad_position.equipment.quiver and
222-
assigned_item_id ~= squad_position.equipment.backpack and
223-
assigned_item_id ~= squad_position.equipment.flask
224-
then
215+
if uniform_assigned_items[assigned_item_id] == nil then
225216
local item = df.item.find(assigned_item_id)
226217
if item ~= nil then
227218
print(unit_name .. " has an improperly assigned item, " .. item_description(item) .. "; removing it")
@@ -240,8 +231,10 @@ local function process(unit, args)
240231
local covered = {} -- map of body part id to true/nil
241232
if not args.multi then
242233
for item_id, item in pairs(present_ids) do
243-
-- weapons and shields don't "cover" the bodypart they're assigned to. (Needed to figure out if we're missing gloves.)
244-
if item._type ~= df.item_weaponst and item._type ~= df.item_shieldst then
234+
-- only the five clothing types can block armor for the bodypart they're worn on.
235+
if utils.linear_index({ df.item_helmst, df.item_armorst, df.item_glovesst,
236+
df.item_pantsst, df.item_shoesst }, item._type)
237+
then
245238
covered[worn_parts[item_id]] = true
246239
end
247240
end
@@ -257,9 +250,13 @@ local function process(unit, args)
257250
end
258251
end
259252

260-
-- Drop everything (except uniform pieces) from body parts which should be covered but aren't
253+
-- Drop clothing (except uniform pieces) from body parts which should be covered but aren't
261254
for worn_item_id, item in pairs(worn_items) do
262-
if uniform_assigned_items[worn_item_id] == nil then -- don't drop uniform pieces (including shields, weapons for hands)
255+
if uniform_assigned_items[worn_item_id] == nil -- don't drop uniform pieces
256+
-- only the five clothing types can block armor for the bodypart they're worn on.
257+
and utils.linear_index({ df.item_helmst, df.item_armorst, df.item_glovesst,
258+
df.item_pantsst, df.item_shoesst }, item._type)
259+
then
263260
if uncovered[worn_parts[worn_item_id]] then
264261
print(unit_name .. " potentially has " .. item_description(item) .. " blocking a missing uniform item.")
265262
printed = true
@@ -270,23 +267,22 @@ local function process(unit, args)
270267
end
271268
end
272269

273-
-- add a spacing line if there was any output
274-
if printed then
275-
print()
276-
end
277-
278-
return to_drop
270+
return to_drop, printed
279271
end
280272

281-
local function do_drop(item_list)
273+
local function do_drop(item_list, printed)
282274
if not item_list then
283275
return
284276
end
285277

286278
for _, item in pairs(item_list) do
287279
local pos = get_visible_item_pos(item)
280+
281+
-- only drop if the item is on the map and is being held by a unit.
288282
if not pos then
289283
dfhack.printerr("Could not find drop location for " .. item_description(item))
284+
elseif dfhack.items.getHolderUnit(item) == nil then
285+
-- dfhack.printerr("Not in inventory: " .. item_description(item))
290286
else
291287
if dfhack.items.moveToGround(item, pos) then
292288
print("Dropped " .. item_description(item))
@@ -295,6 +291,11 @@ local function do_drop(item_list)
295291
end
296292
end
297293
end
294+
295+
-- add a spacing line if there was any output
296+
if printed then
297+
print()
298+
end
298299
end
299300

300301
local function main(args)

0 commit comments

Comments
 (0)