diff options
| -rw-r--r-- | Malmstone/Addons/PvPMatchAddon.cs | 7 | ||||
| -rw-r--r-- | Malmstone/Plugin.cs | 20 | ||||
| -rw-r--r-- | Malmstone/Utils/MalmstoneXPCalculator.cs | 43 | ||||
| -rw-r--r-- | Malmstone/Windows/MainWindow.cs | 50 |
4 files changed, 113 insertions, 7 deletions
diff --git a/Malmstone/Addons/PvPMatchAddon.cs b/Malmstone/Addons/PvPMatchAddon.cs index 00f9399..b50d3f9 100644 --- a/Malmstone/Addons/PvPMatchAddon.cs +++ b/Malmstone/Addons/PvPMatchAddon.cs @@ -214,7 +214,8 @@ namespace Malmstone.Addons seString.Append(new TextPayload("[Crystalline Conflict to Level " + TargetGoal + "]\n")); seString.Append(new UIForegroundPayload(35)); seString.Append(new TextPayload($"Win: {ccResultData.CrystallineConflictWin} " + (ccResultData.CrystallineConflictWin == 1 ? "time" : "times") + "\n")); - seString.Append(new TextPayload($"Lose: {ccResultData.CrystallineConflictLose} " + (ccResultData.CrystallineConflictLose == 1 ? "time" : "times"))); + seString.Append(new TextPayload($"Lose: {ccResultData.CrystallineConflictLose} " + (ccResultData.CrystallineConflictLose == 1 ? "time" : "times") + "\n")); + seString.Append(new TextPayload($"Estimated Matches: {ccResultData.CrystallineConflictExpectedMatches}\n")); seString.Append(UIForegroundPayload.UIForegroundOff); break; case PvPContentType.Frontlines: @@ -226,6 +227,7 @@ namespace Malmstone.Addons seString.Append(new TextPayload($"Take 1st Place: {flResultData.FrontlineWin} " + (flResultData.FrontlineWin == 1 ? "time" : "times") +" (" + (flResultData.FrontlineDailyWin) + ")\n")); seString.Append(new TextPayload($"Take 2nd Place: {flResultData.FrontlineWin} " + (flResultData.FrontlineWin == 1 ? "time" : "times") + " (" + (flResultData.FrontlineDailyLose2nd) + ")\n")); seString.Append(new TextPayload($"Take 3rd Place: {flResultData.FrontlineWin} " + (flResultData.FrontlineWin == 1 ? "time" : "times") + " (" + (flResultData.FrontlineDailyLose3rd) + ")\n")); + seString.Append(new TextPayload($"Estimated Matches: {flResultData.FrontlineExpectedMatches} (" + (flResultData.FrontlineDailyExpectedMatches) + ")\n")); seString.Append(new TextPayload($"Frontline Roulette Shown in Parentheses")); seString.Append(UIForegroundPayload.UIForegroundOff); break; @@ -236,7 +238,8 @@ namespace Malmstone.Addons seString.Append(new TextPayload("[Rival Wings to Level " + TargetGoal + "]\n")); seString.Append(new UIForegroundPayload(43)); seString.Append(new TextPayload($"Win: {rwResultData.RivalWingsWin} " + (rwResultData.RivalWingsWin == 1 ? "time" : "times") + "\n")); - seString.Append(new TextPayload($"Lose: {rwResultData.RivalWingsLose} " + (rwResultData.RivalWingsLose == 1 ? "time" : "times"))); + seString.Append(new TextPayload($"Lose: {rwResultData.RivalWingsLose} " + (rwResultData.RivalWingsLose == 1 ? "time" : "times") + "\n")); + seString.Append(new TextPayload($"Estimated Matches: {rwResultData.RivalWingsExpectedMatches}\n")); seString.Append(UIForegroundPayload.UIForegroundOff); break; } diff --git a/Malmstone/Plugin.cs b/Malmstone/Plugin.cs index f9b366a..bb877fd 100644 --- a/Malmstone/Plugin.cs +++ b/Malmstone/Plugin.cs @@ -190,6 +190,11 @@ private void OnCommand(string command, string args) { seString.Append(new TextPayload($"Lose: {xpResult.CrystallineConflictLose} " + (xpResult.CrystallineConflictLose == 1 ? "time" : "times") + "\n")); } + + if(xpResult.CrystallineConflictExpectedMatches > 0) + { + seString.Append(new TextPayload($"Estimate: {xpResult.CrystallineConflictExpectedMatches} " + (xpResult.CrystallineConflictExpectedMatches == 1 ? "match" : "matches") + "\n")); + } seString.Append(UIForegroundPayload.UIForegroundOff); } @@ -214,6 +219,11 @@ private void OnCommand(string command, string args) { seString.Append(new TextPayload($"Take 3rd Place: {xpResult.FrontlineLose3rd} " + (xpResult.FrontlineLose3rd == 1 ? "time" : "times") + "\n")); } + + if (xpResult.FrontlineExpectedMatches > 0) + { + seString.Append(new TextPayload($"Estimate: {xpResult.FrontlineExpectedMatches} " + (xpResult.FrontlineExpectedMatches == 1 ? "match" : "matches") + "\n")); + } seString.Append(UIForegroundPayload.UIForegroundOff); @@ -234,6 +244,11 @@ private void OnCommand(string command, string args) { seString.Append(new TextPayload($"Take 3rd Place: {xpResult.FrontlineDailyLose3rd} " + (xpResult.FrontlineDailyLose3rd == 1 ? "time" : "times") + "\n")); } + + if (xpResult.FrontlineDailyExpectedMatches > 0) + { + seString.Append(new TextPayload($"Estimate: {xpResult.FrontlineDailyExpectedMatches} " + (xpResult.FrontlineDailyExpectedMatches == 1 ? "match" : "matches") + "\n")); + } seString.Append(UIForegroundPayload.UIForegroundOff); } @@ -253,6 +268,11 @@ private void OnCommand(string command, string args) { seString.Append(new TextPayload($"Lose: {xpResult.RivalWingsLose} " + (xpResult.RivalWingsLose == 1 ? "time" : "times") + "\n")); } + + if (xpResult.RivalWingsExpectedMatches > 0) + { + seString.Append(new TextPayload($"Estimate: {xpResult.RivalWingsExpectedMatches} " + (xpResult.RivalWingsExpectedMatches == 1 ? "match" : "matches") + "\n")); + } seString.Append(UIForegroundPayload.UIForegroundOff); } diff --git a/Malmstone/Utils/MalmstoneXPCalculator.cs b/Malmstone/Utils/MalmstoneXPCalculator.cs index bf11075..1a97fdd 100644 --- a/Malmstone/Utils/MalmstoneXPCalculator.cs +++ b/Malmstone/Utils/MalmstoneXPCalculator.cs @@ -27,14 +27,18 @@ namespace Malmstone.Utils public int TargetLevel; public int CrystallineConflictWin; public int CrystallineConflictLose; + public int CrystallineConflictExpectedMatches; public int FrontlineWin; public int FrontlineLose2nd; public int FrontlineLose3rd; + public int FrontlineExpectedMatches; public int FrontlineDailyWin; public int FrontlineDailyLose2nd; public int FrontlineDailyLose3rd; + public int FrontlineDailyExpectedMatches; public int RivalWingsWin; public int RivalWingsLose; + public int RivalWingsExpectedMatches; } public static XpCalculationResult CalculateXp(int currentLevel, int goalLevel, int currentProgress) @@ -53,14 +57,18 @@ namespace Malmstone.Utils TargetLevel = goalLevel, CrystallineConflictWin = CalculateActivityCount(remainingXp, CrystallineWinExp), CrystallineConflictLose = CalculateActivityCount(remainingXp, CrystallineLoseExp), + CrystallineConflictExpectedMatches = CalculateExpectedCrystallineMatches(remainingXp), FrontlineWin = CalculateActivityCount(remainingXp, FrontlineWinExp), FrontlineLose2nd = CalculateActivityCount(remainingXp, FrontlineLose2Exp), FrontlineLose3rd = CalculateActivityCount(remainingXp, FrontlineLoseExp), + FrontlineExpectedMatches = CalculateExpectedFrontlineMatches(remainingXp, false), FrontlineDailyWin = CalculateActivityCount(remainingXp, FrontlineDailyWinExp), FrontlineDailyLose2nd = CalculateActivityCount(remainingXp, FrontlineDailyLose2Exp), FrontlineDailyLose3rd = CalculateActivityCount(remainingXp, FrontlineDailyLoseExp), + FrontlineDailyExpectedMatches = CalculateExpectedFrontlineMatches(remainingXp, true), RivalWingsWin = CalculateActivityCount(remainingXp, RivalWingsWinExp), - RivalWingsLose = CalculateActivityCount(remainingXp, RivalWingsLoseExp) + RivalWingsLose = CalculateActivityCount(remainingXp, RivalWingsLoseExp), + RivalWingsExpectedMatches = CalculateExpectedRivalWingsMatches(remainingXp) }; } @@ -73,7 +81,8 @@ namespace Malmstone.Utils RemainingXp = remainingXp, TargetLevel = goalLevel, CrystallineConflictWin = CalculateActivityCount(remainingXp, CrystallineWinExp), - CrystallineConflictLose = CalculateActivityCount(remainingXp, CrystallineLoseExp) + CrystallineConflictLose = CalculateActivityCount(remainingXp, CrystallineLoseExp), + CrystallineConflictExpectedMatches = CalculateExpectedCrystallineMatches(remainingXp) }; } @@ -88,9 +97,11 @@ namespace Malmstone.Utils FrontlineWin = CalculateActivityCount(remainingXp, FrontlineWinExp), FrontlineLose2nd = CalculateActivityCount(remainingXp, FrontlineLose2Exp), FrontlineLose3rd = CalculateActivityCount(remainingXp, FrontlineLoseExp), + FrontlineExpectedMatches = CalculateExpectedFrontlineMatches(remainingXp, false), FrontlineDailyWin = CalculateActivityCount(remainingXp, FrontlineDailyWinExp), FrontlineDailyLose2nd = CalculateActivityCount(remainingXp, FrontlineDailyLose2Exp), - FrontlineDailyLose3rd = CalculateActivityCount(remainingXp, FrontlineDailyLoseExp) + FrontlineDailyLose3rd = CalculateActivityCount(remainingXp, FrontlineDailyLoseExp), + FrontlineDailyExpectedMatches = CalculateExpectedFrontlineMatches(remainingXp, true) }; } @@ -103,7 +114,8 @@ namespace Malmstone.Utils RemainingXp = remainingXp, TargetLevel = goalLevel, RivalWingsWin = CalculateActivityCount(remainingXp, RivalWingsWinExp), - RivalWingsLose = CalculateActivityCount(remainingXp, RivalWingsLoseExp) + RivalWingsLose = CalculateActivityCount(remainingXp, RivalWingsLoseExp), + RivalWingsExpectedMatches = CalculateExpectedRivalWingsMatches(remainingXp) }; } @@ -161,6 +173,29 @@ namespace Malmstone.Utils // Should always be greater than 0 return Math.Max(1, (int)Math.Ceiling((double)remainingXp / activityXp)); } + + private static int CalculateExpectedCrystallineMatches(int remainingXp) + { + // Expected Value assuming 50% win rate + return (int)Math.Ceiling(remainingXp / ((CrystallineWinExp + CrystallineLoseExp) / 2.0)); + } + + private static int CalculateExpectedFrontlineMatches(int remainingXp, bool isDaily) + { + if (isDaily) + { + // Expected Value assuming 33% win rate, 33% 2nd place, 33% 3rd place + return (int)Math.Ceiling(remainingXp / ((FrontlineDailyWinExp + FrontlineDailyLose2Exp + FrontlineDailyLoseExp) / 3.0)); + } + // Expected Value assuming 33% win rate, 33% 2nd place, 33% 3rd place + return (int)Math.Ceiling(remainingXp / ((FrontlineWinExp + FrontlineLose2Exp + FrontlineLoseExp) / 3.0)); + } + + private static int CalculateExpectedRivalWingsMatches(int remainingXp) + { + // Expected Value assuming 50% win rate + return (int)Math.Ceiling(remainingXp / ((RivalWingsWinExp + RivalWingsLoseExp) / 2.0)); + } } } diff --git a/Malmstone/Windows/MainWindow.cs b/Malmstone/Windows/MainWindow.cs index f7b65af..2805972 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, 550), + MinimumSize = new Vector2(460, 630), MaximumSize = new Vector2(float.MaxValue, float.MaxValue) }; @@ -97,6 +97,18 @@ namespace Malmstone.Windows ImGui.Spacing(); ImGui.BulletText($"Win: {xpResult.CrystallineConflictWin} " + (xpResult.CrystallineConflictWin == 1 ? "time" : "times")); ImGui.BulletText($"Lose: {xpResult.CrystallineConflictLose} " + (xpResult.CrystallineConflictLose == 1 ? "time" : "times")); + ImGui.Bullet(); + ImGui.SameLine(); + ImGui.TextColored(new Vector4(1.0f, 0.84f, 0.0f, 1.0f), + $"Estimate: {xpResult.CrystallineConflictExpectedMatches} " + + (xpResult.CrystallineConflictExpectedMatches == 1 ? "match" : "matches")); + + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.Text("Calculated Expected Value based on a 50/50 win/loss ratio"); + ImGui.EndTooltip(); + } ImGui.Spacing(); ImGui.Separator(); @@ -115,6 +127,18 @@ namespace Malmstone.Windows ImGui.BulletText($"Take 1st Place: {xpResult.FrontlineWin} " + (xpResult.FrontlineWin == 1 ? "time" : "times")); ImGui.BulletText($"Take 2nd Place: {xpResult.FrontlineLose2nd} " + (xpResult.FrontlineLose2nd == 1 ? "time" : "times")); ImGui.BulletText($"Take 3rd Place: {xpResult.FrontlineLose3rd} " + (xpResult.FrontlineLose3rd == 1 ? "time" : "times")); + ImGui.Bullet(); + ImGui.SameLine(); + ImGui.TextColored(new Vector4(1.0f, 0.84f, 0.0f, 1.0f), + $"Estimate: {xpResult.FrontlineExpectedMatches} " + + (xpResult.FrontlineExpectedMatches == 1 ? "match" : "matches")); + + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.Text("Calculated Expected Value based on a 1/3 chance for each placement"); + ImGui.EndTooltip(); + } // Frontlines Roulette Section ImGui.TextColored(new Vector4(0.8f, 0.6f, 0.6f, 1f), "Frontlines (Roulette)"); @@ -128,6 +152,18 @@ namespace Malmstone.Windows ImGui.BulletText($"Take 1st Place: {xpResult.FrontlineDailyWin} " + (xpResult.FrontlineDailyWin == 1 ? "time" : "times")); ImGui.BulletText($"Take 2nd Place: {xpResult.FrontlineDailyLose2nd} " + (xpResult.FrontlineDailyLose2nd == 1 ? "time" : "times")); ImGui.BulletText($"Take 3rd Place: {xpResult.FrontlineDailyLose3rd} " + (xpResult.FrontlineDailyLose3rd == 1 ? "time" : "times")); + ImGui.Bullet(); + ImGui.SameLine(); + ImGui.TextColored(new Vector4(1.0f, 0.84f, 0.0f, 1.0f), + $"Estimate: {xpResult.FrontlineDailyExpectedMatches} " + + (xpResult.FrontlineDailyExpectedMatches == 1 ? "match/day" : "matches/days")); + + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.Text("Calculated Expected Value based on a 1/3 chance for each placement.\nAlso the minimum number of days to reach your goal if you only play Frontlines once per day."); + ImGui.EndTooltip(); + } if (Plugin.Configuration.TrackFrontlineBonus) @@ -216,6 +252,18 @@ namespace Malmstone.Windows ImGui.Spacing(); ImGui.BulletText($"Win: {xpResult.RivalWingsWin} " + (xpResult.RivalWingsWin == 1 ? "time" : "times")); ImGui.BulletText($"Lose: {xpResult.RivalWingsLose} " + (xpResult.RivalWingsLose == 1 ? "time" : "times")); + ImGui.Bullet(); + ImGui.SameLine(); + ImGui.TextColored(new Vector4(1.0f, 0.84f, 0.0f, 1.0f), + $"Estimate: {xpResult.RivalWingsExpectedMatches} " + + (xpResult.RivalWingsExpectedMatches == 1 ? "match" : "matches")); + + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.Text("Calculated Expected Value based on a 50/50 win/loss ratio"); + ImGui.EndTooltip(); + } ImGui.Separator(); ImGui.Spacing(); |
