diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index 531d0ba1..ea713fbe 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -123,6 +123,9 @@ + + + diff --git a/FModel/MainWindow.cs b/FModel/MainWindow.cs index 5c573b2e..5a72540b 100644 --- a/FModel/MainWindow.cs +++ b/FModel/MainWindow.cs @@ -1558,7 +1558,68 @@ namespace FModel } } - //TODO: SIMPLIFY + + /// + /// this is the main method that draw the bundle of challenges + /// + /// needed for the DisplayName + /// to parse from this instead of calling MyAsset.GetSerialized() again + /// needed for the LastFolder + /// the bundle image ready to be displayed in pictureBox1 + public Bitmap CreateBundleChallengesIcon(ItemsIdParser theItem, string theParsedJson, string extractedBundlePath) + { + Bitmap bmp = new Bitmap(2500, 10000); + BundleDesign.BundlePath = extractedBundlePath; + BundleDesign.theY = 275; + BundleDesign.toDrawOn = Graphics.FromImage(bmp); + BundleDesign.toDrawOn.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; + BundleDesign.toDrawOn.SmoothingMode = SmoothingMode.HighQuality; + BundleDesign.myItem = theItem; + + ChallengeBundleIdParser bundleParser = ChallengeBundleIdParser.FromJson(theParsedJson).FirstOrDefault(); + BundleInfos.getBundleData(bundleParser); + + BundleDesign.drawBackground(bmp, bundleParser); + + int justSkip = 0; + for (int i = 0; i < BundleInfos.BundleData.Count; i++) + { + AppendText(BundleInfos.BundleData[i].questDescr, Color.SteelBlue); + AppendText("\t\tCount: " + BundleInfos.BundleData[i].questCount, Color.DarkRed); + AppendText("\t\t" + BundleInfos.BundleData[i].rewardItemId + ":" + BundleInfos.BundleData[i].rewardItemQuantity, Color.DarkGreen, true); + + BundleDesign.theY += 140; + justSkip += 1; + + //draw quest description + BundleDesign.toDrawOn.DrawString(BundleInfos.BundleData[i].questDescr, new Font(FontUtilities.pfc.Families[1], 50), new SolidBrush(Color.White), new Point(100, BundleDesign.theY)); + + //draw slider + quest count + Image slider = Resources.Challenges_Slider; + BundleDesign.toDrawOn.DrawImage(slider, new Point(108, BundleDesign.theY + 86)); + BundleDesign.toDrawOn.DrawString(BundleInfos.BundleData[i].questCount.ToString(), new Font(FontUtilities.pfc.Families[0], 20), new SolidBrush(Color.FromArgb(255, 255, 255, 255)), new Point(968, BundleDesign.theY + 87)); + + //draw quest reward + DrawingRewards.getRewards(BundleInfos.BundleData[i].rewardItemId, BundleInfos.BundleData[i].rewardItemQuantity); + + if (justSkip != 1) + { + //draw separator + BundleDesign.toDrawOn.DrawLine(new Pen(Color.FromArgb(30, 255, 255, 255)), 100, BundleDesign.theY - 10, 2410, BundleDesign.theY - 10); + } + } + AppendText("", Color.Black, true); + + //cut if too long and return the bitmap + using (Bitmap bmp2 = bmp) + { + var newImg = bmp2.Clone( + new Rectangle { X = 0, Y = 0, Width = bmp.Width, Height = BundleDesign.theY + 280 }, + bmp2.PixelFormat); + + return newImg; + } + } private void CreateChallengesIcon(ItemsIdParser theItem, string theParsedJson, string questJson = null) { if (theItem.ExportType == "FortChallengeBundleItemDefinition") diff --git a/FModel/Methods/ChallengeGenerator/BundleDesign.cs b/FModel/Methods/ChallengeGenerator/BundleDesign.cs new file mode 100644 index 00000000..93c45248 --- /dev/null +++ b/FModel/Methods/ChallengeGenerator/BundleDesign.cs @@ -0,0 +1,75 @@ +using FModel.Parser.Challenges; +using FModel.Parser.Items; +using FModel.Properties; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Text; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace FModel +{ + static class BundleDesign + { + public static string BundlePath { get; set; } + public static int theY { get; set; } + public static Graphics toDrawOn { get; set; } + public static ItemsIdParser myItem { get; set; } + + /// + /// draw the pretty header if DisplayStyle exist, else the shitty background + /// + /// + /// + public static void drawBackground(Bitmap myBitmap, ChallengeBundleIdParser myBundle) + { + if (Settings.Default.createIconForChallenges && myBundle.DisplayStyle != null) + { + //main header + toDrawOn.FillRectangle(new SolidBrush(BundleInfos.getSecondaryColor(myBundle)), new Rectangle(0, 0, myBitmap.Width, 271)); + + //gradient at left and right main header + LinearGradientBrush linGrBrush_left = new LinearGradientBrush(new Point(0, 282 / 2), new Point(282, 282 / 2), + ControlPaint.Light(BundleInfos.getSecondaryColor(myBundle), (float)0.3), BundleInfos.getSecondaryColor(myBundle)); + toDrawOn.FillRectangle(linGrBrush_left, new Rectangle(0, 0, 282, 282)); + LinearGradientBrush linGrBrush_right = new LinearGradientBrush(new Point(2500, 282 / 2), new Point(1500, 282 / 2), + ControlPaint.Light(BundleInfos.getSecondaryColor(myBundle), (float)0.3), BundleInfos.getSecondaryColor(myBundle)); + toDrawOn.FillRectangle(linGrBrush_right, new Rectangle(1500, 0, 1000, 282)); + + //last folder with border + GraphicsPath p = new GraphicsPath(); + Pen myPen = new Pen(ControlPaint.Light(BundleInfos.getSecondaryColor(myBundle), (float)0.2), 3); + myPen.LineJoin = LineJoin.Round; //needed to avoid spikes + p.AddString(BundleInfos.getLastFolder(BundlePath), FontUtilities.pfc.Families[1], (int)FontStyle.Regular, 55, new Point(342, 40), FontUtilities.leftString); + toDrawOn.DrawPath(myPen, p); + toDrawOn.FillPath(new SolidBrush(ControlPaint.Dark(BundleInfos.getSecondaryColor(myBundle), (float)0.05)), p); + + //name + toDrawOn.DrawString(BundleInfos.getBundleDisplayName(myItem), new Font(FontUtilities.pfc.Families[1], 115), new SolidBrush(Color.White), new Point(325, 70)); + + //image + string textureFile = Path.GetFileName(myBundle.DisplayStyle.DisplayImage.AssetPathName).Substring(0, Path.GetFileName(myBundle.DisplayStyle.DisplayImage.AssetPathName).LastIndexOf('.')); + Image challengeIcon = new Bitmap(JohnWick.AssetToTexture2D(textureFile)); + toDrawOn.DrawImage(ImageUtilities.ResizeImage(challengeIcon, 282, 282), new Point(40, 0)); + + //fill the rest + toDrawOn.FillRectangle(new SolidBrush(ControlPaint.Dark(BundleInfos.getSecondaryColor(myBundle), (float)0.1)), new Rectangle(0, 271, myBitmap.Width, myBitmap.Height)); + } + else + { + toDrawOn.DrawImage(new Bitmap(Resources.Quest), new Point(0, 0)); + + //last folder + toDrawOn.DrawString(BundleInfos.getLastFolder(BundlePath), new Font(FontUtilities.pfc.Families[1], 42), new SolidBrush(Color.FromArgb(255, 149, 213, 255)), new Point(340, 40)); + + //name + toDrawOn.DrawString(BundleInfos.getBundleDisplayName(myItem), new Font(FontUtilities.pfc.Families[1], 115), new SolidBrush(Color.White), new Point(325, 70)); + } + } + } +} diff --git a/FModel/Methods/ChallengeGenerator/BundleInfos.cs b/FModel/Methods/ChallengeGenerator/BundleInfos.cs new file mode 100644 index 00000000..388edb8d --- /dev/null +++ b/FModel/Methods/ChallengeGenerator/BundleInfos.cs @@ -0,0 +1,130 @@ +using csharp_wick; +using FModel.Parser.Challenges; +using FModel.Parser.Items; +using FModel.Parser.Quests; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; + +namespace FModel +{ + static class BundleInfos + { + public static List BundleData { get; set; } + public static Color getSecondaryColor(ChallengeBundleIdParser myBundle) + { + int Red = (int)(myBundle.DisplayStyle.SecondaryColor.R * 255); + int Green = (int)(myBundle.DisplayStyle.SecondaryColor.G * 255); + int Blue = (int)(myBundle.DisplayStyle.SecondaryColor.B * 255); + + if (Red + Green + Blue <= 75 || getLastFolder(BundleDesign.BundlePath) == "LTM") { return getAccentColor(myBundle); } + else { return Color.FromArgb(255, Red, Green, Blue); } + } + public static Color getAccentColor(ChallengeBundleIdParser myBundle) + { + int Red = (int)(myBundle.DisplayStyle.AccentColor.R * 255); + int Green = (int)(myBundle.DisplayStyle.AccentColor.G * 255); + int Blue = (int)(myBundle.DisplayStyle.AccentColor.B * 255); + + return Color.FromArgb(255, Red, Green, Blue); + } + public static string getBundleDisplayName(ItemsIdParser theItem) + { + return theItem.DisplayName.ToUpper(); + } + public static string getLastFolder(string pathToExtractedBundle) + { + string folderAndFileNameWithExtension = pathToExtractedBundle.Substring(pathToExtractedBundle.Substring(0, pathToExtractedBundle.LastIndexOf("\\", StringComparison.Ordinal)).LastIndexOf("\\", StringComparison.Ordinal) + 1).ToUpper(); + return folderAndFileNameWithExtension.Substring(0, folderAndFileNameWithExtension.LastIndexOf("\\", StringComparison.Ordinal)); + } + + /// + /// main method to set the data to get it out of this class + /// extract quests one by one and add description, count, reward item, reward quantity to List BundleData + /// + /// + public static void getBundleData(ChallengeBundleIdParser myBundle) + { + BundleData = new List(); + + for (int i = 0; i < myBundle.QuestInfos.Length; i++) + { + string questName = Path.GetFileName(myBundle.QuestInfos[i].QuestDefinition.AssetPathName); + getQuestData(questName.Substring(0, questName.LastIndexOf("."))); + } + } + private static void getQuestData(string questFile) + { + string questFilePath; + if (ThePak.CurrentUsedPakGuid != null && ThePak.CurrentUsedPakGuid != "0-0-0-0") + { + questFilePath = JohnWick.ExtractAsset(ThePak.CurrentUsedPak, questFile); + } + else + { + questFilePath = JohnWick.ExtractAsset(ThePak.AllpaksDictionary[questFile], questFile); + } + + if (questFilePath != null) + { + if (questFilePath.Contains(".uasset") || questFilePath.Contains(".uexp") || questFilePath.Contains(".ubulk")) + { + JohnWick.MyAsset = new PakAsset(questFilePath.Substring(0, questFilePath.LastIndexOf('.'))); + try + { + if (JohnWick.MyAsset.GetSerialized() != null) + { + QuestParser[] questParser = QuestParser.FromJson(JToken.Parse(JohnWick.MyAsset.GetSerialized()).ToString()); + for (int x = 0; x < questParser.Length; x++) + { + string oldQuest = string.Empty; + long oldCount = 0; + for (int p = 0; p < questParser[x].Objectives.Length; p++) + { + string newQuest = questParser[x].Objectives[p].Description; + long newCount = questParser[x].Objectives[p].Count; + + if (newQuest != oldQuest && newCount != oldCount) + { + if (questParser[x].Rewards != null) + { + try + { + string rewardId = questParser[x].Rewards.Where(item => item.ItemPrimaryAssetId.PrimaryAssetType.Name != "Quest").Where(item => item.ItemPrimaryAssetId.PrimaryAssetType.Name != "Token").FirstOrDefault().ItemPrimaryAssetId.PrimaryAssetName; + string rewardQuantity = questParser[x].Rewards.Where(item => item.ItemPrimaryAssetId.PrimaryAssetType.Name != "Quest").Where(item => item.ItemPrimaryAssetId.PrimaryAssetType.Name != "Token").FirstOrDefault().Quantity.ToString(); + + BundleData.Add(new BundleInfoEntry(newQuest, newCount, rewardId, rewardQuantity)); + } + catch (NullReferenceException) + { + if (questParser[x].HiddenRewards != null) + { + string rewardId = questParser[x].HiddenRewards.FirstOrDefault().TemplateId; + string rewardQuantity = questParser[x].HiddenRewards.FirstOrDefault().Quantity.ToString(); + + BundleData.Add(new BundleInfoEntry(newQuest, newCount, rewardId, rewardQuantity)); + } + } + } + else + { + BundleData.Add(new BundleInfoEntry(newQuest, newCount, "", "")); + } + } + + oldQuest = newQuest; + oldCount = newCount; + } + } + } + } + catch (JsonSerializationException) { } + } + } + } + } +} diff --git a/FModel/Methods/ChallengeGenerator/DrawingRewards.cs b/FModel/Methods/ChallengeGenerator/DrawingRewards.cs new file mode 100644 index 00000000..bbf2485d --- /dev/null +++ b/FModel/Methods/ChallengeGenerator/DrawingRewards.cs @@ -0,0 +1,177 @@ +using csharp_wick; +using FModel.Parser.Items; +using FModel.Properties; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.IO; +using System.Linq; + +namespace FModel +{ + class DrawingRewards + { + public static void getRewards(string itemToExtract, string itemQuantity) + { + if (itemToExtract.Contains(":")) + { + var parts = itemToExtract.Split(':'); + if (parts[0] == "HomebaseBannerIcon") { DrawRewardBanner(parts[1]); } + else { DrawRewardIcon(parts[1]); } + } + else if (string.Equals(itemToExtract, "athenabattlestar", StringComparison.CurrentCultureIgnoreCase)) { drawBattleStar(itemQuantity); } + else if (string.Equals(itemToExtract, "AthenaSeasonalXP", StringComparison.CurrentCultureIgnoreCase)) { drawSeasonalXp(itemQuantity); } + else if (string.Equals(itemToExtract, "MtxGiveaway", StringComparison.CurrentCultureIgnoreCase)) { drawMtxGiveaway(itemQuantity); } + else { DrawRewardIcon(itemToExtract); } + } + public static void DrawRewardIcon(string item) + { + ItemIcon.ItemIconPath = string.Empty; + try + { + var value = ThePak.AllpaksDictionary.Where(x => string.Equals(x.Key, item, StringComparison.CurrentCultureIgnoreCase)).Select(d => d.Key).FirstOrDefault(); + if (value != null) + { + string extractedIconPath = JohnWick.ExtractAsset(ThePak.AllpaksDictionary[value], value); + if (extractedIconPath != null) + { + if (extractedIconPath.Contains(".uasset") || extractedIconPath.Contains(".uexp") || extractedIconPath.Contains(".ubulk")) + { + JohnWick.MyAsset = new PakAsset(extractedIconPath.Substring(0, extractedIconPath.LastIndexOf('.'))); + try + { + if (JohnWick.MyAsset.GetSerialized() != null) + { + var itemId = ItemsIdParser.FromJson(JToken.Parse(JohnWick.MyAsset.GetSerialized()).ToString()); + for (int i = 0; i < itemId.Length; i++) + { + ItemIcon.SearchAthIteDefIcon(itemId[i]); + + if (File.Exists(ItemIcon.ItemIconPath)) + { + Image itemIcon; + using (var bmpTemp = new Bitmap(ItemIcon.ItemIconPath)) + { + itemIcon = new Bitmap(bmpTemp); + } + BundleDesign.toDrawOn.DrawImage(ImageUtilities.ResizeImage(itemIcon, 110, 110), new Point(2300, BundleDesign.theY + 6)); + } + else + { + Image itemIcon = Resources.unknown512; + BundleDesign.toDrawOn.DrawImage(ImageUtilities.ResizeImage(itemIcon, 110, 110), new Point(2300, BundleDesign.theY + 6)); + } + } + } + } + catch (JsonSerializationException) { } + } + } + } + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + public static void DrawRewardBanner(string bannerName) + { + ItemIcon.ItemIconPath = string.Empty; + string extractedBannerPath = JohnWick.ExtractAsset(ThePak.AllpaksDictionary["BannerIcons"], "BannerIcons"); + if (extractedBannerPath != null) + { + if (extractedBannerPath.Contains(".uasset") || extractedBannerPath.Contains(".uexp") || extractedBannerPath.Contains(".ubulk")) + { + JohnWick.MyAsset = new PakAsset(extractedBannerPath.Substring(0, extractedBannerPath.LastIndexOf('.'))); + try + { + if (JohnWick.MyAsset.GetSerialized() != null) + { + string parsedJson = JToken.Parse(JohnWick.MyAsset.GetSerialized()).ToString().TrimStart('[').TrimEnd(']'); + JObject jo = JObject.Parse(parsedJson); + foreach (JToken token in jo.FindTokens(bannerName)) + { + var bannerId = Parser.Banners.BannersParser.FromJson(token.ToString()); + + if (bannerId.LargeImage != null) + { + string textureFile = Path.GetFileName(bannerId.LargeImage.AssetPathName) + ?.Substring(0, + Path.GetFileName(bannerId.LargeImage.AssetPathName).LastIndexOf('.')); + + ItemIcon.ItemIconPath = JohnWick.AssetToTexture2D(textureFile); + } + else if (bannerId.SmallImage != null) + { + string textureFile = Path.GetFileName(bannerId.SmallImage.AssetPathName) + ?.Substring(0, + Path.GetFileName(bannerId.SmallImage.AssetPathName).LastIndexOf('.')); + + ItemIcon.ItemIconPath = JohnWick.AssetToTexture2D(textureFile); + } + + if (File.Exists(ItemIcon.ItemIconPath)) + { + Image itemIcon; + using (var bmpTemp = new Bitmap(ItemIcon.ItemIconPath)) + { + itemIcon = new Bitmap(bmpTemp); + } + BundleDesign.toDrawOn.DrawImage(ImageUtilities.ResizeImage(itemIcon, 110, 110), new Point(2300, BundleDesign.theY + 6)); + } + else + { + Image itemIcon = Resources.unknown512; + BundleDesign.toDrawOn.DrawImage(ImageUtilities.ResizeImage(itemIcon, 110, 110), new Point(2300, BundleDesign.theY + 6)); + } + } + } + } + catch (JsonSerializationException) { } + } + } + } + + private static void drawBattleStar(string quantity) + { + Image rewardIcon = Resources.T_FNBR_BattlePoints_L; + BundleDesign.toDrawOn.DrawImage(ImageUtilities.ResizeImage(rewardIcon, 75, 75), new Point(2325, BundleDesign.theY + 22)); + + GraphicsPath p = new GraphicsPath(); + Pen myPen = new Pen(Color.FromArgb(255, 143, 74, 32), 5); + myPen.LineJoin = LineJoin.Round; //needed to avoid spikes + p.AddString(quantity, FontUtilities.pfc.Families[1], (int)FontStyle.Regular, 60, new Point(2322, BundleDesign.theY + 25), FontUtilities.rightString); + BundleDesign.toDrawOn.DrawPath(myPen, p); + + BundleDesign.toDrawOn.FillPath(new SolidBrush(Color.FromArgb(255, 255, 219, 103)), p); + } + private static void drawSeasonalXp(string quantity) + { + Image rewardIcon = Resources.T_FNBR_SeasonalXP_L; + BundleDesign.toDrawOn.DrawImage(ImageUtilities.ResizeImage(rewardIcon, 75, 75), new Point(2325, BundleDesign.theY + 22)); + + GraphicsPath p = new GraphicsPath(); + Pen myPen = new Pen(Color.FromArgb(255, 81, 131, 15), 5); + myPen.LineJoin = LineJoin.Round; //needed to avoid spikes + p.AddString(quantity, FontUtilities.pfc.Families[1], (int)FontStyle.Regular, 60, new Point(2322, BundleDesign.theY + 25), FontUtilities.rightString); + BundleDesign.toDrawOn.DrawPath(myPen, p); + + BundleDesign.toDrawOn.FillPath(new SolidBrush(Color.FromArgb(255, 230, 253, 177)), p); + } + private static void drawMtxGiveaway(string quantity) + { + Image rewardIcon = Resources.T_Items_MTX_L; + BundleDesign.toDrawOn.DrawImage(ImageUtilities.ResizeImage(rewardIcon, 75, 75), new Point(2325, BundleDesign.theY + 22)); + + GraphicsPath p = new GraphicsPath(); + Pen myPen = new Pen(Color.FromArgb(255, 100, 160, 175), 5); + myPen.LineJoin = LineJoin.Round; //needed to avoid spikes + p.AddString(quantity, FontUtilities.pfc.Families[1], (int)FontStyle.Regular, 60, new Point(2322, BundleDesign.theY + 25), FontUtilities.rightString); + BundleDesign.toDrawOn.DrawPath(myPen, p); + + BundleDesign.toDrawOn.FillPath(new SolidBrush(Color.FromArgb(255, 220, 230, 255)), p); + } + } +} diff --git a/FModel/Methods/Utilities/FontUtilities.cs b/FModel/Methods/Utilities/FontUtilities.cs index 363dcbd5..32aa9038 100644 --- a/FModel/Methods/Utilities/FontUtilities.cs +++ b/FModel/Methods/Utilities/FontUtilities.cs @@ -8,10 +8,11 @@ namespace FModel { static class FontUtilities { - public static PrivateFontCollection pfc = new PrivateFontCollection(); - public static StringFormat centeredString = new StringFormat(); - public static StringFormat rightString = new StringFormat(); - public static StringFormat centeredStringLine = new StringFormat(); + public static readonly PrivateFontCollection pfc = new PrivateFontCollection(); + public static readonly StringFormat centeredString = new StringFormat(); + public static readonly StringFormat rightString = new StringFormat(); + public static readonly StringFormat leftString = new StringFormat(); + public static readonly StringFormat centeredStringLine = new StringFormat(); private static int _fontLength { get; set; } private static byte[] _fontdata { get; set; } @@ -34,6 +35,8 @@ namespace FModel centeredString.Alignment = StringAlignment.Center; rightString.Alignment = StringAlignment.Far; + leftString.Alignment = StringAlignment.Near; + centeredStringLine.LineAlignment = StringAlignment.Center; centeredStringLine.Alignment = StringAlignment.Center; } diff --git a/FModel/Methods/VarApp.cs b/FModel/Methods/VarApp.cs index c6d933a1..cc27f51d 100644 --- a/FModel/Methods/VarApp.cs +++ b/FModel/Methods/VarApp.cs @@ -66,4 +66,18 @@ namespace FModel public static bool UmWorking { get; set; } } + public struct BundleInfoEntry + { + public BundleInfoEntry(string QuestDescription, long QuestCount, string RewardId, string RewardQuantity) + { + questDescr = QuestDescription; + questCount = QuestCount; + rewardItemId = RewardId; + rewardItemQuantity = RewardQuantity; + } + public string questDescr { get; set; } + public long questCount { get; set; } + public string rewardItemId { get; set; } + public string rewardItemQuantity { get; set; } + } }