Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  

Author Topic: Modifying DFHack's fix/dead-units  (Read 2828 times)

YetAnotherLurker

  • Bay Watcher
    • View Profile
Modifying DFHack's fix/dead-units
« on: June 22, 2016, 05:26:57 am »

So, I want to modify DFHack's fix/dead-units script to leave notable dead invaders (historical figures, ones with actual kills, legendaries, nobility, forgotten beasts, etc) alone, while removing the "axe fodder" and such. However, I don't know the structure of the data files, so I'm having a bit of trouble working out the right flags and such. Here's what I've got at the moment, basically only removing slaughtered unnamed animals and the three most common war animals I've had visit in my current fort.

Main questions:
1. Do race ID numbers (unit.race below) stay constant between worlds? If yes, is there a list somewhere?
2. Is there someplace I can see the file structure of the unit info? Of most interest are things relating to, say, kills, or legendary status, or titles/noble positions for my current purposes.
3. For that matter, is there a wiki or guide for DFHack scripting somewhere?

Code: [Select]
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.

=end]]
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

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
        end
-- Should remove horses (174), trolls (593), beak dogs (609), even if named.
if unit.race == 174 then
    remove = true
elseif unit.race == 593 then
    remove = true
elseif unit.race == 609 then
    remove = true
end
        if remove then
            count = count + 1
            units:erase(i)
        end
    end
end

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

Quietust

  • Bay Watcher
  • Does not suffer fools gladly
    • View Profile
    • QMT Productions
Re: Modifying DFHack's fix/dead-units
« Reply #1 on: June 22, 2016, 06:31:19 am »

1. Do race ID numbers (unit.race below) stay constant between worlds? If yes, is there a list somewhere?
No, they do not - they are derived from the raws, which users are free to modify. You should look them up in df.world.raws.creatures.all[] by creature_id (e.g. 'DWARF', 'HUMAN', 'HORSE').

2. Is there someplace I can see the file structure of the unit info? Of most interest are things relating to, say, kills, or legendary status, or titles/noble positions for my current purposes.
Look in df-structures - "df.units.xml" should be a good starting point, since that's where "unit" is defined (along with most of its sub-structures), and you'll probably want "df.history.xml" as well (for historical figure info).

3. For that matter, is there a wiki or guide for DFHack scripting somewhere?
https://dfhack.readthedocs.io/en/stable/ should be a good starting point.
Logged
P.S. If you don't get this note, let me know and I'll write you another.
It's amazing how dwarves can make a stack of bones completely waterproof and magmaproof.
It's amazing how they can make an entire floodgate out of the bones of 2 cats.

YetAnotherLurker

  • Bay Watcher
    • View Profile
Re: Modifying DFHack's fix/dead-units
« Reply #2 on: June 22, 2016, 09:12:39 am »

No, they do not - they are derived from the raws, which users are free to modify. You should look them up in df.world.raws.creatures.all[] by creature_id (e.g. 'DWARF', 'HUMAN', 'HORSE').
I worded my question poorly, I meant to ask if the race ID numbers stayed consistent for a given set of raws, across multiple worldgens. Anyway, yeah, much safer to look them up anyway, now that I know where to look.
Look in df-structures - "df.units.xml" should be a good starting point, since that's where "unit" is defined (along with most of its sub-structures), and you'll probably want "df.history.xml" as well (for historical figure info).
Thank you very much, that is exactly what I was looking for. I figure I can work out everything else from there.
https://dfhack.readthedocs.io/en/stable/ should be a good starting point.
You just told me to RTFM, didn't you  :(
Anyway, I'd looked through that, but failed to find where the actual XML files mentioned were located, hence my confusion. Should've realized they'd be on GitHub. Thanks again!
Logged

YetAnotherLurker

  • Bay Watcher
    • View Profile
Re: Modifying DFHack's fix/dead-units
« Reply #3 on: June 22, 2016, 10:38:43 pm »

Ok, so setting specific removal criteria is complicated and requires more familiarity with DFHack's data structures than I have or can acquire quickly. Therefore, I just went with a quick and dirty change to the removal criteria. What this should do is remove dead units that are slaughtered, unnamed, and non-historical figures (as defined by the flags in DFHack's structures/units.xml), unless they happen to have been a merchant or diplomat. Anyway, I'm not certain what the specific criteria are, but a few test runs in a couple of forts seem to have left the most interesting dead alone while clearing out the hundreds of dead invaders. Only issue is that invasion-generated Weapon Lords are also cleared, but that's minor enough that I don't feel like fiddling with code to check weapon skills of invaders.

Should be simple enough to swap the removal criteria into the save/loadable version of the script that's elsewhere on the forums, if desired.

Code: [Select]
-- Remove slaughtered livestock, unnamed units (basically animals and generic zombies), and non-historical figures from units list.
--[[=begin

fix/dead-nonhistfigs
==============
Removes uninteresting dead units from the unit list. Doesn't seem to give any
noticeable performance gain, but migrants are limited to 10 if the unit list grows
to around 1000 units, and stop entirely at around 3000. This script reduces it back.

Mostly lifted wholesale from the fix/dead-units script included in DFHack, only with
tweaked removal criteria.
=end]]
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
for i=#units-1,0,-1 do
    local unit = units[i]
    local flags1 = unit.flags1
    local flags2 = unit.flags2

    if flags1.dead then
        local remove = false
        if flags2.slaughter then
            remove = true
elseif not unit.name.has_name then
            remove = true
elseif not (flags1.important_historical_figure or flags2.important_historical_figure) then
    remove = true
end
if unit.civ_id ~= dwarf_civ and (flags1.merchant or flags1.diplomat) then
            remove = false
end
        if remove then
            count = count + 1
            units:erase(i)
        end
    end
end

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