diff --git a/Maple2.File.Parser/Maple2.File.Parser.csproj b/Maple2.File.Parser/Maple2.File.Parser.csproj
index 985a1a1..2a37cf9 100644
--- a/Maple2.File.Parser/Maple2.File.Parser.csproj
+++ b/Maple2.File.Parser/Maple2.File.Parser.csproj
@@ -13,7 +13,7 @@
MapleStory2, File, Parser, m2d, xml
true
- 2.4.28
+ 2.4.29
net8.0
README.md
enable
diff --git a/Maple2.File.Parser/ServerTableParser.cs b/Maple2.File.Parser/ServerTableParser.cs
index 0e84ba4..3b5cecc 100644
--- a/Maple2.File.Parser/ServerTableParser.cs
+++ b/Maple2.File.Parser/ServerTableParser.cs
@@ -66,6 +66,7 @@ public class ServerTableParser {
private readonly XmlSerializer maidGradeInfoSerializer;
private readonly XmlSerializer maidRecipeSerializer;
private readonly XmlSerializer defaultCharacterInfoSerializer;
+ private readonly XmlSerializer dungeonScaleStatSerializer;
public ServerTableParser(M2dReader xmlReader) {
this.xmlReader = xmlReader;
@@ -113,6 +114,7 @@ public ServerTableParser(M2dReader xmlReader) {
maidGradeInfoSerializer = new XmlSerializer(typeof(MaidGradeInfoRoot));
maidRecipeSerializer = new XmlSerializer(typeof(MaidRecipeRoot));
defaultCharacterInfoSerializer = new XmlSerializer(typeof(DefaultCharacterInfoRoot));
+ dungeonScaleStatSerializer = new XmlSerializer(typeof(DungeonScaleStatRoot));
// var seen = new HashSet();
// this.bankTypeSerializer.UnknownAttribute += (sender, args) => {
@@ -768,4 +770,14 @@ public IEnumerable ParseNpcStatFactorByLevel() {
yield return (info.value, info);
}
}
+
+ public IEnumerable<(int Id, DungeonScaleStat ScaleStat)> ParseDungeonScaleStat() {
+ XmlReader reader = xmlReader.GetXmlReader(xmlReader.GetEntry("table/Server/DungeonScaleStat.xml"));
+ var data = dungeonScaleStatSerializer.Deserialize(reader) as DungeonScaleStatRoot;
+ Debug.Assert(data != null);
+
+ foreach (DungeonScaleStat entry in data.DungeonScaleStat) {
+ yield return (entry.dungeonScaleStatID, entry);
+ }
+ }
}
diff --git a/Maple2.File.Parser/Xml/Table/Server/DungeonScaleStat.cs b/Maple2.File.Parser/Xml/Table/Server/DungeonScaleStat.cs
new file mode 100644
index 0000000..54509b3
--- /dev/null
+++ b/Maple2.File.Parser/Xml/Table/Server/DungeonScaleStat.cs
@@ -0,0 +1,18 @@
+using System.Xml.Serialization;
+
+namespace Maple2.File.Parser.Xml.Table.Server;
+
+// ./data/server/table/Server/DungeonScaleStat.xml
+// Per-dungeon counterpart of the scale* attributes in npc Stat. No dungeonroom column references it.
+[XmlRoot("ms2")]
+public class DungeonScaleStatRoot {
+ [XmlElement] public List DungeonScaleStat;
+}
+
+public partial class DungeonScaleStat {
+ [XmlAttribute] public int dungeonScaleStatID;
+ [XmlAttribute] public float scaleStatRate;
+ [XmlAttribute] public long scaleBaseTap;
+ [XmlAttribute] public long scaleBaseDef;
+ [XmlAttribute] public float scaleBaseSpaRate;
+}
diff --git a/Maple2.File.Tests/ServerTableParserTest.cs b/Maple2.File.Tests/ServerTableParserTest.cs
index d2b415c..5a84fd0 100644
--- a/Maple2.File.Tests/ServerTableParserTest.cs
+++ b/Maple2.File.Tests/ServerTableParserTest.cs
@@ -513,5 +513,21 @@ public void TestDefaultCharacterInfo() {
Assert.AreNotEqual(Vector3.Zero, hair.controls.control[0].position);
Assert.AreNotEqual(Vector3.Zero, hair.controls.control[0].rotation);
}
+
+ [TestMethod]
+ public void TestDungeonScaleStat() {
+ var parser = new ServerTableParser(TestUtils.ServerReader);
+
+ Dictionary scaleStats = parser.ParseDungeonScaleStat()
+ .ToDictionary(entry => entry.Id, entry => entry.ScaleStat);
+
+ // Retail row:
+ DungeonScaleStat row = scaleStats[6001];
+ Assert.AreEqual(8.0f, row.scaleStatRate);
+ Assert.AreEqual(1911810L, row.scaleBaseTap);
+ Assert.AreEqual(2552L, row.scaleBaseDef);
+ Assert.AreEqual(0.35f, row.scaleBaseSpaRate);
+ }
}