Closed LightHardt closed 7 months ago
yes, a dfhack.items.setOwner(item, nil)
followed by a dfhack.items.setOwner(item, unit)
for the unit that should keep ownership looks like it would do it. Maybe an algorithm like:
local owners = {}
for _,unit in ipairs(dfhack.units.getCitizens()) do
for _,item in ipairs(unit.owned_items) do
local owner = owners[item.id]
if owner then
dfhack.items.setOwner(item)
dfhack.items.setOwner(item, owner)
else
owners[item.id] = unit
end
end
end
maybe it could be smarter and specifically assign ownership to the unit that already has the item in inventory.
A fix tool like this could also keep an eye on squad equipment and do the same for multiple squad members who have claimed the same item for their uniform. That code is already written in uniform-unstick
, but it could be refactored to be callable by this fixer tool too.
Oh wow thanks for the algo ill test it out here soon as I seemingly have a couple dwarves in this predicament right now. I will also look into uniform-unstick
.
After more exploration it seems the problem (or at least part of it) lies with for some reason when a dwarf unclaims the item it deletes the ref but it doesn't delete the item id from the dwarfs owned_items vector. This allows other dwarfs to just grab it and claim it for themselves now causing the item to have multiple "owners" when in actuality i believe the one that has the ref (sometimes neither do) should be recognized as the real owner. The only thing i can think would cause this is tailor
however looking at the code it seems to properly clean up the ref and remove the item id from the dwarf. This leads me to believe it might be buggy vanilla behavior?
With all that out the way with this knowledge i made some modifications and am curious on thought/opinions on code and mentioned behavior.
for _,unit in ipairs(dfhack.units.getCitizens()) do
for index = #unit.owned_items-1, 0, -1 do
local item = df.item.find(unit.owned_items[index])
if not item then goto continue end
for _, ref in ipairs(item.general_refs) do
if df.general_ref_unit_itemownerst:is_instance(ref) then
-- make sure the ref belongs to unit
if ref.unit_id == unit.id then goto continue end
end
end
print('Erasing ' .. dfhack.TranslateName(unit.name) .. ' claim on item #' .. item.id)
unit.owned_items:erase(index)
::continue::
end
end
Have started running into an issue where multiple dwarves are claiming the same clothing items.
Dwarf 1 attempting to store item in cabinet that it believes it owns (it is stuck repeatedly attempting this)
Who the item believes it belongs to (Dwarf 2)
Dwarf 2 who also claims the item as their own
Potential idea loop through all dwarves
owned_items
vector and every time a duplicate is found remove duplicate id.item::setOwner
appears to be a good function to use for this. Any thoughts or input is appreciated on this.