diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj
index 81d4f03a..d4103fc2 100644
--- a/FModel/FModel.csproj
+++ b/FModel/FModel.csproj
@@ -106,7 +106,9 @@
PAKWindow.cs
+
+
diff --git a/FModel/PAKWindow.Designer.cs b/FModel/PAKWindow.Designer.cs
index 2be38bc2..90fe0ff5 100644
--- a/FModel/PAKWindow.Designer.cs
+++ b/FModel/PAKWindow.Designer.cs
@@ -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 = "";
//
diff --git a/FModel/PAKWindow.cs b/FModel/PAKWindow.cs
index 4777af6d..6509092b 100644
--- a/FModel/PAKWindow.cs
+++ b/FModel/PAKWindow.cs
@@ -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 afterItems;
public static string[] SelectedArray;
+ public static string[] challengesArray;
+ public static Dictionary 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();
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);
diff --git a/FModel/PAKWindow.resx b/FModel/PAKWindow.resx
index 42097a9b..5ebce2b5 100644
--- a/FModel/PAKWindow.resx
+++ b/FModel/PAKWindow.resx
@@ -131,7 +131,7 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACc
- BwAAAk1TRnQBSQFMAgEBAgEAATgBAAE4AQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
+ BwAAAk1TRnQBSQFMAgEBAgEAAUABAAFAAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
diff --git a/FModel/Parser/ChallengeBundleIdParser.cs b/FModel/Parser/ChallengeBundleIdParser.cs
new file mode 100644
index 00000000..643a5639
--- /dev/null
+++ b/FModel/Parser/ChallengeBundleIdParser.cs
@@ -0,0 +1,157 @@
+//
+//
+// 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(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 }
+ },
+ };
+ }
+}
diff --git a/FModel/Parser/ItemsIDParser.cs b/FModel/Parser/ItemsIDParser.cs
index 0f124617..b9f73ddc 100644
--- a/FModel/Parser/ItemsIDParser.cs
+++ b/FModel/Parser/ItemsIDParser.cs
@@ -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(json, FModel.Converter.Settings);
+ public static ItemsIdParser[] FromJson(string json) => JsonConvert.DeserializeObject(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
diff --git a/FModel/Parser/QuestParser.cs b/FModel/Parser/QuestParser.cs
new file mode 100644
index 00000000..5666ddfb
--- /dev/null
+++ b/FModel/Parser/QuestParser.cs
@@ -0,0 +1,199 @@
+//
+//
+// 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(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 }
+ },
+ };
+ }
+}
diff --git a/README.md b/README.md
index 73bd888a..d96c3f93 100644
--- a/README.md
+++ b/README.md
@@ -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.
-
+
**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