added challenges bundle viewer [WIP]

This commit is contained in:
AsvalGTA 2019-03-18 22:00:42 +01:00
parent 0f1c328adf
commit ce967290ef
8 changed files with 519 additions and 17 deletions

View File

@ -106,7 +106,9 @@
<Compile Include="PAKWindow.Designer.cs">
<DependentUpon>PAKWindow.cs</DependentUpon>
</Compile>
<Compile Include="Parser\ChallengeBundleIdParser.cs" />
<Compile Include="Parser\ItemsIDParser.cs" />
<Compile Include="Parser\QuestParser.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Custom\SplitButtonControl.cs">

View File

@ -94,12 +94,12 @@
this.LoadContext.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.optionsToolStripMenuItem});
this.LoadContext.Name = "LoadContext";
this.LoadContext.Size = new System.Drawing.Size(128, 28);
this.LoadContext.Size = new System.Drawing.Size(117, 26);
//
// optionsToolStripMenuItem
//
this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem";
this.optionsToolStripMenuItem.Size = new System.Drawing.Size(127, 24);
this.optionsToolStripMenuItem.Size = new System.Drawing.Size(116, 22);
this.optionsToolStripMenuItem.Text = "Options";
this.optionsToolStripMenuItem.Click += new System.EventHandler(this.optionsToolStripMenuItem_Click);
//
@ -209,13 +209,13 @@
this.ImageContext.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.OpenImageTS});
this.ImageContext.Name = "ImageContext";
this.ImageContext.Size = new System.Drawing.Size(155, 28);
this.ImageContext.Size = new System.Drawing.Size(140, 26);
//
// OpenImageTS
//
this.OpenImageTS.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
this.OpenImageTS.Name = "OpenImageTS";
this.OpenImageTS.Size = new System.Drawing.Size(154, 24);
this.OpenImageTS.Size = new System.Drawing.Size(139, 22);
this.OpenImageTS.Text = "Open Image";
this.OpenImageTS.Click += new System.EventHandler(this.OpenImageTS_Click);
//
@ -240,7 +240,7 @@
this.toolStripSeparator1,
this.mergeGeneratedImagesToolStripMenuItem});
this.ExtractAsset.Name = "ExtractAsset";
this.ExtractAsset.Size = new System.Drawing.Size(252, 82);
this.ExtractAsset.Size = new System.Drawing.Size(223, 76);
//
// LoadDataTS
//
@ -250,7 +250,7 @@
this.LoadDataTS.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
this.LoadDataTS.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.LoadDataTS.Name = "LoadDataTS";
this.LoadDataTS.Size = new System.Drawing.Size(251, 24);
this.LoadDataTS.Size = new System.Drawing.Size(222, 22);
this.LoadDataTS.Text = "Load Data After Serialization";
//
// SaveImageTS
@ -258,18 +258,18 @@
this.SaveImageTS.CheckOnClick = true;
this.SaveImageTS.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
this.SaveImageTS.Name = "SaveImageTS";
this.SaveImageTS.Size = new System.Drawing.Size(251, 24);
this.SaveImageTS.Size = new System.Drawing.Size(222, 22);
this.SaveImageTS.Text = "Auto Save Generated Image";
//
// toolStripSeparator1
//
this.toolStripSeparator1.Name = "toolStripSeparator1";
this.toolStripSeparator1.Size = new System.Drawing.Size(248, 6);
this.toolStripSeparator1.Size = new System.Drawing.Size(219, 6);
//
// mergeGeneratedImagesToolStripMenuItem
//
this.mergeGeneratedImagesToolStripMenuItem.Name = "mergeGeneratedImagesToolStripMenuItem";
this.mergeGeneratedImagesToolStripMenuItem.Size = new System.Drawing.Size(251, 24);
this.mergeGeneratedImagesToolStripMenuItem.Size = new System.Drawing.Size(222, 22);
this.mergeGeneratedImagesToolStripMenuItem.Text = "Merge Generated Images";
this.mergeGeneratedImagesToolStripMenuItem.Click += new System.EventHandler(this.mergeGeneratedImagesToolStripMenuItem_Click);
//
@ -279,7 +279,7 @@
this.ConsoleRichTextBox.Location = new System.Drawing.Point(6, 374);
this.ConsoleRichTextBox.Name = "ConsoleRichTextBox";
this.ConsoleRichTextBox.ReadOnly = true;
this.ConsoleRichTextBox.Size = new System.Drawing.Size(922, 229);
this.ConsoleRichTextBox.Size = new System.Drawing.Size(922, 255);
this.ConsoleRichTextBox.TabIndex = 6;
this.ConsoleRichTextBox.Text = "";
//

View File

@ -1,4 +1,7 @@
using Newtonsoft.Json;
using FModel.Items;
using FModel.Challenges;
using FModel.Quest;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
@ -15,6 +18,7 @@ using System.Net;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace FModel
{
@ -25,6 +29,8 @@ namespace FModel
private static string ItemName;
private static List<string> afterItems;
public static string[] SelectedArray;
public static string[] challengesArray;
public static Dictionary<string, long> questStageDict;
PrivateFontCollection pfc = new PrivateFontCollection();
StringFormat centeredString = new StringFormat();
@ -644,6 +650,63 @@ namespace FModel
}
}
private void loopStageQuest(string qAssetType, string qAssetName)
{
if (qAssetType == "Quest")
{
var filesPath = Directory.GetFiles(docPath + "\\Extracted", qAssetName + ".*", SearchOption.AllDirectories).Where(x => !x.EndsWith(".png")).FirstOrDefault();
if (!File.Exists(filesPath))
{
jwpmProcess("extract \"" + Properties.Settings.Default.FortnitePAKs + "\\" + currentPAK + "\" \"" + qAssetName + "\" \"" + docPath + "\"");
filesPath = Directory.GetFiles(docPath + "\\Extracted", qAssetName + ".*", SearchOption.AllDirectories).Where(x => !x.EndsWith(".png")).FirstOrDefault();
}
try
{
if (filesPath != null)
{
jwpmProcess("serialize \"" + filesPath.Substring(0, filesPath.LastIndexOf('.')) + "\"");
var filesJSON3 = Directory.GetFiles(docPath, qAssetName + ".json", SearchOption.AllDirectories).FirstOrDefault();
if (filesJSON3 != null)
{
var json3 = JToken.Parse(File.ReadAllText(filesJSON3)).ToString();
File.Delete(filesJSON3);
var questParser2 = QuestParser.FromJson(json3);
for (int p2 = 0; p2 < questParser2.Length; p2++)
{
for (int pp = 0; pp < questParser2[p2].Objectives.Length; pp++)
{
if (!questStageDict.ContainsKey(questParser2[p2].Objectives[pp].Description)) //AVOID DUPLICATA, THANKS EPIC...
{
questStageDict.Add(questParser2[p2].Objectives[pp].Description, questParser2[p2].Objectives[pp].Count);
AppendText(questParser2[p2].Objectives[pp].Description, Color.SteelBlue);
AppendText("\t\tCount: " + questParser2[p2].Objectives[pp].Count, Color.DarkRed, true);
}
for (int ppp = 0; ppp < questParser2[p2].Rewards.Length; ppp++)
{
loopStageQuest(questParser2[p2].Rewards[ppp].ItemPrimaryAssetId.PrimaryAssetType.Name, questParser2[p2].Rewards[ppp].ItemPrimaryAssetId.PrimaryAssetName);
}
}
}
}
else
{
AppendText("✗ ", Color.Red);
AppendText("No serialized file found", Color.Black, true);
}
}
}
catch (IndexOutOfRangeException)
{
AppendText("[IndexOutOfRangeException] ", Color.Red);
AppendText("Can't extract ", Color.Black);
AppendText(qAssetName, Color.SteelBlue);
AppendText(" in ", Color.Black);
AppendText(PAKsComboBox.SelectedItem.ToString(), Color.DarkRed, true);
}
}
}
public static string currentItem;
private async void ExtractAssetButton_Click(object sender, EventArgs e)
{
@ -652,6 +715,7 @@ namespace FModel
scintilla1.Text = "";
ItemIconPictureBox.Image = null;
questStageDict = new Dictionary<string, long>();
if (!Directory.Exists(docPath + "\\Extracted\\")) //Create Extracted Subfolder
Directory.CreateDirectory(docPath + "\\Extracted\\");
@ -1911,6 +1975,83 @@ namespace FModel
}
for (int ii = 0; ii < IDParser.Length; ii++)
{
if (IDParser[ii].ExportType == "FortChallengeBundleItemDefinition")
{
var ChallengeParser = ChallengeBundleIdParser.FromJson(json);
AppendText("Parsing...Please wait while extracting all challenges\n", Color.Black, true);
for (int iii = 0; iii < ChallengeParser.Length; iii++)
{
challengesArray = new string[ChallengeParser[iii].QuestInfos.Length];
for (int y = 0; y < ChallengeParser[iii].QuestInfos.Length; y++)
{
string cName = Path.GetFileName(ChallengeParser[iii].QuestInfos[y].QuestDefinition.AssetPathName);
challengesArray[y] = cName.Substring(cName.LastIndexOf('.') + 1);
}
for (int w = 0; w < challengesArray.Length; w++)
{
var filesPath = Directory.GetFiles(docPath + "\\Extracted", challengesArray[w] + ".*", SearchOption.AllDirectories).Where(x => !x.EndsWith(".png")).FirstOrDefault();
if (!File.Exists(filesPath))
{
await Task.Run(() =>
{
jwpmProcess("extract \"" + Properties.Settings.Default.FortnitePAKs + "\\" + currentPAK + "\" \"" + challengesArray[w] + "\" \"" + docPath + "\"");
});
filesPath = Directory.GetFiles(docPath + "\\Extracted", challengesArray[w] + ".*", SearchOption.AllDirectories).Where(x => !x.EndsWith(".png")).FirstOrDefault();
}
try
{
if (filesPath != null)
{
await Task.Run(() =>
{
jwpmProcess("serialize \"" + filesPath.Substring(0, filesPath.LastIndexOf('.')) + "\"");
});
var filesJSON2 = Directory.GetFiles(docPath, challengesArray[w] + ".json", SearchOption.AllDirectories).FirstOrDefault();
if (filesJSON2 != null)
{
var json2 = JToken.Parse(File.ReadAllText(filesJSON2)).ToString();
File.Delete(filesJSON2);
var questParser = QuestParser.FromJson(json2);
for (int p = 0; p < questParser.Length; p++)
{
string oldQuest = null;
for (int pp = 0; pp < questParser[p].Objectives.Length; pp++)
{
string newQuest = questParser[p].Objectives[pp].Description;
if (newQuest != oldQuest)
{
AppendText(questParser[p].Objectives[pp].Description, Color.SteelBlue);
AppendText("\t\tCount: " + questParser[p].Objectives[pp].Count, Color.DarkRed, true);
oldQuest = questParser[p].Objectives[pp].Description;
}
for (int ppp = 0; ppp < questParser[p].Rewards.Length; ppp++)
{
loopStageQuest(questParser[p].Rewards[ppp].ItemPrimaryAssetId.PrimaryAssetType.Name, questParser[p].Rewards[ppp].ItemPrimaryAssetId.PrimaryAssetName);
}
}
}
}
else
{
AppendText("✗ ", Color.Red);
AppendText("No serialized file found", Color.Black, true);
}
}
}
catch (IndexOutOfRangeException)
{
AppendText("[IndexOutOfRangeException] ", Color.Red);
AppendText("Can't extract ", Color.Black);
AppendText(challengesArray[w], Color.SteelBlue);
AppendText(" in ", Color.Black);
AppendText(PAKsComboBox.SelectedItem.ToString(), Color.DarkRed, true);
}
}
}
} //ASSET IS A CHALLENGE =>
if (IDParser[ii].ExportType == "Texture2D")
{
AppendText("Parsing...", Color.Black, true);

View File

@ -131,7 +131,7 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACc
BwAAAk1TRnQBSQFMAgEBAgEAATgBAAE4AQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
BwAAAk1TRnQBSQFMAgEBAgEAAUABAAFAAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA

View File

@ -0,0 +1,157 @@
// <auto-generated />
//
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
// using FModel;
//
// var challengeBundleIdParser = ChallengeBundleIdParser.FromJson(jsonString);
namespace FModel.Challenges
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public partial class ChallengeBundleIdParser
{
[JsonProperty("export_type")]
public string ExportType { get; set; }
[JsonProperty("QuestInfos")]
public QuestInfo[] QuestInfos { get; set; }
[JsonProperty("BundleCompletionRewards")]
public BundleCompletionReward[] BundleCompletionRewards { get; set; }
[JsonProperty("DisplayStyle")]
public DisplayStyle DisplayStyle { get; set; }
[JsonProperty("DisplayName")]
public string DisplayName { get; set; }
[JsonProperty("SmallPreviewImage")]
public LargePreviewImage SmallPreviewImage { get; set; }
[JsonProperty("LargePreviewImage")]
public LargePreviewImage LargePreviewImage { get; set; }
}
public partial class BundleCompletionReward
{
[JsonProperty("CompletionCount")]
public long CompletionCount { get; set; }
[JsonProperty("Rewards")]
public Reward[] Rewards { get; set; }
}
public partial class Reward
{
[JsonProperty("ItemDefinition")]
public LargePreviewImage ItemDefinition { get; set; }
[JsonProperty("TemplateId")]
public string TemplateId { get; set; }
[JsonProperty("Quantity")]
public long Quantity { get; set; }
[JsonProperty("RewardGiftBox")]
public RewardGiftBox RewardGiftBox { get; set; }
[JsonProperty("IsChaseReward")]
public bool IsChaseReward { get; set; }
[JsonProperty("RewardType")]
public string RewardType { get; set; }
}
public partial class LargePreviewImage
{
[JsonProperty("asset_path_name")]
public string AssetPathName { get; set; }
[JsonProperty("sub_path_string")]
public string SubPathString { get; set; }
}
public partial class RewardGiftBox
{
[JsonProperty("GiftBoxToUse")]
public LargePreviewImage GiftBoxToUse { get; set; }
[JsonProperty("GiftBoxFormatData")]
public object[] GiftBoxFormatData { get; set; }
}
public partial class DisplayStyle
{
[JsonProperty("PrimaryColor")]
public ColorChallenge PrimaryColor { get; set; }
[JsonProperty("SecondaryColor")]
public ColorChallenge SecondaryColor { get; set; }
[JsonProperty("AccentColor")]
public ColorChallenge AccentColor { get; set; }
[JsonProperty("DisplayImage")]
public LargePreviewImage DisplayImage { get; set; }
}
public partial class ColorChallenge
{
[JsonProperty("r")]
public double R { get; set; }
[JsonProperty("g")]
public double G { get; set; }
[JsonProperty("b")]
public double B { get; set; }
[JsonProperty("a")]
public long A { get; set; }
}
public partial class QuestInfo
{
[JsonProperty("QuestDefinition")]
public LargePreviewImage QuestDefinition { get; set; }
[JsonProperty("QuestUnlockType")]
public string QuestUnlockType { get; set; }
[JsonProperty("UnlockValue")]
public long UnlockValue { get; set; }
[JsonProperty("RewardGiftBox")]
public RewardGiftBox RewardGiftBox { get; set; }
}
public partial class ChallengeBundleIdParser
{
public static ChallengeBundleIdParser[] FromJson(string json) => JsonConvert.DeserializeObject<ChallengeBundleIdParser[]>(json, FModel.Challenges.Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this ChallengeBundleIdParser[] self) => JsonConvert.SerializeObject(self, FModel.Challenges.Converter.Settings);
}
internal static class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
}
}

View File

@ -6,7 +6,7 @@
//
// var itemsIdParser = ItemsIdParser.FromJson(jsonString);
namespace FModel
namespace FModel.Items
{
using System;
using System.Collections.Generic;
@ -71,12 +71,12 @@ namespace FModel
public partial class ItemsIdParser
{
public static ItemsIdParser[] FromJson(string json) => JsonConvert.DeserializeObject<ItemsIdParser[]>(json, FModel.Converter.Settings);
public static ItemsIdParser[] FromJson(string json) => JsonConvert.DeserializeObject<ItemsIdParser[]>(json, FModel.Items.Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this ItemsIdParser[] self) => JsonConvert.SerializeObject(self, FModel.Converter.Settings);
public static string ToJson(this ItemsIdParser[] self) => JsonConvert.SerializeObject(self, FModel.Items.Converter.Settings);
}
internal static class Converter

View File

@ -0,0 +1,199 @@
// <auto-generated />
//
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
// using FModel.Quest;
//
// var questParser = QuestParser.FromJson(jsonString);
namespace FModel.Quest
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public partial class QuestParser
{
[JsonProperty("export_type")]
public string ExportType { get; set; }
[JsonProperty("QuestType")]
public string QuestType { get; set; }
[JsonProperty("bIncludedInCategories")]
public bool BIncludedInCategories { get; set; }
[JsonProperty("Rewards")]
public Reward[] Rewards { get; set; }
[JsonProperty("Objectives")]
public Objective[] Objectives { get; set; }
[JsonProperty("CompletionText")]
public string CompletionText { get; set; }
[JsonProperty("GrantToProfileType")]
public string GrantToProfileType { get; set; }
[JsonProperty("DisplayName")]
public string DisplayName { get; set; }
[JsonProperty("Description")]
public string Description { get; set; }
[JsonProperty("GameplayTags")]
public GameplayTags GameplayTags { get; set; }
[JsonProperty("SmallPreviewImage")]
public LargePreviewImage SmallPreviewImage { get; set; }
[JsonProperty("LargePreviewImage")]
public LargePreviewImage LargePreviewImage { get; set; }
}
public partial class GameplayTags
{
[JsonProperty("gameplay_tags")]
public string[] GameplayTagsGameplayTags { get; set; }
}
public partial class LargePreviewImage
{
[JsonProperty("asset_path_name")]
public string AssetPathName { get; set; }
[JsonProperty("sub_path_string")]
public string SubPathString { get; set; }
}
public partial class Objective
{
[JsonProperty("BackendName")]
public string BackendName { get; set; }
[JsonProperty("ObjectiveStatHandle")]
public ObjectiveStatHandle ObjectiveStatHandle { get; set; }
[JsonProperty("AlternativeStatHandles")]
public object[] AlternativeStatHandles { get; set; }
[JsonProperty("ItemEvent")]
public string ItemEvent { get; set; }
[JsonProperty("bHidden")]
public bool BHidden { get; set; }
[JsonProperty("bRequirePrimaryMissionCompletion")]
public bool BRequirePrimaryMissionCompletion { get; set; }
[JsonProperty("bCanProgressInZone")]
public bool BCanProgressInZone { get; set; }
[JsonProperty("bDisplayDynamicAnnouncementUpdate")]
public bool BDisplayDynamicAnnouncementUpdate { get; set; }
[JsonProperty("DynamicStatusUpdateType")]
public string DynamicStatusUpdateType { get; set; }
[JsonProperty("LinkVaultTab")]
public string LinkVaultTab { get; set; }
[JsonProperty("LinkToItemManagement")]
public string LinkToItemManagement { get; set; }
[JsonProperty("ItemReference")]
public LargePreviewImage ItemReference { get; set; }
[JsonProperty("ItemTemplateIdOverride")]
public string ItemTemplateIdOverride { get; set; }
[JsonProperty("LinkSquadID")]
public string LinkSquadId { get; set; }
[JsonProperty("LinkSquadIndex")]
public long LinkSquadIndex { get; set; }
[JsonProperty("Description")]
public string Description { get; set; }
[JsonProperty("HudShortDescription")]
public string HudShortDescription { get; set; }
[JsonProperty("HudIcon")]
public LargePreviewImage HudIcon { get; set; }
[JsonProperty("Count")]
public long Count { get; set; }
[JsonProperty("Stage")]
public long Stage { get; set; }
[JsonProperty("DynamicStatusUpdatePercentInterval")]
public long DynamicStatusUpdatePercentInterval { get; set; }
[JsonProperty("DynamicUpdateCompletionDelay")]
public long DynamicUpdateCompletionDelay { get; set; }
[JsonProperty("ScriptedAction")]
public LargePreviewImage ScriptedAction { get; set; }
}
public partial class ObjectiveStatHandle
{
[JsonProperty("DataTable")]
public string DataTable { get; set; }
[JsonProperty("RowName")]
public string RowName { get; set; }
}
public partial class Reward
{
[JsonProperty("ItemPrimaryAssetId")]
public ItemPrimaryAssetId ItemPrimaryAssetId { get; set; }
[JsonProperty("Quantity")]
public long Quantity { get; set; }
}
public partial class ItemPrimaryAssetId
{
[JsonProperty("PrimaryAssetType")]
public PrimaryAssetType PrimaryAssetType { get; set; }
[JsonProperty("PrimaryAssetName")]
public string PrimaryAssetName { get; set; }
}
public partial class PrimaryAssetType
{
[JsonProperty("Name")]
public string Name { get; set; }
}
public partial class QuestParser
{
public static QuestParser[] FromJson(string json) => JsonConvert.DeserializeObject<QuestParser[]>(json, FModel.Quest.Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this QuestParser[] self) => JsonConvert.SerializeObject(self, FModel.Quest.Converter.Settings);
}
internal static class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
}
}

View File

@ -14,7 +14,7 @@
[.NET Framework 4.6.1](https://dotnet.microsoft.com/download/dotnet-framework-runtime/net461)
### How does it works
**1.** Once you start the executable, you'll be asked to set your path to your Fortnite .PAK files. Meanwhile a `FModel` subfolder will be created in your `Documents` folder and it'll automatically download the latest version of the modded Fortnite Asset Parser in this subfolder.
![](https://i.imgur.com/oaceS8K.gif)
![](https://i.imgur.com/sO6G6Vy.gif)
**2.** Restart the executable, select your .PAK file, enter the AES key and click **Load**
- It will parse all Assets contained in the selected .PAK file with their respective path
@ -28,6 +28,8 @@
- Try to display the Asset as PNG
- Asset is a **_Sound_**:
- Try to convert the Asset to OGG and play the sound
- Asset is a **_Bundle Of Challenges_**:
- Will display all challenges' description & count needed to complete them
- Asset is a **_Font_**:
- Try to convert the Asset to OTF
@ -45,8 +47,9 @@ I'd highly suggest you to use [UModel](https://github.com/gildor2/UModel) instea
## TODO
- [ ] Improve speed
- [x] Multithreading
- [x] Multithreading - Need improvements
- [x] Filter for the items ListBox
- [x] Quest viewer or something
- [ ] More settings
- [ ] Stop button while extracting
- [ ] Support for meshes