-
Notifications
You must be signed in to change notification settings - Fork 198
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
WIP New lua script: a gui pregnancy tool #873
Changes from 6 commits
f41adf2
15e6752
d0d7106
523c585
fb43a1e
04d2b66
c144ed3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,379 @@ | ||
local gui = require('gui') | ||
local widgets = require('gui.widgets') | ||
|
||
PregnancyGui = defclass(PregnancyGui, widgets.Window) | ||
PregnancyGui.ATTRS { | ||
frame_title='Pregnancy manager', | ||
frame={w=64, h=35}, | ||
resizable=true, -- if resizing makes sense for your dialog | ||
resize_min={w=50, h=20}, -- try to allow users to shrink your windows | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are these numbers still appropriate? |
||
} | ||
|
||
function PregnancyGui:init() | ||
if dfhack.gui.getSelectedUnit(true).sex == df.pronoun_type.she then | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this will throw if there is no unit selected when the UI is opened. You should check for a nil return value from |
||
self.mother = dfhack.gui.getSelectedUnit(true) | ||
else self.mother = false | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unless a field is always intended to be a boolean, it's better to leave unset values unset so they are |
||
end | ||
self.father = false | ||
self.father_historical = false | ||
self.msg = {} | ||
|
||
local term_options = {} | ||
local term_index = {} | ||
local months | ||
for months=0,10 do | ||
-- table.insert(term_options,{label=('%s months'):format(months),value=months}) --I tried this to add labels, probably doing something wrong, it broke the range widget | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I notice below you were getting the label to index an array. this should work fine if you get the option value instead |
||
table.insert(term_options,months) --this works though | ||
end | ||
for k,v in ipairs(term_options) do | ||
term_index[v] = k | ||
end | ||
|
||
self:addviews{ | ||
widgets.ResizingPanel{ | ||
frame={t=0}, | ||
frame_style=gui.FRAME_INTERIOR, | ||
autoarrange_subviews=true, | ||
subviews={ | ||
widgets.WrappedLabel{ | ||
text_to_wrap=self:callback('getMotherLabel') | ||
}, | ||
widgets.HotkeyLabel{ | ||
frame={l=0}, | ||
label="Set mother to selected unit", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you could also set There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and similarly for the father HotkeyLabel |
||
key='CUSTOM_SHIFT_M', | ||
on_activate=self:callback('selectmother'), | ||
}, | ||
}, | ||
}, | ||
widgets.ResizingPanel{ | ||
frame={t=5}, | ||
frame_style=gui.FRAME_INTERIOR, | ||
autoarrange_subviews=true, | ||
subviews={ | ||
widgets.WrappedLabel{ | ||
text_to_wrap=self:callback('getFatherLabel') | ||
}, | ||
widgets.HotkeyLabel{ | ||
frame={l=0}, | ||
label="Set father to selected unit", | ||
key='CUSTOM_SHIFT_F', | ||
on_activate=self:callback('selectfather'), | ||
}, | ||
widgets.HotkeyLabel{ | ||
frame={l=5}, | ||
label="Set mother's spouse as the father", | ||
key='CUSTOM_F', | ||
on_activate=self:callback('spouseFather'), | ||
disabled=function() return not self.mother or self.mother.relationship_ids.Spouse == -1 end | ||
}, | ||
}, | ||
}, | ||
widgets.Panel{ | ||
frame={t=12,h=14}, | ||
frame_style=gui.FRAME_INTERIOR, | ||
subviews={ | ||
widgets.HotkeyLabel{ | ||
frame={l=0, t=0}, | ||
key='CUSTOM_SHIFT_P', | ||
label="Create pregnancy", | ||
on_activate=self:callback('CreatePregnancy'), | ||
enabled=function() return self.mother or self.father and self.father_historical end | ||
Pebob marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}, | ||
widgets.ToggleHotkeyLabel{ | ||
frame={l=1, t=1}, | ||
view_id='Force', | ||
label='Replace existing pregnancy', | ||
options={{label='On', value=true, pen=COLOR_GREEN}, | ||
{label='Off', value=false, pen=COLOR_RED}}, | ||
initial_option=false | ||
myk002 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}, | ||
widgets.TooltipLabel{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you use a plain |
||
frame={l=0, t=3}, | ||
text_to_wrap='Pregnancy term range (months):', | ||
show_tooltip=true, | ||
text_pen=COLOR_WHITE | ||
}, | ||
widgets.CycleHotkeyLabel{ | ||
view_id='min_term', | ||
frame={l=0, t=6, w=SLIDER_LABEL_WIDTH}, | ||
label='Min pregnancy term:', | ||
key_back='CUSTOM_SHIFT_Z', | ||
key='CUSTOM_SHIFT_X', | ||
options=term_options, | ||
initial_option=7 | ||
}, | ||
widgets.CycleHotkeyLabel{ | ||
view_id='max_term', | ||
frame={l=30, t=6, w=SLIDER_LABEL_WIDTH}, | ||
label='Max pregnancy term:', | ||
key_back='CUSTOM_SHIFT_Q', | ||
key='CUSTOM_SHIFT_W', | ||
options=term_options, | ||
initial_option=9 | ||
}, | ||
widgets.RangeSlider{ | ||
frame={l=0, t=4}, | ||
num_stops=#term_options, | ||
get_left_idx_fn=function() | ||
return term_index[self.subviews.min_term:getOptionLabel()] | ||
end, | ||
get_right_idx_fn=function() | ||
return term_index[self.subviews.max_term:getOptionLabel()] | ||
end, | ||
on_left_change=function(idx) self.subviews.min_term:setOption(idx, true) end, | ||
on_right_change=function(idx) self.subviews.max_term:setOption(idx, true) end, | ||
}, | ||
widgets.WrappedLabel{ | ||
frame={t=8},--, h=5}, | ||
text_to_wrap=function() return self.msg end | ||
}, | ||
}, | ||
}, | ||
widgets.ResizingPanel{ | ||
frame={t=26}, | ||
frame_style=gui.FRAME_INTERIOR, | ||
autoarrange_subviews=true, | ||
subviews={ | ||
widgets.HotkeyLabel{ | ||
frame={l=1, b=0}, | ||
key='LEAVESCREEN', | ||
label="Return to game", | ||
on_activate=function() | ||
repeat until not self:onInput{LEAVESCREEN=true} | ||
view:dismiss() | ||
end, | ||
}, | ||
}, | ||
}, | ||
} | ||
end | ||
|
||
function PregnancyGui:selectmother() | ||
local unit = dfhack.gui.getSelectedUnit(true) | ||
if unit then | ||
if unit.sex==df.pronoun_type.she and dfhack.units.isAdult(unit) then | ||
self.mother = unit | ||
self:updateLayout() | ||
end | ||
end | ||
end | ||
|
||
function PregnancyGui:selectfather() | ||
local unit = dfhack.gui.getSelectedUnit(true) | ||
if unit and dfhack.units.isAdult(unit) then | ||
self.father = unit | ||
self.father_historical = false | ||
self:updateLayout() | ||
end | ||
end | ||
|
||
function PregnancyGui:spouseFather() | ||
local father = self:findSpouse(self.mother)[3] | ||
if father then | ||
if df.unit.find(father.unit_id) then | ||
self.father = df.unit.find(father.unit_id) | ||
self.father_historical = false | ||
else | ||
self.father_historical = father | ||
self.father = false | ||
end | ||
self:updateLayout() | ||
Pebob marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
end | ||
|
||
function PregnancyGui:getMotherLabel() | ||
if self.mother then | ||
local motherName = dfhack.TranslateName(self.mother.name) | ||
if self.mother.relationship_ids.Spouse > -1 then | ||
local spouseInfo = self:findSpouse(self.mother) | ||
return ('Selected mother: %s.%sShe is married to %s (%s).'):format( | ||
self:findName(self.mother), | ||
NEWLINE, | ||
spouseInfo[1], | ||
spouseInfo[2] | ||
) | ||
else | ||
return ('Selected mother: %s.%sShe is unmarried.'):format( | ||
self:findName(self.mother), | ||
NEWLINE | ||
) | ||
end | ||
else return ('No mother selected - Must be an adult female') | ||
end | ||
end | ||
|
||
function PregnancyGui:getFatherLabel() | ||
if self.father or self.father_historical then | ||
if self.father_historical or self.father.relationship_ids.Spouse > -1 then | ||
local father = self.father or self.father_historical | ||
local spouseInfo = self:findSpouse(father) | ||
return ('Selected father: %s.%s%s is married to %s (%s).'):format( | ||
self:findName(father), | ||
NEWLINE, | ||
df.pronoun_type[father.sex]:gsub("^%l", string.upper), | ||
spouseInfo[1], | ||
spouseInfo[2] | ||
) | ||
else | ||
return ('Selected father: %s.%s%s is unmarried.'):format( | ||
self:findName(self.father), | ||
NEWLINE, | ||
df.pronoun_type[self.father.sex]:gsub("^%l", string.upper) | ||
) | ||
end | ||
else return ('No father selected') | ||
end | ||
end | ||
|
||
function PregnancyGui:findName(unit) | ||
local name = dfhack.TranslateName(unit.name) | ||
if name ~= "" then | ||
return name | ||
else return ('Unnamed %s. (Unit id:%s)'):format( | ||
string.upper(df.global.world.raws.creatures.all[unit.race].name[0]), | ||
unit.id | ||
) | ||
end | ||
end | ||
|
||
function PregnancyGui:findSpouse(unit) | ||
local historical_spouse, spouse_loc, spouse, spouseid | ||
local culled = false | ||
|
||
--setting variables for if mother or father are local, followed by finding the father's spouse if he is not local | ||
if self.father == unit or self.mother == unit then | ||
spouseid = unit.relationship_ids.Spouse | ||
spouse = df.unit.find(spouseid) | ||
elseif self.father_historical == unit then | ||
for index, relation in pairs(unit.histfig_links) do | ||
if relation._type == df.histfig_hf_link_spousest then | ||
historical_spouse=df.historical_figure.find(relation.target_hf) | ||
if not historical_spouse then culled = true --there was an id, but there wasn't a histfig with that id (due culling) | ||
elseif df.global.plotinfo.site_id==historical_spouse.info.whereabouts.site then | ||
spouse_loc = 'local' | ||
else spouse_loc = 'offsite' | ||
end | ||
end | ||
end | ||
return {dfhack.TranslateName(historical_spouse.name),spouse_loc,historical_spouse} | ||
end | ||
|
||
--if the spouse is local this should identify them: | ||
if spouse then | ||
historical_spouse = df.historical_figure.find(spouse.hist_figure_id) or false | ||
spouse_loc = 'local' | ||
end | ||
|
||
--if spouse is not local (offsite): | ||
if spouseid > -1 and not spouse then --spouse exists but isnt on the map, so search historical units: | ||
local historical_unit = df.historical_figure.find(unit.hist_figure_id) | ||
for index, relation in pairs(historical_unit.histfig_links) do | ||
if relation._type == df.histfig_hf_link_spousest then | ||
historical_spouse=df.historical_figure.find(relation.target_hf) | ||
if not historical_spouse then culled = true --there was an id, but there wasn't a histfig with that id (due culling) | ||
elseif df.global.plotinfo.site_id==historical_spouse.info.whereabouts.site then--i dont think this should ever be true | ||
spouse_loc = 'local' | ||
else spouse_loc = 'offsite' | ||
end | ||
end | ||
end | ||
end | ||
if culled then | ||
return {'Unknown','culled'} | ||
else | ||
return {dfhack.TranslateName(historical_spouse.name),spouse_loc,historical_spouse} | ||
end | ||
end | ||
|
||
function PregnancyGui:CreatePregnancy() | ||
local genes,father_id,father_caste,father_name | ||
local bypass = true | ||
local force = self.subviews.Force:getOptionValue() | ||
|
||
self.msg = {} | ||
|
||
if self.subviews.min_term:getOptionLabel() > self.subviews.max_term:getOptionLabel() then | ||
table.insert(self.msg,('Min term has to be less then max term')) | ||
self:updateLayout() | ||
return | ||
end | ||
|
||
if self.father then | ||
genes=self.father.appearance.genes:new() | ||
father_id=self.father.hist_figure_id | ||
father_caste=self.father.caste | ||
father_name=self:findName(self.father) | ||
else | ||
genes=self.mother.appearance.genes:new()--i dont think historical figures have genes | ||
father_id=self.father_historical.id | ||
father_caste=self.father_historical.caste | ||
father_name=self:findName(self.father_historical) | ||
end | ||
|
||
if self.mother.pregnancy_timer > 0 then | ||
local og_father = df.historical_figure.find(self.mother.pregnancy_spouse) | ||
bypass = false | ||
if force and og_father then | ||
table.insert(self.msg, ('SUCCESS:%sMother:%s%sFather:%s%sPrevious pregnancy with %s replaced'):format( | ||
NEWLINE, | ||
self:findName(self.mother), | ||
NEWLINE, | ||
father_name, | ||
NEWLINE, | ||
dfhack.TranslateName(og_father.name) | ||
)) | ||
elseif force then | ||
table.insert(self.msg, ('SUCCESS:%sMother:%s%sFather:%s%sPrevious pregnancy aborted'):format( | ||
NEWLINE, | ||
self:findName(self.mother), | ||
NEWLINE, | ||
father_name, | ||
NEWLINE | ||
)) | ||
elseif og_father then | ||
table.insert(self.msg, ('FAILED:%s%s already pregnant with %s%s'):format( | ||
NEWLINE, | ||
self:findName(self.mother), | ||
dfhack.TranslateName(og_father.name), | ||
force | ||
)) | ||
else | ||
table.insert(self.msg, ('FAILED:%s%s is already pregnant, no father is recorded'):format( | ||
NEWLINE, | ||
self:findName(self.mother) | ||
)) | ||
end | ||
end | ||
|
||
if bypass or force then | ||
self.mother.pregnancy_timer=math.random(self.subviews.min_term:getOptionLabel()*33600+1, self.subviews.max_term:getOptionLabel()*33600+1) | ||
self.mother.pregnancy_caste=father_caste | ||
self.mother.pregnancy_spouse=father_id | ||
self.mother.pregnancy_genes=genes | ||
if not force then | ||
table.insert(self.msg, ('SUCCESS:%sMother:%s%sFather:%s'):format( | ||
NEWLINE, | ||
self:findName(self.mother), | ||
NEWLINE, | ||
father_name | ||
)) | ||
end | ||
end | ||
self:updateLayout() | ||
end | ||
|
||
PregnancyScreen = defclass(PregnancyScreen, gui.ZScreen) | ||
PregnancyScreen.ATTRS { | ||
focus_path='pregnancy', | ||
} | ||
|
||
function PregnancyScreen:init() | ||
self:addviews{PregnancyGui{}} | ||
end | ||
|
||
function PregnancyScreen:onDismiss() | ||
view = nil | ||
end | ||
|
||
view = view and view:raise() or PregnancyScreen{}:show() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
docs for this script would go in
docs/gui/pregnancy.rst
-- see other files in that directory and copy the format.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
docs are still required