updated clear-dead-units.lua . I think this is essentially complete as it now clears the saved list when restoring and resaves missing ids if the unit is not found (shouldn't happen) and only restores one copy of duplicate ids in the save file (also shouldn't happen under normal circumstances), doesn't allow clearing the list without the save file, and it should be less likely to fail and lose the saved list. If for some weird reason a unit still exists in the active list and has a saved id from this script (I don't see why it would happen without user editing the list) a duplicate will still be added as duplicates are only detected in the saved list rather than in the active units list. The save list is appended so future clears add to the saved list.
The only thing I can things that is missing from making this script complete are: ensuring fortress mode, and clearing the saved list if the fort is lost or abandoned so that the next fort doesn't inherit a saved list of invalid unit ids. Not that the invalid ids will hurt anything but can lead to duplicate units entries when that id becomes used again by the new fort and is then restored from the saved list.
add this to the save's init.lua to save the save games path to a persistent entry:
CODE
fix/clear-dead-units.lua using fix/dead-units original unit selection criteria, saving removed active unit ids to the save dir:
-- Remove uninteresting dead units from the unit list. Use option 'restore' to put them back
local utils = require('utils')
local restore = false
for _,arg in pairs({...}) do
if arg == "restore" then restore = true end
end
local SAVE_FILE = 'data/save/' .. df.global.world.cur_savegame.save_dir .. '/cleared-dead-units.txt'
if restore then
file = assert(io.open(SAVE_FILE, "r"))
local units = df.global.world.units
local count = 0
local ids = {}
for n in file:lines() do
ids[n] = tonumber(n) -- prevent duplicates, not an array
end
file:close()
file = io.open(SAVE_FILE, "w") -- empty file, re-add failures
for _,id in pairs(ids) do
local unit = utils.binsearch(units.all,id,'id')
if unit then
units.active:insert('#',unit)
count = count + 1
else
file:write(id,NEWLINE)
end
id = table.remove(ids,#ids) -- pop laste element
end
file:close()
print('Restored dead units to active from saved list: '..count)
else
file = assert(io.open(SAVE_FILE, "a"))
local dwarf_race = df.global.ui.race_id
local dwarf_civ = df.global.ui.civ_id
local units = df.global.world.units.active
local count = 0
for i=#units-1,0,-1 do
local unit = units[i]
local flags1 = unit.flags1
local flags2 = unit.flags2
if flags1.dead and unit.race ~= dwarf_race then
local remove = false
if flags2.slaughter then
remove = true
elseif not unit.name.has_name then
remove = true
elseif unit.civ_id ~= dwarf_civ and
not (flags1.merchant or flags1.diplomat) then
remove = true
end
if remove then
count = count + 1
file:write(units[i].id, NEWLINE)
units:erase(i)
end
end
end
file:close()
print('Removed dead units from active to saved list: '..count)
end
EDIT: applied suggestion from expwnent to use df.global.world.cur_savegame.save_dir so that init.lua is no longer needed.