From 3a59e56049450bace55652f42618c78305ad18e3 Mon Sep 17 00:00:00 2001 From: Hevlikn <46378533+Hevlikn@users.noreply.github.com> Date: Fri, 3 Jun 2022 16:34:31 +0100 Subject: [PATCH] list-agreements overhaul (#393) * list-agreements overhaul + handling of Deity names (as mentioned in DFHack/scripts#390) + age of petitions + added status 'expired' for outstanding petitions more than 1 year old + race specific guild professions + formatting characters to reduce mid-wo rd wrapping - consolidated functions for output and name lookup - minimised repeated work within if...elseif... blocks * #393 review1 changes +run arguments handler for `all` and `help` +localised variables +culling resolved agreements by default +general good practices implemented * Update changelog.txt Co-authored-by: Myk * further review changes (#393) * standardise default fn return (#393) * Update list-agreements.lua * fix syntax in help text Co-authored-by: Myk --- changelog.txt | 1 + list-agreements.lua | 216 ++++++++++++++++++++++++++++++++------------ 2 files changed, 160 insertions(+), 57 deletions(-) diff --git a/changelog.txt b/changelog.txt index bf8c96752e..c9137298dc 100644 --- a/changelog.txt +++ b/changelog.txt @@ -23,6 +23,7 @@ that repo. ## Misc Improvements - `deteriorate`: new ``now`` command immediately deteriorates all items of the specified types. +- `list-agreements`: now displays translated Guild Names, worshiped Deity, age of petition, and "man" to race-specific professions (e.g. "Craftsman" -> "Craftsdwarf") ## Removed - `devel/unforbidall`: please use `unforbid` instead. You can silence the output with ``unforbid all --quiet`` diff --git a/list-agreements.lua b/list-agreements.lua index 2971f8d317..451a507823 100644 --- a/list-agreements.lua +++ b/list-agreements.lua @@ -1,21 +1,51 @@ --- Lists all guildhall and temple agreements +-- list location agreements with guilds or religions --[====[ list-agreements =============== -Lists all guildhall and temple agreements in fortress mode. +Lists Guildhall and Temple agreements in fortress mode. +In addition: -]====] +* Translates names of the associated Guilds and Orders respectively +* Displays worshiped Professions and Deities respectively +* Petition age and status satisfied, denied or expired, or blank for outstanding + +Usage:: + + list-agreements [options] + +Examples: + + ``list-agreements`` + List outstanding, unfullfilled location agreements. + + ``list-agreements all`` + Lists all location agreements, whether satisfied, denied, or expired. + +Options: +:all: list all agreements; past and present +:help: shows this help screen + +]====] local playerfortid = df.global.ui.site_id -- Player fortress id local templeagreements = {} -- Table of agreements for temples in player fort local guildhallagreements = {} -- Table of agreements for guildhalls in player fort -function get_location_tier(agr) - loctier = agr.details[0].data.Location.tier - return loctier +function get_location_name(loctier,loctype) + local locstr = "Unknown Location" + if loctype == df.abstract_building_type.TEMPLE and loctier == 1 then + locstr = "Temple" + elseif loctype == df.abstract_building_type.TEMPLE and loctier == 2 then + locstr = "Temple Complex" + elseif loctype == df.abstract_building_type.GUILDHALL and loctier == 1 then + locstr = "Guildhall" + elseif loctype == df.abstract_building_type.GUILDHALL and loctier == 2 then + locstr = "Grand Guildhall" + end + return locstr end function get_location_type(agr) @@ -23,98 +53,170 @@ function get_location_type(agr) return loctype end -function get_location_name(agr) - if get_location_type(agr) == df.abstract_building_type.TEMPLE and get_location_tier(agr) == 1 then - return "temple" - elseif get_location_type(agr) == df.abstract_building_type.TEMPLE and get_location_tier(agr) == 2 then - return "temple complex" - elseif get_location_type(agr) == df.abstract_building_type.GUILDHALL and get_location_tier(agr) == 1 then - return "guildhall" - elseif get_location_type(agr) == df.abstract_building_type.GUILDHALL and get_location_tier(agr) == 2 then - return "grand guildhall" - end +function get_petition_date(agr) + local agr_year = agr.details[0].year + local agr_year_tick = agr.details[0].year_tick + local julian_day = math.floor(agr_year_tick / 1200) + 1 + local agr_month = math.floor(julian_day / 28) + 1 + local agr_day = julian_day % 28 + return string.format("%03d-%02d-%02d",agr_year, agr_month, agr_day) end -function get_petition_date(agr) - agr_year = agr.details[0].year - agr_year_tick = agr.details[0].year_tick - julian_day = math.floor(agr_year_tick / 1200) + 1 - agr_month = math.floor(julian_day / 28) + 1 - agr_day = julian_day % 28 - return agr_year.."-"..agr_month.."-"..agr_day +function get_petition_age(agr) + local agr_year_tick = agr.details[0].year_tick + local agr_year = agr.details[0].year + local cur_year_tick = df.global.cur_year_tick + local cur_year = df.global.cur_year + local del_year, del_year_tick + --delta, check to prevent off by 1 error, not validated + if cur_year_tick > agr_year_tick then + del_year = cur_year - agr_year + del_year_tick = cur_year_tick - agr_year_tick + else + del_year = cur_year - agr_year - 1 + del_year_tick = agr_year_tick - cur_year_tick + end + local julian_day = math.floor(del_year_tick / 1200) + 1 + local del_month = math.floor(julian_day / 28) + local del_day = julian_day % 28 + return {del_year,del_month,del_day} end function get_guildhall_profession(agr) - prof = agr.details[0].data.Location.profession - profname = string.lower(df.profession[prof]) + local prof = agr.details[0].data.Location.profession + local profname = string.lower(df.profession[prof]) + -- *VERY* important code follows + if string.find(profname, "man") then + profname = string.gsub(profname,"man",string.lower(dfhack.units.getRaceNameById(df.global.ui.race_id))) + end + if not profname then + profname = 'profession-less' + end return profname:gsub("_", " ") end -function get_religion_name(agr) - religion_id = agr.details[0].data.Location.deity_data.Religion - religion_name = dfhack.TranslateName(df.global.world.entities.all[religion_id].name, true) - return religion_name +function get_agr_party_name(agr) + --assume party 0 is guild/order, 1 is local government as siteid = playerfortid + local party_id = agr.parties[0].entity_ids[0] + local party_name = dfhack.TranslateName(df.global.world.entities.all[party_id].name, true) + if not party_name then + party_name = 'An Unknown Entity or Group' + end + return party_name end -function is_satisfied(agr) - satisfied = agr.flags.convicted_accepted - return satisfied +function get_deity_name(agr) + local religion_id = agr.details[0].data.Location.deity_data.Religion + local deities = df.global.world.entities.all[religion_id].relations.deities + if #deities == 0 then return 'An Unknown Deity' end + return dfhack.TranslateName(df.global.world.history.figures[deities[0]].name,true) end -function is_denied(agr) - denied = agr.flags.petition_not_accepted - return denied +--get resolution status, and string +function is_resolved(agr) + local res = false + local res_str = 'outstanding' + + if agr.flags.convicted_accepted then + res = true + res_str = 'satisfied' + elseif agr.flags.petition_not_accepted then + res = true + res_str = 'denied' + elseif get_petition_age(agr)[1] ~= 0 then + res = true + res_str = 'expired' + end + return res,res_str end -function generate_output_guild(agr) - if is_satisfied(agr) == true then - print("Establish a "..get_location_name(agr).." for the "..get_guildhall_profession(agr).." guild, as agreed on "..get_petition_date(agr).." (satisfied)") - elseif is_denied(agr) == true then - print("Establish a "..get_location_name(agr).." for the "..get_guildhall_profession(agr).." guild, as agreed on "..get_petition_date(agr).." (denied)") +--universal handler +function generate_output(agr,loctype) + local loc_name = get_location_name(agr.details[0].data.Location.tier,loctype) + local agr_age = get_petition_age(agr) + local output_str = 'Establish a '.. loc_name..' for "'..get_agr_party_name(agr) + local resolved, resolution_string = is_resolved(agr) + + if loctype == df.abstract_building_type.TEMPLE then + output_str = output_str..'" worshiping "'..get_deity_name(agr)..',"' + elseif loctype == df.abstract_building_type.GUILDHALL then + output_str = output_str..'", a '..get_guildhall_profession(agr)..' guild,' else - print("Establish a "..get_location_name(agr).." for the "..get_guildhall_profession(agr).." guild, as agreed on "..get_petition_date(agr)) + print("Agreement with unknown org") + return + end + + output_str = output_str..'\n\tas agreed on '..get_petition_date(agr)..'. \t'..agr_age[1]..'y, '..agr_age[2]..'m, '..agr_age[3]..'d ago' + + -- can print '(outstanding)' status here, but imho none is cleaner + if not resolved then + print(output_str) + else + print(output_str..' ('..resolution_string..')') end end -function generate_output_temple(agr) - if is_satisfied(agr) == true then - print("Establish a "..get_location_name(agr).." for "..get_religion_name(agr)..", as agreed on "..get_petition_date(agr).." (satisfied)") - elseif is_denied(agr) == true then - print("Establish a "..get_location_name(agr).." for "..get_religion_name(agr)..", as agreed on "..get_petition_date(agr).." (denied)") +--------------------------------------------------------------------------- +-- Main Script operation +--------------------------------------------------------------------------- + +local args = {...} +local cmd = args[1] +local cull_resolved = true + +-- args handler +if cmd then + if cmd == "all" then + cull_resolved = false + elseif cmd == "help" then + print(dfhack.script_help()) + return else - print("Establish a "..get_location_name(agr).." for "..get_religion_name(agr)..", as agreed on "..get_petition_date(agr)) + print('argument ``'..cmd..'`` not supported') + print(dfhack.script_help()) + return end end for _, agr in pairs(df.agreement.get_vector()) do if agr.details[0].data.Location.site == playerfortid then - if get_location_type(agr) == df.abstract_building_type.TEMPLE then - table.insert(templeagreements, agr) - elseif get_location_type(agr) == df.abstract_building_type.GUILDHALL then - table.insert(guildhallagreements, agr) + if not is_resolved(agr) or not cull_resolved then + if get_location_type(agr) == df.abstract_building_type.TEMPLE then + table.insert(templeagreements, agr) + elseif get_location_type(agr) == df.abstract_building_type.GUILDHALL then + table.insert(guildhallagreements, agr) + end end end end print "-----------------------" -print "Agreements for temples:" +print "Agreements for Temples:" print "-----------------------" if next(templeagreements) == nil then - print "No agreements" + if cull_resolved then + print "No outstanding agreements" + else + print "No agreements" + end else for _, agr in pairs(templeagreements) do - generate_output_temple(agr) + generate_output(agr,df.abstract_building_type.TEMPLE) end end print "" print "--------------------------" -print "Agreements for guildhalls:" +print "Agreements for Guildhalls:" print "--------------------------" if next(guildhallagreements) == nil then - print "No agreements" + if cull_resolved then + print "No outstanding agreements" + else + print "No agreements" + end else for _, agr in pairs(guildhallagreements) do - generate_output_guild(agr) + generate_output(agr,df.abstract_building_type.GUILDHALL) end end