コード例 #1
0
        public void CreateFhAnchor()
        {
            FootholdAnchor fhAnchor = new FootholdAnchor(Board, X, Y, Board.SelectedLayerIndex, false);

            Board.BoardItems.FHAnchors.Add(fhAnchor);
            Board.UndoRedoMan.AddUndoBatch(new List <UndoRedoAction> {
                UndoRedoManager.ItemAdded(fhAnchor)
            });
            if (connectedLines.Count == 0)
            {
                Board.BoardItems.FootholdLines.Add(new FootholdLine(Board, fhAnchor));
            }
            else
            {
                connectedLines[0].ConnectSecondDot(fhAnchor);
                Board.BoardItems.FootholdLines.Add(new FootholdLine(Board, fhAnchor));
            }
        }
コード例 #2
0
        public virtual void DoSnap()
        {
            if (!InputHandler.IsKeyPushedDown(System.Windows.Forms.Keys.ShiftKey) || connectedLines.Count == 0 || !(connectedLines[0] is FootholdLine))
            {
                return;
            }
            FootholdAnchor closestAnchor = null;
            double         closestAngle  = double.MaxValue;
            bool           xClosest      = true;

            foreach (FootholdLine line in connectedLines)
            {
                FootholdAnchor otherAnchor = (FootholdAnchor)(line.FirstDot == this ? line.SecondDot : line.FirstDot);
                double         xAngle      = Math.Abs(Math.Atan((double)(Y - otherAnchor.Y) / (double)(X - otherAnchor.X)));
                double         yAngle      = Math.Abs(Math.Atan((double)(X - otherAnchor.X) / (double)(Y - otherAnchor.Y)));
                double         minAngle;
                bool           xSmaller = false;
                if (xAngle < yAngle)
                {
                    xSmaller = true; minAngle = xAngle;
                }
                else
                {
                    xSmaller = false; minAngle = yAngle;
                }
                if (minAngle < closestAngle)
                {
                    xClosest = xSmaller; closestAnchor = otherAnchor; closestAngle = minAngle;
                }
            }
            if (closestAnchor != null)
            {
                if (xClosest)
                {
                    Y = closestAnchor.Y;
                }
                else
                {
                    X = closestAnchor.X;
                }
            }
        }
コード例 #3
0
 public static int FHAnchorSorter(FootholdAnchor c, FootholdAnchor d)
 {
     if (c.X > d.X)
     {
         return(1);
     }
     else if (c.X < d.X)
     {
         return(-1);
     }
     else
     {
         if (c.Y > d.Y)
         {
             return(1);
         }
         else if (c.Y < d.Y)
         {
             return(-1);
         }
         else
         {
             if (c.LayerNumber > d.LayerNumber)
             {
                 return(1);
             }
             else if (c.LayerNumber < d.LayerNumber)
             {
                 return(-1);
             }
             else
             {
                 return(0);
             }
         }
     }
 }
コード例 #4
0
ファイル: Mouse.cs プロジェクト: hanistory/hasuite
 public void CreateFhAnchor()
 {
     FootholdAnchor fhAnchor = new FootholdAnchor(Board, X, Y, Board.SelectedLayerIndex, false);
     Board.BoardItems.FHAnchors.Add(fhAnchor);
     Board.UndoRedoMan.AddUndoBatch(new List<UndoRedoAction> { UndoRedoManager.ItemAdded(fhAnchor) });
     if (connectedLines.Count == 0)
     {
         Board.BoardItems.FootholdLines.Add(new FootholdLine(Board, fhAnchor));
     }
     else
     {
         connectedLines[0].ConnectSecondDot(fhAnchor);
         Board.BoardItems.FootholdLines.Add(new FootholdLine(Board, fhAnchor));
     }
 }
コード例 #5
0
ファイル: MapleInfo.cs プロジェクト: hanistory/hasuite
 public void ParseOffsets(TileInstance instance, Board board, Layer layer, int x, int y)
 {
     List<FootholdAnchor> anchors = new List<FootholdAnchor>();
     foreach (XNA.Point foothold in footholdOffsets)
     {
         FootholdAnchor anchor = new FootholdAnchor(board, x + foothold.X, y + foothold.Y, layer.LayerNumber, false);
         anchors.Add(anchor);
         board.BoardItems.FHAnchors.Add(anchor);
         instance.BindItem(anchor, foothold);
     }
     for (int i = 0; i < anchors.Count - 1; i++)
     {
         FootholdLine fh = new FootholdLine(board, anchors[i], anchors[i + 1]);
         board.BoardItems.FootholdLines.Add(fh);
     }
 }
コード例 #6
0
ファイル: MapleInfo.cs プロジェクト: hanistory/hasuite
 public void ParseOffsets(ObjectInstance instance, Layer layer, Board board, int x, int y)
 {
     List<FootholdAnchor> anchors = new List<FootholdAnchor>();
     bool ladder = l0 == "ladder";
     if (footholdOffsets != null || footholdFullOffsets != null)
     {
         if (!fullFootholdInfo)
         {
             foreach (XNA.Point foothold in footholdOffsets)
             {
                 FootholdAnchor anchor = new FootholdAnchor(board, x + foothold.X, y + foothold.Y, layer.LayerNumber, false);
                 board.BoardItems.FHAnchors.Add(anchor);
                 instance.BindItem(anchor, foothold);
                 anchors.Add(anchor);
             }
             CreateFootholdsFromAnchorList(board, anchors);
         }
         else
         {
             foreach (List<XNA.Point> anchorList in footholdFullOffsets)
             {
                 foreach (XNA.Point foothold in anchorList)
                 {
                     FootholdAnchor anchor = new FootholdAnchor(board, x + foothold.X, y + foothold.Y, layer.LayerNumber, false);
                     board.BoardItems.FHAnchors.Add(anchor);
                     instance.BindItem(anchor, foothold);
                     anchors.Add(anchor);
                 }
                 CreateFootholdsFromAnchorList(board, anchors);
                 anchors.Clear();
             }
         }
     }
     if  (chairOffsets != null) foreach (XNA.Point chairPos in chairOffsets)
     {
         Chair chair = new Chair(board, x + chairPos.X, y + chairPos.Y, false);
         board.BoardItems.Chairs.Add(chair);
         instance.BindItem(chair, chairPos);
     }
     /*foreach (XNA.Point rope in ropeOffsets) //second thought: what the f**k is this even good for? rope origins aren't multilined anyway, why add them as board items?
     {
         RopeLadderAnchor ropeAnchor = new RopeLadderAnchor(board, x + rope.X, y + rope.Y, layer.LayerNumber, ladder, false);
         board.BoardItems.RopeAnchors.Add(ropeAnchor);
         instance.BindItem(ropeAnchor, rope);
     }*/
 }
コード例 #7
0
ファイル: MapleShape.cs プロジェクト: johnnyeven/hasuite
 public static int FHAnchorSorter(FootholdAnchor c, FootholdAnchor d)
 {
     if (c.X > d.X)
         return 1;
     else if (c.X < d.X)
         return -1;
     else
     {
         if (c.Y > d.Y)
             return 1;
         else if (c.Y < d.Y)
             return -1;
         else
         {
             if (c.LayerNumber > d.LayerNumber)
                 return 1;
             else if (c.LayerNumber < d.LayerNumber)
                 return -1;
             else return 0;
         }
     }
 }
コード例 #8
0
ファイル: MapSimulator.cs プロジェクト: hanistory/hasuite
 private static FootholdLine GetOtherFh(FootholdAnchor anchor, FootholdLine source, Hashtable fhListByPoint)
 {
     List<FootholdLine> connectedLines = (List<FootholdLine>)fhListByPoint[new Point(anchor.X, anchor.Y)];
     if (connectedLines.Count < 2) return null;
     else if (connectedLines.Count == 2)
     {
         return connectedLines[1].FhEquals(source) ? connectedLines[0] : connectedLines[1];
     }
     else //reaching this part means whoever made the map is a f*****g idiot
     {
         FootholdLine longestFh = null;
         int longestFhLenth = 0;
         foreach (FootholdLine fh in connectedLines)
         {
             int length = (int)Math.Sqrt(Math.Pow((fh.SecondDot.X - fh.FirstDot.X), 2) + Math.Pow((fh.SecondDot.Y - fh.FirstDot.Y), 2));
             if (!fh.FhEquals(source) && length > longestFhLenth)
             {
                 longestFh = fh;
                 longestFhLenth = length;
             }
         }
         return longestFh;
     }
 }
コード例 #9
0
ファイル: MapLoader.cs プロジェクト: ilvmoney/hasuite-new
        private static void LoadFootholds(WzImage mapImage, Board mapBoard)
        {
            List<FootholdAnchor> anchors = new List<FootholdAnchor>();
            WzSubProperty footholdParent = (WzSubProperty)mapImage["foothold"];
            int layer;
            int plat;
            FootholdAnchor a;
            FootholdAnchor b;
            FootholdAnchor c;
            FootholdAnchor d;
            foreach (WzSubProperty layerProp in footholdParent.WzProperties)
            {
                layer = int.Parse(layerProp.Name);
                foreach (WzSubProperty platProp in layerProp.WzProperties)
                {
                    plat = int.Parse(platProp.Name);
                    foreach (WzSubProperty fhProp in platProp.WzProperties)
                    {
                        a = new FootholdAnchor(mapBoard, InfoTool.GetInt(fhProp["x1"]), InfoTool.GetInt(fhProp["y1"]), layer, false, plat);
                        b = new FootholdAnchor(mapBoard, InfoTool.GetInt(fhProp["x2"]), InfoTool.GetInt(fhProp["y2"]), layer, false, plat);
                        int num = int.Parse(fhProp.Name);
                        int next = InfoTool.GetInt(fhProp["next"]);
                        int prev = InfoTool.GetInt(fhProp["prev"]);
                        if (a.X != b.X || a.Y != b.Y)
                        {
                            FootholdLine fh = new FootholdLine(mapBoard, a, b);
                            fh.num = num;
                            fh.prev = prev;
                            fh.next = next;
                            fh.Name = fhProp.Name;
                            mapBoard.BoardItems.FootholdLines.Add(fh);
                            anchors.Add(a);
                            anchors.Add(b);
                        }
                    }
                }

                anchors.Sort(new Comparison<FootholdAnchor>(FootholdAnchor.FHAnchorSorter));
                int groupStart = 0; //inclusive
                int groupEnd = 0; //inclusive
                for (int i = 0; i < anchors.Count - 1; i++)
                {
                    a = anchors[i];
                    b = anchors[i + 1];
                    if (a.Y != b.Y && a.X != b.X && a.LayerNumber == b.LayerNumber)
                    {
                        groupEnd = i;
                        if (groupEnd - groupStart == 1) //there are 2 objects in the group, since groupEnd and groupStart are inclusive
                        {
                            c = anchors[groupStart];
                            d = anchors[groupEnd];
                            CheckAnchorPairMerge(c, d);
                        }
                        else if (groupEnd - groupStart != 0)
                        {
                            for (int j = groupStart; j <= groupEnd; j++)
                            {
                                c = anchors[j];
                                for (int k = groupStart; k <= groupEnd; k++)
                                {
                                    if (c.removed) break;
                                    d = anchors[k];
                                    if (d.removed) continue;
                                    CheckAnchorPairMerge(c, d);
                                }
                            }
                        }
                        groupStart = groupEnd + 1;
                    }
                }

                groupEnd = anchors.Count - 1;
                if (groupEnd - groupStart == 1) //there are 2 objects in the group, since groupEnd and groupStart are inclusive
                {
                    c = anchors[groupStart];
                    d = anchors[groupEnd];
                    CheckAnchorPairMerge(c, d);
                }
                else if (groupEnd - groupStart != 0)
                {
                    for (int j = groupStart; j <= groupEnd; j++)
                    {
                        c = anchors[j];
                        for (int k = groupStart; k <= groupEnd; k++)
                        {
                            if (c.removed) break;
                            d = anchors[k];
                            if (d.removed) continue;
                            CheckAnchorPairMerge(c, d);
                        }
                    }
                }

                //FootholdAnchor.MergeAnchors(ref anchors);
                /*if (mapBoard.BoardItems.FHAnchors.Count + anchors.Count > mapBoard.BoardItems.FHAnchors.Capacity)
                    mapBoard.BoardItems.FHAnchors.Capacity = mapBoard.BoardItems.FHAnchors.Count + anchors.Count;
                anchors.ForEach(X => if  mapBoard.BoardItems.FHAnchors.Add(X));
                anchors.Clear();*/
                mapBoard.BoardItems.FHAnchors.Capacity = mapBoard.BoardItems.FHAnchors.Count + anchors.Count * 2;
                foreach (FootholdAnchor anchor in anchors)
                    if (!anchor.removed)
                        mapBoard.BoardItems.FHAnchors.Add(anchor);
                anchors.Clear();
            }
        }
コード例 #10
0
ファイル: MapSaver.cs プロジェクト: hanistory/hasuite
 private static int FHAnchorSorter(FootholdAnchor a, FootholdAnchor b)
 {
     if (a.X > b.X)
         return 1;
     else if (a.X < b.X)
         return -1;
     else
     {
         if (a.Y > b.Y)
             return 1;
         else if (a.Y < b.Y)
             return -1;
         else return 0;
     }
 }
コード例 #11
0
ファイル: MapLoader.cs プロジェクト: ilvmoney/hasuite-new
 private static void CheckAnchorPairMerge(FootholdAnchor a, FootholdAnchor b)
 {
     if (a.X == b.X && a.Y == b.Y && a.LayerNumber == b.LayerNumber)
     {
         FootholdLine lineA = (FootholdLine)a.connectedLines[0];
         FootholdLine lineB = (FootholdLine)b.connectedLines[0];
         if ((lineA.next == lineB.num && lineB.prev == lineA.num)
             || (lineA.prev == lineB.num && lineB.next == lineA.num))
         {
             b.removed = true;
             if (lineB.FirstDot == b) //b is firstdot
                 lineB.FirstDot = a;
             else
                 lineB.SecondDot = a;
             a.connectedLines.Add(lineB);
         }
     }
 }
コード例 #12
0
ファイル: MapSaver.cs プロジェクト: hanistory/hasuite
 private static void EliminateFootholdTree(FootholdAnchor anchor, int lineIndex, ref List<FootholdLine> footholds)
 {
     FootholdLine line = (FootholdLine)anchor.connectedLines[lineIndex];
     footholds.Remove(line);
     line.remove = true;
     FootholdAnchor otherAnchor = GetOtherAnchor(line, anchor);
     for (int i = 0; i < otherAnchor.connectedLines.Count; i++)
         if (otherAnchor.connectedLines[i] != line) EliminateFootholdTree(otherAnchor, i, ref footholds);
 }
コード例 #13
0
ファイル: MapSaver.cs プロジェクト: hanistory/hasuite
        /*private static double CalculateFootholdTreeLength(FootholdAnchor anchor, int lineIndex)
        {
            double length = 0;
            FootholdLine line = (FootholdLine)anchor.connectedLines[lineIndex];
            int dx = line.FirstDot.X - line.SecondDot.X;
            int dy = line.FirstDot.Y - line.SecondDot.Y;
            length += Math.Sqrt(dx * dx + dy * dy);
            FootholdAnchor otherAnchor = GetOtherAnchor(line, anchor);
            for (int i = 0; i < otherAnchor.connectedLines.Count; i++)
                if (otherAnchor.connectedLines[i] != line) 
                    length += CalculateFootholdTreeLength(anchor, i);
            return length;
        }*/

        private static bool FootholdTreeLengthExceeds(FootholdAnchor anchor, int lineIndex, int max) //max is inclusive
        {
            FootholdLine line = (FootholdLine)anchor.connectedLines[0];
            int length = 1;
            while (length <= max)
            {
                anchor = GetOtherAnchor(line, anchor);
                line = GetOtherLine(line, anchor);
                if (line == null) return false;
            }
            return true;
        }
コード例 #14
0
ファイル: MapSaver.cs プロジェクト: hanistory/hasuite
 private static FootholdLine GetOtherLine(FootholdLine line, FootholdAnchor currAnchor)
 {
     foreach (FootholdLine currLine in currAnchor.connectedLines)
         if (line != currLine)
             return currLine;
     return null;
 }
コード例 #15
0
ファイル: MapSaver.cs プロジェクト: hanistory/hasuite
 private static FootholdAnchor GetOtherAnchor(FootholdLine line, FootholdAnchor currAnchor)
 {
     return (FootholdAnchor)(line.FirstDot == currAnchor ? line.SecondDot : line.FirstDot);
 }
コード例 #16
0
ファイル: MapSaver.cs プロジェクト: hanistory/hasuite
        public static void ConvertToMapleFootholds2(ref MapleList<FootholdLine> oldFootholds, ref MapleList<FootholdAnchor> oldAnchors)
        {
            //Part 1 - copying and filtering out unused anchors
            List<FootholdLine> footholds = new List<FootholdLine>(oldFootholds.Count);
            List<FootholdAnchor> anchors = new List<FootholdAnchor>(oldAnchors.Count);
            foreach (FootholdAnchor oldAnchor in oldAnchors)
            {
                if (oldAnchor.connectedLines.Count == 0) continue;
                //if (oldAnchor.IsMoveHandled) throw new Exception();
                FootholdAnchor anchor = new FootholdAnchor(oldAnchor.Board, oldAnchor.X, oldAnchor.Y, oldAnchor.LayerNumber, oldAnchor.BeforeAdding);
                anchor.connectedLines = new List<MapleLine>(oldAnchor.connectedLines.Count);
                foreach (FootholdLine oldLine in oldAnchor.connectedLines)
                {
                    if (oldLine.cloneLine == null)
                    {
                        FootholdAnchor firstDot = null;
                        FootholdAnchor secondDot = null;
                        if (oldLine.FirstDot.X > oldLine.SecondDot.X)
                        {
                            firstDot = (FootholdAnchor)oldLine.SecondDot;
                            secondDot = (FootholdAnchor)oldLine.FirstDot;
                        }
                        else if (oldLine.FirstDot.X < oldLine.SecondDot.X)
                        {
                            firstDot = (FootholdAnchor)oldLine.FirstDot;
                            secondDot = (FootholdAnchor)oldLine.SecondDot;
                        }
                        else
                        {
                            if (oldLine.FirstDot.Y > oldLine.SecondDot.Y)
                            {
                                firstDot = (FootholdAnchor)oldLine.SecondDot;
                                secondDot = (FootholdAnchor)oldLine.FirstDot;
                            }
                            else
                            {
                                firstDot = (FootholdAnchor)oldLine.FirstDot;
                                secondDot = (FootholdAnchor)oldLine.SecondDot;

                            }
                        }
                        if (anchor.X == firstDot.X && anchor.Y == firstDot.Y) //we are firstdot
                        {
                            firstDot = anchor;
                            secondDot = null;
                        }
                        else //we are seconddot
                        {
                            firstDot = null;
                            secondDot = anchor;
                        }
                        oldLine.cloneLine = FootholdLine.CreateCustomFootholdLine(oldLine.Board, firstDot, secondDot);
                        footholds.Add(oldLine.cloneLine);
                    }
                    else
                    {
                        if (oldLine.cloneLine.FirstDot == null) oldLine.cloneLine.FirstDot = anchor;
                        else oldLine.cloneLine.SecondDot = anchor;
                    }
                    anchor.connectedLines.Add(oldLine.cloneLine);
                }
                anchors.Add(anchor);
            }
            foreach (FootholdLine fhLine in oldFootholds)
                fhLine.cloneLine = null;

            //Part 2 - combining anchors that are on the exact same position
            anchors.Sort(new Comparison<FootholdAnchor>(FootholdAnchor.FHAnchorSorter));
            int groupStart = 0; //inclusive
            int groupEnd = 0; //inclusive
            FootholdAnchor a;
            FootholdAnchor b;
            FootholdAnchor c;
            FootholdAnchor d;
            FootholdLine line;
            for (int i = 0; i < anchors.Count - 1; i++)
            {
                a = anchors[i];
                b = anchors[i + 1];
                if (a.Y != b.Y && a.X != b.X && a.LayerNumber == b.LayerNumber)
                {
                    groupEnd = i;
                    if (groupEnd - groupStart == 1) //there are 2 objects in the group, since groupEnd and groupStart are inclusive
                    {
                        c = anchors[groupStart];
                        d = anchors[groupEnd];
                        if (c.connectedLines.Count == 1 && d.connectedLines.Count == 1)
                        {
                            d.removed = true;
                            line = (FootholdLine)d.connectedLines[0];
                            if (line.FirstDot == d)
                                line.FirstDot = c;
                            else
                                line.SecondDot = c;
                            c.connectedLines.Add(line);
                        }
                    }
                    groupStart = groupEnd + 1;
                }
            }

            groupEnd = anchors.Count - 1;
            if (groupEnd - groupStart == 1) //there are 2 objects in the group, since groupEnd and groupStart are inclusive
            {
                c = anchors[groupStart];
                d = anchors[groupEnd];
                if (c.connectedLines.Count == 1 && d.connectedLines.Count == 1)
                {
                    d.removed = true;
                    line = (FootholdLine)d.connectedLines[0];
                    if (line.FirstDot == d)
                        line.FirstDot = c;
                    else
                        line.SecondDot = c;
                    c.connectedLines.Add(line);
                }
            }

            //Part 3 - connecting footholds to anchors they pass through, selectively 
            //this part is made purely to fix problems in the foothold structure caused
            //by the auto foothold connection feature for tiles
            for (int i = 0; i < footholds.Count; i++)
            {
                line = footholds[i];
                if (line.FirstDot.Y != line.SecondDot.Y) continue;
                foreach (FootholdAnchor anchor in anchors)
                {
                    if (anchor.X == line.FirstDot.Y && ((IContainsLayerInfo)line.FirstDot).LayerNumber == anchor.LayerNumber)
                    {
                        if (anchor.connectedLines.Count == 1)
                            line = (FootholdLine)anchor.connectedLines[0];
                        else
                            line = (FootholdLine)(anchor.connectedLines[0].FirstDot.Y == anchor.connectedLines[0].SecondDot.Y ? anchor.connectedLines[0] : anchor.connectedLines[1]);
                        if (line.FirstDot.Y == line.SecondDot.Y) //blueCave2 tiles, first anchor of sloped tiles
                        {
                            //footholds.RemoveAt(i);
                            line.remove = true;
                            footholds.Add(new FootholdLine(line.Board, line.FirstDot, anchor));
                            footholds.Add(new FootholdLine(line.Board, anchor, line.SecondDot));
                            //i--;
                            break;
                            //anchor.keyAnchor = line.FirstDot.Y == line.SecondDot.Y && IsValidKeyAnchor(anchor);
                        }
                        else //junction anchor for sloped tiles
                        {
                            bool direction = line.FirstDot == anchor; //true = anchor is the left dot, so we need to delete the line going to the right
                            //footholds.RemoveAt(i);
                            line.remove = true;
                            if (direction)
                                footholds.Add(new FootholdLine(line.Board, line.FirstDot, anchor));
                            else
                                footholds.Add(new FootholdLine(line.Board, anchor, line.SecondDot));
                            break;
                        }
                    }
                }
                /*                     if (((line.FirstDot.X == line.SecondDot.X) && (anchor.X == line.FirstDot.X && anchor.Y > line.FirstDot.Y && anchor.Y < line.SecondDot.Y)
                 || ((line.FirstDot.Y == line.SecondDot.Y) && (anchor.Y == line.FirstDot.Y && anchor.X > line.FirstDot.X && anchor.X < line.SecondDot.X))) 
                 && ((IContainsLayerInfo)line.FirstDot).LayerNumber == anchor.LayerNumber)*/
            }

            FootholdLine lineA;
            FootholdLine lineB;
            //Part 4 - removing duplicate footholds (caused by step 3, case 1)
            footholds.Sort(new Comparison<FootholdLine>(FHSorter));
            for (int i = 0; i < footholds.Count - 1; i++)
            {
                lineA = footholds[i];
                lineB = footholds[i + 1];
                if (lineA.FirstDot.X == lineB.FirstDot.X && lineA.FirstDot.Y == lineB.FirstDot.Y &&
                    lineA.SecondDot.X == lineB.SecondDot.X && lineA.SecondDot.Y == lineB.SecondDot.Y)
                {
                    //footholds.RemoveAt(i);
                    lineA.remove = true;
                    i--;
                }
            }

            //Part 5 - executing foothold changes and updating anchors
            foreach (FootholdAnchor anchor in anchors)
                for (int i = 0; i < anchor.connectedLines.Count; i++)
                    if (((FootholdLine)anchor.connectedLines[i]).remove)
                        anchor.connectedLines.RemoveAt(i);
            List<FootholdLine> newFootholds = new List<FootholdLine>(footholds.Count);
            foreach (FootholdLine fh in footholds)
                if (!fh.remove)
                    newFootholds.Add(fh);
            footholds = newFootholds;


            //Part 6 - dealing with 3 way (or more) foothold junctions
            /*foreach (FootholdAnchor anchor in anchors)
            {
                if (anchor.connectedLines.Count > 2)
                {
                    if (anchor.keyAnchor)
                    {
                        int leftLineIndex = -1;
                        int rightLineIndex = -1;
                        int slopedLineIndex = -1;
                        for(int i=0; i<anchor.connectedLines.Count; i++)
                        {
                            FootholdLine line = (FootholdLine)anchor.connectedLines[i];
                            if (line.FirstDot.Y == line.SecondDot.Y)
                            {
                                if (anchor == line.FirstDot) rightLineIndex = i;
                                else if (anchor == line.SecondDot) leftLineIndex = i;
                                else
                                {
                                    MessageBox.Show("Error at foothold parsing"); //TODO
                                }
                            }
                            else if (line.FirstDot.X != line.SecondDot.X) slopedLineIndex = i;
                        }
                        if (leftLineIndex == -1 || rightLineIndex == -1 || slopedLineIndex == -1)
                        {
                            MessageBox.Show("Error at foothold parsing"); //TODO
                        }
                        FootholdLine slopedLine = (FootholdLine)anchor.connectedLines[slopedLineIndex];
                        if (slopedLine.FirstDot.Y < slopedLine.SecondDot.Y)
                        { //eliminate left
                            EliminateFootholdTree(anchor, leftLineIndex, ref footholds);
                        }
                        else
                        {
                            //eliminate right
                            EliminateFootholdTree(anchor, rightLineIndex, ref footholds);
                        }
                    }
                    else
                    {
                        double lowestLength = double.MaxValue;
                        int shortestLineIndex = -1;
                        for (int i = 0; i < anchor.connectedLines.Count; i++)
                        {
                            double length = CalculateFootholdTreeLength(anchor, i);
                            if (length < lowestLength)
                            {
                                lowestLength = length;
                                shortestLineIndex = i;
                            }
                        }
                        EliminateFootholdTree(anchor, shortestLineIndex, ref footholds);
                    }
                }
            }

            //Part 7 - executing foothold changes and updating anchors (again)
            foreach (FootholdAnchor anchor in anchors)
                for (int i = 0; i < anchor.connectedLines.Count; i++)
                    if (((FootholdLine)anchor.connectedLines[i]).remove)
                        anchor.connectedLines.RemoveAt(i);*/

            oldAnchors.Clear();
            foreach (FootholdAnchor anchor in anchors) { /*anchor.keyAnchor = false; */oldAnchors.Add(anchor); }
            oldFootholds.Clear();
            foreach (FootholdLine fh in footholds) { /*anchor.keyAnchor = false; */oldFootholds.Add(fh); }
        }