From 45c3f145e58270cda73dd268a7f68e8709b62da5 Mon Sep 17 00:00:00 2001 From: PeridexisErrant Date: Thu, 5 Nov 2015 13:17:26 +1100 Subject: [PATCH] Add gui/family-affairs --- docs/images/family-affairs.png | Bin 0 -> 3961 bytes scripts/gui/family-affairs.lua | 296 +++++++++++++++++++++++++++++++++ 2 files changed, 296 insertions(+) create mode 100644 docs/images/family-affairs.png create mode 100644 scripts/gui/family-affairs.lua diff --git a/docs/images/family-affairs.png b/docs/images/family-affairs.png new file mode 100644 index 0000000000000000000000000000000000000000..faf59390eb85e5e8b3aca9a4633fc7315b1b3ade GIT binary patch literal 3961 zcmbVP2~d+)yZ)$Kt0J{jTtK*riZ&pPL81tuE){A83Me6Lp+rEI5HMxSs$l_dsASVD*`nac$I(UZ()#r|%C=W&S5O%<0o6H#4EBtOl%J z!p2ShvL8+zKbH|PJL*}xr(tu~eE2$F!WO$1TYsu<|Mm~;5ymR7O&{82Uq&ABuimf( zwBE3EsEcQ=Svj}gFte}tL5X7B#g;fL#D(Yhm(b@H%kyp5EIjoY0Pt*x4l}L>B0;Wu zfESyGZvlW;zTd>$ zrTXP^Q%uWI>Fz&d;F!8Y!lw$lPXSq-X@My_Gn=q7l3B6r z#G^nR^P3a!rO#$9`@4|F$pHp$=nElu=J1E+EB^ck(~arPhq5d?b72PBb}=qb(T3NCYn= zH69GF%I`P}8keAJ9m^RQe#L3Y^NtocU;2-DM#1ppnN1C-K#`hSg1n%96;fok&-dAZ zj@-`OP8wWAvy%YRl1H20PKlm9WUJ^^gk(bQADfnw>sQVffUJL&^+h3!I~4xBiT-IM zug;vp-I{er85dxj|8Rls(Pm5a_O%YMm= z$re^&Kh_IIFDM}>JyY)l(Q(Tfj8#HSMR4khn-FL5F&|xeYd7~OF8>U)8&zd{KX6GE zi+vl7=*iT6IJyAydqB4HONgk=<2sOeC5G53`NYf;_^%m7BMVU*mhN1tp%Q!EXcT{g zVXeEOw;o-1qw95{p~{Kn+6eyyJ!H~5j{F?!`LkvTSwpVzlx!)@wZ(;#&=CUr1gyj+ zyot4)Ww5?u_sw{+2NawnDUa)ER|fRiRuhWEPWCIYsUfqdFn;eveA)bF2BuO5794Uj^lzJcsl#$s@a_f0!LUo? z16%=gq$yjd{*B^k>#1L?o6t-Um*uig(M}%gzAkyJZ;e^wOrIgShr7#cDHC!?w@O2Qdc$%v8lRXPM!bK|`9RYKV9iT{b*Q8afz zz^zkG0IB^;H6IUG6JDvdU+1@3@~^?lCcBvhqLwygIGYR!@2%0qyvGu#;lh$kwwP4e zVCbHsVn%&I6YV1_!w@l?AmH}(OG1$3>C=L4%Q*2=5(%CE{-g4xw8nsH zx!W)}o>BcZw4$+aJH0I0uP&tntn=FmPb2OP5k|zKJ<CZHz8K=&OY~-#v861wX{TjLlc})7WH)tyXGBC5_IFw6ieBM@@4L$vcf(rGIUBvqpHH~l=i5Ch(t35w z41i~C3PHJTymU&6X4{p7>b0s8SC+lOJnr4(7%}oD>oB6W zI`P~A`hc*ul6*{qI@d#&aiWSr(#NkE?J3O8?R5Uln{+`#wpJQ;FZj_)?9uZ*m@~7X zO=nyhUMqu)9#M0fO{W^hkNx|9Lv~(&L61z^u+&SjP;LZkx?6$BuZ@Lc#}}cuw{WTL z6Sp=NZ@%noX5D{*b##jHmn9K+F~CanHi$Wf0#8ZOvU3L;>3P|iC$+xg{D)4wGWAf` z?(pl_1`liV%jqV*%Z88K3`**8UF!+F`9cgWPxK$^_}G1QI3Af}3WL5mES^Xp!9`RB z-Y5!j?~Jkm(lQAr7kVq}x8aJC&e`Y0R1raQ(Va6F5tQMiG$W!Y;e9$Mg}w@?LTi5; z4B41VEsXNOiRr<=a1`Myt6qRa3tr}}KM7s;A|KNa4yTKe6+-m|?sF}%d(IrFPS)EU z9u5CGbXL)+5RG{P4)%sVuydIohtTaP<}6cZ3JI z{v}#61N??{81ITT7?-(gASyd(v|e(Uf$k|wae^}&I~S8HE?JtQDDbRp9ywwLjIa8a znd|@HI10v_YvfzVuP7hjFpEuyqpd?)h`o@BBKV^>dN2YAm4RKVO|}!a3@S0D6uGh} z;%5RhRkyN+-+R6?!ZI0j9N2Sp7RLldC) zJv&EB)DUHHP|Im?$T3el`9w6@r-pd5>9)a3NvVh0He4dk;&ejRqXr@+@$6G7cc`_Z zz_asgl~I&2m#5k}He$yjov14g#~+C*S_rNl5VyWd!ecCR^Y|#lPK-Dn89&pKS5Q>l zqsrr!Q#DB>Df+oOA|}eCklHjpPnB?HbE&bZ_2_aHlh&XqMI>7F?u3>a_2cb(UGc7iI4*>H$Xla_wz6x-^~mUyK!8c{vDWwNV_mEg}2bNMrQ z416ic92AGl=$t1HCaZh`A7UQS)|nt%*@P!n$z(%HFHtEh$FFF}n8)DvKVN&dn;|fX zf*G^9%;2z~@qq~bj|`dtGTu3r0KMZ0qRgsV;E9&Y^P|3elyM)6o}F1n)9-*F!kq`O zTX}QupbVl<6{m3MVyGp*qyTT1-bHsQ>>oYNM`<4)G0{^$r=?ykH zdR^pBt3g=Lzz*kScp5O-@3+3JbjSFW-fWWyn{qT!(bjgWV2_VK_V7noXm9TFvL`v^ zRK-FOZE98Q0-g^69-x*T%E?B#Md_xB4Xbn31ihpk1MoXF)Dp~h&5_ljyTNyXH#X|M z(;vBnz9rDHv5a$${OJz!r+3@NvO~{yeJQ>_+*&b2_VF_^^*E=4pelJUT~+5+>spYJ z6hG?&s;$!lwfHJ--N2gmt((IyhoqD-_Opc8ilb2mD-52=Il!byq40&m`h^5UP^Ae? zLxv<0ux!KLHM0AT)1H*uuYd2VmpFV(;MHOZXnMGA!h_3M(S&(kes1y^vT~zPtxAFj z4t5ku$`(HNp&h>|frQs-+(^KYi62SPvYcDaF3tOy5+_ki`PdUl>Xd3Efs&b-Gs!;0 zP0v-+Rb~&+%ULeXkyE?h&He&Lo5a>x_XZuQ$EvGR25HyFOs3v^$Dghjbv4q8U#m|` zeWgI(vswBF-z{4iqK8>F*tIS61|5h!gd?||?vwRQB>)%ST7CsY?l380Aj0j4X`7-?A24)G0oA(=p;c9je%8ym7^>2XFlcA>QDvlkm)eGg0eW?v^gX+7Ly4B2iH z*~J%%1M2bl8U2Iw4*(F&iea^;@%r#HJDjmQAe{MX%5A2h8=e+uO6|TY6=58wNqsyz{T_1^)iUp*uM literal 0 HcmV?d00001 diff --git a/scripts/gui/family-affairs.lua b/scripts/gui/family-affairs.lua new file mode 100644 index 000000000..51525f36e --- /dev/null +++ b/scripts/gui/family-affairs.lua @@ -0,0 +1,296 @@ +-- gui/family-affairs +-- derived from v1.2 @ http://www.bay12forums.com/smf/index.php?topic=147779 +local help = [[=begin + +gui/family-affairs +================== +A user-friendly interface to view romantic relationships, +with the ability to add, remove, or otherwise change them at +your whim - fantastic for depressed dwarves with a dead spouse +(or matchmaking players...). + +The target/s must be alive, sane, and in fortress mode. + +.. image:: /docs/images/family-affairs.png + :align: center + +``gui/family-affairs [unitID]`` + shows GUI for the selected unit, or the specified unit ID + +``gui/family-affairs divorce [unitID]`` + removes all spouse and lover information from the unit + and it's partner, bypassing almost all checks. + +``gui/family-affairs [unitID] [unitID]`` + divorces the two specificed units and their partners, + then arranges for the two units to marry, bypassing + almost all checks. Use with caution. + +=end]] + +local dlg = require ('gui.dialogs') + +function ErrorPopup (msg,color) + if not tostring(msg) then msg = "Error" end + if not color then color = COLOR_LIGHTRED end + dlg.showMessage("Dwarven Family Affairs", msg, color, nil) +end + +function AnnounceAndGamelog (text,l) + if not l then l = true end + dfhack.gui.showAnnouncement(text, _G["COLOR_LIGHTMAGENTA"]) + if l then + local log = io.open('gamelog.txt', 'a') + log:write(text.."\n") + log:close() + end +end + +function ListPrompt (msg, choicelist, bool, yes_func) +dlg.showListPrompt( + "Dwarven Family Affairs", + msg, + COLOR_WHITE, + choicelist, + --called if choice is yes + yes_func, + --called on cancel + function() end, + 15, + bool + ) +end + +function GetMarriageSummary (source) + local familystate = "" + + if source.relations.spouse_id ~= -1 then + if dfhack.units.isSane(df.unit.find(source.relations.spouse_id)) then + familystate = dfhack.TranslateName(source.name).." has a spouse ("..dfhack.TranslateName(df.unit.find(source.relations.spouse_id).name)..")" + end + if dfhack.units.isSane(df.unit.find(source.relations.spouse_id)) == false then + familystate = dfhack.TranslateName(source.name).."'s spouse is dead or not sane, would you like to choose a new one?" + end + end + + if source.relations.spouse_id == -1 and source.relations.lover_id ~= -1 then + if dfhack.units.isSane(df.unit.find(source.relations.lover_id)) then + familystate = dfhack.TranslateName(source.name).." already has a lover ("..dfhack.TranslateName(df.unit.find(source.relations.spouse_id).name)..")" + end + if dfhack.units.isSane(df.unit.find(source.relations.lover_id)) == false then + familystate = dfhack.TranslateName(source.name).."'s lover is dead or not sane, would you like that love forgotten?" + end + end + + if source.relations.spouse_id == -1 and source.relations.lover_id == -1 then + familystate = dfhack.TranslateName(source.name).." is not involved in romantic relationships with anyone" + end + + if source.relations.pregnancy_timer > 0 then + familystate = familystate.."\nShe is pregnant." + local father = df.historical_figure.find(source.relations.pregnancy_spouse) + if father then + familystate = familystate.." The father is "..dfhack.TranslateName(father.name).."." + end + end + + return familystate +end + +function GetSpouseData (source) + local spouse = df.unit.find(source.relations.spouse_id) + local spouse_hf + if spouse then + spouse_hf = df.historical_figure.find (spouse.hist_figure_id) + end + return spouse,spouse_hf +end + +function GetLoverData (source) + local lover = df.unit.find(source.relations.spouse_id) + local lover_hf + if lover then + lover_hf = df.historical_figure.find (lover.hist_figure_id) + end + return lover,lover_hf +end + +function EraseHFLinksLoverSpouse (hf) + for i = #hf.histfig_links-1,0,-1 do + if hf.histfig_links[i]._type == df.histfig_hf_link_spousest or hf.histfig_links[i]._type == df.histfig_hf_link_loverst then + local todelete = hf.histfig_links[i] + hf.histfig_links:erase(i) + todelete:delete() + end + end +end + +function Divorce (source) + local source_hf = df.historical_figure.find(source.hist_figure_id) + local spouse,spouse_hf = GetSpouseData (source) + local lover,lover_hf = GetLoverData (source) + + source.relations.spouse_id = -1 + source.relations.lover_id = -1 + + if source_hf then + EraseHFLinksLoverSpouse (source_hf) + end + if spouse then + spouse.relations.spouse_id = -1 + spouse.relations.lover_id = -1 + end + if lover then + spouse.relations.spouse_id = -1 + spouse.relations.lover_id = -1 + end + if spouse_hf then + EraseHFLinksLoverSpouse (spouse_hf) + end + if lover_hf then + EraseHFLinksLoverSpouse (lover_hf) + end + + local partner = spouse or lover + if not partner then + AnnounceAndGamelog(dfhack.TranslateName(source.name).." is now single") + else + AnnounceAndGamelog(dfhack.TranslateName(source.name).." and "..dfhack.TranslateName(partner.name).." are now single") + end +end + +function Marriage (source,target) + local source_hf = df.historical_figure.find(source.hist_figure_id) + local target_hf = df.historical_figure.find(target.hist_figure_id) + source.relations.spouse_id = target.id + target.relations.spouse_id = source.id + + local new_link = df.histfig_hf_link_spousest:new() -- adding hf link to source + new_link.target_hf = target_hf.id + new_link.link_strength = 100 + source_hf.histfig_links:insert('#',new_link) + + new_link = df.histfig_hf_link_spousest:new() -- adding hf link to target + new_link.target_hf = source_hf.id + new_link.link_strength = 100 + target_hf.histfig_links:insert('#',new_link) +end + +function ChooseNewSpouse (source) + + if not source then + qerror("no unit") return + end + if (source.profession == 103 or source.profession == 104) then + ErrorPopup("target is too young") return + end + if not (source.relations.spouse_id == -1 and source.relations.lover_id == -1) then + ErrorPopup("target already has a spouse or a lover") + qerror("source already has a spouse or a lover") + return + end + + local choicelist = {} + targetlist = {} + + for k,v in pairs (df.global.world.units.active) do + if dfhack.units.isCitizen(v) + and v.race == source.race + and v.sex ~= source.sex + and v.relations.spouse_id == -1 + and v.relations.lover_id == -1 + and not (v.profession == 103 or v.profession == 104) + then + table.insert(choicelist,dfhack.TranslateName(v.name)..', '..dfhack.units.getProfessionName(v)) + table.insert(targetlist,v) + end + end + + if #choicelist > 0 then + ListPrompt( + "Assign new spouse for "..dfhack.TranslateName(source.name), + choicelist, + true, + function(a,b) + local target = targetlist[a] + Marriage (source,target) + AnnounceAndGamelog(dfhack.TranslateName(source.name).." and "..dfhack.TranslateName(target.name).." have married!") + end) + else + ErrorPopup("No suitable candidates") + end +end + +function MainDialog (source) + + local familystate = GetMarriageSummary(source) + + familystate = familystate.."\nSelect action:" + local choicelist = {} + local on_select = {} + + local child = (source.profession == 103 or source.profession == 104) + local is_single = source.relations.spouse_id == -1 and source.relations.lover_id == -1 + local ready_for_marriage = single and not child + + if not child then + table.insert(choicelist,"Remove romantic relationships (if any)") + table.insert(on_select, Divorce) + if ready_for_marriage then + table.insert(choicelist,"Assign a new spouse") + table.insert(on_select,ChooseNewSpouse) + end + if not ready_for_marriage then + table.insert(choicelist,"[Assign a new spouse]") + table.insert(on_select,function () ErrorPopup ("Existing relationships must be removed if you wish to assign a new spouse.") end) + end + else + table.insert(choicelist,"Leave this child alone") + table.insert(on_select,nil) + end + + ListPrompt(familystate, choicelist, false, + function(a,b) if on_select[a] then on_select[a](source) end end) +end + + +local args = {...} + +if args[1] == "help" or args[1] == "?" then print(helpstr) return end + +if not df.global.gamemode == 0 then + print (helpstr) qerror ("invalid gamemode") return +end + +if args[1] == "divorce" and tonumber(args[2]) then + local unit = df.unit.find(args[2]) + if unit then Divorce (unit) return end +end + +if tonumber(args[1]) and tonumber(args[2]) then + local unit1 = df.unit.find(args[1]) + local unit2 = df.unit.find(args[2]) + if unit1 and unit2 then + Divorce (unit1) + Divorce (unit2) + Marriage (unit1,unit2) + return + end +end + +local selected = dfhack.gui.getSelectedUnit(true) +if tonumber(args[1]) then + selected = df.unit.find(tonumber(args[1])) or selected +end + +if selected then + if dfhack.units.isCitizen(selected) and dfhack.units.isSane(selected) then + MainDialog(selected) + else + qerror("You must select sane fortress citizen.") + return + end +else + print (helpstr) + qerror("select a sane fortress dwarf") +end