diff --git a/XIVCalc.Tests/JobStatMock.cs b/XIVCalc.Tests/JobStatMock.cs
new file mode 100644
index 0000000..eacaa72
--- /dev/null
+++ b/XIVCalc.Tests/JobStatMock.cs
@@ -0,0 +1,29 @@
+using Lumina.Excel.GeneratedSheets;
+using XIVCalc.Interfaces;
+
+namespace XIVCalc.Tests;
+
+public class JobStatMock : IJobStatBlock
+{
+ public ClassJob Job { get; init; } = new ClassJob();
+ public int Level { get; init; }
+ public int WeaponDamage { get;init; }
+ public int WeaponDelay { get; init;}
+ public int Vitality { get; init;}
+ public int Strength { get; init;}
+ public int Dexterity { get; init;}
+ public int Intelligence { get; init;}
+ public int Mind { get; init;}
+ public int PhysicalDefense { get; init;}
+ public int MagicalDefense { get; init;}
+ public int AttackPower { get; init;}
+ public int AttackMagicPotency { get; init;}
+ public int HealingMagicPotency { get; init;}
+ public int DirectHit { get; init;}
+ public int CriticalHit { get; init;}
+ public int Determination { get; init;}
+ public int SkillSpeed { get; init;}
+ public int SpellSpeed { get; init;}
+ public int Piety { get; init;}
+ public int Tenacity { get; init;}
+}
\ No newline at end of file
diff --git a/XIVCalc.Tests/SimpleTests.cs b/XIVCalc.Tests/SimpleTests.cs
new file mode 100644
index 0000000..75f9b35
--- /dev/null
+++ b/XIVCalc.Tests/SimpleTests.cs
@@ -0,0 +1,42 @@
+using Lumina.Excel.GeneratedSheets;
+using XIVCalc.Calculations;
+
+namespace XIVCalc.Tests;
+
+public class SimpleTests
+{
+ private ClassJob WHM = new ClassJob()
+ {
+ ModifierStrength = 55,
+ ModifierDexterity = 105,
+ ModifierIntelligence = 105,
+ ModifierMind = 115,
+ ModifierVitality = 100,
+ ModifierHitPoints = 105,
+ PrimaryStat = (byte) StatType.Mind,
+ };
+
+ [SetUp]
+ public void Setup()
+ {
+ }
+
+ [Test]
+ public void MainStatMulti()
+ {
+ Assert.Multiple(() =>
+ {
+ Assert.That(StatEquations.MainStatMultiplier(440, 100, WHM), Is.EqualTo(1d));
+ Assert.That(StatEquations.MainStatMultiplier(452, 100, WHM), Is.EqualTo(1.06));
+ Assert.That(StatEquations.MainStatMultiplier(531, 100, WHM), Is.EqualTo( 1.49));
+ Assert.That(StatEquations.MainStatMultiplier(555, 100, WHM), Is.EqualTo( 1.61));
+ Assert.That(StatEquations.MainStatMultiplier(629, 100, WHM), Is.EqualTo( 2.01));
+ });
+ }
+
+ [Test]
+ public void TestBasicStats()
+ {
+ Assert.Pass();
+ }
+}
\ No newline at end of file
diff --git a/XIVCalc.Tests/XIVCalc.Tests.csproj b/XIVCalc.Tests/XIVCalc.Tests.csproj
new file mode 100644
index 0000000..e2950f3
--- /dev/null
+++ b/XIVCalc.Tests/XIVCalc.Tests.csproj
@@ -0,0 +1,29 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/XIVCalc.sln b/XIVCalc.sln
index b066df1..9e35667 100644
--- a/XIVCalc.sln
+++ b/XIVCalc.sln
@@ -5,6 +5,8 @@ VisualStudioVersion = 17.4.33205.214
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XIVCalc", "XIVCalc\XIVCalc.csproj", "{C4D9F54E-983A-45DD-A6E5-F36BF4E54FBE}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XIVCalc.Tests", "XIVCalc.Tests\XIVCalc.Tests.csproj", "{576C4195-146C-4058-B5E4-3A1F1FD04D24}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
{C4D9F54E-983A-45DD-A6E5-F36BF4E54FBE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C4D9F54E-983A-45DD-A6E5-F36BF4E54FBE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C4D9F54E-983A-45DD-A6E5-F36BF4E54FBE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {576C4195-146C-4058-B5E4-3A1F1FD04D24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {576C4195-146C-4058-B5E4-3A1F1FD04D24}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {576C4195-146C-4058-B5E4-3A1F1FD04D24}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {576C4195-146C-4058-B5E4-3A1F1FD04D24}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/XIVCalc/Calculations/Stats.cs b/XIVCalc/Calculations/Stats.cs
index 621ba61..5850591 100644
--- a/XIVCalc/Calculations/Stats.cs
+++ b/XIVCalc/Calculations/Stats.cs
@@ -182,6 +182,20 @@ public static double GetHpMultiplier(int level, Job job)
};
}
+ private static double MainStatPowerMod(int level, ClassJob job) => (job.IsTank(), level) switch
+ {
+ (_,< 70) => 100,
+ (true,< 80) => 105,
+ (false, < 80) => 125,
+ (true, < 90) => 115,
+ (false,< 90) => 165,
+ (true, < 100) => 156,
+ (false, < 100) => 195,
+ (true, _) => 190,
+ (_,_) => 237,
+
+ };
+
public static double CritDamage(int criticalHit, int level) =>
Floor(1400 + 200 * (criticalHit - LevelTable.SUB(level)) / LevelTable.DIV(level)) / 1000d;
@@ -293,7 +307,7 @@ public static double WeaponDamageMultiplier(int weaponDamage, int level, ClassJo
/// Active job
/// Damage Multiplier F(AP)/F(ATK)
public static double MainStatMultiplier(int mainStat, int level, ClassJob job) =>
- Max(Floor(GetAttackModifierM(level, job) * (mainStat - LevelTable.MAIN(level)/LevelTable.MAIN(level)))/100d,0);
+ Max(0, (Floor(MainStatPowerMod(level,job) * (mainStat - LevelTable.MAIN(level)) / LevelTable.MAIN(level) + 100) / 100f));
///
/// Like , but for auto-attacks.