I've managed to cobble together a script that lists all guildhall and temple petitions in fortress mode. I've tested it on a few saves I had strewn about on my hard drive and it seems to work reliably.
Just a couple things I noticed that you might want to keep in mind for future development (not asking you to address them or anything):
function get_location_type(agr)
loctype = agr.details[0].data.Location.type
return loctype
end
function get_location_name(agr)
if get_location_type(agr) == 2 and get_location_tier(agr) == 1 then
return "temple"
...
elseif get_location_type(agr) == 11 and get_location_tier(agr) == 2 then
return "grand guildhall"
end
You should generally use named enum values instead of magic numbers (1, 2, 11, etc). In this case, I had to look in
df.entities.xml to find the definition of the agreement_details_data_location type. The "type" field's type is
abstract_building_type, so in Lua, 2 = df.abstract_building_type.TEMPLE and 11 = df.abstract_building_type.GUILDHALL. gui/gm-editor will also show a human-friendly list if you can navigate to this structure in it.
tier doesn't correspond to an enum, though - it's different for each abstract_building_type value, as you've found.
function is_satisfied(agr)
satisfied = agr.anon_3.convicted_accepted
return satisfied
end
function is_denied(agr)
denied = agr.anon_3.petition_not_accepted
return denied
end
You should generally avoid using anon names, because they're generated (for fields that don't have a "name=" attribute in the XML files at all) and not stable (any changes to whether nearby fields have names affect the number after "anon_" for other fields). I realize this isn't particularly helpful when you need that field, so the best practice is generally to make a pull request in df-structures or suggest a name for the field some other way.
In this case, anon_3 should probably be named "flags" for convention, so I'll tackle that. (If you're curious, it was identified as a bitfield
here and flags were identified
here, but the bitfield itself never got named.)
for agr, _ in pairs(allagreements) do
if allagreements[agr].details[0].data.Location.site == playerfortid then
if get_location_type(allagreements[agr]) == 2 then
table.insert(templeagreementids, agr)
elseif get_location_type(allagreements[agr]) == 11 then
table.insert(guildhallagreementids, agr)
end
end
end
The second thing returned by pairs is the item itself, so you could rewrite the loop as "for _, agr in pairs(...)" and then just use "agr" everywhere you're using "allagreements[agr]". The only place I see you using the index by itself is in table.insert() - the agreements you're getting are just pointers, so there isn't really any more overhead in storing the agreements themselves in the tables instead of storing their indices.