Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -501,4 +501,7 @@ fabric.properties
/documentation/*.received.md
/documentation/*.received.txt
/documentation/*.approved.txt
build_output.txt
build_output.txt
# Vim swap files
*.swp
*.swo
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Family Experience Table
- Level 1 - XP: 100000
- Level 2 - XP: 250000
- Level 3 - XP: 370000
- Level 4 - XP: 560000
- Level 5 - XP: 840000
- Level 6 - XP: 1260000
- Level 7 - XP: 1900000
- Level 8 - XP: 2850000
- Level 9 - XP: 3570000
- Level 10 - XP: 3830000
- Level 11 - XP: 4150000
- Level 12 - XP: 4750000
- Level 13 - XP: 5500000
- Level 14 - XP: 6500000
- Level 15 - XP: 7000000
- Level 16 - XP: 8500000
- Level 17 - XP: 9500000
- Level 18 - XP: 10000000
- Level 19 - XP: 17000000
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Mate Experience Table
- Level 1 - Pet: 15 - Partner: 60
- Level 2 - Pet: 42 - Partner: 168
- Level 3 - Pet: 90 - Partner: 360
- Level 4 - Pet: 165 - Partner: 660
- Level 5 - Pet: 273 - Partner: 1092
- Level 6 - Pet: 420 - Partner: 1680
- Level 7 - Pet: 612 - Partner: 2448
- Level 8 - Pet: 855 - Partner: 3420
- Level 9 - Pet: 1155 - Partner: 4620
- Level 10 - Pet: 1518 - Partner: 6072
- Level 11 - Pet: 1950 - Partner: 7800
- Level 12 - Pet: 2457 - Partner: 9828
- Level 13 - Pet: 3045 - Partner: 12180
- Level 14 - Pet: 3720 - Partner: 14880
- Level 15 - Pet: 5256 - Partner: 21024
- Level 16 - Pet: 6990 - Partner: 27960
- Level 17 - Pet: 8934 - Partner: 35736
- Level 18 - Pet: 11100 - Partner: 44400
- Level 19 - Pet: 13500 - Partner: 54000
- Level 20 - Pet: 16146 - Partner: 64584
- Level 21 - Pet: 19050 - Partner: 76200
- Level 22 - Pet: 22224 - Partner: 88896
- Level 23 - Pet: 25680 - Partner: 102720
- Level 24 - Pet: 29430 - Partner: 117720
- Level 25 - Pet: 33486 - Partner: 133944
- Level 26 - Pet: 37860 - Partner: 151440
- Level 27 - Pet: 42564 - Partner: 170256
- Level 28 - Pet: 47610 - Partner: 190440
- Level 29 - Pet: 53010 - Partner: 212040
- Level 30 - Pet: 58776 - Partner: 235104
- Level 31 - Pet: 64920 - Partner: 259680
- Level 32 - Pet: 71454 - Partner: 285816
- Level 33 - Pet: 78390 - Partner: 313560
- Level 34 - Pet: 85740 - Partner: 342960
- Level 35 - Pet: 93516 - Partner: 374064
- Level 36 - Pet: 101730 - Partner: 406920
- Level 37 - Pet: 110394 - Partner: 441576
- Level 38 - Pet: 119520 - Partner: 478080
- Level 39 - Pet: 129120 - Partner: 516480
- Level 40 - Pet: 161059 - Partner: 644236
- Level 41 - Pet: 194575 - Partner: 778300
- Level 42 - Pet: 229706 - Partner: 918824
- Level 43 - Pet: 266490 - Partner: 1065960
- Level 44 - Pet: 304965 - Partner: 1219860
- Level 45 - Pet: 345169 - Partner: 1380676
- Level 46 - Pet: 387140 - Partner: 1548560
- Level 47 - Pet: 430916 - Partner: 1723664
- Level 48 - Pet: 476535 - Partner: 1906140
- Level 49 - Pet: 524035 - Partner: 2096140
- Level 50 - Pet: 573454 - Partner: 2293816
- Level 51 - Pet: 624830 - Partner: 2499320
- Level 52 - Pet: 678201 - Partner: 2712804
- Level 53 - Pet: 733605 - Partner: 2934420
- Level 54 - Pet: 791080 - Partner: 3164320
- Level 55 - Pet: 850664 - Partner: 3402656
- Level 56 - Pet: 912395 - Partner: 3649580
- Level 57 - Pet: 976311 - Partner: 3905244
- Level 58 - Pet: 1042450 - Partner: 4169800
- Level 59 - Pet: 1110850 - Partner: 4443400
- Level 60 - Pet: 1371320 - Partner: 5485280
- Level 61 - Pet: 1640400 - Partner: 6561600
- Level 62 - Pet: 1918230 - Partner: 7672920
- Level 63 - Pet: 2204950 - Partner: 8819800
- Level 64 - Pet: 2500700 - Partner: 10002800
- Level 65 - Pet: 2805620 - Partner: 11222480
- Level 66 - Pet: 3119850 - Partner: 12479400
- Level 67 - Pet: 3443530 - Partner: 13774120
- Level 68 - Pet: 3776800 - Partner: 15107200
- Level 69 - Pet: 4119800 - Partner: 16479200
- Level 70 - Pet: 4472670 - Partner: 17890680
- Level 71 - Pet: 4835550 - Partner: 19342200
- Level 72 - Pet: 5208580 - Partner: 20834320
- Level 73 - Pet: 5591900 - Partner: 22367600
- Level 74 - Pet: 5985650 - Partner: 23942600
- Level 75 - Pet: 6389970 - Partner: 25559880
- Level 76 - Pet: 6805000 - Partner: 27220000
- Level 77 - Pet: 7230880 - Partner: 28923520
- Level 78 - Pet: 7667750 - Partner: 30671000
- Level 79 - Pet: 8115750 - Partner: 32463000
- Level 80 - Pet: 9756000 - Partner: 39024000
- Level 81 - Pet: 11437000 - Partner: 45748000
- Level 82 - Pet: 13159250 - Partner: 52637000
- Level 83 - Pet: 16334450 - Partner: 65337800
- Level 84 - Pet: 19585700 - Partner: 78342800
- Level 85 - Pet: 24393100 - Partner: 97572400
- Level 86 - Pet: 29312950 - Partner: 117251800
- Level 87 - Pet: 34346550 - Partner: 137386200
- Level 88 - Pet: 39495200 - Partner: 157980800
- Level 89 - Pet: 44760200 - Partner: 179040800
- Level 90 - Pet: 50142850 - Partner: 200571400
- Level 91 - Pet: 55644450 - Partner: 222577800
- Level 92 - Pet: 61266300 - Partner: 245065200
- Level 93 - Pet: 67009700 - Partner: 268038800
- Level 94 - Pet: 72875950 - Partner: 291503800
- Level 95 - Pet: 78866350 - Partner: 315465400
- Level 96 - Pet: 84982200 - Partner: 339928800
- Level 97 - Pet: 91224800 - Partner: 364899200
- Level 98 - Pet: 97595450 - Partner: 390381800
- Level 99 - Pet: 104095450 - Partner: 416381800
1 change: 1 addition & 0 deletions src/NosCore.Algorithm/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ internal class Constants
internal const byte MaxFairyLevel = 80;
internal const byte MaxJobLevel = 80;
internal const byte MaxHeroLevel = 60;
internal const byte MaxMateLevel = 99;
internal static readonly int ClassCount = Enum.GetNames(typeof(CharacterClassType)).Length;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
// -----------------------------------

namespace NosCore.Algorithm.FamilyExperienceService
{
/// <summary>
/// Provides family experience requirement calculations for different levels
/// </summary>
/// <remarks>
/// A ginfo line puts a level 7 family's bar at 640 000 against the 1 900 000 here, so at
/// least that row is suspect. One observation is not enough to rebuild the curve, so the
/// table stands until more levels can be checked.
/// </remarks>
public class FamilyExperienceService : IFamilyExperienceService
{
private static readonly uint[] FamilyXpData =
[
100_000, 250_000, 370_000, 560_000, 840_000,
1_260_000, 1_900_000, 2_850_000, 3_570_000, 3_830_000,
4_150_000, 4_750_000, 5_500_000, 6_500_000, 7_000_000,
8_500_000, 9_500_000, 10_000_000, 17_000_000
];

/// <summary>
/// Gets the experience a family needs to leave a specific level
/// </summary>
/// <param name="level">The family level</param>
/// <returns>The experience required, or uint.MaxValue past the last known level</returns>
public uint GetFamilyExperience(byte level)
{
return level >= 1 && level <= FamilyXpData.Length ? FamilyXpData[level - 1] : uint.MaxValue;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
// -----------------------------------

namespace NosCore.Algorithm.FamilyExperienceService
{
/// <summary>
/// Service for calculating family experience requirements
/// </summary>
public interface IFamilyExperienceService
{
/// <summary>
/// Gets the experience a family needs to leave a specific level
/// </summary>
/// <param name="level">The family level</param>
/// <returns>The experience required</returns>
uint GetFamilyExperience(byte level);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
// -----------------------------------

namespace NosCore.Algorithm.MateExperienceService
{
/// <summary>
/// Service for calculating pet and partner experience requirements
/// </summary>
public interface IMateExperienceService
{
/// <summary>
/// Gets the experience a pet needs to leave a specific level
/// </summary>
/// <param name="level">The pet level</param>
/// <returns>The experience required</returns>
long GetPetExperience(byte level);

/// <summary>
/// Gets the experience a partner needs to leave a specific level
/// </summary>
/// <param name="level">The partner level</param>
/// <returns>The experience required</returns>
long GetPartnerExperience(byte level);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
// -----------------------------------

namespace NosCore.Algorithm.MateExperienceService
{
/// <summary>
/// Provides pet and partner experience requirement calculations for different levels
/// </summary>
/// <remarks>
/// A pet needs a twentieth of the curve and a partner a fifth. Both divisors come from the
/// XpLoad field of sc_p and sc_n, which match to the unit across eleven levels between 1
/// and 88.
/// </remarks>
public class MateExperienceService : IMateExperienceService
{
private const int PetDivisor = 20;
private const int PartnerDivisor = 5;

private readonly long[] _mateXpData = new long[Constants.MaxMateLevel + 1];

/// <summary>
/// Initializes a new instance of the MateExperienceService and pre-calculates experience
/// requirements for all mate levels
/// </summary>
public MateExperienceService()
{
var step = new double[_mateXpData.Length];
step[0] = 540;
step[1] = 960;
for (var i = 2; i < step.Length; i++)
{
step[i] = step[i - 1] + 420 + 120 * (i - 1);
}

var factor = 1d;
_mateXpData[0] = 300;
for (var i = 1; i < _mateXpData.Length; i++)
{
if (i < 79)
{
factor = i switch
{
14 => 6 / 3d,
39 => 19 / 3d,
59 => 70 / 3d,
_ => factor
};

_mateXpData[i] = (long)(_mateXpData[i - 1] + factor * step[i - 1]);
continue;
}

factor = i switch
{
79 => 5000,
82 => 9000,
84 => 13000,
_ => factor
};

_mateXpData[i] = (long)(_mateXpData[i - 1] + factor * (i + 2) * (i + 2));
}
}

/// <summary>
/// Gets the experience a pet needs to leave a specific level
/// </summary>
/// <param name="level">The pet level</param>
/// <returns>The experience required</returns>
public long GetPetExperience(byte level)
{
return At(level) / PetDivisor;
}

/// <summary>
/// Gets the experience a partner needs to leave a specific level
/// </summary>
/// <param name="level">The partner level</param>
/// <returns>The experience required</returns>
public long GetPartnerExperience(byte level)
{
return At(level) / PartnerDivisor;
}

private long At(byte level)
{
var index = level < 1 ? 0 : level - 1;
return _mateXpData[index >= _mateXpData.Length ? _mateXpData.Length - 1 : index];
}
}
}
34 changes: 34 additions & 0 deletions test/NosCore.Algorithm.Tests/DocumentationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -405,5 +405,39 @@ public void SumDocumentation()

Approvals.Verify(WriterFactory.CreateTextWriter(resultBuilder.ToString(), "md"));
}

[TestMethod]
public void MateExperienceDocumentation()
{
var mateExperienceService = new MateExperienceService.MateExperienceService();

var resultBuilder = new StringBuilder("# Mate Experience Table");
resultBuilder.AppendLine();

for (byte level = 1; level < 100; level++)
{
resultBuilder.AppendLine(
$"- Level {level,2} - Pet: {mateExperienceService.GetPetExperience(level)} - Partner: {mateExperienceService.GetPartnerExperience(level)}");
}

Approvals.Verify(WriterFactory.CreateTextWriter(resultBuilder.ToString(), "md"));
}

[TestMethod]
public void FamilyExperienceDocumentation()
{
var familyExperienceService = new FamilyExperienceService.FamilyExperienceService();

var resultBuilder = new StringBuilder("# Family Experience Table");
resultBuilder.AppendLine();

for (byte level = 1; level < 20; level++)
{
resultBuilder.AppendLine(
$"- Level {level,2} - XP: {familyExperienceService.GetFamilyExperience(level)}");
}

Approvals.Verify(WriterFactory.CreateTextWriter(resultBuilder.ToString(), "md"));
}
}
}
Loading