@@ -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
10991-- @param squad_position df.squad_position
11092-- @param item_id number
11193local 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
122111end
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
125115local 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
279271end
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
298299end
299300
300301local function main (args )
0 commit comments