diff --git a/Maple2.File.Parser/Maple2.File.Parser.csproj b/Maple2.File.Parser/Maple2.File.Parser.csproj index ab4ad23..5917e98 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.33 + 2.4.34 net8.0 README.md enable diff --git a/Maple2.File.Parser/ServerTableParser.cs b/Maple2.File.Parser/ServerTableParser.cs index 2a1e101..c959bd0 100644 --- a/Maple2.File.Parser/ServerTableParser.cs +++ b/Maple2.File.Parser/ServerTableParser.cs @@ -44,6 +44,7 @@ public class ServerTableParser { private readonly XmlSerializer spawnInteractObjectSerializer; private readonly XmlSerializer groupSpawnSerializer; private readonly XmlSerializer shadowExpeditionDropSerializer; + private readonly XmlSerializer additionalEffectGroupSerializer; private readonly XmlSerializer fishSerializer; private readonly XmlSerializer fishingSpotSerializer; private readonly XmlSerializer fishLureSerializer; @@ -93,6 +94,7 @@ public ServerTableParser(M2dReader xmlReader) { spawnInteractObjectSerializer = new XmlSerializer(typeof(SpawnInteractObjectRoot)); groupSpawnSerializer = new XmlSerializer(typeof(GroupSpawnRoot)); shadowExpeditionDropSerializer = new XmlSerializer(typeof(ShadowExpeditionDropRoot)); + additionalEffectGroupSerializer = new XmlSerializer(typeof(AdditionalEffectGroupRoot)); fishSerializer = new XmlSerializer(typeof(FishRoot)); fishingSpotSerializer = new XmlSerializer(typeof(FishingSpotRoot)); fishLureSerializer = new XmlSerializer(typeof(FishLureRoot)); @@ -524,6 +526,17 @@ public IEnumerable ParseShadowExpeditionDrop() { } } + public IEnumerable<(int Id, AdditionalEffectGroup Group)> ParseAdditionalEffectGroup() { + string xml = Sanitizer.RemoveEmpty(xmlReader.GetString(xmlReader.GetEntry("table/Server/additionalEffectGroup.xml"))); + var reader = XmlReader.Create(new StringReader(xml)); + var data = additionalEffectGroupSerializer.Deserialize(reader) as AdditionalEffectGroupRoot; + Debug.Assert(data != null); + + foreach (AdditionalEffectGroup group in data.group) { + yield return (group.groupId, group); + } + } + public IEnumerable<(int Id, Fish Fish)> ParseFish() { string xml = Sanitizer.RemoveEmpty(xmlReader.GetString(xmlReader.GetEntry("table/Server/fish.xml"))); var reader = XmlReader.Create(new StringReader(xml)); diff --git a/Maple2.File.Parser/Xml/Npc/AdditionalEffect.cs b/Maple2.File.Parser/Xml/Npc/AdditionalEffect.cs index d550322..77acf1d 100644 --- a/Maple2.File.Parser/Xml/Npc/AdditionalEffect.cs +++ b/Maple2.File.Parser/Xml/Npc/AdditionalEffect.cs @@ -5,7 +5,7 @@ namespace Maple2.File.Parser.Xml.Npc; public partial class AdditionalEffect { [M2dArray] public int[] codes = Array.Empty(); [M2dArray] public short[] levels = Array.Empty(); - [M2dArray(Delimiter = ':')] public string[] group = Array.Empty(); + [M2dArray] public int[] group = Array.Empty(); [M2dArray] public int[] rewardCodes = Array.Empty(); [M2dArray] public short[] rewardLevels = Array.Empty(); } diff --git a/Maple2.File.Parser/Xml/Table/Server/AdditionalEffectGroup.cs b/Maple2.File.Parser/Xml/Table/Server/AdditionalEffectGroup.cs new file mode 100644 index 0000000..ee868a3 --- /dev/null +++ b/Maple2.File.Parser/Xml/Table/Server/AdditionalEffectGroup.cs @@ -0,0 +1,22 @@ +using System.Xml.Serialization; +using M2dXmlGenerator; + +namespace Maple2.File.Parser.Xml.Table.Server; + +// ./data/server/table/Server/additionalEffectGroup.xml +// An npc's names group G and how many of its rows to roll. +[XmlRoot("ms2")] +public class AdditionalEffectGroupRoot { + [XmlElement] public List group; +} + +public partial class AdditionalEffectGroup { + [XmlAttribute] public int groupId; + [XmlElement] public List value; + + // One row is one buff. Two ids are a visible effect plus its hidden driver or splash helper. + public partial class Value { + [M2dArray] public int[] effectId = Array.Empty(); + [M2dArray] public short[] effectLevel = Array.Empty(); + } +} diff --git a/Maple2.File.Tests/NpcParserTest.cs b/Maple2.File.Tests/NpcParserTest.cs index 919f7dd..6bcb523 100644 --- a/Maple2.File.Tests/NpcParserTest.cs +++ b/Maple2.File.Tests/NpcParserTest.cs @@ -29,6 +29,22 @@ public void TestNpcParser() { Assert.AreEqual(7535, count); } + [TestMethod] + public void TestNpcAdditionalEffectGroup() { + var locale = Locale.NA; + Filter.Load(TestUtils.XmlReader, locale.ToString(), "Live"); + var parser = new NpcParser(TestUtils.XmlReader, "en"); + + // npc 49300001 (Destroyer), ShadowExpedition: + // npc 21000001 (Orange Mushroom): group="" + Dictionary npcs = parser.Parse() + .Where(entry => entry.Id is 49300001 or 21000001) + .ToDictionary(entry => entry.Id, entry => entry.Data); + CollectionAssert.AreEqual(new[] { 92900999 }, npcs[49300001].additionalEffect.codes); + CollectionAssert.AreEqual(new[] { 101, 2 }, npcs[49300001].additionalEffect.group); + Assert.AreEqual(0, npcs[21000001].additionalEffect.group.Length); + } + [TestMethod] public void TestNpcParserNew() { var locale = Locale.KR; diff --git a/Maple2.File.Tests/ServerTableParserTest.cs b/Maple2.File.Tests/ServerTableParserTest.cs index 979f80e..a037be6 100644 --- a/Maple2.File.Tests/ServerTableParserTest.cs +++ b/Maple2.File.Tests/ServerTableParserTest.cs @@ -289,6 +289,26 @@ public void TestShadowExpeditionDrop() { CollectionAssert.AreEqual(new[] { 920001002, 920006034, 920000034, 820000034 }, last.dropBoxId); } + [TestMethod] + public void TestAdditionalEffectGroup() { + var parser = new ServerTableParser(TestUtils.ServerReader); + + Dictionary groups = parser.ParseAdditionalEffectGroup() + .ToDictionary(entry => entry.Id, entry => entry.Group); + CollectionAssert.AreEquivalent(new[] { 1, 101, 999 }, groups.Keys.ToArray()); + Assert.AreEqual(9, groups[1].value.Count); + Assert.AreEqual(7, groups[101].value.Count); + Assert.AreEqual(1, groups[999].value.Count); + + // group 101, first row: + CollectionAssert.AreEqual(new[] { 60125001, 60125002 }, groups[101].value[0].effectId); + CollectionAssert.AreEqual(new short[] { 1, 1 }, groups[101].value[0].effectLevel); + + // group 1, fourth row: + CollectionAssert.AreEqual(new[] { 60128001 }, groups[1].value[3].effectId); + CollectionAssert.AreEqual(new short[] { 2 }, groups[1].value[3].effectLevel); + } + [TestMethod] public void TestSpawnInteractObject() { var parser = new ServerTableParser(TestUtils.ServerReader);