-- Export everything from legends mode --[[=begin exportlegends ============= Controls legends mode to export data - especially useful to set-and-forget large worlds, or when you want a map of every site when there are several hundred. The 'info' option exports more data than is possible in vanilla, to a :file:`region-date-legends_plus.xml` file developed to extend :forums:`World Viewer <128932>` and other legends utilities. Options: :info: Exports the world/gen info, the legends XML, and a custom XML with more information :custom: Exports a custom XML with more information :sites: Exports all available site maps :maps: Exports all seventeen detailed maps :all: Equivalent to calling all of the above, in that order =end]] gui = require 'gui' local args = {...} local vs = dfhack.gui.getCurViewscreen() local i = 1 local MAPS = { "Standard biome+site map", "Elevations including lake and ocean floors", "Elevations respecting water level", "Biome", "Hydrosphere", "Temperature", "Rainfall", "Drainage", "Savagery", "Volcanism", "Current vegetation", "Evil", "Salinity", "Structures/fields/roads/etc.", "Trade", "Nobility and Holdings", "Diplomacy", } function getItemSubTypeName(itemType, subType) if (dfhack.items.getSubtypeCount(itemType)) <= 0 then return tostring(-1) end local subtypename = dfhack.items.getSubtypeDef(itemType, subType) if (subtypename == nil) then return tostring(-1) else return tostring(subtypename.name):lower() end end function findEntity(id) for k,v in ipairs(df.global.world.entities.all) do if (v.id == id) then return v end end return nil end function table.contains(table, element) for _, value in pairs(table) do if value == element then return true end end return false end function table.containskey(table, key) for value, _ in pairs(table) do if value == key then return true end end return false end --create an extra legends xml with extra data, by Mason11987 for World Viewer function export_more_legends_xml() local month = dfhack.world.ReadCurrentMonth() + 1 --days and months are 1-indexed local day = dfhack.world.ReadCurrentDay() local year_str = string.format('%0'..math.max(5, string.len(''..df.global.cur_year))..'d', df.global.cur_year) local date_str = year_str..string.format('-%02d-%02d', month, day) local filename = df.global.world.cur_savegame.save_dir.."-"..date_str.."-legends_plus.xml" local file = io.open(filename, 'w') if not file then qerror("could not open file: " .. filename) end file:write("\n") file:write("\n") file:write(""..dfhack.df2utf(dfhack.TranslateName(df.global.world.world_data.name)).."\n") file:write(""..dfhack.df2utf(dfhack.TranslateName(df.global.world.world_data.name,1)).."\n") file:write("\n") for landmassK, landmassV in ipairs(df.global.world.world_data.landmasses) do file:write("\t\n") file:write("\t\t"..landmassV.index.."\n") file:write("\t\t"..dfhack.df2utf(dfhack.TranslateName(landmassV.name,1)).."\n") file:write("\t\t"..landmassV.min_x..","..landmassV.min_y.."\n") file:write("\t\t"..landmassV.max_x..","..landmassV.max_y.."\n") file:write("\t\n") end file:write("\n") file:write("\n") for mountainK, mountainV in ipairs(df.global.world.world_data.mountain_peaks) do file:write("\t\n") file:write("\t\t"..mountainK.."\n") file:write("\t\t"..dfhack.df2utf(dfhack.TranslateName(mountainV.name,1)).."\n") file:write("\t\t"..mountainV.pos.x..","..mountainV.pos.y.."\n") file:write("\t\t"..mountainV.height.."\n") file:write("\t\n") end file:write("\n") file:write("\n") for regionK, regionV in ipairs(df.global.world.world_data.regions) do file:write("\t\n") file:write("\t\t"..regionV.index.."\n") file:write("\t\t") for xK, xVal in ipairs(regionV.region_coords.x) do file:write(xVal..","..regionV.region_coords.y[xK].."|") end file:write("\n") file:write("\t\n") end file:write("\n") file:write("\n") for regionK, regionV in ipairs(df.global.world.world_data.underground_regions) do file:write("\t\n") file:write("\t\t"..regionV.index.."\n") file:write("\t\t") for xK, xVal in ipairs(regionV.region_coords.x) do file:write(xVal..","..regionV.region_coords.y[xK].."|") end file:write("\n") file:write("\t\n") end file:write("\n") file:write("\n") for siteK, siteV in ipairs(df.global.world.world_data.sites) do file:write("\t\n") for k,v in pairs(siteV) do if (k == "id" or k == "civ_id" or k == "cur_owner_id") then file:write("\t\t<"..k..">"..tostring(v).."\n") elseif (k == "buildings") then if (#siteV.buildings > 0) then file:write("\t\t\n") for buildingK, buildingV in ipairs(siteV.buildings) do file:write("\t\t\t\n") file:write("\t\t\t\t"..buildingV.id.."\n") file:write("\t\t\t\t"..df.abstract_building_type[buildingV:getType()]:lower().."\n") if (df.abstract_building_type[buildingV:getType()]:lower() ~= "underworld_spire" or table.containskey(buildingV,"name")) then file:write("\t\t\t\t"..dfhack.df2utf(dfhack.TranslateName(buildingV.name, 1)).."\n") file:write("\t\t\t\t"..dfhack.df2utf(dfhack.TranslateName(buildingV.name)).."\n") end if (buildingV:getType() == df.abstract_building_type.TEMPLE) then file:write("\t\t\t\t"..buildingV.deity.."\n") file:write("\t\t\t\t"..buildingV.religion.."\n") end if (buildingV:getType() == df.abstract_building_type.DUNGEON) then file:write("\t\t\t\t"..buildingV.dungeon_type.."\n") end for inhabitabntK,inhabitabntV in pairs(buildingV.inhabitants) do file:write("\t\t\t\t"..inhabitabntV.anon_2.."\n") end file:write("\t\t\t\n") end file:write("\t\t\n") end end end file:write("\t\n") end file:write("\n") file:write("\n") for wcK, wcV in ipairs(df.global.world.world_data.constructions.list) do file:write("\t\n") file:write("\t\t"..wcV.id.."\n") file:write("\t\t"..dfhack.df2utf(dfhack.TranslateName(wcV.name,1)).."\n") file:write("\t\t"..(df.world_construction_type[wcV:getType()]):lower().."\n") file:write("\t\t") for xK, xVal in ipairs(wcV.square_pos.x) do file:write(xVal..","..wcV.square_pos.y[xK].."|") end file:write("\n") file:write("\t\n") end file:write("\n") file:write("\n") for artifactK, artifactV in ipairs(df.global.world.artifacts.all) do file:write("\t\n") file:write("\t\t"..artifactV.id.."\n") if (artifactV.item:getType() ~= -1) then file:write("\t\t"..tostring(df.item_type[artifactV.item:getType()]):lower().."\n") if (artifactV.item:getSubtype() ~= -1) then file:write("\t\t"..artifactV.item.subtype.name.."\n") end for improvementK,impovementV in pairs(artifactV.item.improvements) do if impovementV:getType() == df.improvement_type.WRITING then for writingk,writingV in pairs(impovementV["itemimprovement_writingst.anon_1"]) do file:write("\t\t"..writingV.."\n") end elseif impovementV:getType() == df.improvement_type.PAGES then file:write("\t\t"..impovementV.count.."\n") for writingk,writingV in pairs(impovementV.contents) do file:write("\t\t"..writingV.."\n") end end end end if (table.containskey(artifactV.item,"description")) then file:write("\t\t"..dfhack.df2utf(artifactV.item.description:lower()).."\n") end if artifactV.item:getMaterial() ~= -1 then file:write("\t\t"..dfhack.matinfo.toString(dfhack.matinfo.decode(artifactV.item:getMaterial(), artifactV.item:getMaterialIndex())).."\n") end file:write("\t\n") end file:write("\n") file:write("\n") for hfK, hfV in ipairs(df.global.world.history.figures) do file:write("\t\n") file:write("\t\t"..hfV.id.."\n") file:write("\t\t"..hfV.sex.."\n") if hfV.race >= 0 then file:write("\t\t"..df.global.world.raws.creatures.all[hfV.race].name[0].."\n") end file:write("\t\n") end file:write("\n") file:write("\n") for entityPopK, entityPopV in ipairs(df.global.world.entity_populations) do file:write("\t\n") file:write("\t\t"..entityPopV.id.."\n") for raceK, raceV in ipairs(entityPopV.races) do local raceName = (df.global.world.raws.creatures.all[raceV].creature_id):lower() file:write("\t\t"..raceName..":"..entityPopV.counts[raceK].."\n") end file:write("\t\t"..entityPopV.civ_id.."\n") file:write("\t\n") end file:write("\n") file:write("\n") for entityK, entityV in ipairs(df.global.world.entities.all) do file:write("\t\n") file:write("\t\t"..entityV.id.."\n") if entityV.race >= 0 then file:write("\t\t"..(df.global.world.raws.creatures.all[entityV.race].creature_id):lower().."\n") end file:write("\t\t"..(df.historical_entity_type[entityV.type]):lower().."\n") if entityV.type == df.historical_entity_type.Religion then -- Get worshipped figure if (entityV.unknown1b ~= nil and entityV.unknown1b.worship ~= nil) then for k,v in pairs(entityV.unknown1b.worship) do file:write("\t\t"..v.."\n") end end end for id, link in pairs(entityV.entity_links) do file:write("\t\t\n") for k, v in pairs(link) do if (k == "type") then file:write("\t\t\t<"..k..">"..tostring(df.entity_entity_link_type[v]).."\n") else file:write("\t\t\t<"..k..">"..v.."\n") end end file:write("\t\t\n") end for positionK,positionV in pairs(entityV.positions.own) do file:write("\t\t\n") file:write("\t\t\t"..positionV.id.."\n") if positionV.name[0] ~= "" then file:write("\t\t\t"..positionV.name[0].."\n") end if positionV.name_male[0] ~= "" then file:write("\t\t\t"..positionV.name_male[0].."\n") end if positionV.name_female[0] ~= "" then file:write("\t\t\t"..positionV.name_female[0].."\n") end if positionV.spouse[0] ~= "" then file:write("\t\t\t"..positionV.spouse[0].."\n") end if positionV.spouse_male[0] ~= "" then file:write("\t\t\t"..positionV.spouse_male[0].."\n") end if positionV.spouse_female[0] ~= "" then file:write("\t\t\t"..positionV.spouse_female[0].."\n") end file:write("\t\t\n") end for assignmentK,assignmentV in pairs(entityV.positions.assignments) do file:write("\t\t\n") for k, v in pairs(assignmentV) do if (k == "id" or k == "histfig" or k == "position_id" or k == "squad_id") then file:write("\t\t\t<"..k..">"..v.."\n") end end file:write("\t\t\n") end for idx,id in pairs(entityV.histfig_ids) do file:write("\t\t"..id.."\n") end for id, link in ipairs(entityV.children) do file:write("\t\t"..link.."\n") end file:write("\t\t") for xK, xVal in ipairs(entityV.claims.unk2.x) do file:write(xVal..","..entityV.claims.unk2.y[xK].."|") end file:write("\t\t\n") if (table.containskey(entityV,"occasion_info") and entityV.occasion_info ~= nil) then for occasionK, occasionV in pairs(entityV.occasion_info.occasions) do file:write("\t\t\n") file:write("\t\t\t"..occasionV.id.."\n") file:write("\t\t\t"..dfhack.df2utf(dfhack.TranslateName(occasionV.name,1)).."\n") file:write("\t\t\t"..occasionV.event.."\n") for scheduleK, scheduleV in pairs(occasionV.schedule) do file:write("\t\t\t\n") file:write("\t\t\t\t"..scheduleK.."\n") file:write("\t\t\t\t"..df.occasion_schedule_type[scheduleV.type]:lower().."\n") if(scheduleV.type == df.occasion_schedule_type.THROWING_COMPETITION) then file:write("\t\t\t\t"..df.item_type[scheduleV.reference]:lower().."\n") file:write("\t\t\t\t"..getItemSubTypeName(scheduleV.reference,scheduleV.reference2).."\n") else file:write("\t\t\t\t"..scheduleV.reference.."\n") file:write("\t\t\t\t"..scheduleV.reference2.."\n") end for featureK, featureV in pairs(scheduleV.features) do file:write("\t\t\t\t\n") if(df.occasion_schedule_feature[featureV.feature] ~= nil) then file:write("\t\t\t\t\t"..df.occasion_schedule_feature[featureV.feature]:lower().."\n") else file:write("\t\t\t\t\t"..featureV.feature.."\n") end file:write("\t\t\t\t\t"..featureV.reference.."\n") file:write("\t\t\t\t\n") end file:write("\t\t\t\n") end file:write("\t\t\n") end end file:write("\t\n") end file:write("\n") file:write("\n") for formK, formV in ipairs(df.global.world.poetic_forms.all) do file:write("\t\n") file:write("\t\t"..formV.id.."\n") file:write("\t\t"..dfhack.df2utf(dfhack.TranslateName(formV.name,1)).."\n") file:write("\t\n") end file:write("\n") file:write("\n") for formK, formV in ipairs(df.global.world.musical_forms.all) do file:write("\t\n") file:write("\t\t"..formV.id.."\n") file:write("\t\t"..dfhack.df2utf(dfhack.TranslateName(formV.name,1)).."\n") file:write("\t\n") end file:write("\n") file:write("\n") for formK, formV in ipairs(df.global.world.dance_forms.all) do file:write("\t\n") file:write("\t\t"..formV.id.."\n") file:write("\t\t"..dfhack.df2utf(dfhack.TranslateName(formV.name,1)).."\n") file:write("\t\n") end file:write("\n") file:write("\n") for wcK, wcV in ipairs(df.global.world.written_contents.all) do file:write("\t\n") file:write("\t\t"..wcV.id.."\n") file:write("\t\t"..wcV.title.."\n") file:write("\t\t"..wcV.page_start.."\n") file:write("\t\t"..wcV.page_end.."\n") for refK, refV in pairs(wcV.refs) do file:write("\t\t\n") file:write("\t\t\t"..df.general_ref_type[refV:getType()].."\n") if refV:getType() == df.general_ref_type.ARTIFACT then file:write("\t\t\t"..refV.artifact_id.."\n") -- artifact elseif refV:getType() == df.general_ref_type.ENTITY then file:write("\t\t\t"..refV.entity_id.."\n") -- entity elseif refV:getType() == df.general_ref_type.HISTORICAL_EVENT then file:write("\t\t\t"..refV.event_id.."\n") -- event elseif refV:getType() == df.general_ref_type.SITE then file:write("\t\t\t"..refV.site_id.."\n") -- site elseif refV:getType() == df.general_ref_type.SUBREGION then file:write("\t\t\t"..refV.region_id.."\n") -- region elseif refV:getType() == df.general_ref_type.HISTORICAL_FIGURE then file:write("\t\t\t"..refV.hist_figure_id.."\n") -- hist figure elseif refV:getType() == df.general_ref_type.WRITTEN_CONTENT then file:write("\t\t\t"..refV.anon_1.."\n") elseif refV:getType() == df.general_ref_type.POETIC_FORM then file:write("\t\t\t"..refV.poetic_form_id.."\n") -- poetic form elseif refV:getType() == df.general_ref_type.MUSICAL_FORM then file:write("\t\t\t"..refV.musical_form_id.."\n") -- musical form elseif refV:getType() == df.general_ref_type.DANCE_FORM then file:write("\t\t\t"..refV.dance_form_id.."\n") -- dance form elseif refV:getType() == df.general_ref_type.INTERACTION then -- TODO INTERACTION elseif refV:getType() == df.general_ref_type.KNOWLEDGE_SCHOLAR_FLAG then -- TODO KNOWLEDGE_SCHOLAR_FLAG elseif refV:getType() == df.general_ref_type.VALUE_LEVEL then -- TODO VALUE_LEVEL elseif refV:getType() == df.general_ref_type.LANGUAGE then -- TODO LANGUAGE else print("unknown reference",refV:getType(),df.general_ref_type[refV:getType()]) --for k,v in pairs(refV) do print(k,v) end end file:write("\t\t\n") end file:write("\t\t"..(df.written_content_type[wcV.type] or wcV.type).."\n") for styleK, styleV in pairs(wcV.styles) do file:write("\t\t\n") end file:write("\t\t"..wcV.author.."\n") file:write("\t\n") end file:write("\n") file:write("\n") for ID, event in ipairs(df.global.world.history.events) do if event:getType() == df.history_event_type.ADD_HF_ENTITY_LINK or event:getType() == df.history_event_type.ADD_HF_SITE_LINK or event:getType() == df.history_event_type.ADD_HF_HF_LINK or event:getType() == df.history_event_type.ADD_HF_ENTITY_LINK or event:getType() == df.history_event_type.TOPICAGREEMENT_CONCLUDED or event:getType() == df.history_event_type.TOPICAGREEMENT_REJECTED or event:getType() == df.history_event_type.TOPICAGREEMENT_MADE or event:getType() == df.history_event_type.BODY_ABUSED or event:getType() == df.history_event_type.CHANGE_CREATURE_TYPE or event:getType() == df.history_event_type.CHANGE_HF_JOB or event:getType() == df.history_event_type.CHANGE_HF_STATE or event:getType() == df.history_event_type.CREATED_BUILDING or event:getType() == df.history_event_type.CREATURE_DEVOURED or event:getType() == df.history_event_type.HF_DOES_INTERACTION or event:getType() == df.history_event_type.HF_LEARNS_SECRET or event:getType() == df.history_event_type.HIST_FIGURE_NEW_PET or event:getType() == df.history_event_type.HIST_FIGURE_REACH_SUMMIT or event:getType() == df.history_event_type.ITEM_STOLEN or event:getType() == df.history_event_type.REMOVE_HF_ENTITY_LINK or event:getType() == df.history_event_type.REMOVE_HF_SITE_LINK or event:getType() == df.history_event_type.REPLACED_BUILDING or event:getType() == df.history_event_type.MASTERPIECE_CREATED_ARCH_DESIGN or event:getType() == df.history_event_type.MASTERPIECE_CREATED_DYE_ITEM or event:getType() == df.history_event_type.MASTERPIECE_CREATED_ARCH_CONSTRUCT or event:getType() == df.history_event_type.MASTERPIECE_CREATED_ITEM or event:getType() == df.history_event_type.MASTERPIECE_CREATED_ITEM_IMPROVEMENT or event:getType() == df.history_event_type.MASTERPIECE_CREATED_FOOD or event:getType() == df.history_event_type.MASTERPIECE_CREATED_ENGRAVING or event:getType() == df.history_event_type.MASTERPIECE_LOST or event:getType() == df.history_event_type.ENTITY_ACTION or event:getType() == df.history_event_type.HF_ACT_ON_BUILDING or event:getType() == df.history_event_type.ARTIFACT_CREATED or event:getType() == df.history_event_type.ASSUME_IDENTITY or event:getType() == df.history_event_type.CREATE_ENTITY_POSITION or event:getType() == df.history_event_type.DIPLOMAT_LOST or event:getType() == df.history_event_type.MERCHANT or event:getType() == df.history_event_type.WAR_PEACE_ACCEPTED or event:getType() == df.history_event_type.WAR_PEACE_REJECTED or event:getType() == df.history_event_type.HIST_FIGURE_WOUNDED or event:getType() == df.history_event_type.HIST_FIGURE_DIED then file:write("\t\n") file:write("\t\t"..event.id.."\n") file:write("\t\t"..tostring(df.history_event_type[event:getType()]):lower().."\n") for k,v in pairs(event) do if k == "year" or k == "seconds" or k == "flags" or k == "id" or (k == "region" and event:getType() ~= df.history_event_type.HF_DOES_INTERACTION) or k == "region_pos" or k == "layer" or k == "feature_layer" or k == "subregion" or k == "anon_1" or k == "anon_2" or k == "flags2" or k == "unk1" then elseif event:getType() == df.history_event_type.ADD_HF_ENTITY_LINK and k == "link_type" then file:write("\t\t<"..k..">"..df.histfig_entity_link_type[v]:lower().."\n") elseif event:getType() == df.history_event_type.ADD_HF_ENTITY_LINK and k == "position_id" then local entity = findEntity(event.civ) if (entity ~= nil and event.civ > -1 and v > -1) then for entitypositionsK, entityPositionsV in ipairs(entity.positions.own) do if entityPositionsV.id == v then file:write("\t\t"..tostring(entityPositionsV.name[0]):lower().."\n") break end end else file:write("\t\t-1\n") end elseif event:getType() == df.history_event_type.CREATE_ENTITY_POSITION and k == "position" then local entity = findEntity(event.site_civ) if (entity ~= nil and v > -1) then for entitypositionsK, entityPositionsV in ipairs(entity.positions.own) do if entityPositionsV.id == v then file:write("\t\t"..tostring(entityPositionsV.name[0]):lower().."\n") break end end else file:write("\t\t-1\n") end elseif event:getType() == df.history_event_type.REMOVE_HF_ENTITY_LINK and k == "link_type" then file:write("\t\t<"..k..">"..df.histfig_entity_link_type[v]:lower().."\n") elseif event:getType() == df.history_event_type.REMOVE_HF_ENTITY_LINK and k == "position_id" then local entity = findEntity(event.civ) if (entity ~= nil and event.civ > -1 and v > -1) then for entitypositionsK, entityPositionsV in ipairs(entity.positions.own) do if entityPositionsV.id == v then file:write("\t\t"..tostring(entityPositionsV.name[0]):lower().."\n") break end end else file:write("\t\t-1\n") end elseif event:getType() == df.history_event_type.ADD_HF_HF_LINK and k == "type" then file:write("\t\t"..df.histfig_hf_link_type[v]:lower().."\n") elseif event:getType() == df.history_event_type.ADD_HF_SITE_LINK and k == "type" then file:write("\t\t"..df.histfig_site_link_type[v]:lower().."\n") elseif event:getType() == df.history_event_type.REMOVE_HF_SITE_LINK and k == "type" then file:write("\t\t"..df.histfig_site_link_type[v]:lower().."\n") elseif (event:getType() == df.history_event_type.ITEM_STOLEN or event:getType() == df.history_event_type.MASTERPIECE_CREATED_ITEM or event:getType() == df.history_event_type.MASTERPIECE_CREATED_ITEM_IMPROVEMENT or event:getType() == df.history_event_type.MASTERPIECE_CREATED_DYE_ITEM ) and k == "item_type" then file:write("\t\t"..df.item_type[v]:lower().."\n") elseif (event:getType() == df.history_event_type.ITEM_STOLEN or event:getType() == df.history_event_type.MASTERPIECE_CREATED_ITEM or event:getType() == df.history_event_type.MASTERPIECE_CREATED_ITEM_IMPROVEMENT or event:getType() == df.history_event_type.MASTERPIECE_CREATED_DYE_ITEM ) and k == "item_subtype" then --if event.item_type > -1 and v > -1 then file:write("\t\t<"..k..">"..getItemSubTypeName(event.item_type,v).."\n") --end elseif event:getType() == df.history_event_type.MASTERPIECE_CREATED_FOOD and k == "item_subtype" then --if event.item_type > -1 and v > -1 then file:write("\t\tfood\n") file:write("\t\t<"..k..">"..getItemSubTypeName(df.item_type.FOOD,v).."\n") --end elseif event:getType() == df.history_event_type.ITEM_STOLEN and k == "mattype" then if (v > -1) then if (dfhack.matinfo.decode(event.mattype, event.matindex) == nil) then file:write("\t\t"..event.mattype.."\n") file:write("\t\t"..event.matindex.."\n") else file:write("\t\t"..dfhack.matinfo.toString(dfhack.matinfo.decode(event.mattype, event.matindex)).."\n") end end elseif (event:getType() == df.history_event_type.MASTERPIECE_CREATED_ITEM or event:getType() == df.history_event_type.MASTERPIECE_CREATED_ITEM_IMPROVEMENT or event:getType() == df.history_event_type.MASTERPIECE_CREATED_FOOD or event:getType() == df.history_event_type.MASTERPIECE_CREATED_DYE_ITEM ) and k == "mat_type" then if (v > -1) then if (dfhack.matinfo.decode(event.mat_type, event.mat_index) == nil) then file:write("\t\t"..event.mat_type.."\n") file:write("\t\t"..event.mat_index.."\n") else file:write("\t\t"..dfhack.matinfo.toString(dfhack.matinfo.decode(event.mat_type, event.mat_index)).."\n") end end elseif event:getType() == df.history_event_type.MASTERPIECE_CREATED_ITEM_IMPROVEMENT and k == "imp_mat_type" then if (v > -1) then if (dfhack.matinfo.decode(event.imp_mat_type, event.imp_mat_index) == nil) then file:write("\t\t"..event.imp_mat_type.."\n") file:write("\t\t"..event.imp_mat_index.."\n") else file:write("\t\t"..dfhack.matinfo.toString(dfhack.matinfo.decode(event.imp_mat_type, event.imp_mat_index)).."\n") end end elseif event:getType() == df.history_event_type.MASTERPIECE_CREATED_DYE_ITEM and k == "dye_mat_type" then if (v > -1) then if (dfhack.matinfo.decode(event.dye_mat_type, event.dye_mat_index) == nil) then file:write("\t\t"..event.dye_mat_type.."\n") file:write("\t\t"..event.dye_mat_index.."\n") else file:write("\t\t"..dfhack.matinfo.toString(dfhack.matinfo.decode(event.dye_mat_type, event.dye_mat_index)).."\n") end end elseif event:getType() == df.history_event_type.ITEM_STOLEN and k == "matindex" then --skip elseif event:getType() == df.history_event_type.ITEM_STOLEN and k == "item" and v == -1 then --skip elseif (event:getType() == df.history_event_type.MASTERPIECE_CREATED_ITEM or event:getType() == df.history_event_type.MASTERPIECE_CREATED_ITEM_IMPROVEMENT ) and k == "mat_index" then --skip elseif event:getType() == df.history_event_type.MASTERPIECE_CREATED_ITEM_IMPROVEMENT and k == "imp_mat_index" then --skip elseif (event:getType() == df.history_event_type.WAR_PEACE_ACCEPTED or event:getType() == df.history_event_type.WAR_PEACE_REJECTED or event:getType() == df.history_event_type.TOPICAGREEMENT_CONCLUDED or event:getType() == df.history_event_type.TOPICAGREEMENT_REJECTED or event:getType() == df.history_event_type.TOPICAGREEMENT_MADE ) and k == "topic" then file:write("\t\t"..tostring(df.meeting_topic[v]):lower().."\n") elseif event:getType() == df.history_event_type.MASTERPIECE_CREATED_ITEM_IMPROVEMENT and k == "improvement_type" then file:write("\t\t"..df.improvement_type[v]:lower().."\n") elseif ((event:getType() == df.history_event_type.HIST_FIGURE_REACH_SUMMIT and k == "group") or (event:getType() == df.history_event_type.HIST_FIGURE_NEW_PET and k == "group") or (event:getType() == df.history_event_type.BODY_ABUSED and k == "bodies")) then for detailK,detailV in pairs(v) do file:write("\t\t<"..k..">"..detailV.."\n") end elseif event:getType() == df.history_event_type.HIST_FIGURE_NEW_PET and k == "pets" then for detailK,detailV in pairs(v) do file:write("\t\t<"..k..">"..df.global.world.raws.creatures.all[detailV].name[0].."\n") end elseif event:getType() == df.history_event_type.BODY_ABUSED and (k == "props") then file:write("\t\t<"..k.."_item_type>"..tostring(df.item_type[event.props.item.item_type]):lower().."\n") file:write("\t\t<"..k.."_item_subtype>"..getItemSubTypeName(event.props.item.item_type,event.props.item.item_subtype).."\n") if (event.props.item.mat_type > -1) then if (dfhack.matinfo.decode(event.props.item.mat_type, event.props.item.mat_index) == nil) then file:write("\t\t"..event.props.item.mat_type.."\n") file:write("\t\t"..event.props.item.mat_index.."\n") else file:write("\t\t"..dfhack.matinfo.toString(dfhack.matinfo.decode(event.props.item.mat_type, event.props.item.mat_index)).."\n") end end --file:write("\t\t<"..k.."_item_mat_type>"..tostring(event.props.item.mat_type).."\n") --file:write("\t\t<"..k.."_item_mat_index>"..tostring(event.props.item.mat_index).."\n") file:write("\t\t<"..k.."_pile_type>"..tostring(event.props.pile_type).."\n") elseif event:getType() == df.history_event_type.ASSUME_IDENTITY and k == "identity" then if (table.contains(df.global.world.identities.all,v)) then if (df.global.world.identities.all[v].histfig_id == -1) then local thisIdentity = df.global.world.identities.all[v] file:write("\t\t"..thisIdentity.name.first_name.."\n") file:write("\t\t"..(df.global.world.raws.creatures.all[thisIdentity.race].creature_id):lower().."\n") file:write("\t\t"..(df.global.world.raws.creatures.all[thisIdentity.race].caste[thisIdentity.caste].caste_id):lower().."\n") else file:write("\t\t"..df.global.world.identities.all[v].histfig_id.."\n") end end elseif event:getType() == df.history_event_type.MASTERPIECE_CREATED_ARCH_CONSTRUCT and k == "building_type" then file:write("\t\t"..df.building_type[v]:lower().."\n") elseif event:getType() == df.history_event_type.MASTERPIECE_CREATED_ARCH_CONSTRUCT and k == "building_subtype" then if (df.building_type[event.building_type]:lower() == "furnace") then file:write("\t\t"..df.furnace_type[v]:lower().."\n") elseif v > -1 then file:write("\t\t"..tostring(v).."\n") end elseif k == "race" then if v > -1 then file:write("\t\t"..df.global.world.raws.creatures.all[v].name[0].."\n") end elseif k == "caste" then if v > -1 then file:write("\t\t"..(df.global.world.raws.creatures.all[event.race].caste[v].caste_id):lower().."\n") end elseif k == "interaction" and event:getType() == df.history_event_type.HF_DOES_INTERACTION then file:write("\t\t"..df.global.world.raws.interactions[v].str[3].value.."\n") file:write("\t\t"..df.global.world.raws.interactions[v].str[4].value.."\n") elseif k == "interaction" and event:getType() == df.history_event_type.HF_LEARNS_SECRET then file:write("\t\t"..df.global.world.raws.interactions[v].str[2].value.."\n") elseif event:getType() == df.history_event_type.HIST_FIGURE_DIED and k == "weapon" then for detailK,detailV in pairs(v) do if (detailK == "item") then if detailV > -1 then file:write("\t\t<"..detailK..">"..detailV.."\n") local thisItem = df.item.find(detailV) if (thisItem ~= nil) then if (thisItem.flags.artifact == true) then for refk,refv in pairs(thisItem.general_refs) do if (refv:getType() == df.general_ref_type.IS_ARTIFACT) then file:write("\t\t"..refv.artifact_id.."\n") break end end end end end elseif (detailK == "item_type") then if event.weapon.item > -1 then file:write("\t\t<"..detailK..">"..tostring(df.item_type[detailV]):lower().."\n") end elseif (detailK == "item_subtype") then if event.weapon.item > -1 and detailV > -1 then file:write("\t\t<"..detailK..">"..getItemSubTypeName(event.weapon.item_type,detailV).."\n") end elseif (detailK == "mattype") then if (detailV > -1) then file:write("\t\t"..dfhack.matinfo.toString(dfhack.matinfo.decode(event.weapon.mattype, event.weapon.matindex)).."\n") end elseif (detailK == "matindex") then elseif (detailK == "shooter_item") then if detailV > -1 then file:write("\t\t<"..detailK..">"..detailV.."\n") local thisItem = df.item.find(detailV) if thisItem ~= nil then if (thisItem.flags.artifact == true) then for refk,refv in pairs(thisItem.general_refs) do if (refv:getType() == df.general_ref_type.IS_ARTIFACT) then file:write("\t\t"..refv.artifact_id.."\n") break end end end end end elseif (detailK == "shooter_item_type") then if event.weapon.shooter_item > -1 then file:write("\t\t<"..detailK..">"..tostring(df.item_type[detailV]):lower().."\n") end elseif (detailK == "shooter_item_subtype") then if event.weapon.shooter_item > -1 and detailV > -1 then file:write("\t\t<"..detailK..">"..getItemSubTypeName(event.weapon.shooter_item_type,detailV).."\n") end elseif (detailK == "shooter_mattype") then if (detailV > -1) then file:write("\t\t"..dfhack.matinfo.toString(dfhack.matinfo.decode(event.weapon.shooter_mattype, event.weapon.shooter_matindex)).."\n") end elseif (detailK == "shooter_matindex") then --skip elseif detailK == "slayer_race" or detailK == "slayer_caste" then --skip else file:write("\t\t<"..detailK..">"..detailV.."\n") end end elseif event:getType() == df.history_event_type.HIST_FIGURE_DIED and k == "death_cause" then file:write("\t\t<"..k..">"..df.death_type[v]:lower().."\n") elseif event:getType() == df.history_event_type.CHANGE_HF_JOB and (k == "new_job" or k == "old_job") then file:write("\t\t<"..k..">"..df.profession[v]:lower().."\n") elseif event:getType() == df.history_event_type.CHANGE_CREATURE_TYPE and (k == "old_race" or k == "new_race") and v >= 0 then file:write("\t\t<"..k..">"..df.global.world.raws.creatures.all[v].name[0].."\n") else file:write("\t\t<"..k..">"..tostring(v).."\n") end end file:write("\t\n") end end file:write("\n") file:write("\n") file:write("\n") file:write("\n") file:write("\n") file:write("\n") file:close() end -- export information and XML ('p, x') function export_legends_info() print(' Exporting: World map/gen info') gui.simulateInput(vs, 'LEGENDS_EXPORT_MAP') print(' Exporting: Legends xml') gui.simulateInput(vs, 'LEGENDS_EXPORT_XML') print(" Exporting: Extra legends_plus xml") export_more_legends_xml() end --- presses 'd' for detailed maps function wait_for_legends_vs() local vs = dfhack.gui.getCurViewscreen() if i <= #MAPS then if df.viewscreen_legendsst:is_instance(vs.parent) then vs = vs.parent end if df.viewscreen_legendsst:is_instance(vs) then gui.simulateInput(vs, 'LEGENDS_EXPORT_DETAILED_MAP') dfhack.timeout(10,'frames',wait_for_export_maps_vs) else dfhack.timeout(10,'frames',wait_for_legends_vs) end end end -- selects detailed map and export it function wait_for_export_maps_vs() local vs = dfhack.gui.getCurViewscreen() if dfhack.gui.getCurFocus() == "export_graphical_map" then vs.sel_idx = i-1 print(' Exporting: '..MAPS[i]..' map') gui.simulateInput(vs, 'SELECT') i = i + 1 dfhack.timeout(10,'frames',wait_for_legends_vs) else dfhack.timeout(10,'frames',wait_for_export_maps_vs) end end -- export site maps function export_site_maps() local vs = dfhack.gui.getCurViewscreen() if ((dfhack.gui.getCurFocus() ~= "legends" ) and (not table.contains(vs, "main_cursor"))) then -- Using open-legends vs = vs.parent end print(' Exporting: All possible site maps') vs.main_cursor = 1 gui.simulateInput(vs, 'SELECT') for i=1, #vs.sites do gui.simulateInput(vs, 'LEGENDS_EXPORT_MAP') gui.simulateInput(vs, 'STANDARDSCROLL_DOWN') end gui.simulateInput(vs, 'LEAVESCREEN') end -- main() if dfhack.gui.getCurFocus() == "legends" or dfhack.gui.getCurFocus() == "dfhack/lua/legends" then -- either native legends mode, or using the open-legends.lua script if args[1] == "all" then export_legends_info() export_site_maps() wait_for_legends_vs() elseif args[1] == "info" then export_legends_info() elseif args[1] == "custom" then export_more_legends_xml() elseif args[1] == "maps" then wait_for_legends_vs() elseif args[1] == "sites" then export_site_maps() else dfhack.printerr('Valid arguments are "all", "info", "maps" or "sites"') end elseif args[1] == "maps" and dfhack.gui.getCurFocus() == "export_graphical_map" then wait_for_export_maps_vs() else dfhack.printerr('Exportlegends must be run from the main legends view') end