diff --git a/HaCreator/Wz/MapSaver.cs b/HaCreator/Wz/MapSaver.cs index 2af38459..82ff681e 100644 --- a/HaCreator/Wz/MapSaver.cs +++ b/HaCreator/Wz/MapSaver.cs @@ -64,7 +64,13 @@ private void InsertImage() WzDirectory parent; if (board.IsNewMapDesign) { - parent = (WzDirectory)WzInfoTools.FindMapDirectoryParent(mapId, Program.WzManager); + parent = WzInfoTools.FindMapDirectoryParent(mapId, Program.WzManager); + + if (parent == null) { + throw new Exception("Could not find a suitable Map.wz parent to place the new map into."); + } else if (parent[image.Name] != null) { + throw new Exception("Parent '"+ parent.FullPath+ "' contains an existing map, the new map [Name='"+ image.Name + "'] is attempting to override it."); + } } else { WzObject mapImage = WzInfoTools.FindMapImage(mapId, Program.WzManager); @@ -80,7 +86,7 @@ private void InsertImage() } else { - WzDirectory mapDir = (WzDirectory)Program.WzManager["ui"]; + WzDirectory mapDir = Program.WzManager["ui"]; WzImage mapImg = (WzImage)mapDir[image.Name]; if (mapImg != null) { @@ -736,6 +742,9 @@ public void SaveFootholds() image["foothold"] = fhParent; } + /// + /// Save life object (NPC, mobs) + /// public void SaveLife() { WzSubProperty lifeParent = new WzSubProperty(); @@ -760,7 +769,7 @@ public void SaveLife() lifeProp["hide"] = InfoTool.SetOptionalBool(lifeInst.Hide); lifeProp["type"] = InfoTool.SetString(mob ? "m" : "n"); lifeProp["limitedname"] = InfoTool.SetOptionalString(lifeInst.LimitedName); - lifeProp["fh"] = InfoTool.SetInt(GetFootholdBelow(lifeInst.X, lifeInst.Y)); + lifeProp["fh"] = InfoTool.SetInt(FindFootholdBelowAndAround(lifeInst.X, lifeInst.Y)); lifeParent[i.ToString()] = lifeProp; } image["life"] = lifeParent; @@ -981,6 +990,12 @@ public WzImage MapImage get { return image; } } + /// + /// Gets the precisely foothold below the specified x and y coordinates + /// + /// + /// + /// private int GetFootholdBelow(int x, int y) { double bestDistance = double.MaxValue; @@ -1011,6 +1026,37 @@ private int GetFootholdBelow(int x, int y) return bestFoothold; } + /// + /// Finds a foothold around the x and y coordinates, or below + /// + /// + /// + /// + private int FindFootholdBelowAndAround(int x, int y, int yTolerance = 5) { + double bestDistance = double.MaxValue; + int bestFoothold = -1; + foreach (FootholdLine fh in board.BoardItems.FootholdLines) { + if (Math.Min(fh.FirstDot.X, fh.SecondDot.X) <= x && Math.Max(fh.FirstDot.X, fh.SecondDot.X) >= x) { + double fhY = fh.CalculateY(x); + // Check if the foothold is within 5 units above OR below the y-coordinate + if (fhY >= y - yTolerance && (fhY - y) < bestDistance) { + bestDistance = Math.Abs(fhY - y); + bestFoothold = fh.num; + if (bestDistance == 0) { + // Not going to find anything better than 0 + return bestFoothold; + } + } + } + } + if (bestFoothold == -1) { + // 0 stands in the game for flying or nonexistant foothold; I do not know what are the results of putting an NPC there, + // however, if the user puts an NPC with no floor under it he should expect weird things to happen. + return 0; + } + return bestFoothold; + } + private FootholdAnchor FindOptimalContinuationAnchor(int y, int x0, int x1, int layer) { @@ -1229,7 +1275,7 @@ public void ChangeMapTypeAndID(int newId, MapType newType) public void UpdateMapLists() { - Program.InfoManager.Maps[WzInfoTools.AddLeadingZeros(board.MapInfo.id.ToString(), 9)] = + Program.InfoManager.MapsNameCache[WzInfoTools.AddLeadingZeros(board.MapInfo.id.ToString(), 9)] = new Tuple(board.MapInfo.strStreetName, board.MapInfo.strMapName); } }