DFhack assign function on Pen/Pastures not working
This button and hotkey to assign animals to a pen or pasture does not activate/work.
relevant log file extract
...teamapps\common\Dwarf Fortress\hack\lua\plugins\zone.lua:992: attempt to index a nil value (local 'civzone')
stack traceback:
...teamapps\common\Dwarf Fortress\hack\lua\plugins\zone.lua:992: in field 'get_status'
...teamapps\common\Dwarf Fortress\hack\lua\plugins\zone.lua:642: in method 'cache_choices'
...teamapps\common\Dwarf Fortress\hack\lua\plugins\zone.lua:709: in method 'get_choices'
...teamapps\common\Dwarf Fortress\hack\lua\plugins\zone.lua:456: in local 'fun'
...Steam\steamapps\common\Dwarf Fortress\hack\lua\class.lua:124: in upvalue 'invoke_after_rec'
...Steam\steamapps\common\Dwarf Fortress\hack\lua\class.lua:153: in global 'AssignAnimal'
...teamapps\common\Dwarf Fortress\hack\lua\plugins\zone.lua:889: in local 'fun'
...Steam\steamapps\common\Dwarf Fortress\hack\lua\class.lua:124: in upvalue 'invoke_after_rec'
...Steam\steamapps\common\Dwarf Fortress\hack\lua\class.lua:153: in global 'AssignAnimalScreen'
...teamapps\common\Dwarf Fortress\hack\lua\plugins\zone.lua:1030: in upvalue 'show_pasture_pond_screen'
...teamapps\common\Dwarf Fortress\hack\lua\plugins\zone.lua:1049: in field 'on_activate'
...rf Fortress\hack\lua\gui\widgets\labels\hotkey_label.lua:65: in function 'gui.widgets.labels.hotkey_label.onInput'
...)\Steam\steamapps\common\Dwarf Fortress\hack\lua\gui.lua:869: in function <...)\Steam\steamapps\common\Dwarf Fortress\hack\lua\gui.lua:856>
(...tail calls...)
...Dwarf Fortress\hack\lua\gui\widgets\containers\panel.lua:306: in function 'gui.widgets.containers.panel.onInput'
...)\Steam\steamapps\common\Dwarf Fortress\hack\lua\gui.lua:869: in function <...)\Steam\steamapps\common\Dwarf Fortress\hack\lua\gui.lua:856>
(...tail calls...)
...Dwarf Fortress\hack\lua\gui\widgets\containers\panel.lua:306: in function 'gui.widgets.containers.panel.onInput'
(...tail calls...)
...mapps\common\Dwarf Fortress\hack\lua\plugins\overlay.lua:435: in upvalue 'detect_frame_change'
...mapps\common\Dwarf Fortress\hack\lua\plugins\overlay.lua:524: in upvalue '_feed_viewscreen_widgets'
...mapps\common\Dwarf Fortress\hack\lua\plugins\overlay.lua:534: in function 'plugins.overlay.feed_viewscreen_widgets'
The animal has a link to a civzone building that doesn't exist, or to a building that is not a civzone.
I was able to reproduce this by setting a pastured unit's general_ref_building_civzone_assignedst.building_id to 999999, a nonexistent building. I was also able to reproduce it by setting the same field to 2, a workshop.
Maybe this needs:
(change to line 992, loads and runs without errors but has minimal testing) (edit: found a second instance of the same bug, loads and runs without errors but has minimal testing)
diff --git a/plugins/lua/zone.lua b/plugins/lua/zone.lua
index 92940ef48..2923f8e33 100644
--- a/plugins/lua/zone.lua
+++ b/plugins/lua/zone.lua
@@ -989,7 +989,9 @@ local function get_zone_status(unit_or_vermin, bld_assignments)
return PASTURE_STATUS.ASSIGNED_HERE.value
else
local civzone = df.building.find(assigned_zone_ref.building_id)
- if civzone.type == df.civzone_type.Pen then
+ if not civzone or not df.building_civzonest:is_instance(civzone) then
+ return PASTURE_STATUS.NONE.value
+ elseif civzone.type == df.civzone_type.Pen then
return PASTURE_STATUS.PASTURED.value
elseif civzone.type == df.civzone_type.Pond then
return PASTURE_STATUS.PITTED.value
@@ -1150,7 +1152,9 @@ local function get_cage_status(unit_or_vermin, bld_assignments)
local assigned_zone_ref = get_general_ref(unit_or_vermin, df.general_ref_type.BUILDING_CIVZONE_ASSIGNED)
if assigned_zone_ref then
local civzone = df.building.find(assigned_zone_ref.building_id)
- if civzone.type == df.civzone_type.Pen then
+ if not civzone or not df.building_civzonest:is_instance(civzone) then
+ return CAGE_STATUS.NONE.value
+ elseif civzone.type == df.civzone_type.Pen then
return CAGE_STATUS.PASTURED.value
elseif civzone.type == df.civzone_type.Pond then
return CAGE_STATUS.PITTED.value
I am torn on whether to treat this case as PASTURED, ROAMING, or NONE. NONE is an unknown or script-error case, and cannot be displayed with the sliders. This makes the animal essentially disappear from the overlay, even if (see below) it is also assigned to a valid pasture.
In the game itself:
- if a pasture has a link to the animal, it roams free for a while, then a
PenLargeAnimaljob is created and a worker takes the job, the animal is led to the pasture, but the invalid link from animal to invalid/nonexistent pasture is not cleaned up. This sequence then repeats, presumably indefinitely. - If no pasture has a link to the animal, it roams free. Again, the invalid link from animal to invalid/nonexistent pasture is not cleaned up.
- In either case, the invalid link is not cleaned up even if the animal is subsequently assigned to a valid pasture through the normal DF interface. Instead, the animal gets a second link to the valid pasture.
- This situation was not cleared up by a save/load.
I did not test pits, cages or chains.
Do you want me to make a PR?
Use the NONE case for now. This is probably a bug in DF. If we can figure out a way to safely clean up after it, we should do so, but I don't want to delay a usability fix while we try to come up with a mitigation for a DF bug.