Skip to content

fix/dead-units.lua has a significant bug #1246

@PatrikLundell

Description

@PatrikLundell

I've made a post in the DFHack thread, but this is really the appropriate place for it:
The script uses flags1.dead as if it indicated that the unit was dead, rather than just inactive. This causes the script to remove incoming critters and units that happen not to have entered the map yet when the script is executed (in the case of a quester infiltrator army, the tricking onto the map takes weeks for 120 units after the mastodon announcement of their arrival is made).

While at it, I've tweaked a few other annoying properties of the script. The "--###" sections indicate changes I'd like discussed. Obviously, the script version below is not intended as the final version, but rather a starting point for a discussion. The trace type output again is there because I use it to see what the script does, and doesn't belong to an updated version of the script. To just fix the script bug you really only need to add the first change, i.e. a test against "flags2.killed".

--[====[

fix/dead-units
==============
Removes uninteresting dead units from the unit list. Doesn't seem to give any
noticeable performance gain, but migrants normally stop if the unit list grows
to around 3000 units, and this script reduces it back.

]====]
local units = df.global.world.units.active
--local dwarf_race = df.global.ui.race_id
local dwarf_civ = df.global.ui.civ_id
local count = 0
local month = 1200 * 28
local year = month * 12

for i=#units-1,0,-1 do
    local unit = units[i]
    local flags1 = unit.flags1
    local flags2 = unit.flags2
    if flags1.dead and  --  Probably redundant, but if a killed unit is still active we probably don't want to remove it.
       flags2.killed then --and
       --unit.race ~= dwarf_race then  --###  Keeping dead non civ dwarves in the list does not make sense anymore.
                                       --###  It did make sense in 0.40.24 when all dead dwarves went to the corpse
                                       --###  stockpile and everyone else to the refuse one.
        local remove = false
        if flags2.slaughter then
            remove = true
        elseif unit.hist_figure_id == -1 then  --### I don't want to keep animals DFHack named for various purposes in the
        --elseif not unit.name.has_name then   --### dead unit list. A better criterion ought to be if they have a histfig id.
            remove = true
        elseif unit.civ_id ~= dwarf_civ and  --###  What about visitors from our own civ? If we have to bury them we
                                             --###  may want to keep them, but otherwise I see no reason. I don't know about burial, though...
               not flags1.merchant then
               --not (flags1.merchant or flags1.diplomat) then  --###  Questers that have demanded artifacts and then return are flagged as
                                                                --###  "diplomats" even if the demand happened during a previous visit, i.e.
                                                                --###  the diplomat flag isn't cleared.
            remove = true
        end
        if unit.counters.death_id ~= -1 then  --###  Keep recent deaths around for a month before culling them. It's annoying to have that
                                              --###  rampaging FB just be gone from both the other and dead lists, and you may want to keep
                                              --###  killed wildlife around for a while too.
                                              --###  If a unit doesn't have a death_id, is it actually dead, or should those units be blocked
                                              --###  from removal as well?
          local incident = df.incident.find(unit.counters.death_id)
          if incident then
            local incident_time = incident.event_year * year + incident.event_time
            local now = df.global.cur_year * year + df.global.cur_year_tick
            if now - incident_time < month then
              dfhack.println ("Not time yet", now - incident_time, month)
              remove = false
            end
          end
        else
          dfhack.println ("Missing death_id!")
        end
        
        if remove then
          dfhack.println ("Removing " .. dfhack.TranslateName (unit.name, false) .. " with unit id " .. tostring (unit.id) .. " race: " .. df.global.world.raws.creatures.all [unit.race].name [0])
          count = count + 1
          units:erase(i)
        end
    end
end

print('Units removed from active: '..count)

Also note that this is what prompted issue #247 under DFHack/df-structures.

Edit: Apparently slaughtered animals do not have a death_id, so they will have to be removed directly.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions