@@ -235,6 +235,9 @@ watched = watched or {}
235235--- @type integer[]
236236thresholds = thresholds or { 10000 , 1000 , 500 }
237237
238+ --- @type boolean
239+ ignore_happy = ignore_happy == nil and true or ignore_happy
240+
238241-- persisting a table with numeric keys results in a json array with a huge number of null entries
239242-- therefore, we convert the keys to strings for persistence
240243-- also, we clear the frame counter values since the frame counter gets reset on load
@@ -262,7 +265,8 @@ local function persist_state()
262265 dfhack .persistent .saveSiteData (GLOBAL_KEY , {
263266 enabled = enabled ,
264267 allowed = to_persist_allowed (),
265- thresholds = thresholds
268+ thresholds = thresholds ,
269+ ignore_happy = ignore_happy
266270 })
267271end
268272
@@ -273,6 +277,7 @@ local function load_state()
273277 enabled = persisted_data .enabled or false
274278 allowed = from_persist_allowed (persisted_data .allowed ) or {}
275279 thresholds = persisted_data .thresholds or { 10000 , 1000 , 500 }
280+ ignore_happy = persisted_data .ignore_happy == nil and true or ignore_happy
276281end
277282
278283-- frequently accessed values
@@ -281,16 +286,18 @@ local BONE_CARVE = df.unit_labor['BONE_CARVE']
281286local STONE_CRAFT = df .unit_labor [' STONE_CRAFT' ]
282287
283288--- negative crafting focus penalty
289+ --- @generic T
284290--- @param unit df.unit
285- --- @return number
286- function getCraftingNeed (unit )
291+ --- @param value_if_absent T
292+ --- @return number | T
293+ function getCraftingNeed (unit , value_if_absent )
287294 local needs = unit .status .current_soul .personality .needs
288295 for _ , need in ipairs (needs ) do
289296 if need .id == CraftObject then
290297 return - need .focus_level
291298 end
292299 end
293- return 0
300+ return value_if_absent
294301end
295302
296303local function stop ()
383390--- @return boolean " proceed to next workshop"
384391local function processUnit (workshop , idx , unit_id )
385392 local unit = df .unit .find (unit_id )
386- -- check that unit is still there and not caged or chained
387- if not unit or unit .flags1 .caged or unit .flags1 .chained then
393+ -- check that unit is still there, not caged or chained, and still has crafting needs
394+ if not unit or unit .flags1 .caged or unit .flags1 .chained or getCraftingNeed ( unit , - 1 ) < 0 then
388395 watched [idx ][unit_id ] = nil
389396 return false
390397 elseif not canAccessWorkshop (unit , workshop ) then
@@ -511,16 +518,33 @@ local function main_loop()
511518 num_watched [idx ] = 0
512519 end
513520
521+ local max_threshold = thresholds [1 ]
514522 for _ , unit in ipairs (dfhack .units .getCitizens (true , false )) do
523+
524+ local crafting_need = getCraftingNeed (unit , nil )
525+
526+ if not crafting_need then
527+ goto next_unit
528+ end
529+
530+ local is_happy = unit .status .current_soul .personality .stress < - 25000 and
531+ unit .status .current_soul .personality .longterm_stress < 0
532+
515533 for idx , threshold in ipairs (thresholds ) do
516- if getCraftingNeed (unit ) > threshold then
534+ if ignore_happy and is_happy and threshold < max_threshold then
535+ -- ignore happy and ecstatic units for any threshold but the highest
536+ print (dfhack .df2console ((" idle-crafting: skipping happy unit %s" ):format (dfhack .units .getReadableName (unit ))))
537+ goto next_unit
538+ end
539+
540+ if crafting_need > threshold then
517541 watched [idx ][unit .id ] = true
518542 num_watched [idx ] = num_watched [idx ] + 1
519543 watching = true
520- goto continue
544+ goto next_unit
521545 end
522546 end
523- :: continue ::
547+ :: next_unit ::
524548 end
525549 -- print(('watching %s dwarfs with crafting needs'):format(
526550 -- table.concat(num_watched, '/')
@@ -665,9 +689,12 @@ if not positionals[1] or positionals[1] == 'status' then
665689 --- @type integer[]
666690 stats = {}
667691 for _ , unit in ipairs (dfhack .units .getCitizens (true , false )) do
668- local fulfillment = - getCraftingNeed (unit )
692+ local crafting_need = getCraftingNeed (unit , nil )
693+ if not crafting_need then
694+ goto continue
695+ end
669696 for i = 1 , 7 do
670- if fulfillment >= fulfillment_threshold [i ] then
697+ if - crafting_need >= fulfillment_threshold [i ] then
671698 stats [i ] = stats [i ] and stats [i ] + 1 or 1
672699 goto continue
673700 end
@@ -686,11 +713,19 @@ if not positionals[1] or positionals[1] == 'status' then
686713 format (enabled and ' enabled' or ' disabled' , num_workshops ))
687714 print ((' The thresholds for "craft item" needs are %s' ):
688715 format (table.concat (thresholds , ' ,' )))
716+ if ignore_happy then
717+ print (' Will only assign crafting jobs to happy dwarves with strong needs' )
718+ else
719+ print (' Will treat happy units like all other units' )
720+ end
721+
689722elseif positionals [1 ] == ' thresholds' then
690723 thresholds = argparse .numberList (positionals [2 ], ' thresholds' )
691724 table.sort (thresholds , function (a , b ) return a > b end )
692725 print ((' Thresholds for "craft item" needs set to %s' ):
693726 format (table.concat (thresholds , ' ,' )))
727+ elseif positionals [1 ] == ' happy' then
728+ ignore_happy = not argparse .boolean (positionals [2 ], ' happy' )
694729elseif positionals [1 ] == ' disable' then
695730 allowed = {}
696731 stop ()
0 commit comments