diff options
| -rw-r--r-- | Malmstone/Addons/PvPMatchAddon.cs | 65 | ||||
| -rw-r--r-- | Malmstone/Configuration.cs | 4 | ||||
| -rw-r--r-- | Malmstone/Plugin.cs | 10 | ||||
| -rw-r--r-- | Malmstone/Services/PVPService.cs | 131 | ||||
| -rw-r--r-- | Malmstone/Windows/ConfigWindow.cs | 30 | ||||
| -rw-r--r-- | Malmstone/Windows/MainWindow.cs | 74 |
6 files changed, 306 insertions, 8 deletions
diff --git a/Malmstone/Addons/PvPMatchAddon.cs b/Malmstone/Addons/PvPMatchAddon.cs index 78e0e38..896001a 100644 --- a/Malmstone/Addons/PvPMatchAddon.cs +++ b/Malmstone/Addons/PvPMatchAddon.cs @@ -5,12 +5,16 @@ using Malmstone.Utils; using Dalamud.Game.Text.SeStringHandling; using System.Collections.Generic; using Dalamud.Game.Text.SeStringHandling.Payloads; +using FFXIVClientStructs.FFXIV.Component.GUI; +using Dalamud.Memory; +using static Malmstone.Services.PvPService; namespace Malmstone.Addons { internal class PvPMatchAddon { private Plugin Plugin; + public bool FrontlineRecordPostSetupEnabled = false; private enum PvPContentType { CrystallineConflict = 1, @@ -49,11 +53,15 @@ namespace Malmstone.Addons public void EnableFrontlinePostMatch() { Plugin.AddonLifeCycle.RegisterListener(AddonEvent.PostSetup, "FrontlineRecord", OnFrontlineRecordTrigger); + Plugin.PvPService.CurrentFrontlineLosingBonus = Plugin.Configuration.SavedFrontlineRewardBonus; + Plugin.Configuration.OutdatedFrontlineRewardBonus = true; + FrontlineRecordPostSetupEnabled = true; } public void DisableFrontlinePostMatch() { Plugin.AddonLifeCycle.UnregisterListener(AddonEvent.PostSetup, "FrontlineRecord", OnFrontlineRecordTrigger); + FrontlineRecordPostSetupEnabled = false; } public void EnableRivalWingsPostMatch() @@ -64,12 +72,13 @@ namespace Malmstone.Addons { Plugin.AddonLifeCycle.UnregisterListener(AddonEvent.PostSetup, "ManeuversRecord", OnRivalWingsRecordTrigger); } - + // Runs on the result screen of the respective game mode private void OnCrystallineConflictRecordTrigger(AddonEvent eventType, AddonArgs addonInfo) { PvPSeriesInfo? seriesInfo = Plugin.PvPService.GetPvPSeriesInfo(); + CheckFrontlineBonus(eventType, addonInfo); if (seriesInfo == null) return; if (Plugin.Configuration.ShowProgressionChatPostCC) ShowSeriesProgressionMessage(seriesInfo, PvPContentType.CrystallineConflict); @@ -77,6 +86,8 @@ namespace Malmstone.Addons private void OnFrontlineRecordTrigger(AddonEvent eventType, AddonArgs addonInfo) { + if (Plugin.Configuration.TrackFrontlineBonus) + CheckFrontlineBonus(eventType, addonInfo); PvPSeriesInfo? seriesInfo = Plugin.PvPService.GetPvPSeriesInfo(); if (seriesInfo == null) return; if (Plugin.Configuration.ShowProgressionChatPostFL) @@ -91,6 +102,58 @@ namespace Malmstone.Addons ShowSeriesProgressionMessage(seriesInfo, PvPContentType.RivalWings); } + private void CheckFrontlineBonus(AddonEvent eventType, AddonArgs addonInfo) + { + PVPProfileFrontlineResults CurrentFrontlineResults = Plugin.PvPService.GetPVPProfileFrontlineResults(); + if (CurrentFrontlineResults.FirstPlace == 0 && + CurrentFrontlineResults.SecondPlace == 0 && + CurrentFrontlineResults.ThirdPlace == 0) return; + // Check placement of current Frontline match + FrontlinePlacement FrontlineMatchResult = FrontlinePlacement.Unknown; + if (CurrentFrontlineResults.FirstPlace > Plugin.PvPService.CachedFrontlineResults.FirstPlace) + { + FrontlineMatchResult = FrontlinePlacement.FirstPlace; + } + else if (CurrentFrontlineResults.SecondPlace > Plugin.PvPService.CachedFrontlineResults.SecondPlace) + { + FrontlineMatchResult = FrontlinePlacement.SecondPlace; + } + else if (CurrentFrontlineResults.ThirdPlace > Plugin.PvPService.CachedFrontlineResults.ThirdPlace) + { + FrontlineMatchResult = FrontlinePlacement.ThirdPlace; + } + Plugin.Logger.Debug("Frontline Match Result: " + FrontlineMatchResult.ToString()); + if (FrontlineMatchResult != FrontlinePlacement.Unknown) + { + unsafe + { + var FrontlineResultUnit = (AtkUnitBase*)addonInfo.Addon; + if (FrontlineResultUnit == null) return; + var SeriesExpComponent = FrontlineResultUnit->GetComponentByNodeId(35); + var SeriesExpTextNode = (AtkTextNode*)SeriesExpComponent->GetTextNodeById(2); + byte* SeriesExpTextBytePointer = SeriesExpTextNode->GetText(); + nint SeriesExpTextAddr = (nint)SeriesExpTextBytePointer; + string SeriesExpText = MemoryHelper.ReadStringNullTerminated(SeriesExpTextAddr); + if (int.TryParse(SeriesExpText, out int SeriesExpEarned)) + { + int CurrentLossBonus = Plugin.PvPService.GenerateFrontlineBonus(FrontlineMatchResult, SeriesExpEarned); + Plugin.Logger.Debug("Series EXP Earned: " + SeriesExpEarned.ToString()); + Plugin.Configuration.SavedFrontlineRewardBonus = CurrentLossBonus; + Plugin.Configuration.OutdatedFrontlineRewardBonus = false; + } + else + { + Plugin.Chat.PrintError("[Malmstone Calculator] Unable to get earned Series EXP: " + SeriesExpText); + } + } + } + else + { + Plugin.Chat.PrintError("[Malmstone Calculator] Unable to get current Frontline match results"); + } + Plugin.PvPService.UpdateFrontlineResultCache(); + } + private void ShowSeriesProgressionToast(AddonEvent eventType, AddonArgs addonInfo) { PvPSeriesInfo? seriesInfo = Plugin.PvPService.GetPvPSeriesInfo(); diff --git a/Malmstone/Configuration.cs b/Malmstone/Configuration.cs index 1d0ed84..4f62a96 100644 --- a/Malmstone/Configuration.cs +++ b/Malmstone/Configuration.cs @@ -1,5 +1,4 @@ using Dalamud.Configuration; -using Dalamud.Plugin; using System; namespace Malmstone; @@ -18,6 +17,9 @@ public class Configuration : IPluginConfiguration public bool ShowMainWindowOnPVPReward { get; set; } = true; public bool SkipProgressionToastAfterGoal { get; set; } = false; public bool SkipProgressionChatAfterGoal { get; set; } = false; + public bool TrackFrontlineBonus { get; set; } = true; + public int SavedFrontlineRewardBonus { get; set; } = -1; + public bool OutdatedFrontlineRewardBonus { get; set; } = false; // the below exist just to make saving less cumbersome public void Save() diff --git a/Malmstone/Plugin.cs b/Malmstone/Plugin.cs index 5ed6a65..ada8202 100644 --- a/Malmstone/Plugin.cs +++ b/Malmstone/Plugin.cs @@ -24,6 +24,7 @@ public sealed class Plugin : IDalamudPlugin [PluginService] internal static IChatGui Chat { get; private set; } = null!; [PluginService] internal static IAddonLifecycle AddonLifeCycle { get; private set; } = null!; [PluginService] internal static IToastGui ToastGui { get; private set; } = null!; + [PluginService] internal static IPluginLog Logger { get; set; } = default!; private const string CommandName = "/pmalm"; @@ -48,12 +49,14 @@ public sealed class Plugin : IDalamudPlugin PvPAddon.EnableCrystallineConflictPostMatch(); if (Configuration.ShowProgressionChatPostRW) PvPAddon.EnableRivalWingsPostMatch(); - if (Configuration.ShowProgressionChatPostFL) + if (Configuration.ShowProgressionChatPostFL || Configuration.TrackFrontlineBonus) PvPAddon.EnableFrontlinePostMatch(); if (Configuration.ShowProgressionToastPostMatch) PvPAddon.EnablePostMatchProgressionToast(); if (Configuration.ShowMainWindowOnPVPReward) EnablePVPRewardWindowAddon(); + + PvPService.UpdateFrontlineResultCache(); if (Configuration.PostmatchProgressionToastType < 0 || Configuration.PostmatchProgressionToastType > 2) { @@ -84,13 +87,13 @@ public sealed class Plugin : IDalamudPlugin PvPAddon.DisableCrystallineConflictPostMatch(); if (Configuration.ShowProgressionChatPostRW) PvPAddon.DisableRivalWingsPostMatch(); - if (Configuration.ShowProgressionChatPostFL) + if (Configuration.ShowProgressionChatPostFL || Configuration.TrackFrontlineBonus) PvPAddon.DisableFrontlinePostMatch(); if (Configuration.ShowProgressionToastPostMatch) PvPAddon.DisablePostMatchProgressionToast(); if(Configuration.ShowMainWindowOnPVPReward) DisablePVPRewardWindowAddon(); - + CommandManager.RemoveHandler(CommandName); } @@ -254,5 +257,6 @@ private void OnCommand(string command, string args) AddonLifeCycle.UnregisterListener(AddonEvent.PostSetup, "PvpReward", MainWindow.OnOpenPVPRewardWindow); AddonLifeCycle.UnregisterListener(AddonEvent.PreFinalize, "PvpReward", MainWindow.OnClosePVPRewardWindow); } + } diff --git a/Malmstone/Services/PVPService.cs b/Malmstone/Services/PVPService.cs index cf08fea..12b4c2a 100644 --- a/Malmstone/Services/PVPService.cs +++ b/Malmstone/Services/PVPService.cs @@ -4,6 +4,23 @@ namespace Malmstone.Services { public class PvPService { + public int CurrentFrontlineLosingBonus = -1; + public int ConsecutiveThirdPlaceFrontline = 0; + + public enum FrontlinePlacement + { + FirstPlace = 1, SecondPlace = 2, ThirdPlace = 3, Unknown=4 + } + + public struct PVPProfileFrontlineResults + { + public uint FirstPlace; + public uint SecondPlace; + public uint ThirdPlace; + } + + public PVPProfileFrontlineResults CachedFrontlineResults; + public PvPSeriesInfo? GetPvPSeriesInfo() { unsafe @@ -21,6 +38,120 @@ namespace Malmstone.Services return null; } } + + public bool UpdateFrontlineResultCache() + { + unsafe + { + var pvpProfile = PvPProfile.Instance(); + if (pvpProfile != null && pvpProfile->IsLoaded != 0) + { + CachedFrontlineResults = new PVPProfileFrontlineResults + { + FirstPlace = pvpProfile->FrontlineTotalFirstPlace, + SecondPlace = pvpProfile->FrontlineTotalSecondPlace, + ThirdPlace = pvpProfile->FrontlineTotalThirdPlace + }; + return true; + } + return false; + } + } + + public int GenerateFrontlineBonus(FrontlinePlacement FrontlineResult, int EarnedSeriesEXP) + { + // Calculates the current Frontline Bonus + // 1000 (no bonus), 1100, 1200, 1300, 1400, 1500 3rd + // 1250 (no bonus), 1375, 1500, 1625, 1750, 1875 2nd + // 1500 (no bonus), 1650, 1800, 1950, 2100, 2250 1st + if (FrontlineResult == FrontlinePlacement.ThirdPlace) + { + ConsecutiveThirdPlaceFrontline++; + switch (EarnedSeriesEXP) + { // Next 3rd place will get +10% value + case 1000: + CurrentFrontlineLosingBonus = 0; // Primed for buff + return 0; + case 1100: + CurrentFrontlineLosingBonus = 10; + return 10; + case 1200: + CurrentFrontlineLosingBonus = 20; + return 20; + case 1300: + CurrentFrontlineLosingBonus = 30; + return 30; + case 1400: + CurrentFrontlineLosingBonus = 40; + return 40; + case 1500: + CurrentFrontlineLosingBonus = 50; + return 50; + default: + return -1; + } + } + else if (FrontlineResult == FrontlinePlacement.SecondPlace) + { + switch (EarnedSeriesEXP) + { + case 1250: + CurrentFrontlineLosingBonus = 0; + return 0; + case 1375: + CurrentFrontlineLosingBonus = 10; + return 10; + case 1500: + CurrentFrontlineLosingBonus = 20; + return 20; + case 1625: + CurrentFrontlineLosingBonus = 30; + return 30; + case 2100: + CurrentFrontlineLosingBonus = 40; + return 40; + case 2250: + CurrentFrontlineLosingBonus = 50; + return 50; + default: + return -1; + } + } + else if (FrontlineResult == FrontlinePlacement.FirstPlace) + { + // Buff is reset regardless + ConsecutiveThirdPlaceFrontline = 0; + CurrentFrontlineLosingBonus = 0; + return 0; + } + return -1; + } + + public PVPProfileFrontlineResults GetPVPProfileFrontlineResults() + { + unsafe + { + var pvpProfile = PvPProfile.Instance(); + if (pvpProfile != null && pvpProfile->IsLoaded != 0) + { + return new PVPProfileFrontlineResults + { + FirstPlace = pvpProfile->FrontlineTotalFirstPlace, + SecondPlace = pvpProfile->FrontlineTotalSecondPlace, + ThirdPlace = pvpProfile->FrontlineTotalThirdPlace, + + }; + } + } + return new PVPProfileFrontlineResults + { + FirstPlace = 0, + SecondPlace = 0, + ThirdPlace = 0, + + }; + } + } public class PvPSeriesInfo diff --git a/Malmstone/Windows/ConfigWindow.cs b/Malmstone/Windows/ConfigWindow.cs index 93af7b5..0dc4e11 100644 --- a/Malmstone/Windows/ConfigWindow.cs +++ b/Malmstone/Windows/ConfigWindow.cs @@ -151,9 +151,9 @@ public class ConfigWindow : Window, IDisposable if (ImGui.Checkbox("##ShowFLMatchesRemainingPostGame", ref showFLMatchesRemainingPostGame)) { Configuration.ShowProgressionChatPostFL = showFLMatchesRemainingPostGame; - if (showFLMatchesRemainingPostGame) + if (showFLMatchesRemainingPostGame && !Plugin.PvPAddon.FrontlineRecordPostSetupEnabled) Plugin.PvPAddon.EnableFrontlinePostMatch(); - else + else if (!showFLMatchesRemainingPostGame && !Configuration.TrackFrontlineBonus) Plugin.PvPAddon.DisableFrontlinePostMatch(); Configuration.Save(); } @@ -166,6 +166,32 @@ public class ConfigWindow : Window, IDisposable ImGui.SameLine(); ImGui.Text("Frontlines"); + ImGui.SameLine(); + ImGui.Spacing(); + ImGui.SameLine(); + + var trackFrontlineBonus = Configuration.TrackFrontlineBonus; + if (ImGui.Checkbox("##TrackFrontlineBonus", ref trackFrontlineBonus)) + { + Configuration.TrackFrontlineBonus = trackFrontlineBonus; + if (trackFrontlineBonus && !Plugin.PvPAddon.FrontlineRecordPostSetupEnabled) + Plugin.PvPAddon.EnableFrontlinePostMatch(); + else if(!trackFrontlineBonus && !Configuration.ShowProgressionChatPostFL) + Plugin.PvPAddon.DisableFrontlinePostMatch(); + Configuration.Save(); + } + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.Text("(EXPERIMENTAL) Track the reward bonus you get for consecutive losses in Frontline" + + "\n3rd place = +10 percent bonus (max 50 percent)" + + "\n2nd place = Current bonus is kept" + + "\n1st Place = Bonus reset to 0\n"); + ImGui.EndTooltip(); + } + ImGui.SameLine(); + ImGui.Text("Track Frontline Reward Bonus"); + var showRWMatchesRemainingPostGame = Configuration.ShowProgressionChatPostRW; if (ImGui.Checkbox("##ShowRWMatchesRemainingPostGame", ref showRWMatchesRemainingPostGame)) diff --git a/Malmstone/Windows/MainWindow.cs b/Malmstone/Windows/MainWindow.cs index 0e91c4d..1617a00 100644 --- a/Malmstone/Windows/MainWindow.cs +++ b/Malmstone/Windows/MainWindow.cs @@ -26,7 +26,7 @@ namespace Malmstone.Windows { SizeConstraints = new WindowSizeConstraints { - MinimumSize = new Vector2(460, 510), + MinimumSize = new Vector2(460, 545), MaximumSize = new Vector2(float.MaxValue, float.MaxValue) }; @@ -101,6 +101,78 @@ namespace Malmstone.Windows ImGui.BulletText($"Take 2nd Place: {xpResult.FrontlineDailyLose2nd} " + (xpResult.FrontlineDailyLose2nd == 1 ? "time" : "times")); ImGui.BulletText($"Take 3rd Place: {xpResult.FrontlineDailyLose3rd} " + (xpResult.FrontlineDailyLose3rd == 1 ? "time" : "times")); + + if (Plugin.Configuration.TrackFrontlineBonus) + { + if (Plugin.PvPService.CurrentFrontlineLosingBonus == -1) + { + ImGui.TextColored(new Vector4(0.0f, 1.0f, 0.0f, 1.0f), "Complete a Frontline match to view current reward bonus"); + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.Text("This calculates the losing streak bonus you receive after consecutive losses in Frontlines" + + "\nPlay a match of Frontline to confirm your existing losing bonus" + + "\nYou can turn off tracking entirely in the settings"); + ImGui.EndTooltip(); + } + } + else + { + if(Plugin.PvPService.CurrentFrontlineLosingBonus == 0) + { + if(Plugin.PvPService.ConsecutiveThirdPlaceFrontline == 1) + { + ImGui.TextColored(new Vector4(0.0f, 1.0f, 0.0f, 1.0f), "You'll receive 10%% reward bonus if you place 3rd"); + } + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.Text("You're primed for a reward bonus! You will get a 10% reward bonus if you place 3rd again" + + "\nCounter resets if you rank 1st"); + ImGui.EndTooltip(); + } + ImGui.Text("No Frontline Reward Bonus Currently Active"); + } + else + { + if (Plugin.PvPService.CurrentFrontlineLosingBonus != 50) + ImGui.TextColored(new Vector4(0.0f, 1.0f, 0.0f, 1.0f), "You'll receive a " + Plugin.PvPService.CurrentFrontlineLosingBonus + "%% reward bonus placing 1st or 2nd"); + else + ImGui.TextColored(new Vector4(0.0f, 1.0f, 0.0f, 1.0f), "You'll receive a " + Plugin.PvPService.CurrentFrontlineLosingBonus + "%% reward bonus placing 1st, 2nd, or 3rd"); + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.Text("You'll earn a percentage bonus on PvP EXP, Series EXP, and Wolf Marks " + + "until attaining First Place" ); + ImGui.EndTooltip(); + } + if (Plugin.PvPService.CurrentFrontlineLosingBonus != 50) + { + ImGui.TextColored(new Vector4(0.0f, 1.0f, 0.0f, 1.0f), "Your reward bonus will increase to " + (Plugin.PvPService.CurrentFrontlineLosingBonus + 10) + "%% if place 3rd"); + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.Text($"Finishing 3rd again will increase your bonus to {Plugin.PvPService.CurrentFrontlineLosingBonus + 10}%." + + "\nThis increased bonus will also apply to the match where this happens."); + ImGui.EndTooltip(); + } + } + } + if (Plugin.Configuration.OutdatedFrontlineRewardBonus) + { + ImGui.SameLine(); + ImGui.TextColored(new Vector4(1.0f, 0.0f, 0.0f, 1.0f),"(Outdated)"); + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.Text("This information may be outdated due to Frontline tracking loading and unloading!" + + "\nCalculations will refresh after your next match of Frontlines"); + ImGui.EndTooltip(); + } + } + } + } + ImGui.Spacing(); ImGui.Separator(); |
