Skip to content

Commit

Permalink
Merge pull request #1295 from myk002/myk_rejuvenate
Browse files Browse the repository at this point in the history
[rejuvenate]: ensure histfig data stays consistent and respect age-related caste data per race
  • Loading branch information
myk002 authored Sep 7, 2024
2 parents 64af1a4 + f8a4753 commit a6cdf8c
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 40 deletions.
19 changes: 2 additions & 17 deletions armoks-blessing.lua
Original file line number Diff line number Diff line change
@@ -1,24 +1,9 @@
-- Adjust all attributes of all dwarves to an ideal
-- by vjek

local rejuvenate = reqscript('rejuvenate')
local utils = require('utils')

function rejuvenate(unit)
if unit==nil then
print ("No unit available! Aborting with extreme prejudice.")
return
end

local current_year=df.global.cur_year
local newbirthyear=current_year - 20
if unit.birth_year < newbirthyear then
unit.birth_year=newbirthyear
end
if unit.old_year < current_year+100 then
unit.old_year=current_year+100
end

end
-- ---------------------------------------------------------------------------
function brainwash_unit(unit)
if unit==nil then
Expand Down Expand Up @@ -251,7 +236,7 @@ function adjust_all_dwarves(skillname)
print("Adjusting "..dfhack.df2console(dfhack.TranslateName(dfhack.units.getVisibleName(v))))
brainwash_unit(v)
elevate_attributes(v)
rejuvenate(v)
rejuvenate.rejuvenate(v, true)
if skillname then
if df.job_skill_class[skillname] then
LegendaryByClass(skillname,v)
Expand Down
2 changes: 2 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ Template for new versions:
- `deep-embark`: fix error when embarking where there is no land to stand on (e.g. when embarking in the ocean with `gui/embark-anywhere`)
- `deep-embark`: fix failure to transport units and items when embarking where there is no room to spawn the starting wagon
- `gui/create-item`, `modtools/create-item`: items of type "VERMIN", "PET", "REMANS", "FISH", "RAW FISH", and "EGG" no longer spawn creature item "nothing" and will now stack correctly
- `rejuvenate`: don't set a lifespan limit for creatures that are immortal (e.g. elves, goblins)
- `rejuvenate`: properly disconnect babies from mothers when aging babies up to adults

## Misc Improvements
- `gui/sitemap`: show whether a unit is friendly, hostile, or wild
Expand Down
23 changes: 14 additions & 9 deletions docs/rejuvenate.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ rejuvenate
:tags: fort armok units

If your most valuable citizens are getting old, this tool can save them. It
decreases the age of the selected dwarf to 20 years, or to the age specified.
Age is only increased using the --force option.
decreases the age of the selected dwarf to the minimum adult age, or to the age
specified. Age can only be increased (e.g. when this tool is run on babies or
children) if the ``--force`` option is specified.

Usage
-----
Expand All @@ -20,23 +21,27 @@ Examples
--------

``rejuvenate``
Set the age of the selected dwarf to 20 (if they're older).
Set the age of the selected dwarf to 18 (if they're older than 18). The
target age may be different if you have modded dwarves to become an adult
at a different age, or if you have selected a unit that is not a dwarf.
``rejuvenate --all``
Set the age of all dwarves over 20 to 20.
Set the ages of all adult citizens and residents to their minimum adult
ages.
``rejuvenate --all --force``
Set the age of all dwarves (including babies) to 20.
Set the ages of all citizens and residents (including children and babies)
to their minimum adult ages.
``rejuvenate --age 149 --force``
Set the age of the selected dwarf to 149, even if they are younger.

Options
-------

``--all``
Rejuvenate all citizens, not just the selected one.
Rejuvenate all citizens and residents instead of a selected unit.
``--age <num>``
Sets the target to the age specified. If this is not set, the target age is 20.
Sets the target to the age specified. If this is not set, the target age defaults to the minimum adult age for the unit.
``--force``
Set age for units under the specified age to the specified age. Useful if there are too
many babies around...
Set age for units under the specified age to the specified age. Useful if
there are too many babies around...
``--dry-run``
Only list units that would be changed; don't actually change ages.
78 changes: 64 additions & 14 deletions rejuvenate.lua
Original file line number Diff line number Diff line change
@@ -1,43 +1,93 @@
-- set age of selected unit
-- by vjek
--@ module = true

local utils = require('utils')

function rejuvenate(unit, force, dry_run, age)
local current_year = df.global.cur_year
if not age then
age = 20
local DEFAULT_CHILD_AGE = 18
local DEFAULT_OLD_AGE = 160
local ANY_BABY = df.global.world.units.other.ANY_BABY

local function get_caste_misc(unit)
local cre = df.creature_raw.find(unit.race)
if not cre then return end
if unit.caste < 0 or unit.caste >= #cre.caste then
return
end
return cre.caste[unit.caste].misc
end

local function get_adult_age(misc)
return misc and misc.child_age or DEFAULT_CHILD_AGE
end

local function get_rand_old_age(misc)
return misc and math.random(misc.maxage_min, misc.maxage_max) or DEFAULT_OLD_AGE
end

-- called by armoks-blessing
function rejuvenate(unit, quiet, force, dry_run, age)
local name = dfhack.df2console(dfhack.units.getReadableName(unit))
local misc = get_caste_misc(unit)
local adult_age = get_adult_age(misc)
age = age or adult_age
if age < adult_age then
dfhack.printerr('cannot set age to child or baby range')
return
end
local current_year = df.global.cur_year
local new_birth_year = current_year - age
local name = dfhack.df2console(dfhack.TranslateName(dfhack.units.getVisibleName(unit)))
local new_old_year = unit.old_year < 0 and -1 or math.max(unit.old_year, new_birth_year + get_rand_old_age(misc))
if unit.birth_year > new_birth_year and not force then
print(name .. ' is under ' .. age .. ' years old. Use --force to force.')
if not quiet then
dfhack.printerr(name .. ' is under ' .. age .. ' years old. Use --force to force.')
end
return
end
if dry_run then
print('would change: ' .. name)
return
end

local hf = df.historical_figure.find(unit.hist_figure_id)
unit.birth_year = new_birth_year
if unit.old_year < new_birth_year + 160 then
unit.old_year = new_birth_year + 160
end
if hf then hf.born_year = new_birth_year end
unit.old_year = new_old_year
if hf then hf.old_year = new_old_year end

if unit.profession == df.profession.BABY or unit.profession == df.profession.CHILD then
if unit.profession == df.profession.BABY then
local idx = utils.linear_index(ANY_BABY, unit.id, 'id')
if idx then
ANY_BABY:erase(idx)
end
unit.flags1.rider = false
unit.relationship_ids.RiderMount = -1
unit.mount_type = df.rider_positions_type.STANDARD
unit.profession2 = df.profession.STANDARD
unit.idle_area_type = df.unit_station_type.MillBuilding
unit.mood = -1

-- let the mom know she isn't carrying anyone anymore
local mother = df.unit.find(unit.relationship_ids.Mother)
if mother then mother.flags1.ridden = false end
end
unit.profession = df.profession.STANDARD
unit.profession2 = df.profession.STANDARD
if hf then hf.profession = df.profession.STANDARD end
end
if not quiet then
print(name .. ' is now ' .. age .. ' years old and will live a normal lifespan henceforth')
end
print(name .. ' is now ' .. age .. ' years old and will live to at least 160')
end

function main(args)
local function main(args)
local units = {} --as:df.unit[]
if args.all then
units = dfhack.units.getCitizens()
else
table.insert(units, dfhack.gui.getSelectedUnit(true) or qerror("Please select a unit in the UI."))
end
for _, u in ipairs(units) do
rejuvenate(u, args.force, args['dry-run'], args.age)
rejuvenate(u, false, args.force, args['dry-run'], args.age)
end
end

Expand Down

0 comments on commit a6cdf8c

Please sign in to comment.