Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed mothers attempting to seek their units that were babies #1284

Merged
merged 1 commit into from
Sep 7, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions rejuvenate.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,36 @@ function rejuvenate(unit, force, dry_run, age)
unit.old_year = new_birth_year + 160
end
if unit.profession == df.profession.BABY or unit.profession == df.profession.CHILD then
if unit.profession == df.profession.BABY then
local leftoverUnits = {}
local shiftedLeftoverUnits = {}
-- create a copy
local babyUnits = df.global.world.units.other.ANY_BABY
-- create a new table with the units that aren't being removed in this iteration
for _, v in ipairs(babyUnits) do
if not v.id == unit.id then
table.insert(leftoverUnits, v)
end
end
-- create a shifted table of the leftover units to make up for lua tables starting with index 1 and the game starting with index 0
Copy link
Member

@ab9rf ab9rf Sep 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use the erase method on the world.units.other.ANY_BABY vector for this. this method directly calls the appropriate C++ method on the underlying vector instead of rewriting the vector

you can simply do world.units.other.ANY_BABY:erase(i) where i is the (0-based) index of the item to erase. note that this will invalidate the ipairs iterator, but the unit should only be on the vector once so once you find it you don't have to keep searching to find it again

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can also avoid finding the index entirely by using utils.erase_sorted(df.global.world.units.other.ANY_BABY, unit, 'id')

Copy link
Member

@ab9rf ab9rf Sep 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can also avoid finding the index entirely by using utils.erase_sorted(df.global.world.units.other.ANY_BABY, unit, 'id')

do note that the unit classification subvectors (such as ANY_BABY) are not guaranteed to be sorted. the categorize methods simply insert the unit/item/building at the end of the classified subvector. using tools that expect these vectors to be sorted may result in unexpected behavior

unfortunately just uncategorizing and recategorizing the unit is unsafe, because categorizing a unit sets the unit's schedule_id to -1 (why, toady, why?), which means it's not safe to do this here forgot that these methods aren't virtual for unitst

TL;DR: do not use utils.erase_sorted on a unit subvector, this is not safe.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the heads up. I had trouble with lua doing a 1 based index vs C++ (as well as what I'm used to from other languages) doing a 0 based index and then that translating back into the game vector. I'll update with these fixes later this week/this weekend. Appreciate the suggestions

for i = 0, #leftoverUnits - 1, 1 do
local x = i+1
shiftedLeftoverUnits[i] = leftoverUnits[x]
end
-- copy the leftover units back to the game table
df.global.world.units.other.ANY_BABY = shiftedLeftoverUnits
-- set extra flags to defaults
unit.flags1.rider = false
unit.relationship_ids.RiderMount = -1
unit.mount_type = 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should use df.rider_positions_type.STANDARD instead of 0

unit.profession2 = df.profession.STANDARD
unit.idle_area_type = 26
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use df.unit_station_type.MillBuilding instead of 26

unit.mood = -1

-- let the mom know she isn't carrying anyone anymore
local motherUnitId = unit.relationship_ids.Mother
df.unit.find(motherUnitId).flags1.ridden = false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is a good idea to always protect from nil when using any find method. The mother could have just been obliterated and the unit could be gone by the time this is run.

end
unit.profession = df.profession.STANDARD
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also check and update unit.profession2 and the profession in the histfig (df.historical_figure.find(unit.hist_figure_id))

end
print(name .. ' is now ' .. age .. ' years old and will live to at least 160')
Expand Down