void SplitChunk(FloorChunk Chunk, FloorChunk OutLeft, FloorChunk OutRight)
        {
            int MinRoomLength = floorPlanConfig.MinRoomSize;
            int Length        = Chunk.GetLength();
            int LengthLeft    = MinRoomLength + random.Next(0, Mathf.Max(0, Length - MinRoomLength * 2));
            int LengthRight   = Length - LengthLeft;

            OutLeft.Bounds    = Chunk.Bounds;
            OutLeft.ChunkType = FloorChunkType.Room;
            OutLeft.SetLength(LengthLeft);

            OutRight.Bounds = Chunk.Bounds;
            OutRight.OffsetAlongLength(LengthLeft);
            OutRight.ChunkType = FloorChunkType.Room;
            OutRight.SetLength(LengthRight);
        }
        void SplitChunk(FloorChunk Chunk, FloorChunk OutLeft, FloorChunk OutRight, FloorChunk OutHallway)
        {
            int HallWidth       = floorPlanConfig.HallWidth;
            int Length          = Chunk.GetLength();
            int RemainingLength = Length - HallWidth;
            int MinChunkLength  = floorPlanConfig.MinRoomSize;
            int LengthLeft      = MinChunkLength + random.Next(0, Mathf.Max(0, RemainingLength - MinChunkLength * 2 + 1));
            int LengthRight     = RemainingLength - LengthLeft;

            OutLeft.Bounds    = Chunk.Bounds;
            OutLeft.ChunkType = FloorChunkType.Room;
            OutLeft.SetLength(LengthLeft);

            OutHallway.Bounds    = Chunk.Bounds;
            OutHallway.ChunkType = FloorChunkType.Hall;
            OutHallway.OffsetAlongLength(LengthLeft);
            OutHallway.SetLength(HallWidth);

            OutRight.Bounds    = Chunk.Bounds;
            OutRight.ChunkType = FloorChunkType.Room;
            OutRight.OffsetAlongLength(LengthLeft + HallWidth);
            OutRight.SetLength(LengthRight);
        }
        void BuildLayout()
        {
            ChunkDB     = new FloorChunkDB();
            DoorManager = new FloorDoorManager();
            Visited.Clear();
            random = new System.Random((int)floorPlanConfig.Seed);

            int NumFloors = Mathf.RoundToInt(floorPlanConfig.BuildingSize.y);

            for (int y = 0; y < NumFloors; y++)
            {
                // Build the hallways and the intermediate floor chunks (which will hold the rooms)
                List <FloorChunk> FloorChunks = new List <FloorChunk>();
                {
                    FloorChunk InitialFloor = ChunkDB.Create();
                    InitialFloor.Bounds.Location = new IntVector(0, y, 0);
                    InitialFloor.Bounds.Size     = MathUtils.ToIntVector(floorPlanConfig.BuildingSize);

                    Stack <FloorChunk> Stack = new Stack <FloorChunk>();
                    Stack.Push(InitialFloor);
                    while (Stack.Count > 0)
                    {
                        FloorChunk Top  = Stack.Pop();
                        float      Area = Top.Area();
                        if (Area <= 0)
                        {
                            continue;
                        }
                        if (Top.Area() <= floorPlanConfig.MinRoomChunkArea)
                        {
                            FloorChunks.Add(Top);
                        }
                        else
                        {
                            // Needs to be split further
                            FloorChunk Left    = ChunkDB.Create();
                            FloorChunk Right   = ChunkDB.Create();
                            FloorChunk Hallway = ChunkDB.Create();

                            SplitChunk(Top, Left, Right, Hallway);
                            ChunkDB.Register(Hallway);

                            Stack.Push(Left);
                            Stack.Push(Right);
                        }
                    }
                }

                // Split the floor chunks (space between the hallways) to create rooms
                foreach (FloorChunk Chunk in FloorChunks)
                {
                    Stack <FloorChunk> Stack = new Stack <FloorChunk>();
                    Stack.Push(Chunk);
                    int MinArea = floorPlanConfig.MinRoomSize * floorPlanConfig.MinRoomSize;
                    int MaxArea = floorPlanConfig.MaxRoomSize * floorPlanConfig.MaxRoomSize;

                    while (Stack.Count > 0)
                    {
                        FloorChunk Top            = Stack.Pop();
                        bool       bRequiresSplit = true;
                        int        Area           = Top.Area();
                        int        Length         = Top.GetLength();
                        if (Length > floorPlanConfig.MaxRoomSize)
                        {
                            // Length is too big. force a split
                            bRequiresSplit = true;
                        }
                        else if (Area <= MinArea)
                        {
                            // This room is too small and should not be split
                            bRequiresSplit = false;
                        }
                        else if (Area <= MaxArea)
                        {
                            float SplitProbability = (Area - MinArea) / (MaxArea - MinArea);
                            SplitProbability += floorPlanConfig.RoomSplitProbabilityOffset;
                            if (Chunk.GetLength() >= Chunk.GetWidth() * 2)
                            {
                                SplitProbability += floorPlanConfig.RoomSplitProbabilityOffset;
                            }
                            bRequiresSplit = (random.Next() < SplitProbability);
                        }

                        if (bRequiresSplit)
                        {
                            FloorChunk Left  = ChunkDB.Create();
                            FloorChunk Right = ChunkDB.Create();
                            SplitChunk(Top, Left, Right);
                            Stack.Push(Left);
                            Stack.Push(Right);
                        }
                        else
                        {
                            ChunkDB.Register(Top);
                        }
                    }
                }

                /*
                 *      // Get the chunks defined by the room volumes
                 *      List<FloorChunk> RoomVolumeChunks = new List<FloorChunk>();
                 *      if (World) {
                 *              FRectangle BuildingBounds;
                 *              BuildingBounds.Location = FIntVector::ZeroValue;
                 *              BuildingBounds.Size = FMathUtils::ToIntVector(floorPlanConfig.BuildingSize);
                 *              for (TActorIterator<AFloorPlanRoomVolume> It(World); It; ++It) {
                 *                      AFloorPlanRoomVolume* Volume = *It;
                 *                      if (Volume.Dungeon != Dungeon) {
                 *                              // This volume is not supposed to affect this dungeon
                 *                              continue;
                 *                      }
                 *                      FVector GridSize = floorPlanConfig.GridSize;
                 *                      FRectangle VolumeBounds;
                 *                      Volume.GetDungeonVolumeBounds(GridSize, VolumeBounds);
                 *                      int VolumeStartZ = VolumeBounds.Location.Z;
                 *                      int VolumeEndZ = VolumeStartZ + VolumeBounds.Size.Z;
                 *
                 *                      if (z < VolumeStartZ || z >= VolumeEndZ) {
                 *                              // Out of the volume bounds
                 *                              continue;
                 *                      }
                 *
                 *                      FRectangle ChunkBounds = VolumeBounds;
                 *                      ChunkBounds.Location.Z = z;
                 *                      ChunkBounds.Size.Z = 1;
                 *                      ChunkBounds.Clip(BuildingBounds);
                 *                      if (ChunkBounds.Size.Z == 0) continue;
                 *                      int ChunkZ = ChunkBounds.Location.Z;
                 *
                 *                      FloorChunk RoomVolumeChunk = ChunkDB.Create();
                 *                      RoomVolumeChunk.Bounds = ChunkBounds;
                 *                      RoomVolumeChunk.ChunkType = FloorChunkType.Room;
                 *                      RoomVolumeChunk.bEmitGroundMarker = (ChunkZ == VolumeStartZ);
                 *                      RoomVolumeChunk.bEmitCeilingMarker = (ChunkZ == VolumeEndZ - 1);
                 *                      RoomVolumeChunk.bConnectDoors = Volume.bConnectDoors;
                 *                      RoomVolumeChunk.WallMarker = Volume.WallMarker;
                 *                      RoomVolumeChunk.GroundMarker = Volume.GroundMarker;
                 *                      RoomVolumeChunk.CeilingMarker = Volume.CeilingMarker;
                 *                      RoomVolumeChunk.DoorMarker = Volume.DoorMarker;
                 *                      RoomVolumeChunk.CenterMarker = Volume.CenterMarker;
                 *                      RoomVolumeChunk.bCreateWalls = Volume.bCreateWalls;
                 *
                 *                      // Since this chunk is defined by a volume, we can have a more detailed rasterised cell shape
                 *                      GetVolumeCells(Volume, z, RoomVolumeChunk.BoundCells);
                 *
                 *                      // Give a higher priority to the volume chunk so it overrides everything in its path
                 *                      RoomVolumeChunk.Priority = Volume.Priority;
                 *
                 *                      RoomVolumeChunks.Add(RoomVolumeChunk);
                 *                      ChunkDB.Register(RoomVolumeChunk);
                 *              }
                 *      }
                 */
            }

            ChunkDB.CacheChunkPositions();

            for (int y = 0; y < floorPlanConfig.BuildingSize.y; y++)
            {
                CreateDoors(y);
            }
        }
Esempio n. 4
0
        void BuildLayout()
        {
            ChunkDB     = new FloorChunkDB();
            DoorManager = new FloorDoorManager();
            Visited.Clear();
            random = new System.Random((int)floorPlanConfig.Seed);

            int NumFloors = Mathf.RoundToInt(floorPlanConfig.BuildingSize.y);

            for (int y = 0; y < NumFloors; y++)
            {
                // Build the hallways and the intermediate floor chunks (which will hold the rooms)
                List <FloorChunk> FloorChunks = new List <FloorChunk>();
                {
                    FloorChunk InitialFloor = ChunkDB.Create();
                    InitialFloor.Bounds.Location = new IntVector(0, y, 0);
                    InitialFloor.Bounds.Size     = MathUtils.ToIntVector(floorPlanConfig.BuildingSize);

                    Stack <FloorChunk> Stack = new Stack <FloorChunk>();
                    Stack.Push(InitialFloor);
                    while (Stack.Count > 0)
                    {
                        FloorChunk Top  = Stack.Pop();
                        float      Area = Top.Area();
                        if (Area <= 0)
                        {
                            continue;
                        }
                        if (Top.Area() <= floorPlanConfig.MinRoomChunkArea)
                        {
                            FloorChunks.Add(Top);
                        }
                        else
                        {
                            // Needs to be split further
                            FloorChunk Left    = ChunkDB.Create();
                            FloorChunk Right   = ChunkDB.Create();
                            FloorChunk Hallway = ChunkDB.Create();

                            SplitChunk(Top, Left, Right, Hallway);
                            ChunkDB.Register(Hallway);

                            Stack.Push(Left);
                            Stack.Push(Right);
                        }
                    }
                }

                // Split the floor chunks (space between the hallways) to create rooms
                foreach (FloorChunk Chunk in FloorChunks)
                {
                    Stack <FloorChunk> Stack = new Stack <FloorChunk>();
                    Stack.Push(Chunk);
                    int MinRoomSize = floorPlanConfig.MinRoomSize;
                    int MaxRoomSize = floorPlanConfig.MaxRoomSize;
                    MaxRoomSize = Mathf.Max(MinRoomSize, MaxRoomSize);

                    int MinArea = MinRoomSize * MinRoomSize;
                    int MaxArea = MaxRoomSize * MaxRoomSize;

                    while (Stack.Count > 0)
                    {
                        FloorChunk Top            = Stack.Pop();
                        bool       bRequiresSplit = true;
                        int        Area           = Top.Area();
                        int        Length         = Top.GetLength();
                        if (Length > MaxRoomSize)
                        {
                            // Length is too big. force a split
                            bRequiresSplit = true;
                        }
                        else if (Area <= MinArea)
                        {
                            // This room is too small and should not be split
                            bRequiresSplit = false;
                        }
                        else if (Area <= MaxArea)
                        {
                            float SplitProbability = (Area - MinArea) / (MaxArea - MinArea);
                            SplitProbability += floorPlanConfig.RoomSplitProbabilityOffset;
                            if (Chunk.GetLength() >= Chunk.GetWidth() * 2)
                            {
                                SplitProbability += floorPlanConfig.RoomSplitProbabilityOffset;
                            }
                            bRequiresSplit = (random.Next() < SplitProbability);
                        }

                        if (bRequiresSplit)
                        {
                            FloorChunk Left  = ChunkDB.Create();
                            FloorChunk Right = ChunkDB.Create();
                            SplitChunk(Top, Left, Right);
                            Stack.Push(Left);
                            Stack.Push(Right);
                        }
                        else
                        {
                            ChunkDB.Register(Top);
                        }
                    }
                }

                // TODO: Add support for floor plan specific volumes
                // ...
            }

            ChunkDB.CacheChunkPositions();

            for (int y = 0; y < floorPlanConfig.BuildingSize.y; y++)
            {
                CreateDoors(y);
            }
        }