22
33local argparse = require (' argparse' )
44local exterminate = reqscript (' exterminate' )
5+ local guidm = require (' gui.dwarfmode' )
56
67local GLOBAL_KEY = ' fix/wildlife'
78
@@ -61,7 +62,7 @@ local function refund_population(entry)
6162 end
6263end
6364
64- -- refund unit to population and ensure it doesn't get picked up by unstick_surface_wildlife in the future
65+ -- refund unit to population and ensure it doesn't get picked up by unstick_wildlife in the future
6566local function detach_unit (unit )
6667 unit .flags2 .roaming_wilderness_population_source = false
6768 unit .flags2 .roaming_wilderness_population_source_not_a_map_feature = false
@@ -74,6 +75,7 @@ local TICKS_PER_MONTH = 28 * TICKS_PER_DAY
7475local TICKS_PER_SEASON = 3 * TICKS_PER_MONTH
7576local TICKS_PER_YEAR = 4 * TICKS_PER_SEASON
7677
78+ -- time checks near year turnover is wishy-washy until we have a datetime API available
7779local WEEK_BEFORE_EOY_TICKS = TICKS_PER_YEAR - TICKS_PER_WEEK
7880
7981-- update stuck_creatures records and check timeout
@@ -113,9 +115,15 @@ function free_all_wildlife(include_hidden)
113115 end
114116end
115117
116- local function unstick_surface_wildlife (opts )
118+ local function is_onscreen (unit , viewport )
119+ viewport = viewport or guidm .Viewport .get ()
120+ return viewport :isVisible (xyz2pos (dfhack .units .getPosition (unit ))), viewport
121+ end
122+
123+ local function unstick_wildlife (opts )
117124 local unstuck = {}
118125 local week_ago_ticks = math.max (0 , df .global .cur_year_tick - TICKS_PER_WEEK )
126+ local viewport
119127 for _ ,unit in ipairs (df .global .world .units .active ) do
120128 if not is_active_wildlife (unit ) or unit .animal .leave_countdown > 0 then
121129 goto skip
@@ -132,7 +140,9 @@ local function unstick_surface_wildlife(opts)
132140 unstuck_entry .count = unstuck_entry .count + 1
133141 if not opts .dry_run then
134142 stuck_creatures [unit .id ] = nil
135- exterminate .killUnit (unit , exterminate .killMethod .DISINTEGRATE )
143+ local unit_is_visible
144+ unit_is_visible , viewport = is_onscreen (unit , viewport )
145+ exterminate .killUnit (unit , not unit_is_visible and exterminate .killMethod .DISINTEGRATE or nil )
136146 end
137147 :: skip::
138148 end
@@ -188,5 +198,5 @@ if positionals[1] == 'ignore' then
188198 print ((' %s will now be ignored by fix/wildlife' ):format (dfhack .units .getReadableName (unit )))
189199 end
190200else
191- unstick_surface_wildlife (opts )
201+ unstick_wildlife (opts )
192202end
0 commit comments