diff --git a/Dalamud/Utility/MapUtil.cs b/Dalamud/Utility/MapUtil.cs
new file mode 100644
index 000000000..b4bbe1038
--- /dev/null
+++ b/Dalamud/Utility/MapUtil.cs
@@ -0,0 +1,131 @@
+using System.Numerics;
+
+using Lumina.Excel.GeneratedSheets;
+
+namespace Dalamud.Utility;
+
+///
+/// Utility helper class for game maps and coordinate translations that don't require state.
+///
+/// The conversion methods were found in 89 54 24 10 56 41 55 41 56 48 81 EC, which itself was found by looking for
+/// uses of AddonText 1631.
+///
+public static class MapUtil
+{
+ ///
+ /// Helper method to convert one of the game's Vector3 X/Z provided by the game to a map coordinate suitable for
+ /// display to the player.
+ ///
+ /// The raw float of a game Vector3 X or Z coordinate to convert.
+ /// The scale factor of the map, generally retrieved from Lumina.
+ /// The dimension offset for either X or Z, generally retrieved from Lumina.
+ /// Returns a converted float for display to the player.
+ public static float ConvertWorldCoordXZToMapCoord(float value, uint scale, int offset)
+ {
+ // Derived from E8 ?? ?? ?? ?? 0F B7 4B 1C and simplified.
+
+ return (0.02f * offset) + (2048f / scale) + (0.02f * value) + 1.0f;
+ }
+
+ ///
+ /// Helper method to convert a game Vector3 Y coordinate to a map coordinate suitable for display to the player.
+ ///
+ /// The raw float of a game Vector3 Y coordinate to convert.
+ /// The zOffset for this map. Retrieved from TerritoryTypeTransient.
+ /// Optionally enable Z offset correction. When a Z offset of -10,000 is set, replace
+ /// it with 0 for calculation purposes to show a more sane Z coordinate.
+ /// Returns a converted float for display to the player.
+ public static float ConvertWorldCoordYToMapCoord(float value, int zOffset, bool correctZOffset = false)
+ {
+ // Derived from 48 83 EC 38 80 3D ?? ?? ?? ?? ?? 0F 29 74 24
+
+ // zOffset of -10000 indicates that the map should not display a Z coordinate.
+ if (zOffset == -10000 && correctZOffset) zOffset = 0;
+
+ return (value - zOffset) / 100;
+ }
+
+ ///
+ /// All-in-one helper method to convert a World Coordinate (internal to the game) to a Map Coordinate (visible to
+ /// players in the minimap/elsewhere).
+ ///
+ ///
+ /// Note that this method will swap Y and Z in the resulting Vector3 to appropriately reflect the game's display.
+ ///
+ /// A Vector3 of raw World coordinates from the game.
+ /// The offset to apply to the incoming X parameter, generally Lumina's Map.OffsetX.
+ /// The offset to apply to the incoming Y parameter, generally Lumina's Map.OffsetY.
+ /// The offset to apply to the incoming Z parameter, generally Lumina's TerritoryTypeTransient.OffsetZ.
+ /// The global scale to apply to the incoming X and Y parameters, generally Lumina's Map.SizeFactor.
+ /// An optional mode to "correct" a Z offset of -10000 to be a more human-friendly value.
+ /// Returns a Vector3 representing visible map coordinates.
+ public static Vector3 WorldToMap(
+ Vector3 worldCoordinates,
+ int xOffset = 0,
+ int yOffset = 0,
+ int zOffset = 0,
+ uint scale = 100,
+ bool correctZOffset = false)
+ {
+ return new Vector3(
+ ConvertWorldCoordXZToMapCoord(worldCoordinates.X, scale, xOffset),
+ ConvertWorldCoordXZToMapCoord(worldCoordinates.Z, scale, yOffset),
+ ConvertWorldCoordYToMapCoord(worldCoordinates.Y, zOffset, correctZOffset));
+ }
+
+ ///
+ /// All-in-one helper method to convert a World Coordinate (internal to the game) to a Map Coordinate (visible to
+ /// players in the minimap/elsewhere).
+ ///
+ ///
+ /// Note that this method will swap Y and Z to appropriately reflect the game's display.
+ ///
+ /// A Vector3 of raw World coordinates from the game.
+ /// A Lumina map to use for offset/scale information.
+ /// A TerritoryTypeTransient to use for Z offset information.
+ /// An optional mode to "correct" a Z offset of -10000 to be a more human-friendly value.
+ /// Returns a Vector3 representing visible map coordinates.
+ public static Vector3 WorldToMap(
+ Vector3 worldCoordinates, Map map, TerritoryTypeTransient territoryTransient, bool correctZOffset = false)
+ {
+ return WorldToMap(
+ worldCoordinates,
+ map.OffsetX,
+ map.OffsetY,
+ territoryTransient.OffsetZ,
+ map.SizeFactor,
+ correctZOffset);
+ }
+
+ ///
+ /// All-in-one helper method to convert a World Coordinate (internal to the game) to a Map Coordinate (visible to
+ /// players in the minimap/elsewhere).
+ ///
+ /// A Vector2 of raw World coordinates from the game.
+ /// The offset to apply to the incoming X parameter, generally Lumina's Map.OffsetX.
+ /// The offset to apply to the incoming Y parameter, generally Lumina's Map.OffsetY.
+ /// The global scale to apply to the incoming X and Y parameters, generally Lumina's Map.SizeFactor.
+ /// Returns a Vector2 representing visible map coordinates.
+ public static Vector2 WorldToMap(
+ Vector2 worldCoordinates,
+ int xOffset = 0,
+ int yOffset = 0,
+ uint scale = 100)
+ {
+ return new Vector2(
+ ConvertWorldCoordXZToMapCoord(worldCoordinates.X, scale, xOffset),
+ ConvertWorldCoordXZToMapCoord(worldCoordinates.Y, scale, yOffset));
+ }
+
+ ///
+ /// All-in-one helper method to convert a World Coordinate (internal to the game) to a Map Coordinate (visible to
+ /// players in the minimap/elsewhere).
+ ///
+ /// A Vector2 of raw World coordinates from the game.
+ /// A Lumina map to use for offset/scale information.
+ /// Returns a Vector2 representing visible map coordinates.
+ public static Vector2 WorldToMap(Vector2 worldCoordinates, Map map)
+ {
+ return WorldToMap(worldCoordinates, map.OffsetX, map.OffsetY, map.SizeFactor);
+ }
+}