protected override bool AttemptBlob(T map, BlobMap blobMap, int blobIdx) { bool IsMapValid(Loc loc) => map.GetTile(loc).TileEquivalent(map.RoomTerrain); // the XY to add to translate from point on the map to point on the blob map Loc offset = Loc.Zero; bool IsBlobValid(Loc loc) { Loc srcLoc = loc + blobMap.Blobs[blobIdx].Bounds.Start; if (!Collision.InBounds(blobMap.Blobs[blobIdx].Bounds, srcLoc)) { return(false); } Loc destLoc = loc + offset; if (!map.CanSetTile(destLoc, this.Terrain)) { return(false); } return(blobMap.Map[srcLoc.X][srcLoc.Y] == blobIdx); } // attempt to place in 20 locations for (int jj = 0; jj < 20; jj++) { Rect blobRect = blobMap.Blobs[blobIdx].Bounds; offset = new Loc(map.Rand.Next(0, map.Width - blobRect.Width), map.Rand.Next(0, map.Height - blobRect.Height)); Loc blobMod = blobMap.Blobs[blobIdx].Bounds.Start - offset; // pass this into the walkable detection function bool disconnects = Detection.DetectDisconnect(new Rect(0, 0, map.Width, map.Height), IsMapValid, offset, blobRect.Size, IsBlobValid, true); // if it's a pass, draw on tile if it's a wall terrain or a room terrain if (disconnects) { continue; } this.DrawBlob(map, blobMap, blobIdx, offset, true); return(true); } return(false); }
public override void Apply(T map) { int waterPercent = this.WaterPercent.Pick(map.Rand); if (waterPercent == 0) { return; } int depthRange = 0x1 << (this.OrderComplexity + this.OrderSoftness); // aka, 2 ^ degree int minWater = waterPercent * map.Width * map.Height / 100; int[][] noise = NoiseGen.PerlinNoise(map.Rand, map.Width, map.Height, this.OrderComplexity, this.OrderSoftness); int[] depthCount = new int[depthRange]; for (int xx = 0; xx < map.Width; xx++) { for (int yy = 0; yy < map.Height; yy++) { depthCount[noise[xx][yy]]++; } } int waterMark = 0; int totalDepths = 0; for (int ii = 0; ii < depthCount.Length; ii++) { if (totalDepths + depthCount[ii] >= minWater) { if (totalDepths + depthCount[ii] - minWater < minWater - totalDepths) { waterMark++; } break; } totalDepths += depthCount[ii]; waterMark++; } if (this.RespectFloor) { this.DrawWhole(map, noise, depthRange, waterMark); return; } while (waterMark > 0) { bool IsWaterValid(Loc loc) { int heightPercent = Math.Min(100, Math.Min(Math.Min(loc.X * 100 / BUFFER_SIZE, loc.Y * 100 / BUFFER_SIZE), Math.Min((map.Width - 1 - loc.X) * 100 / BUFFER_SIZE, (map.Height - 1 - loc.Y) * 100 / BUFFER_SIZE))); int noiseVal = (noise[loc.X][loc.Y] * heightPercent / 100) + (depthRange * (100 - heightPercent) / 100); return(noiseVal < waterMark); } BlobMap blobMap = Detection.DetectBlobs(new Rect(0, 0, map.Width, map.Height), IsWaterValid); bool IsMapValid(Loc loc) => map.GetTile(loc).TileEquivalent(map.RoomTerrain); int blobIdx = 0; bool IsBlobValid(Loc loc) { Loc srcLoc = loc + blobMap.Blobs[blobIdx].Bounds.Start; if (!map.CanSetTile(srcLoc, this.Terrain)) { return(false); } return(blobMap.Map[srcLoc.X][srcLoc.Y] == blobIdx); } for (; blobIdx < blobMap.Blobs.Count; blobIdx++) { Rect blobRect = blobMap.Blobs[blobIdx].Bounds; // pass this into the walkable detection function bool disconnects = Detection.DetectDisconnect(new Rect(0, 0, map.Width, map.Height), IsMapValid, blobRect.Start, blobRect.Size, IsBlobValid, true); // if it's a pass, draw on tile if it's a wall terrain or a room terrain if (!disconnects) { this.DrawBlob(map, blobMap, blobIdx, blobRect.Start, true); } else { // if it's a fail, draw on the tile only if wall terrain this.DrawBlob(map, blobMap, blobIdx, blobRect.Start, false); } } waterMark -= Math.Max(1, depthRange / 8); } }