aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Malmstone/Addons/PvPMatchAddon.cs7
-rw-r--r--Malmstone/Plugin.cs20
-rw-r--r--Malmstone/Utils/MalmstoneXPCalculator.cs43
-rw-r--r--Malmstone/Windows/MainWindow.cs50
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();
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage