diff --git a/documentation/DocumentationTest.CellonDocumentation.approved.md b/documentation/DocumentationTest.CellonDocumentation.approved.md new file mode 100644 index 0000000..1c3e9e4 --- /dev/null +++ b/documentation/DocumentationTest.CellonDocumentation.approved.md @@ -0,0 +1,70 @@ +# Cellon Table +## Cellon 1 - Cost: 700 +- Hp: 30 - 100 +- Mp: 50 - 120 +- HpRecovery: 5 - 10 +- MpRecovery: 8 - 15 + +## Cellon 2 - Cost: 1400 +- Hp: 120 - 200 +- Mp: 150 - 250 +- HpRecovery: 14 - 20 +- MpRecovery: 16 - 25 + +## Cellon 3 - Cost: 3000 +- Hp: 220 - 300 +- Mp: 280 - 330 +- HpRecovery: 22 - 28 +- MpRecovery: 28 - 35 + +## Cellon 4 - Cost: 5000 +- Hp: 330 - 400 +- Mp: 350 - 420 +- HpRecovery: 30 - 38 +- MpRecovery: 38 - 45 + +## Cellon 5 - Cost: 10000 +- Hp: 430 - 550 +- Mp: 450 - 550 +- HpRecovery: 40 - 50 +- MpRecovery: 50 - 60 + +## Cellon 6 - Cost: 20000 +- Hp: 600 - 750 +- Mp: 600 - 750 +- HpRecovery: 55 - 70 +- MpRecovery: 65 - 80 +- MpConsumption: 1 - 7 +- CriticalDamageDecrease: 1 - 10 + +## Cellon 7 - Cost: 32000 +- Hp: 800 - 1000 +- Mp: 800 - 1000 +- HpRecovery: 75 - 90 +- MpRecovery: 75 - 90 +- MpConsumption: 8 - 12 +- CriticalDamageDecrease: 11 - 20 + +## Cellon 8 - Cost: 58000 +- Hp: 1000 - 1300 +- Mp: 1000 - 1300 +- HpRecovery: 100 - 120 +- MpRecovery: 100 - 120 +- MpConsumption: 13 - 17 +- CriticalDamageDecrease: 21 - 35 + +## Cellon 9 - Cost: 95000 +- Hp: 1100 - 1500 +- Mp: 1100 - 1500 +- HpRecovery: 110 - 135 +- MpRecovery: 110 - 135 +- MpConsumption: 14 - 21 +- CriticalDamageDecrease: 22 - 45 + +## Cellon 10 - Cost: 134900 +- Hp: 1200 - 1700 +- Mp: 1200 - 1700 +- HpRecovery: 120 - 150 +- MpRecovery: 120 - 150 +- MpConsumption: 15 - 25 +- CriticalDamageDecrease: 23 - 55 diff --git a/src/NosCore.Algorithm/CellonService/CellonOption.cs b/src/NosCore.Algorithm/CellonService/CellonOption.cs new file mode 100644 index 0000000..e001a52 --- /dev/null +++ b/src/NosCore.Algorithm/CellonService/CellonOption.cs @@ -0,0 +1,18 @@ +// __ _ __ __ ___ __ ___ ___ +// | \| |/__\ /' _/ / _//__\| _ \ __| +// | | ' | \/ |`._`.| \_| \/ | v / _| +// |_|\__|\__/ |___/ \__/\__/|_|_\___| +// ----------------------------------- + +using NosCore.Shared.Enumerations; + +namespace NosCore.Algorithm.CellonService +{ + /// + /// An option a cellon can roll, with the inclusive range its value is drawn from + /// + /// The option type + /// The lowest value the option can roll + /// The highest value the option can roll + public sealed record CellonOption(CellonType Type, int Minimum, int Maximum); +} diff --git a/src/NosCore.Algorithm/CellonService/CellonService.cs b/src/NosCore.Algorithm/CellonService/CellonService.cs new file mode 100644 index 0000000..83f956f --- /dev/null +++ b/src/NosCore.Algorithm/CellonService/CellonService.cs @@ -0,0 +1,56 @@ +// __ _ __ __ ___ __ ___ ___ +// | \| |/__\ /' _/ / _//__\| _ \ __| +// | | ' | \/ |`._`.| \_| \/ | v / _| +// |_|\__|\__/ |___/ \__/\__/|_|_\___| +// ----------------------------------- + +using System; +using System.Collections.Generic; +using NosCore.Shared.Enumerations; + +namespace NosCore.Algorithm.CellonService +{ + /// + /// Provides the options a cellon can add to an accessory and what applying it costs + /// + public class CellonService : ICellonService + { + internal static readonly long[] Price = + { 0, 700, 1400, 3000, 5000, 10000, 20000, 32000, 58000, 95000, 134900 }; + + internal static readonly CellonOption[][] Options = + { + Array.Empty(), + new CellonOption[] { new(CellonType.Hp, 30, 100), new(CellonType.Mp, 50, 120), new(CellonType.HpRecovery, 5, 10), new(CellonType.MpRecovery, 8, 15) }, + new CellonOption[] { new(CellonType.Hp, 120, 200), new(CellonType.Mp, 150, 250), new(CellonType.HpRecovery, 14, 20), new(CellonType.MpRecovery, 16, 25) }, + new CellonOption[] { new(CellonType.Hp, 220, 300), new(CellonType.Mp, 280, 330), new(CellonType.HpRecovery, 22, 28), new(CellonType.MpRecovery, 28, 35) }, + new CellonOption[] { new(CellonType.Hp, 330, 400), new(CellonType.Mp, 350, 420), new(CellonType.HpRecovery, 30, 38), new(CellonType.MpRecovery, 38, 45) }, + new CellonOption[] { new(CellonType.Hp, 430, 550), new(CellonType.Mp, 450, 550), new(CellonType.HpRecovery, 40, 50), new(CellonType.MpRecovery, 50, 60) }, + new CellonOption[] { new(CellonType.Hp, 600, 750), new(CellonType.Mp, 600, 750), new(CellonType.HpRecovery, 55, 70), new(CellonType.MpRecovery, 65, 80), new(CellonType.MpConsumption, 1, 7), new(CellonType.CriticalDamageDecrease, 1, 10) }, + new CellonOption[] { new(CellonType.Hp, 800, 1000), new(CellonType.Mp, 800, 1000), new(CellonType.HpRecovery, 75, 90), new(CellonType.MpRecovery, 75, 90), new(CellonType.MpConsumption, 8, 12), new(CellonType.CriticalDamageDecrease, 11, 20) }, + new CellonOption[] { new(CellonType.Hp, 1000, 1300), new(CellonType.Mp, 1000, 1300), new(CellonType.HpRecovery, 100, 120), new(CellonType.MpRecovery, 100, 120), new(CellonType.MpConsumption, 13, 17), new(CellonType.CriticalDamageDecrease, 21, 35) }, + new CellonOption[] { new(CellonType.Hp, 1100, 1500), new(CellonType.Mp, 1100, 1500), new(CellonType.HpRecovery, 110, 135), new(CellonType.MpRecovery, 110, 135), new(CellonType.MpConsumption, 14, 21), new(CellonType.CriticalDamageDecrease, 22, 45) }, + new CellonOption[] { new(CellonType.Hp, 1200, 1700), new(CellonType.Mp, 1200, 1700), new(CellonType.HpRecovery, 120, 150), new(CellonType.MpRecovery, 120, 150), new(CellonType.MpConsumption, 15, 25), new(CellonType.CriticalDamageDecrease, 23, 55) }, + }; + + /// + /// Gets the options a cellon of a specific level can roll + /// + /// The cellon level + /// The options, or an empty list for a level no cellon has + public IReadOnlyList GetOptions(byte level) + { + return level <= Constants.MaxCellonLevel ? Array.AsReadOnly(Options[level]) : Array.Empty(); + } + + /// + /// Gets the gold cost of applying a cellon of a specific level + /// + /// The cellon level + /// The gold cost + public long GetPrice(byte level) + { + return Price[level]; + } + } +} diff --git a/src/NosCore.Algorithm/CellonService/ICellonService.cs b/src/NosCore.Algorithm/CellonService/ICellonService.cs new file mode 100644 index 0000000..5a21fb4 --- /dev/null +++ b/src/NosCore.Algorithm/CellonService/ICellonService.cs @@ -0,0 +1,30 @@ +// __ _ __ __ ___ __ ___ ___ +// | \| |/__\ /' _/ / _//__\| _ \ __| +// | | ' | \/ |`._`.| \_| \/ | v / _| +// |_|\__|\__/ |___/ \__/\__/|_|_\___| +// ----------------------------------- + +using System.Collections.Generic; + +namespace NosCore.Algorithm.CellonService +{ + /// + /// Service for retrieving the options a cellon can add to an accessory and what applying it costs + /// + public interface ICellonService + { + /// + /// Gets the options a cellon of a specific level can roll + /// + /// The cellon level + /// The options, or an empty list for a level no cellon has + IReadOnlyList GetOptions(byte level); + + /// + /// Gets the gold cost of applying a cellon of a specific level + /// + /// The cellon level + /// The gold cost + long GetPrice(byte level); + } +} diff --git a/src/NosCore.Algorithm/Constants.cs b/src/NosCore.Algorithm/Constants.cs index 1d90315..96566f9 100644 --- a/src/NosCore.Algorithm/Constants.cs +++ b/src/NosCore.Algorithm/Constants.cs @@ -12,6 +12,7 @@ internal class Constants internal const byte MaxMateLevel = 99; internal const byte MaxFamilyLevel = 30; internal const byte MaxGroupSize = 3; + internal const byte MaxCellonLevel = 10; internal static readonly int ClassCount = Enum.GetNames(typeof(CharacterClassType)).Length; } } diff --git a/src/NosCore.Algorithm/NosCore.Algorithm.csproj b/src/NosCore.Algorithm/NosCore.Algorithm.csproj index a9280f6..34b8530 100644 --- a/src/NosCore.Algorithm/NosCore.Algorithm.csproj +++ b/src/NosCore.Algorithm/NosCore.Algorithm.csproj @@ -13,7 +13,7 @@ https://github.com/NosCoreIO/NosCore.Algorithm.git nostale, noscore, nostale private server source, nostale emulator - 2.1.0 + 2.3.0 false NosCore's Algorithm GPL-3.0-only @@ -29,7 +29,7 @@ - + diff --git a/test/NosCore.Algorithm.Tests/DocumentationTest.cs b/test/NosCore.Algorithm.Tests/DocumentationTest.cs index c32bc15..33a367c 100644 --- a/test/NosCore.Algorithm.Tests/DocumentationTest.cs +++ b/test/NosCore.Algorithm.Tests/DocumentationTest.cs @@ -406,6 +406,34 @@ public void SumDocumentation() Approvals.Verify(WriterFactory.CreateTextWriter(resultBuilder.ToString(), "md")); } + [TestMethod] + public void CellonDocumentation() + { + var cellonService = new CellonService.CellonService(); + + var resultBuilder = new StringBuilder("# Cellon Table"); + for (byte level = 1; level <= 10; level++) + { + resultBuilder.AppendLine(); + resultBuilder.AppendLine($"## Cellon {level} - Cost: {cellonService.GetPrice(level)}"); + foreach (var option in cellonService.GetOptions(level)) + { + resultBuilder.AppendLine($"- {option.Type}: {option.Minimum} - {option.Maximum}"); + } + } + + Approvals.Verify(WriterFactory.CreateTextWriter(resultBuilder.ToString(), "md")); + } + + [TestMethod] + public void NoCellonLevelHasNoOptions() + { + var cellonService = new CellonService.CellonService(); + + Assert.AreEqual(0, cellonService.GetOptions(0).Count); + Assert.AreEqual(0, cellonService.GetOptions(11).Count); + } + [TestMethod] public void MateExperienceDocumentation() {