From 899900e8332c7f0cde0c9bda380b34969eaecc50 Mon Sep 17 00:00:00 2001 From: neru Date: Fri, 19 Jun 2026 04:30:59 -0300 Subject: [PATCH] feat: add perks --- src/dumper/dumper.cs | 44 +++++++++++++++++++++++++++++++++++++++++++- src/dumper/main.cs | 13 +++++++------ 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/dumper/dumper.cs b/src/dumper/dumper.cs index 67e183a..fa423f7 100644 --- a/src/dumper/dumper.cs +++ b/src/dumper/dumper.cs @@ -37,6 +37,14 @@ struct OfferingInfo public EPlayerRole role; } +struct PerkInfo +{ + public string id; + public string name; + public string iconFilePath; + public EPlayerRole role; +} + struct DLCInfo { public string id; @@ -53,6 +61,7 @@ struct CustomizationItemInfo public ECustomizationCategory category; } + struct AddonInfo { public string id { get; set; } @@ -70,9 +79,10 @@ class Dumper private readonly Dictionary _characterMap = new(); private readonly Dictionary _itemMap = new(); + private readonly Dictionary _addonMap = new(); + private readonly Dictionary _perkMap = new(); private readonly Dictionary _offeringMap = new(); private readonly Dictionary _customizationItemMap = new(); - private readonly Dictionary _addonMap = new(); public Dumper(string outDir) { @@ -232,6 +242,37 @@ class Dumper WriteJson("addons", _addonMap.Values); } + public void DumpPerks() + { + ProcessDataTables("/PerkDB.uasset", "perks", (rowKey, props) => + { + if (!TryGetProp(props, "Role", out EPlayerRole role) + || !TryGetProp(props, "UIData", out FStructFallback uiDataFb) + || !TryGetProp(props, "Inventory", out bool isInventory) + || !TryGetProp(props, "IsFakeItem", out bool isFakeItem)) + throw new KeyNotFoundException($"Required properties missing for Perk: {rowKey}"); + + UIDataStruct uiData = uiDataFb.MapToStruct(); + + if (!isInventory || isFakeItem) + return; + + if (uiData.IconAssetList.Length == 0) + throw new InvalidDataException("Perk's UIData had no icons"); + + _perkMap[rowKey] = new PerkInfo + { + id = rowKey, + name = uiData.DisplayName.ToString(), + iconFilePath = uiData.IconAssetList[0].ToString(), + role = role + }; + }); + + _log.Info("Dumped {0} perks", _perkMap.Count); + WriteJson("perks", _perkMap.Values); + } + public void DumpOfferings() { ProcessDataTables("/OfferingDB.uasset", "offerings", (rowKey, props) => @@ -331,6 +372,7 @@ class Dumper public void DumpCharacterIcons() => ExportIcons(_characterMap.Values.Select(x => x.iconFilePath), "character", "/character-icons/"); public void DumpItemIcons() => ExportIcons(_itemMap.Values.Select(x => x.iconFilePath), "item", "/item-icons/"); public void DumpAddonIcons() => ExportIcons(_addonMap.Values.Select(x => x.iconFilePath), "addon", "/addon-icons/"); + public void DumpPerkIcons() => ExportIcons(_perkMap.Values.Select(x => x.iconFilePath), "perk", "/perk-icons/"); public void DumpOfferingIcons() => ExportIcons(_offeringMap.Values.Select(x => x.iconFilePath), "offering", "/offering-icons/"); public void DumpCustomizationIcons() { diff --git a/src/dumper/main.cs b/src/dumper/main.cs index f25af96..ba3f007 100644 --- a/src/dumper/main.cs +++ b/src/dumper/main.cs @@ -12,12 +12,13 @@ if (!hasInitialized) var dumpTasks = new (string Name, Action Execute)[] { - ("character", () => { dumper.DumpCharacters(); dumper.DumpCharacterIcons(); }), - ("item", () => { dumper.DumpItems(); dumper.DumpItemIcons(); }), - ("addon", () => { dumper.DumpAddons(); dumper.DumpAddonIcons(); }), - ("offering", () => { dumper.DumpOfferings(); dumper.DumpOfferingIcons(); }), - ("customization", () => { dumper.DumpCustomizations(); dumper.DumpCustomizationIcons(); }), - ("dlc", () => { dumper.DumpDLCs(); }) + //("character", () => { dumper.DumpCharacters(); dumper.DumpCharacterIcons(); }), + //("item", () => { dumper.DumpItems(); dumper.DumpItemIcons(); }), + //("addon", () => { dumper.DumpAddons(); dumper.DumpAddonIcons(); }), + ("perk", () => { dumper.DumpPerks(); dumper.DumpPerkIcons(); }), + //("offering", () => { dumper.DumpOfferings(); dumper.DumpOfferingIcons(); }), + //("customization", () => { dumper.DumpCustomizations(); dumper.DumpCustomizationIcons(); }), + //("dlc", () => { dumper.DumpDLCs(); }) }; foreach (var task in dumpTasks)