From 6f5e1260e313bd234018f572340bea21c2e9bffe Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 30 Apr 2016 14:59:04 -0400 Subject: [PATCH] exportlegends: wrap enum lookups to avoid errors or writing "nil" to xml files Any unidentified enum items should now be represented as "unknown X" Fixes an issue with occasion_schedule_type 8, and probably many others --- scripts/exportlegends.lua | 83 ++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/scripts/exportlegends.lua b/scripts/exportlegends.lua index 537feacb8..86542f930 100644 --- a/scripts/exportlegends.lua +++ b/scripts/exportlegends.lua @@ -84,6 +84,25 @@ function table.containskey(table, key) return false end +-- wrapper that returns "unknown N" for df.enum_type[BAD_VALUE], +-- instead of returning nil or causing an error +df_enums = {} +setmetatable(df_enums, { + __index = function(self, enum) + if not df[enum] or df[enum]._kind ~= 'enum-type' then + error('invalid enum: ' .. enum) + end + local t = {} + setmetatable(t, { + __index = function(self, k) + return df[enum][k] or 'unknown ' .. k + end + }) + return t + end, + __newindex = function() error('read-only') 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 @@ -160,8 +179,8 @@ function export_more_legends_xml() 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"..df_enums.abstract_building_type[buildingV:getType()]:lower().."\n") + if (df_enums.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 @@ -190,7 +209,7 @@ function export_more_legends_xml() 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"..(df_enums.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].."|") @@ -205,7 +224,7 @@ function export_more_legends_xml() 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") + file:write("\t\t"..tostring(df_enums.item_type[artifactV.item:getType()]):lower().."\n") if (artifactV.item:getSubtype() ~= -1) then file:write("\t\t"..artifactV.item.subtype.name.."\n") end @@ -262,7 +281,7 @@ function export_more_legends_xml() 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") + file:write("\t\t"..(df_enums.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 @@ -274,7 +293,7 @@ function export_more_legends_xml() 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") + file:write("\t\t\t<"..k..">"..tostring(df_enums.entity_entity_link_type[v]).."\n") else file:write("\t\t\t<"..k..">"..v.."\n") end @@ -321,9 +340,9 @@ function export_more_legends_xml() 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") + file:write("\t\t\t\t"..df_enums.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"..df_enums.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") @@ -331,8 +350,8 @@ function export_more_legends_xml() 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") + if(df_enums.occasion_schedule_feature[featureV.feature] ~= nil) then + file:write("\t\t\t\t\t"..df_enums.occasion_schedule_feature[featureV.feature]:lower().."\n") else file:write("\t\t\t\t\t"..featureV.feature.."\n") end @@ -384,7 +403,7 @@ function export_more_legends_xml() 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") + file:write("\t\t\t"..df_enums.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 @@ -400,14 +419,14 @@ function export_more_legends_xml() 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()]) + print("unknown reference",refV:getType(),df_enums.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") + file:write("\t\t"..(df_enums.written_content_type[wcV.type] or wcV.type).."\n") for styleK, styleV in pairs(wcV.styles) do - file:write("\t\t\n") + file:write("\t\t\n") end file:write("\t\t"..wcV.author.."\n") file:write("\t\n") @@ -459,7 +478,7 @@ function export_more_legends_xml() 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") + file:write("\t\t"..tostring(df_enums.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) @@ -467,7 +486,7 @@ function export_more_legends_xml() 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") + file:write("\t\t<"..k..">"..df_enums.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 @@ -493,7 +512,7 @@ function export_more_legends_xml() 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") + file:write("\t\t<"..k..">"..df_enums.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 @@ -507,17 +526,17 @@ function export_more_legends_xml() 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") + file:write("\t\t"..df_enums.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") + file:write("\t\t"..df_enums.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") + file:write("\t\t"..df_enums.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") + file:write("\t\t"..df_enums.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 @@ -588,9 +607,9 @@ function export_more_legends_xml() 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") + file:write("\t\t"..tostring(df_enums.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") + file:write("\t\t"..df_enums.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 @@ -602,8 +621,8 @@ function export_more_legends_xml() 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") + file:write("\t\t"..tostring(df_enums.item_type[event.props.item.item_type]):lower().."\n") + file:write("\t\t"..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") @@ -627,10 +646,10 @@ function export_more_legends_xml() 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") + file:write("\t\t"..df_enums.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") + if (df_enums.building_type[event.building_type]:lower() == "furnace") then + file:write("\t\t"..df_enums.furnace_type[v]:lower().."\n") elseif v > -1 then file:write("\t\t"..tostring(v).."\n") end @@ -667,7 +686,7 @@ function export_more_legends_xml() end elseif (detailK == "item_type") then if event.weapon.item > -1 then - file:write("\t\t<"..detailK..">"..tostring(df.item_type[detailV]):lower().."\n") + file:write("\t\t<"..detailK..">"..tostring(df_enums.item_type[detailV]):lower().."\n") end elseif (detailK == "item_subtype") then if event.weapon.item > -1 and detailV > -1 then @@ -696,7 +715,7 @@ function export_more_legends_xml() 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") + file:write("\t\t<"..detailK..">"..tostring(df_enums.item_type[detailV]):lower().."\n") end elseif (detailK == "shooter_item_subtype") then if event.weapon.shooter_item > -1 and detailV > -1 then @@ -715,9 +734,9 @@ function export_more_legends_xml() 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") + file:write("\t\t<"..k..">"..df_enums.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") + file:write("\t\t<"..k..">"..df_enums.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