diff --git a/FModel/Creator/Bases/FN/BaseBundle.cs b/FModel/Creator/Bases/FN/BaseBundle.cs index ea85a775..90c9de2b 100644 --- a/FModel/Creator/Bases/FN/BaseBundle.cs +++ b/FModel/Creator/Bases/FN/BaseBundle.cs @@ -59,7 +59,7 @@ public class BaseBundle : UCreator foreach (var reward in rewards) { if (!reward.TryGetValue(out FSoftObjectPath itemDefinition, "ItemDefinition")) continue; - quest.AddCompletionRequest(itemDefinition); + quest.AddCompletionReward(itemDefinition); } _quests.Add(quest); } diff --git a/FModel/Creator/Bases/FN/BaseCommunity.cs b/FModel/Creator/Bases/FN/BaseCommunity.cs index 8ac06a9d..2492426d 100644 --- a/FModel/Creator/Bases/FN/BaseCommunity.cs +++ b/FModel/Creator/Bases/FN/BaseCommunity.cs @@ -124,7 +124,14 @@ public class BaseCommunity : BaseIcon if (!bShort) return base.GetCosmeticSeason(seasonNumber); var s = seasonNumber["Cosmetics.Filter.Season.".Length..]; (int chapterIdx, int seasonIdx) = GetInternalSID(int.Parse(s)); - return $"C{chapterIdx} S{seasonIdx}"; + return s switch + { + "10" => $"C{chapterIdx} SX", + "27" => $"Fortnite: OG", + "32" => $"Fortnite: Remix", + "35" => $"C{chapterIdx} MS1", + _ => $"C{chapterIdx} S{seasonIdx}" + }; } private new void DrawBackground(SKCanvas c) diff --git a/FModel/Creator/Bases/FN/BaseIcon.cs b/FModel/Creator/Bases/FN/BaseIcon.cs index fc2fc211..e131f358 100644 --- a/FModel/Creator/Bases/FN/BaseIcon.cs +++ b/FModel/Creator/Bases/FN/BaseIcon.cs @@ -257,12 +257,19 @@ public class BaseIcon : UCreator var season = Utils.GetLocalizedResource("AthenaSeasonItemDefinitionInternal", "SeasonTextFormat", "Season {0}"); var introduced = Utils.GetLocalizedResource("Fort.Cosmetics", "CosmeticItemDescription_Season", "\nIntroduced in {0}."); + if (s == "10") return Utils.RemoveHtmlTags(string.Format(introduced, string.Format(season, "X"))); if (initial <= 10) return Utils.RemoveHtmlTags(string.Format(introduced, string.Format(season, s))); var chapter = Utils.GetLocalizedResource("AthenaSeasonItemDefinitionInternal", "ChapterTextFormat", "Chapter {0}"); var chapterFormat = Utils.GetLocalizedResource("AthenaSeasonItemDefinitionInternal", "ChapterSeasonTextFormat", "{0}, {1}"); var d = string.Format(chapterFormat, string.Format(chapter, chapterIdx), string.Format(season, seasonIdx)); - return Utils.RemoveHtmlTags(string.Format(introduced, d)); + return s switch + { + "27" => Utils.RemoveHtmlTags(string.Format(introduced, string.Format("Fortnite: OG"))), + "32" => Utils.RemoveHtmlTags(string.Format(introduced, string.Format("Fortnite: Remix"))), + "35" => Utils.RemoveHtmlTags(string.Format(introduced, string.Format(chapterFormat, string.Format(chapter, chapterIdx), string.Format("MS1")))), + _ => Utils.RemoveHtmlTags(string.Format(introduced, d)) + }; } protected void CheckGameplayTags(FInstancedStruct[] dataList) diff --git a/FModel/Creator/Bases/FN/BaseIconStats.cs b/FModel/Creator/Bases/FN/BaseIconStats.cs index 5db374fb..c7c1e485 100644 --- a/FModel/Creator/Bases/FN/BaseIconStats.cs +++ b/FModel/Creator/Bases/FN/BaseIconStats.cs @@ -84,44 +84,68 @@ public class BaseIconStats : BaseIcon weaponStatHandle.TryGetValue(out UDataTable dataTable, "DataTable") && dataTable.TryGetDataTableRow(weaponRowName.Text, StringComparison.OrdinalIgnoreCase, out var weaponRowValue)) { - if (weaponRowValue.TryGetValue(out int bpc, "BulletsPerCartridge")) + weaponRowValue.TryGetValue(out float dmgPb, "DmgPB"); //Damage at point blank + weaponRowValue.TryGetValue(out float mdpc, "MaxDamagePerCartridge"); //Max damage a weapon can do in a single hit, usually used for shotguns + weaponRowValue.TryGetValue(out float dmgCritical, "DamageZone_Critical"); //Headshot multiplier + weaponRowValue.TryGetValue(out int clipSize, "ClipSize"); //Item magazine size + weaponRowValue.TryGetValue(out float firingRate, "FiringRate"); //Item firing rate, value is shots per second + weaponRowValue.TryGetValue(out float armTime, "ArmTime"); //Time it takes for traps to be able to be set off + weaponRowValue.TryGetValue(out float reloadTime, "ReloadTime"); //Time it takes for a weapon to reload + weaponRowValue.TryGetValue(out int bpc, "BulletsPerCartridge"); //Amount of pellets shot by a weapon at once, usually for shotguns + weaponRowValue.TryGetValue(out float heatMax, "OverheatingMaxValue"); //Maximum heat overheating weapons can hold before they need to cool off + weaponRowValue.TryGetValue(out float heatPerShot, "OverheatHeatingValue"); //Heat generated per shot on overheat weapons + weaponRowValue.TryGetValue(out float overheatCooldown, "OverheatedCooldownDelay"); //Cooldown after a weapon reaches its maximum heat capacity { var multiplier = bpc != 0f ? bpc : 1; - if (weaponRowValue.TryGetValue(out float dmgPb, "DmgPB") && dmgPb != 0f) + if (dmgPb != 0f) { - _statistics.Add(new IconStat(Utils.GetLocalizedResource("", "35D04D1B45737BEA25B69686D9E085B9", "Damage"), dmgPb * multiplier, 200)); + _statistics.Add(new IconStat(Utils.GetLocalizedResource("", "35D04D1B45737BEA25B69686D9E085B9", "Damage"), dmgPb * multiplier, 160)); } - if (weaponRowValue.TryGetValue(out float mdpc, "MaxDamagePerCartridge") && mdpc >= 0f) + if (mdpc > 0f && dmgPb * dmgCritical * multiplier > mdpc) { - _statistics.Add(new IconStat(Utils.GetLocalizedResource("", "0DEF2455463B008C4499FEA03D149EDF", "Headshot Damage"), mdpc, 200)); + _statistics.Add(new IconStat(Utils.GetLocalizedResource("", "0DEF2455463B008C4499FEA03D149EDF", "Headshot Damage"), mdpc, 160)); } - else if (weaponRowValue.TryGetValue(out float dmgCritical, "DamageZone_Critical")) + + else if (dmgCritical != 0f && dmgCritical != 1f && dmgPb != 0f) { - _statistics.Add(new IconStat(Utils.GetLocalizedResource("", "0DEF2455463B008C4499FEA03D149EDF", "Headshot Damage"), dmgPb * dmgCritical * multiplier, 200)); + _statistics.Add(new IconStat(Utils.GetLocalizedResource("", "0DEF2455463B008C4499FEA03D149EDF", "Headshot Damage"), dmgPb * dmgCritical * multiplier, 160)); } } - - if (weaponRowValue.TryGetValue(out int clipSize, "ClipSize") && clipSize != 0) + if (clipSize > 999f || clipSize == 0f) { - _statistics.Add(new IconStat(Utils.GetLocalizedResource("", "068239DD4327B36124498C9C5F61C038", "Magazine Size"), clipSize, 50)); + _statistics.Add(new IconStat(Utils.GetLocalizedResource("", "068239DD4327B36124498C9C5F61C038", "Magazine Size"), Utils.GetLocalizedResource("", "0FAE8E5445029F2AA209ADB0FE49B23C", "Infinite"), -1)); } - if (weaponRowValue.TryGetValue(out float firingRate, "FiringRate") && firingRate != 0f) + else if (clipSize != 0f) { - _statistics.Add(new IconStat(Utils.GetLocalizedResource("", "27B80BA44805ABD5A2D2BAB2902B250C", "Fire Rate"), firingRate, 15)); + _statistics.Add(new IconStat(Utils.GetLocalizedResource("", "068239DD4327B36124498C9C5F61C038", "Magazine Size"), clipSize, 40)); } - if (weaponRowValue.TryGetValue(out float armTime, "ArmTime") && armTime != 0f) + if (firingRate != 0f) { - _statistics.Add(new IconStat(Utils.GetLocalizedResource("", "3BFEB8BD41A677CC5F45B9A90D6EAD6F", "Arming Delay"), armTime, 125)); + _statistics.Add(new IconStat(Utils.GetLocalizedResource("", "27B80BA44805ABD5A2D2BAB2902B250C", "Fire Rate"), firingRate, 11)); } - if (weaponRowValue.TryGetValue(out float reloadTime, "ReloadTime") && reloadTime != 0f) + if (armTime != 0f) { - _statistics.Add(new IconStat(Utils.GetLocalizedResource("", "6EA26D1A4252034FBD869A90F9A6E49A", "Reload Time"), reloadTime, 15)); + _statistics.Add(new IconStat(Utils.GetLocalizedResource("", "3BFEB8BD41A677CC5F45B9A90D6EAD6F", "Arming Delay"), armTime, 5)); } + if (reloadTime != 0f && clipSize < 999f && clipSize != 0f) + { + _statistics.Add(new IconStat(Utils.GetLocalizedResource("", "6EA26D1A4252034FBD869A90F9A6E49A", "Reload Time"), reloadTime, 10)); + } + + if (overheatCooldown != 0f && clipSize > 999f || overheatCooldown != 0f && clipSize == 0f) + { + _statistics.Add(new IconStat("Overheat Cooldown", overheatCooldown, 5)); + } + + if (heatMax != 0f && heatPerShot != 0f && clipSize > 999f || heatMax != 0f && heatPerShot != 0f && clipSize == 0f) + { + _statistics.Add(new IconStat("Shots to Overheat", Math.Ceiling(heatMax / heatPerShot), 80)); + } if ((Object.ExportType.Equals("FortContextTrapItemDefinition", StringComparison.OrdinalIgnoreCase) || Object.ExportType.Equals("FortTrapItemDefinition", StringComparison.OrdinalIgnoreCase)) && weaponRowValue.TryGetValue(out UDataTable durabilityTable, "Durability") && @@ -285,6 +309,10 @@ public class IconStat _statPaint.Color = SKColors.White; c.DrawText(_value.ToString(), new SKPoint(width - 50, y + 10), _statPaint); + if (_maxValue == -1) //fill bar if max value is set to -1, for things that don't return a number here but should still be represented as the maximum value + { + c.DrawRect(new SKRect(height * 2, y, Math.Min(width - height, sliderRight), y + 5), _statPaint); + } if (_maxValue < 1 || !float.TryParse(_value.ToString(), out var floatValue)) return; if (floatValue < 0) floatValue = 0; diff --git a/FModel/Creator/Bases/FN/BaseQuest.cs b/FModel/Creator/Bases/FN/BaseQuest.cs index 48984aff..ef3159aa 100644 --- a/FModel/Creator/Bases/FN/BaseQuest.cs +++ b/FModel/Creator/Bases/FN/BaseQuest.cs @@ -44,12 +44,12 @@ public class BaseQuest : BaseIcon DisplayName = ReformatString(description, completionCount.ToString(), completionCount < 0); } - public void AddCompletionRequest(FSoftObjectPath itemDefinition) + public void AddCompletionReward(FSoftObjectPath itemDefinition) { _rewards.Add(itemDefinition.TryLoad(out UObject uObject) ? new Reward(uObject) : new Reward()); } - public void AddCompletionRequest(int quantity, string reward) + public void AddCompletionReward(int quantity, string reward) { _rewards.Add(new Reward(quantity, reward)); } diff --git a/FModel/Creator/CreatorPackage.cs b/FModel/Creator/CreatorPackage.cs index ad80b17b..0a0ad68c 100644 --- a/FModel/Creator/CreatorPackage.cs +++ b/FModel/Creator/CreatorPackage.cs @@ -49,7 +49,8 @@ public class CreatorPackage : IDisposable case "CosmeticShoesItemDefinition": case "AthenaPickaxeItemDefinition": case "AthenaGadgetItemDefinition": - case "AthenaGliderItemDefinition": + case "AthenaGliderItemDefinition": + case "AthenaHatItemDefinition": case "AthenaSprayItemDefinition": case "AthenaDanceItemDefinition": case "AthenaEmojiItemDefinition": diff --git a/FModel/MainWindow.xaml.cs b/FModel/MainWindow.xaml.cs index 2f915233..e1d71bc3 100644 --- a/FModel/MainWindow.xaml.cs +++ b/FModel/MainWindow.xaml.cs @@ -63,7 +63,6 @@ public partial class MainWindow await ApplicationViewModel.InitOodle(); await ApplicationViewModel.InitZlib(); - await ApplicationViewModel.InitDetex(); await _applicationView.CUE4Parse.Initialize(); await _applicationView.AesManager.InitAes(); await _applicationView.UpdateProvider(true); @@ -74,6 +73,7 @@ public partial class MainWindow _applicationView.CUE4Parse.VerifyConsoleVariables(), _applicationView.CUE4Parse.VerifyOnDemandArchives(), _applicationView.CUE4Parse.InitMappings(), + ApplicationViewModel.InitDetex(), ApplicationViewModel.InitVgmStream(), ApplicationViewModel.InitImGuiSettings(newOrUpdated), Task.Run(() => diff --git a/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs b/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs index aeaf42b9..47b7bd55 100644 --- a/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs +++ b/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs @@ -106,7 +106,11 @@ public class FModelApiEndpoint : AbstractApiProvider public void CheckForUpdates(bool launch = false) { - if (DateTime.Now < UserSettings.Default.NextUpdateCheck) return; + if (DateTime.Now < UserSettings.Default.NextUpdateCheck) + { + Log.Warning("Updates have been silenced until {DateTime}", UserSettings.Default.NextUpdateCheck); + return; + } if (launch) { @@ -140,7 +144,8 @@ public class FModelApiEndpoint : AbstractApiProvider { UserSettings.Default.LastUpdateCheck = DateTime.Now; - if (((CustomMandatory)args.Mandatory).CommitHash == Constants.APP_COMMIT_ID) + var targetHash = ((CustomMandatory) args.Mandatory).CommitHash; + if (targetHash == Constants.APP_COMMIT_ID) { if (UserSettings.Default.ShowChangelog) ShowChangelog(args); @@ -152,6 +157,7 @@ public class FModelApiEndpoint : AbstractApiProvider UserSettings.Default.ShowChangelog = currentVersion != args.InstalledVersion; const string message = "A new update is available!"; + Log.Warning("{message} Version {CurrentVersion} ({Hash})", message, currentVersion, targetHash); Helper.OpenWindow(message, () => new UpdateView { Title = message, ResizeMode = ResizeMode.NoResize }.ShowDialog()); } else diff --git a/FModel/ViewModels/ApplicationViewModel.cs b/FModel/ViewModels/ApplicationViewModel.cs index e3faa892..dd0806c2 100644 --- a/FModel/ViewModels/ApplicationViewModel.cs +++ b/FModel/ViewModels/ApplicationViewModel.cs @@ -260,7 +260,7 @@ public class ApplicationViewModel : ViewModel ZlibHelper.Initialize(zlibPath); } - public static async ValueTask InitDetex() + public static async Task InitDetex() { var detexPath = Path.Combine(UserSettings.Default.OutputDirectory, ".data", DetexHelper.DLL_NAME); if (File.Exists(DetexHelper.DLL_NAME)) diff --git a/FModel/Views/Resources/Controls/Rtb/CustomRichTextBox.cs b/FModel/Views/Resources/Controls/Rtb/CustomRichTextBox.cs index d8dbccfa..0c63a759 100644 --- a/FModel/Views/Resources/Controls/Rtb/CustomRichTextBox.cs +++ b/FModel/Views/Resources/Controls/Rtb/CustomRichTextBox.cs @@ -6,6 +6,7 @@ using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; +using System.Windows.Threading; namespace FModel.Views.Resources.Controls; @@ -54,7 +55,7 @@ public class FLogger : ITextFormatter } job(); - }); + }, DispatcherPriority.Background); } public static void Text(string message, string color, bool newLine = false)