From bfabad1ede3aef8dc4a6a9b274eaea3dffa270a6 Mon Sep 17 00:00:00 2001 From: Emmitt <1337ERJ1337@gmail.com> Date: Tue, 1 Feb 2022 08:23:29 -0800 Subject: [PATCH] Reworked how a JsonPassiveNode Arc is calculated. GGG doesn't use a linear approach to this, so we do have to do a bit of hard-coding here. Converted things over to floats, so we don't have to do unnecessary casting --- .../PassiveTree/Base/JsonPassiveNodeTest.cs | 128 ------------------ .../PassiveTree/Base/JsonPassiveNode.cs | 18 +-- .../Base/JsonPassiveTreeConstants.cs | 36 ++++- .../Converters/PassiveTreeJsonConverter.cs | 3 +- 4 files changed, 44 insertions(+), 141 deletions(-) diff --git a/PoESkillTree.Engine.GameModel.Tests/PassiveTree/Base/JsonPassiveNodeTest.cs b/PoESkillTree.Engine.GameModel.Tests/PassiveTree/Base/JsonPassiveNodeTest.cs index b4286052..1cc33ce2 100644 --- a/PoESkillTree.Engine.GameModel.Tests/PassiveTree/Base/JsonPassiveNodeTest.cs +++ b/PoESkillTree.Engine.GameModel.Tests/PassiveTree/Base/JsonPassiveNodeTest.cs @@ -55,133 +55,5 @@ public PassiveNodeType JsonPassiveNode_PassiveNodeType(PassiveNodeType passiveNo return node.PassiveNodeType; } - - [TestCase(1, new[] { 0f, 82f }, 0, new[] { 1f, 2f })] - [TestCase(0, new[] { 0f, 82f }, 5, new[] { 1f, 2f })] - [TestCase(1, new[] { 0f, 82f }, 10, new[] { 1f, 2f })] - [TestCase(1, new[] { 0f, 82f }, 30, new[] { 1f, 2f })] - public void JsonPassiveNode_Arc(int orbitRadiiIndex, float[] orbitRadii, int skillsPerOrbitIndex, float[] skillsPerOrbit) - { - var node = new JsonPassiveNode - { - OrbitRadiiIndex = orbitRadiiIndex, - OrbitRadii = orbitRadii, - SkillsPerOrbitIndex = skillsPerOrbitIndex, - SkillsPerOrbit = skillsPerOrbit, - }; - - Assert.AreEqual(2 * Math.PI * skillsPerOrbitIndex / skillsPerOrbit[orbitRadiiIndex], node.Arc); - } - - [TestCase(0, 0, 0.3835f, 0, new[] { 0f }, 0, new[] { 1f })] - [TestCase(0, 1, 0.3835f, 0, new[] { 0f }, 0, new[] { 1f })] - [TestCase(1, 0, 0.3835f, 0, new[] { 0f }, 0, new[] { 1f })] - [TestCase(1, 1, 0.3835f, 0, new[] { 0f }, 0, new[] { 1f })] - [TestCase(500, 250, 0.3835f, 1, new[] { 0f, 82f }, 1, new[] { 1f, 2f })] - [TestCase(250, 500, 0.3835f, 1, new[] { 0f, 82f }, 1, new[] { 1f, 2f })] - [TestCase(500, 500, 0.3835f, 1, new[] { 0f, 82f }, 1, new[] { 1f, 2f })] - [TestCase(250, 250, 0.3835f, 1, new[] { 0f, 82f }, 1, new[] { 1f, 2f })] - [TestCase(250, 250, 0.3835f, 0, new[] { 0f, 82f }, 1, new[] { 1f, 2f })] - public void JsonPassiveNode_Position(float x, float y, float zoomLevel, int orbitRadiiIndex, float[] orbitRadii, int skillsPerOrbitIndex, float[] skillsPerOrbit) - { - var group = new JsonPassiveNodeGroup - { - OriginalX = x, - OriginalY = y, - ZoomLevel = zoomLevel, - }; - - var node = new JsonPassiveNode - { - PassiveNodeGroup = group, - OrbitRadiiIndex = orbitRadiiIndex, - OrbitRadii = orbitRadii, - SkillsPerOrbitIndex = skillsPerOrbitIndex, - SkillsPerOrbit = skillsPerOrbit, - ZoomLevel = zoomLevel, - }; - - Assert.AreEqual(group.Position.X - orbitRadii[orbitRadiiIndex] * zoomLevel * (float)Math.Sin(-2 * Math.PI * skillsPerOrbitIndex / skillsPerOrbit[orbitRadiiIndex]), node.Position.X); - Assert.AreEqual(group.Position.Y - orbitRadii[orbitRadiiIndex] * zoomLevel * (float)Math.Cos(-2 * Math.PI * skillsPerOrbitIndex / skillsPerOrbit[orbitRadiiIndex]), node.Position.Y); - } - - [TestCase(0, 0, 0.3835f, 0, new[] { 0f }, 0, new[] { 1f })] - [TestCase(0, 1, 0.3835f, 0, new[] { 0f }, 0, new[] { 1f })] - [TestCase(1, 0, 0.3835f, 0, new[] { 0f }, 0, new[] { 1f })] - [TestCase(1, 1, 0.3835f, 0, new[] { 0f }, 0, new[] { 1f })] - [TestCase(500, 250, 0.3835f, 1, new[] { 0f, 82f }, 1, new[] { 1f, 2f })] - [TestCase(250, 500, 0.3835f, 1, new[] { 0f, 82f }, 1, new[] { 1f, 2f })] - [TestCase(500, 500, 0.3835f, 1, new[] { 0f, 82f }, 1, new[] { 1f, 2f })] - [TestCase(250, 250, 0.3835f, 1, new[] { 0f, 82f }, 1, new[] { 1f, 2f })] - [TestCase(250, 250, 0.3835f, 0, new[] { 0f, 82f }, 1, new[] { 1f, 2f })] - public void JsonPassiveNode_Convert(float _x, float _y, float zoomLevel, int orbitRadiiIndex, float[] orbitRadii, int skillsPerOrbitIndex, float[] skillsPerOrbit) - { - var group = new JsonPassiveNodeGroup - { - OriginalX = _x, - OriginalY = _y, - ZoomLevel = zoomLevel, - }; - - var node = new JsonPassiveNode - { - PassiveNodeGroup = group, - OrbitRadiiIndex = orbitRadiiIndex, - OrbitRadii = orbitRadii, - SkillsPerOrbitIndex = skillsPerOrbitIndex, - SkillsPerOrbit = skillsPerOrbit, - ZoomLevel = zoomLevel, - }; - - var nodeDefinition = PassiveNodeDefinition.Convert(node); - var nodePosition = node.PositionAtZoomLevel(1f); - Assert.AreEqual(nodePosition.X, nodeDefinition.Position.X); - Assert.AreEqual(nodePosition.Y, nodeDefinition.Position.Y); - } - - [TestCase(0, 0, 0.3835f, 0, new[] { 0f }, 0, new[] { 1f })] - [TestCase(0, 1, 0.3835f, 0, new[] { 0f }, 0, new[] { 1f })] - [TestCase(1, 0, 0.3835f, 0, new[] { 0f }, 0, new[] { 1f })] - [TestCase(1, 1, 0.3835f, 0, new[] { 0f }, 0, new[] { 1f })] - [TestCase(500, 250, 0.3835f, 1, new[] { 0f, 82f }, 1, new[] { 1f, 2f })] - [TestCase(250, 500, 0.3835f, 1, new[] { 0f, 82f }, 1, new[] { 1f, 2f })] - [TestCase(500, 500, 0.3835f, 1, new[] { 0f, 82f }, 1, new[] { 1f, 2f })] - [TestCase(250, 250, 0.3835f, 1, new[] { 0f, 82f }, 1, new[] { 1f, 2f })] - [TestCase(250, 250, 0.3835f, 0, new[] { 0f, 82f }, 1, new[] { 1f, 2f })] - public void JsonPassiveNode_ClearPosition(float x, float y, float zoomLevel, int orbitRadiiIndex, float[] orbitRadii, int skillsPerOrbitIndex, float[] skillsPerOrbit) - { - var group = new JsonPassiveNodeGroup - { - OriginalX = x, - OriginalY = y, - ZoomLevel = zoomLevel, - }; - - var node = new JsonPassiveNode - { - PassiveNodeGroup = group, - OrbitRadiiIndex = orbitRadiiIndex, - OrbitRadii = orbitRadii, - SkillsPerOrbitIndex = skillsPerOrbitIndex, - SkillsPerOrbit = skillsPerOrbit, - ZoomLevel = zoomLevel, - }; - - Assert.AreEqual(group.Position.X - orbitRadii[orbitRadiiIndex] * zoomLevel * (float)Math.Sin(-2 * Math.PI * skillsPerOrbitIndex / skillsPerOrbit[skillsPerOrbitIndex]), node.Position.X); - Assert.AreEqual(group.Position.Y - orbitRadii[orbitRadiiIndex] * zoomLevel * (float)Math.Cos(-2 * Math.PI * skillsPerOrbitIndex / skillsPerOrbit[skillsPerOrbitIndex]), node.Position.Y); - - var newGroup = new JsonPassiveNodeGroup - { - OriginalX = x * 10, - OriginalY = y * 10, - ZoomLevel = zoomLevel, - }; - - node.PassiveNodeGroup = newGroup; - node.ClearPositionCache(); - - Assert.AreEqual(newGroup.Position.X - orbitRadii[orbitRadiiIndex] * zoomLevel * (float)Math.Sin(-2 * Math.PI * skillsPerOrbitIndex / skillsPerOrbit[skillsPerOrbitIndex]), node.Position.X); - Assert.AreEqual(newGroup.Position.Y - orbitRadii[orbitRadiiIndex] * zoomLevel * (float)Math.Cos(-2 * Math.PI * skillsPerOrbitIndex / skillsPerOrbit[skillsPerOrbitIndex]), node.Position.Y); - } } } diff --git a/PoESkillTree.Engine.GameModel/PassiveTree/Base/JsonPassiveNode.cs b/PoESkillTree.Engine.GameModel/PassiveTree/Base/JsonPassiveNode.cs index 694bc021..8a0e6889 100644 --- a/PoESkillTree.Engine.GameModel/PassiveTree/Base/JsonPassiveNode.cs +++ b/PoESkillTree.Engine.GameModel/PassiveTree/Base/JsonPassiveNode.cs @@ -100,10 +100,10 @@ public bool IsAscendancyStart public ushort? PassiveNodeGroupId { get; set; } [JsonProperty("orbit")] - public int OrbitRadiiIndex { get; set; } = 0; + public int Orbit { get; set; } = 0; [JsonProperty("orbitIndex")] - public int SkillsPerOrbitIndex { get; set; } = 0; + public int OrbitIndex { get; set; } = 0; [JsonProperty("recipe", NullValueHandling = NullValueHandling.Ignore)] public string[]? Recipe { get; set; } @@ -125,7 +125,7 @@ public bool IsAscendancyStart public bool IsSkilled { get; set; } = false; [JsonIgnore] - public float[] SkillsPerOrbit { get; set; } = new float[] { 1f, 6f, 12f, 12f, 40f }; + public Dictionary OrbitAngles { get; set; } = new Dictionary(); [JsonIgnore] public float[] OrbitRadii { get; set; } = new float[] { 0f, 82f, 162f, 335f, 493f }; @@ -182,10 +182,10 @@ public PassiveNodeType PassiveNodeType } [JsonIgnore] - private double? _arc = null; + private float? _arc = null; [JsonIgnore] - public double Arc => _arc ??= 2 * Math.PI * SkillsPerOrbitIndex / SkillsPerOrbit[OrbitRadiiIndex]; + public float Arc => _arc ??= OrbitAngles[Orbit][OrbitIndex]; [JsonIgnore] public override Vector2 Position @@ -208,8 +208,8 @@ public override Vector2 PositionAtZoomLevel(float zoomLevel) return Vector2.Zero; } - var orbitRadius = OrbitRadii[OrbitRadiiIndex] * zoomLevel; - return PassiveNodeGroup.Position - new Vector2(orbitRadius * (float)Math.Sin(-Arc), orbitRadius * (float)Math.Cos(-Arc)); + var orbitRadius = OrbitRadii[Orbit] * zoomLevel; + return PassiveNodeGroup.Position - new Vector2(orbitRadius * MathF.Sin(-Arc), orbitRadius * MathF.Cos(-Arc)); } #endregion @@ -250,10 +250,10 @@ public override Vector2 PositionAtZoomLevel(float zoomLevel) private ushort? __g { set { PassiveNodeGroupId = value; } } [JsonProperty("o")] - private int __o { set { OrbitRadiiIndex = value; } } + private int __o { set { Orbit = value; } } [JsonProperty("oidx")] - private int __oidx { set { SkillsPerOrbitIndex = value; } } + private int __oidx { set { OrbitIndex = value; } } #pragma warning restore IDE1006 // Naming Styles #pragma warning restore IDE0051 // Remove unused private members #endregion diff --git a/PoESkillTree.Engine.GameModel/PassiveTree/Base/JsonPassiveTreeConstants.cs b/PoESkillTree.Engine.GameModel/PassiveTree/Base/JsonPassiveTreeConstants.cs index fa348469..73a3791b 100644 --- a/PoESkillTree.Engine.GameModel/PassiveTree/Base/JsonPassiveTreeConstants.cs +++ b/PoESkillTree.Engine.GameModel/PassiveTree/Base/JsonPassiveTreeConstants.cs @@ -1,12 +1,14 @@ using Newtonsoft.Json; +using System; using System.Collections.Generic; +using System.Linq; namespace PoESkillTree.Engine.GameModel.PassiveTree.Base { public class JsonPassiveTreeConstants { [JsonProperty("classes")] - public Dictionary Classes { get; private set; } = new Dictionary() + public Dictionary Classes { get; private set; } = new Dictionary() { { "StrDexIntClass", CharacterClass.Scion }, { "StrClass", CharacterClass.Marauder }, @@ -18,7 +20,7 @@ public class JsonPassiveTreeConstants }; [JsonProperty("characterAttributes")] - public Dictionary CharacterAttributes { get; private set; } = new Dictionary() + public Dictionary CharacterAttributes { get; private set; } = new Dictionary() { { "Strength", 0 }, { "Dexterity", 1 }, @@ -29,9 +31,37 @@ public class JsonPassiveTreeConstants public int PSSCentreInnerRadius { get; set; } = 130; [JsonProperty("skillsPerOrbit")] - public float[] SkillsPerOrbit { get; private set; } = new float[] { 1f, 6f, 12f, 12f, 40f }; + public int[] SkillsPerOrbit { get; private set; } = new int[] { 1, 6, 12, 12, 40 }; [JsonProperty("orbitRadii")] public float[] OrbitRadii { get; private set; } = new float[] { 0f, 82f, 162f, 335f, 493f }; + + [JsonIgnore] + public Dictionary OrbitAngles + { + get + { + var angles = new Dictionary(); + + for (var orbit = 0; orbit < SkillsPerOrbit.Length; orbit++) + { + var skillsPerOrbit = SkillsPerOrbit[orbit]; + angles[orbit] = skillsPerOrbit switch + { + 16 => new float[] { 0f, 30f, 45f, 60f, 90f, 120f, 135f, 150f, 180f, 210f, 225f, 240f, 270f, 300f, 315f, 330f }, + 40 => new float[] { 0f, 10f, 20f, 30f, 40f, 45f, 50f, 60f, 70f, 80f, 90f, 100f, 110f, 120f, 130f, 135f, 140f, 150f, 160f, 170f, 180f, 190f, 200f, 210f, 220f, 225f, 230f, 240f, 250f, 260f, 270f, 280f, 290f, 300f, 310f, 315f, 320f, 330f, 340f, 350f }, + _ => Enumerable.Range(0, skillsPerOrbit).Select(x => 360f * x / skillsPerOrbit).ToArray() + }; + } + + var radians = new Dictionary(); + foreach (var (orbit, degrees) in angles) + { + radians[orbit] = degrees.Select(x => x * (MathF.PI / 180f)).ToArray(); + } + + return radians; + } + } } } diff --git a/PoESkillTree.Engine.GameModel/PassiveTree/Converters/PassiveTreeJsonConverter.cs b/PoESkillTree.Engine.GameModel/PassiveTree/Converters/PassiveTreeJsonConverter.cs index 60f6505d..bf43b6be 100644 --- a/PoESkillTree.Engine.GameModel/PassiveTree/Converters/PassiveTreeJsonConverter.cs +++ b/PoESkillTree.Engine.GameModel/PassiveTree/Converters/PassiveTreeJsonConverter.cs @@ -104,9 +104,10 @@ public override object ReadJson(JsonReader reader, Type objectType, object? exis } // Hydrate Passive Nodes + var angles = passiveTree.Constants.OrbitAngles; foreach (var passiveNode in passiveTree.PassiveNodes.Values) { - passiveNode.SkillsPerOrbit = passiveTree.Constants.SkillsPerOrbit; + passiveNode.OrbitAngles = angles; passiveNode.OrbitRadii = passiveTree.Constants.OrbitRadii; passiveNode.ZoomLevel = passiveTree.MaxImageZoomLevel;