Beispiel #1
0
            public void ActionPerform()
            {
                int X = 0;
                int Y = 0;

                GL.Begin(BeginMode.LineStrip);
                GL.Color4(Colour.Red, Colour.Green, Colour.Blue, Colour.Alpha);

                StartTile.Y = (int)(Conversion.Int(StartXY.Y / App.TerrainGridSpacing));
                FinishTile.Y = Conversion.Int(FinishXY.Y / App.TerrainGridSpacing);
                LastXTile = Conversion.Int(StartXY.X / App.TerrainGridSpacing);

                Horizontal = StartXY;
                Vertex.X = Horizontal.X;
                Vertex.Y = (int)(Map.GetTerrainHeight(Horizontal));
                Vertex.Z = Convert.ToInt32(- Horizontal.Y);
                GL.Vertex3(Vertex.X, Vertex.Y, Convert.ToInt32(- Vertex.Z));

                if ( StartTile.Y + 1 <= FinishTile.Y )
                {
                    for ( Y = StartTile.Y + 1; Y <= FinishTile.Y; Y++ )
                    {
                        TileEdgeStart.X = 0;
                        TileEdgeStart.Y = Y * App.TerrainGridSpacing;
                        TileEdgeFinish.X = Map.Terrain.TileSize.X * App.TerrainGridSpacing;
                        TileEdgeFinish.Y = Y * App.TerrainGridSpacing;
                        IntersectY = MathUtil.GetLinesIntersectBetween(StartXY, FinishXY, TileEdgeStart, TileEdgeFinish);
                        if ( IntersectY.Exists )
                        {
                            StartTile.X = LastXTile;
                            FinishTile.X = (int)(Conversion.Int(IntersectY.Pos.X / App.TerrainGridSpacing));

                            for ( X = StartTile.X + 1; X <= FinishTile.X; X++ )
                            {
                                TileEdgeStart.X = X * App.TerrainGridSpacing;
                                TileEdgeStart.Y = 0;
                                TileEdgeFinish.X = X * App.TerrainGridSpacing;
                                TileEdgeFinish.Y = Map.Terrain.TileSize.Y * App.TerrainGridSpacing;
                                IntersectX = MathUtil.GetLinesIntersectBetween(StartXY, FinishXY, TileEdgeStart, TileEdgeFinish);
                                if ( IntersectX.Exists )
                                {
                                    Horizontal = IntersectX.Pos;
                                    Vertex.X = Horizontal.X;
                                    Vertex.Y = (int)(Map.GetTerrainHeight(Horizontal));
                                    Vertex.Z = Convert.ToInt32(- Horizontal.Y);
                                    GL.Vertex3(Vertex.X, Vertex.Y, Convert.ToInt32(- Vertex.Z));
                                }
                            }

                            LastXTile = FinishTile.X;

                            Horizontal = IntersectY.Pos;
                            Vertex.X = Horizontal.X;
                            Vertex.Y = (int)(Map.GetTerrainHeight(Horizontal));
                            Vertex.Z = Convert.ToInt32(- Horizontal.Y);
                            GL.Vertex3(Vertex.X, Vertex.Y, Convert.ToInt32(- Vertex.Z));
                        }
                    }
                }
                else
                {
                    StartTile.X = LastXTile;
                    FinishTile.X = Conversion.Int(FinishXY.X / App.TerrainGridSpacing);
                    for ( X = StartTile.X + 1; X <= FinishTile.X; X++ )
                    {
                        TileEdgeStart.X = X * App.TerrainGridSpacing;
                        TileEdgeStart.Y = 0;
                        TileEdgeFinish.X = X * App.TerrainGridSpacing;
                        TileEdgeFinish.Y = Map.Terrain.TileSize.Y * App.TerrainGridSpacing;
                        IntersectX = MathUtil.GetLinesIntersectBetween(StartXY, FinishXY, TileEdgeStart, TileEdgeFinish);
                        if ( IntersectX.Exists )
                        {
                            Horizontal = IntersectX.Pos;
                            Vertex.X = Horizontal.X;
                            Vertex.Y = (int)(Map.GetTerrainHeight(Horizontal));
                            Vertex.Z = Convert.ToInt32(- Horizontal.Y);
                            GL.Vertex3(Vertex.X, Vertex.Y, Convert.ToInt32(- Vertex.Z));
                        }
                    }
                }

                Horizontal = FinishXY;
                Vertex.X = Horizontal.X;
                Vertex.Y = (int)(Map.GetTerrainHeight(Horizontal));
                Vertex.Z = Convert.ToInt32(- Horizontal.Y);
                GL.Vertex3(Vertex.X, Vertex.Y, Convert.ToInt32(- Vertex.Z));

                GL.End();
            }
Beispiel #2
0
        public clsResult GenerateLayout()
        {
            clsResult ReturnResult = new clsResult("Layout");

            int X = 0;
            int Y = 0;
            int A = 0;
            int B = 0;
            int C = 0;
            int D = 0;
            int E = 0;
            int F = 0;
            int G = 0;
            int H = 0;

            TotalPlayerCount = TopLeftPlayerCount * SymmetryBlockCount;

            sXY_int SymmetrySize = new sXY_int();

            SymmetrySize.X = (int)(TileSize.X * App.TerrainGridSpacing / SymmetryBlockCountXY.X);
            SymmetrySize.Y = (int)(TileSize.Y * App.TerrainGridSpacing / SymmetryBlockCountXY.Y);

            //create passage nodes

            int PassageRadius = (int)(128.0F * NodeScale);
            int MaxLikelyPassageNodeCount = 0;
            MaxLikelyPassageNodeCount =
                (int)(Math.Ceiling(Convert.ToDecimal(2.0D * TileSize.X * 128 * TileSize.Y * 128 / (Math.PI * PassageRadius * PassageRadius))));

            PassageNodes = new clsPassageNode[SymmetryBlockCount, MaxLikelyPassageNodeCount];
            int LoopCount = 0;
            int EdgeOffset = 0 * 128;
            bool PointIsValid;
            sXY_int EdgeSections = new sXY_int();
            Position.XY_dbl EdgeSectionSize = default(Position.XY_dbl);
            sXY_int NewPointPos = new sXY_int();

            if ( SymmetryBlockCountXY.X == 1 )
            {
                EdgeSections.X =
                    Convert.ToInt32(
                        Conversion.Int((TileSize.X * App.TerrainGridSpacing - EdgeOffset * 2.0D) / (NodeScale * App.TerrainGridSpacing * 2.0F)));
                EdgeSectionSize.X = (TileSize.X * App.TerrainGridSpacing - EdgeOffset * 2.0D) / EdgeSections.X;
                EdgeSections.X--;
            }
            else
            {
                EdgeSections.X =
                    (int)
                        (Conversion.Int((TileSize.X * App.TerrainGridSpacing / SymmetryBlockCountXY.X - EdgeOffset) /
                                        (NodeScale * App.TerrainGridSpacing * 2.0F) - 0.5D));
                EdgeSectionSize.X =
                    Convert.ToDouble((TileSize.X * App.TerrainGridSpacing / SymmetryBlockCountXY.X - EdgeOffset) /
                                            (Convert.ToDouble(
                                                Conversion.Int((TileSize.X * App.TerrainGridSpacing / SymmetryBlockCountXY.X - EdgeOffset) /
                                                               (NodeScale * App.TerrainGridSpacing * 2.0F) - 0.5D)) + 0.5D));
            }
            if ( SymmetryBlockCountXY.Y == 1 )
            {
                EdgeSections.Y =
                    Convert.ToInt32(
                        Conversion.Int((TileSize.Y * App.TerrainGridSpacing - EdgeOffset * 2.0D) / (NodeScale * App.TerrainGridSpacing * 2.0F)));
                EdgeSectionSize.Y = (TileSize.Y * App.TerrainGridSpacing - EdgeOffset * 2.0D) / EdgeSections.Y;
                EdgeSections.Y--;
            }
            else
            {
                EdgeSections.Y =
                    Convert.ToInt32(
                        Conversion.Int((TileSize.Y * App.TerrainGridSpacing / SymmetryBlockCountXY.Y - EdgeOffset) /
                                       (NodeScale * App.TerrainGridSpacing * 2.0F) - 0.5D));
                EdgeSectionSize.Y =
                    Convert.ToDouble((TileSize.Y * App.TerrainGridSpacing / SymmetryBlockCountXY.Y - EdgeOffset) /
                                            (Convert.ToDouble(
                                                Conversion.Int((TileSize.Y * App.TerrainGridSpacing / SymmetryBlockCountXY.Y - EdgeOffset) /
                                                               (NodeScale * App.TerrainGridSpacing * 2.0F) - 0.5D)) + 0.5D));
            }

            PassageNodeCount = 0;
            for ( Y = 0; Y <= EdgeSections.Y; Y++ )
            {
                if ( !MakePassageNodes(new sXY_int(EdgeOffset, EdgeOffset + (int)(Y * EdgeSectionSize.Y)), true) )
                {
                    ReturnResult.ProblemAdd("Error: Bad border node.");
                    return ReturnResult;
                }
                if ( SymmetryBlockCountXY.X == 1 )
                {
                    if (
                        !MakePassageNodes(new sXY_int(TileSize.X * App.TerrainGridSpacing - EdgeOffset, EdgeOffset + (int)(Y * EdgeSectionSize.Y)), true) )
                    {
                        ReturnResult.ProblemAdd("Error: Bad border node.");
                        return ReturnResult;
                    }
                }
            }
            for ( X = 1; X <= EdgeSections.X; X++ )
            {
                if ( !MakePassageNodes(new sXY_int(EdgeOffset + (int)(X * EdgeSectionSize.X), EdgeOffset), true) )
                {
                    ReturnResult.ProblemAdd("Error: Bad border node.");
                    return ReturnResult;
                }
                if ( SymmetryBlockCountXY.Y == 1 )
                {
                    if (
                        !MakePassageNodes(new sXY_int(EdgeOffset + (int)(X * EdgeSectionSize.X), TileSize.Y * App.TerrainGridSpacing - EdgeOffset), true) )
                    {
                        ReturnResult.ProblemAdd("Error: Bad border node.");
                        return ReturnResult;
                    }
                }
            }
            do
            {
                LoopCount = 0;
                do
                {
                    PointIsValid = true;
                    if ( SymmetryBlockCountXY.X == 1 )
                    {
                        NewPointPos.X = (int)(EdgeOffset + Conversion.Int(VBMath.Rnd() * (SymmetrySize.X - EdgeOffset * 2 + 1)));
                    }
                    else
                    {
                        NewPointPos.X = EdgeOffset + (int)(Conversion.Int(VBMath.Rnd() * (SymmetrySize.X - EdgeOffset + 1)));
                    }
                    if ( SymmetryBlockCountXY.Y == 1 )
                    {
                        NewPointPos.Y = EdgeOffset + (int)(Conversion.Int(VBMath.Rnd() * (SymmetrySize.Y - EdgeOffset * 2 + 1)));
                    }
                    else
                    {
                        NewPointPos.Y = EdgeOffset + Convert.ToInt32(Conversion.Int(VBMath.Rnd() * (SymmetrySize.Y - EdgeOffset + 1)));
                    }
                    for ( A = 0; A <= PassageNodeCount - 1; A++ )
                    {
                        for ( B = 0; B <= SymmetryBlockCount - 1; B++ )
                        {
                            if ( (PassageNodes[B, A].Pos - NewPointPos).ToDoubles().GetMagnitude() < PassageRadius * 2 )
                            {
                                goto PointTooClose;
                            }
                        }
                    }
                    PointTooClose:
                    if ( A == PassageNodeCount )
                    {
                        if ( MakePassageNodes(NewPointPos, false) )
                        {
                            break;
                        }
                    }
                    LoopCount++;
                    if ( LoopCount >= (int)(64.0F * TileSize.X * TileSize.Y / (NodeScale * NodeScale)) )
                    {
                        goto PointMakingFinished;
                    }
                } while ( true );
            } while ( true );
            PointMakingFinished:
            PassageNodes =
                (clsPassageNode[,])
                    Utils.CopyArray((Array)PassageNodes, new clsPassageNode[SymmetryBlockCount, PassageNodeCount]);

            //connect until all are connected without intersecting

            MathUtil.sIntersectPos IntersectPos = new MathUtil.sIntersectPos();
            int MaxConDist2 = PassageRadius * 2 * 4;
            MaxConDist2 *= MaxConDist2;
            clsNearest NearestA = default(clsNearest);
            Nearests = new clsNearest[PassageNodeCount * 64];
            clsPassageNode tmpPassageNodeA = default(clsPassageNode);
            clsPassageNode tmpPassageNodeB = default(clsPassageNode);
            clsTestNearestArgs NearestArgs = new clsTestNearestArgs();
            int MinConDist = (int)(NodeScale * 1.25F * 128.0F);

            NearestArgs.MaxConDist2 = MaxConDist2;
            NearestArgs.MinConDist = MinConDist;

            for ( A = 0; A <= PassageNodeCount - 1; A++ )
            {
                NearestArgs.PassageNodeA = PassageNodes[0, A];
                for ( B = A; B <= PassageNodeCount - 1; B++ )
                {
                    for ( C = 0; C <= SymmetryBlockCount - 1; C++ )
                    {
                        NearestArgs.PassageNodeB = PassageNodes[C, B];
                        if ( NearestArgs.PassageNodeA != NearestArgs.PassageNodeB )
                        {
                            TestNearest(NearestArgs);
                        }
                    }
                }
            }

            clsNearest NearestB = default(clsNearest);
            bool Flag = default(bool);

            for ( G = 0; G <= NearestCount - 1; G++ )
            {
                NearestA = Nearests[G];
                for ( A = 0; A <= NearestA.NodeCount - 1; A++ )
                {
                    tmpPassageNodeA = NearestA.NodeA[A];
                    tmpPassageNodeB = NearestA.NodeB[A];
                    for ( H = 0; H <= NearestCount - 1; H++ )
                    {
                        NearestB = Nearests[H];
                        if ( NearestB != NearestA )
                        {
                            if ( NearestB.Dist2 < NearestA.Dist2 )
                            {
                                Flag = true;
                            }
                            else if ( NearestB.Dist2 == NearestA.Dist2 )
                            {
                                Flag = NearestA.Num > NearestB.Num;
                            }
                            else
                            {
                                Flag = false;
                            }
                            if ( Flag )
                            {
                                for ( B = 0; B <= NearestB.NodeCount - 1; B++ )
                                {
                                    if ( !(tmpPassageNodeA == NearestB.NodeA[B] || tmpPassageNodeA == NearestB.NodeB[B]
                                           || tmpPassageNodeB == NearestB.NodeA[B] || tmpPassageNodeB == NearestB.NodeB[B]) )
                                    {
                                        IntersectPos = MathUtil.GetLinesIntersectBetween(tmpPassageNodeA.Pos, tmpPassageNodeB.Pos, NearestB.NodeA[B].Pos,
                                            NearestB.NodeB[B].Pos);
                                        if ( IntersectPos.Exists )
                                        {
                                            break;
                                        }
                                    }
                                }
                                if ( B < NearestB.NodeCount )
                                {
                                    NearestA.BlockedCount++;
                                    NearestB.BlockedNearests[NearestB.BlockedNearestCount] = NearestA;
                                    NearestB.BlockedNearestCount++;
                                }
                            }
                        }
                    }
                }
            }

            int ChangeCount = 0;
            Connections = new clsConnection[PassageNodeCount * 16];

            do
            {
                //create valid connections
                ChangeCount = 0;
                G = 0;
                while ( G < NearestCount )
                {
                    NearestA = Nearests[G];
                    Flag = true;
                    if ( NearestA.BlockedCount == 0 && Flag )
                    {
                        F = ConnectionCount;
                        for ( D = 0; D <= NearestA.NodeCount - 1; D++ )
                        {
                            Connections[ConnectionCount] = new clsConnection(NearestA.NodeA[D], NearestA.NodeB[D]);
                            ConnectionCount++;
                        }
                        for ( D = 0; D <= NearestA.NodeCount - 1; D++ )
                        {
                            A = F + D;
                            Connections[A].ReflectionCount = NearestA.NodeCount - 1;
                            Connections[A].Reflections = new clsConnection[Connections[A].ReflectionCount];
                            B = 0;
                            for ( E = 0; E <= NearestA.NodeCount - 1; E++ )
                            {
                                if ( E != D )
                                {
                                    Connections[A].Reflections[B] = Connections[F + E];
                                    B++;
                                }
                            }
                        }
                        for ( C = 0; C <= NearestA.BlockedNearestCount - 1; C++ )
                        {
                            NearestA.BlockedNearests[C].Invalid = true;
                        }
                        NearestCount--;
                        H = NearestA.Num;
                        NearestA.Num = -1;
                        if ( H != NearestCount )
                        {
                            Nearests[H] = Nearests[NearestCount];
                            Nearests[H].Num = H;
                        }
                        ChangeCount++;
                    }
                    else
                    {
                        if ( !Flag )
                        {
                            NearestA.Invalid = true;
                        }
                        G++;
                    }
                }
                //remove blocked ones and their blocking effect
                G = 0;
                while ( G < NearestCount )
                {
                    NearestA = Nearests[G];
                    if ( NearestA.Invalid )
                    {
                        NearestA.Num = -1;
                        for ( D = 0; D <= NearestA.BlockedNearestCount - 1; D++ )
                        {
                            NearestA.BlockedNearests[D].BlockedCount--;
                        }
                        NearestCount--;
                        if ( G != NearestCount )
                        {
                            Nearests[G] = Nearests[NearestCount];
                            Nearests[G].Num = G;
                        }
                    }
                    else
                    {
                        G++;
                    }
                }
            } while ( ChangeCount > 0 );

            //put connections in order of angle

            for ( A = 0; A <= PassageNodeCount - 1; A++ )
            {
                for ( B = 0; B <= SymmetryBlockCount - 1; B++ )
                {
                    PassageNodes[B, A].ReorderConnections();
                    PassageNodes[B, A].CalcIsNearBorder();
                }
            }

            //get nodes in random order

            clsPassageNode[] PassageNodeListOrder = new clsPassageNode[PassageNodeCount];
            int PassageNodeListOrderCount = 0;
            clsPassageNode[] PassageNodeOrder = new clsPassageNode[PassageNodeCount];
            for ( A = 0; A <= PassageNodeCount - 1; A++ )
            {
                PassageNodeListOrder[PassageNodeListOrderCount] = PassageNodes[0, A];
                PassageNodeListOrderCount++;
            }
            B = 0;
            while ( PassageNodeListOrderCount > 0 )
            {
                A = (int)(Conversion.Int(VBMath.Rnd() * PassageNodeListOrderCount));
                PassageNodeOrder[B] = PassageNodeListOrder[A];
                B++;
                PassageNodeListOrderCount--;
                PassageNodeListOrder[A] = PassageNodeListOrder[PassageNodeListOrderCount];
            }

            //designate height levels

            LevelHeight = 255.0F / (LevelCount - 1);
            int BestNum = 0;
            double Dist = 0;
            clsPassageNodeHeightLevelArgs HeightsArgs = new clsPassageNodeHeightLevelArgs();
            HeightsArgs.PassageNodesMinLevel.Nodes = new int[PassageNodeCount];
            HeightsArgs.PassageNodesMaxLevel.Nodes = new int[PassageNodeCount];
            HeightsArgs.MapLevelCount = new int[LevelCount];
            sXY_int RotatedPos = new sXY_int();

            for ( A = 0; A <= PassageNodeCount - 1; A++ )
            {
                HeightsArgs.PassageNodesMinLevel.Nodes[A] = 0;
                HeightsArgs.PassageNodesMaxLevel.Nodes[A] = LevelCount - 1;
            }

            //create bases
            double[] BestDists = new double[BaseFlatArea];
            clsPassageNode[] BestNodes = new clsPassageNode[BaseFlatArea];
            int[] BestNodesReflectionNums = new int[BaseFlatArea];
            int BestDistCount = 0;
            PlayerBases = new sPlayerBase[TotalPlayerCount];
            for ( B = 0; B <= TopLeftPlayerCount - 1; B++ )
            {
                BestDistCount = 0;
                for ( A = 0; A <= PassageNodeCount - 1; A++ )
                {
                    for ( E = 0; E <= SymmetryBlockCount - 1; E++ )
                    {
                        tmpPassageNodeA = PassageNodes[E, A];
                        if ( !tmpPassageNodeA.IsOnBorder )
                        {
                            Dist = (tmpPassageNodeA.Pos - PlayerBasePos[B]).ToDoubles().GetMagnitude();
                            for ( C = BestDistCount - 1; C >= 0; C-- )
                            {
                                if ( Dist > BestDists[C] )
                                {
                                    break;
                                }
                            }
                            C++;
                            for ( D = Math.Min(BestDistCount - 1, BaseFlatArea - 2); D >= C; D-- )
                            {
                                BestDists[D + 1] = BestDists[D];
                                BestNodes[D + 1] = BestNodes[D];
                            }
                            if ( C < BaseFlatArea )
                            {
                                BestDists[C] = Dist;
                                BestNodes[C] = tmpPassageNodeA;
                                BestDistCount = Math.Max(BestDistCount, C + 1);
                            }
                        }
                    }
                }

                if ( BaseLevel < 0 )
                {
                    D = Convert.ToInt32(Conversion.Int(VBMath.Rnd() * LevelCount));
                }
                else
                {
                    D = BaseLevel;
                }

                HeightsArgs.MapLevelCount[D] += BestDistCount;

                for ( A = 0; A <= BestDistCount - 1; A++ )
                {
                    if ( BestNodes[A].MirrorNum == 0 )
                    {
                        BestNodesReflectionNums[A] = -1;
                    }
                    else
                    {
                        for ( C = 0; C <= ((int)(SymmetryBlockCount / 2.0D)) - 1; C++ )
                        {
                            if ( SymmetryBlocks[0].ReflectToNum[C] == BestNodes[A].MirrorNum )
                            {
                                break;
                            }
                        }
                        BestNodesReflectionNums[A] = C;
                    }
                }

                for ( A = 0; A <= SymmetryBlockCount - 1; A++ )
                {
                    E = A * TopLeftPlayerCount + B;
                    PlayerBases[E].NodeCount = BestDistCount;
                    PlayerBases[E].Nodes = new clsPassageNode[PlayerBases[E].NodeCount];
                    for ( C = 0; C <= BestDistCount - 1; C++ )
                    {
                        if ( BestNodesReflectionNums[C] < 0 )
                        {
                            PlayerBases[E].Nodes[C] = PassageNodes[A, BestNodes[C].Num];
                        }
                        else
                        {
                            PlayerBases[E].Nodes[C] = PassageNodes[SymmetryBlocks[A].ReflectToNum[BestNodesReflectionNums[C]], BestNodes[C].Num];
                        }
                        PlayerBases[E].Nodes[C].PlayerBaseNum = E;
                        PlayerBases[E].Nodes[C].Level = D;
                        PassageNodesMinLevelSet(PlayerBases[E].Nodes[C], HeightsArgs.PassageNodesMinLevel, D, MaxLevelTransition);
                        PassageNodesMaxLevelSet(PlayerBases[E].Nodes[C], HeightsArgs.PassageNodesMaxLevel, D, MaxLevelTransition);
                    }
                    //PlayerBases(E).CalcPos()
                    RotatedPos = TileUtil.GetRotatedPos(SymmetryBlocks[A].Orientation, PlayerBasePos[B],
                        new sXY_int(SymmetrySize.X - 1, SymmetrySize.Y - 1));
                    PlayerBases[E].Pos.X = SymmetryBlocks[A].XYNum.X * SymmetrySize.X + RotatedPos.X;
                    PlayerBases[E].Pos.Y = SymmetryBlocks[A].XYNum.Y * SymmetrySize.Y + RotatedPos.Y;
                }
            }

            int WaterCount = 0;
            bool CanDoFlatsAroundWater = default(bool);
            int TotalWater = 0;
            int WaterSpawns = 0;

            for ( A = 0; A <= PassageNodeCount - 1; A++ )
            {
                tmpPassageNodeA = PassageNodeOrder[A];
                if ( tmpPassageNodeA.Level < 0 && !tmpPassageNodeA.IsOnBorder )
                {
                    WaterCount = 0;
                    for ( B = 0; B <= tmpPassageNodeA.ConnectionCount - 1; B++ )
                    {
                        tmpPassageNodeB = tmpPassageNodeA.Connections[B].GetOther();
                        if ( tmpPassageNodeB.IsWater )
                        {
                            WaterCount++;
                        }
                    }
                    CanDoFlatsAroundWater = true;
                    for ( B = 0; B <= tmpPassageNodeA.ConnectionCount - 1; B++ )
                    {
                        if ( HeightsArgs.PassageNodesMinLevel.Nodes[tmpPassageNodeA.Connections[B].GetOther().Num] > 0 )
                        {
                            CanDoFlatsAroundWater = false;
                        }
                    }
                    if ( CanDoFlatsAroundWater &&
                         ((WaterCount == 0 & WaterSpawns < WaterSpawnQuantity) || (WaterCount == 1 & TotalWaterQuantity - TotalWater > WaterSpawnQuantity - WaterSpawns)) &&
                         HeightsArgs.PassageNodesMinLevel.Nodes[tmpPassageNodeA.Num] == 0 & TotalWater < TotalWaterQuantity )
                    {
                        if ( WaterCount == 0 )
                        {
                            WaterSpawns++;
                        }
                        TotalWater++;
                        C = tmpPassageNodeA.Num;
                        for ( D = 0; D <= SymmetryBlockCount - 1; D++ )
                        {
                            PassageNodes[D, C].IsWater = true;
                            PassageNodes[D, C].Level = 0;
                        }
                        PassageNodesMinLevelSet(tmpPassageNodeA, HeightsArgs.PassageNodesMinLevel, 0, MaxLevelTransition);
                        PassageNodesMaxLevelSet(tmpPassageNodeA, HeightsArgs.PassageNodesMaxLevel, 0, MaxLevelTransition);
                        HeightsArgs.MapLevelCount[0]++;
                        for ( B = 0; B <= tmpPassageNodeA.ConnectionCount - 1; B++ )
                        {
                            tmpPassageNodeB = tmpPassageNodeA.Connections[B].GetOther();
                            PassageNodesMinLevelSet(tmpPassageNodeB, HeightsArgs.PassageNodesMinLevel, 0, MaxLevelTransition);
                            PassageNodesMaxLevelSet(tmpPassageNodeB, HeightsArgs.PassageNodesMaxLevel, 0, MaxLevelTransition);
                        }
                    }
                }
            }

            clsPassageNode tmpPassageNodeC = default(clsPassageNode);
            App.sResult Result = new App.sResult();

            HeightsArgs.FlatsCutoff = 1;
            HeightsArgs.PassagesCutoff = 1;
            HeightsArgs.VariationCutoff = 1;
            HeightsArgs.ActionTotal = 1;

            for ( A = 0; A <= PassageNodeCount - 1; A++ )
            {
                tmpPassageNodeA = PassageNodeOrder[A];
                if ( tmpPassageNodeA.Level < 0 && !tmpPassageNodeA.IsOnBorder && tmpPassageNodeA.IsNearBorder )
                {
                    HeightsArgs.PassageNode = tmpPassageNodeA;
                    Result = PassageNodeHeightLevel(HeightsArgs);
                    if ( !Result.Success )
                    {
                        ReturnResult.ProblemAdd(Result.Problem);
                        return ReturnResult;
                    }
                }
            }

            HeightsArgs.FlatsCutoff = FlatsChance;
            HeightsArgs.PassagesCutoff = HeightsArgs.FlatsCutoff + PassagesChance;
            HeightsArgs.VariationCutoff = HeightsArgs.PassagesCutoff + VariationChance;
            HeightsArgs.ActionTotal = HeightsArgs.VariationCutoff;
            if ( HeightsArgs.ActionTotal <= 0 )
            {
                ReturnResult.ProblemAdd("All height level behaviors are zero");
                return ReturnResult;
            }

            for ( A = 0; A <= PassageNodeCount - 1; A++ )
            {
                tmpPassageNodeA = PassageNodeOrder[A];
                if ( tmpPassageNodeA.Level < 0 && !tmpPassageNodeA.IsOnBorder )
                {
                    HeightsArgs.PassageNode = tmpPassageNodeA;
                    Result = PassageNodeHeightLevel(HeightsArgs);
                    if ( !Result.Success )
                    {
                        ReturnResult.ProblemAdd(Result.Problem);
                        return ReturnResult;
                    }
                }
            }

            //set edge points to the level of their neighbour
            for ( A = 0; A <= PassageNodeCount - 1; A++ )
            {
                tmpPassageNodeA = PassageNodes[0, A];
                if ( tmpPassageNodeA.IsOnBorder )
                {
                    if ( tmpPassageNodeA.Level >= 0 )
                    {
                        ReturnResult.ProblemAdd("Error: Border has had its height set.");
                        return ReturnResult;
                    }
                    //If tmpPassageNodeA.ConnectionCount <> 1 Then
                    //    ReturnResult.Problem = "Error: Border has incorrect connections."
                    //    Exit Function
                    //End If
                    tmpPassageNodeC = null;
                    CanDoFlatsAroundWater = true;
                    for ( B = 0; B <= tmpPassageNodeA.ConnectionCount - 1; B++ )
                    {
                        tmpPassageNodeB = tmpPassageNodeA.Connections[B].GetOther();
                        if ( tmpPassageNodeB.Level >= 0 && !tmpPassageNodeB.IsOnBorder )
                        {
                            if ( HeightsArgs.PassageNodesMinLevel.Nodes[tmpPassageNodeA.Num] <= tmpPassageNodeB.Level &&
                                 HeightsArgs.PassageNodesMaxLevel.Nodes[tmpPassageNodeA.Num] >= tmpPassageNodeB.Level )
                            {
                                if ( tmpPassageNodeC == null )
                                {
                                    tmpPassageNodeC = tmpPassageNodeB;
                                }
                            }
                        }
                        if ( HeightsArgs.PassageNodesMinLevel.Nodes[tmpPassageNodeB.Num] > 0 )
                        {
                            CanDoFlatsAroundWater = false;
                        }
                    }
                    //If tmpPassageNodeC Is Nothing Then
                    //    ReturnResult.Problem_Add("Error: No connection for border node")
                    //    Return ReturnResult
                    //End If
                    if ( tmpPassageNodeC != null )
                    {
                        BestNum = tmpPassageNodeC.Level;
                        PassageNodesMinLevelSet(tmpPassageNodeA, HeightsArgs.PassageNodesMinLevel, BestNum, MaxLevelTransition);
                        PassageNodesMaxLevelSet(tmpPassageNodeA, HeightsArgs.PassageNodesMaxLevel, BestNum, MaxLevelTransition);
                        for ( D = 0; D <= SymmetryBlockCount - 1; D++ )
                        {
                            PassageNodes[D, A].IsWater = tmpPassageNodeC.IsWater && CanDoFlatsAroundWater;
                            PassageNodes[D, A].Level = BestNum;
                        }
                        if ( tmpPassageNodeA.IsWater )
                        {
                            for ( B = 0; B <= tmpPassageNodeA.ConnectionCount - 1; B++ )
                            {
                                tmpPassageNodeB = tmpPassageNodeA.Connections[B].GetOther();
                                PassageNodesMinLevelSet(tmpPassageNodeB, HeightsArgs.PassageNodesMinLevel, tmpPassageNodeA.Level, MaxLevelTransition);
                                PassageNodesMaxLevelSet(tmpPassageNodeB, HeightsArgs.PassageNodesMaxLevel, tmpPassageNodeA.Level, MaxLevelTransition);
                            }
                        }
                    }
                }
                else if ( tmpPassageNodeA.Level < 0 )
                {
                    ReturnResult.ProblemAdd("Error: Node height not set");
                    return ReturnResult;
                }
            }
            //set level of edge points only connected to another border point
            for ( A = 0; A <= PassageNodeCount - 1; A++ )
            {
                tmpPassageNodeA = PassageNodes[0, A];
                if ( tmpPassageNodeA.IsOnBorder && tmpPassageNodeA.Level < 0 )
                {
                    tmpPassageNodeC = null;
                    CanDoFlatsAroundWater = true;
                    for ( B = 0; B <= tmpPassageNodeA.ConnectionCount - 1; B++ )
                    {
                        tmpPassageNodeB = tmpPassageNodeA.Connections[B].GetOther();
                        if ( tmpPassageNodeB.Level >= 0 )
                        {
                            if ( HeightsArgs.PassageNodesMinLevel.Nodes[tmpPassageNodeA.Num] <= tmpPassageNodeB.Level &&
                                 HeightsArgs.PassageNodesMaxLevel.Nodes[tmpPassageNodeA.Num] >= tmpPassageNodeB.Level )
                            {
                                if ( tmpPassageNodeC == null )
                                {
                                    tmpPassageNodeC = tmpPassageNodeB;
                                }
                            }
                        }
                        if ( HeightsArgs.PassageNodesMinLevel.Nodes[tmpPassageNodeB.Num] > 0 )
                        {
                            CanDoFlatsAroundWater = false;
                        }
                    }
                    if ( tmpPassageNodeC == null )
                    {
                        ReturnResult.ProblemAdd("Error: No connection for border node");
                        return ReturnResult;
                    }
                    BestNum = tmpPassageNodeC.Level;
                    PassageNodesMinLevelSet(tmpPassageNodeA, HeightsArgs.PassageNodesMinLevel, BestNum, MaxLevelTransition);
                    PassageNodesMaxLevelSet(tmpPassageNodeA, HeightsArgs.PassageNodesMaxLevel, BestNum, MaxLevelTransition);
                    for ( D = 0; D <= SymmetryBlockCount - 1; D++ )
                    {
                        PassageNodes[D, A].IsWater = tmpPassageNodeC.IsWater && CanDoFlatsAroundWater;
                        PassageNodes[D, A].Level = BestNum;
                    }
                    if ( tmpPassageNodeA.IsWater )
                    {
                        for ( B = 0; B <= tmpPassageNodeA.ConnectionCount - 1; B++ )
                        {
                            tmpPassageNodeB = tmpPassageNodeA.Connections[B].GetOther();
                            PassageNodesMinLevelSet(tmpPassageNodeB, HeightsArgs.PassageNodesMinLevel, tmpPassageNodeA.Level, MaxLevelTransition);
                            PassageNodesMaxLevelSet(tmpPassageNodeB, HeightsArgs.PassageNodesMaxLevel, tmpPassageNodeA.Level, MaxLevelTransition);
                        }
                    }
                }
            }

            RampBase = 1.0D;
            MaxDisconnectionDist = 99999.0F;

            clsResult RampResult = GenerateRamps();
            ReturnResult.Add(RampResult);

            return ReturnResult;
        }