protected internal override void OnZap(int cell) { var localLevel = Level; var n = localLevel + 2; if (Actor.FindChar(cell) != null && Ballistica.Distance > 2) { cell = Ballistica.Trace[Ballistica.Distance - 2]; } var passable = BArray.or(levels.Level.passable, levels.Level.avoid, null); foreach (var actor in Actor.All.OfType <Character>()) { passable[(actor).pos] = false; } PathFinder.BuildDistanceMap(cell, passable, n); var dist = 0; if (Actor.FindChar(cell) != null) { PathFinder.Distance[cell] = int.MaxValue; dist = 1; } float lifespan = localLevel + 3; sheepLabel: for (var i = 0; i < n; i++) { do { for (var j = 0; j < levels.Level.Length; j++) { if (PathFinder.Distance[j] != dist) { continue; } var sheep = new Sheep(); sheep.Lifespan = lifespan; sheep.pos = j; GameScene.Add(sheep); Dungeon.Level.MobPress(sheep); CellEmitter.Get(j).Burst(Speck.Factory(Speck.WOOL), 4); PathFinder.Distance[j] = int.MaxValue; goto sheepLabel; } dist++; } while (dist < n); } }
private void Summon() { _nextPedestal = !_nextPedestal; Sprite.CenterEmitter().Start(Speck.Factory(Speck.SCREAM), 0.4f, 2); Sample.Instance.Play(Assets.SND_CHALLENGE); var passable = (bool[])Level.passable.Clone(); foreach (var actor in All.OfType <Character>()) { passable[(actor).pos] = false; } var undeadsToSummon = maxArmySize() - Undead.count; PathFinder.BuildDistanceMap(pos, passable, undeadsToSummon); PathFinder.Distance[pos] = int.MaxValue; var dist = 1; undeadLabel: for (var i = 0; i < undeadsToSummon; i++) { do { for (var j = 0; j < Level.Length; j++) { if (PathFinder.Distance[j] != dist) { continue; } var undead = new Undead(); undead.pos = j; GameScene.Add(undead); WandOfBlink.Appear(undead, j); new Flare(3, 32).Color(0x000000, false).Show(undead.Sprite, 2f); PathFinder.Distance[j] = int.MaxValue; goto undeadLabel; } dist++; }while (dist < undeadsToSummon); } Yell("Arise, slaves!"); }
public override void Activate(Character ch) { base.Activate(ch); PathFinder.BuildDistanceMap(Pos, BArray.not(Level.losBlocking, null), 1); var fire = (Fire)Dungeon.Level.Blobs[typeof(Fire)]; for (var i = 0; i < Level.Length; i++) { if (PathFinder.Distance[i] < int.MaxValue) { Freezing.Affect(i, fire); } } }
protected internal override void OnZap(int cell) { Sample.Instance.Play(Assets.SND_ROCKS); var localLevel = Level; Ballistica.Distance = Math.Min(Ballistica.Distance, 8 + localLevel); var size = 1 + localLevel / 3; PathFinder.BuildDistanceMap(cell, BArray.not(levels.Level.solid, null), size); for (var i = 0; i < levels.Level.Length; i++) { int d = PathFinder.Distance[i]; if (d >= int.MaxValue) { continue; } var ch = Actor.FindChar(i); if (ch != null) { ch.Sprite.Flash(); ch.Damage(pdsharp.utils.Random.Int(2, 6 + (size - d) * 2), this); if (ch.IsAlive && pdsharp.utils.Random.Int(2 + d) == 0) { Buff.Prolong <Paralysis>(ch, pdsharp.utils.Random.IntRange(2, 6)); } } CellEmitter.Get(i).Start(Speck.Factory(Speck.ROCK), 0.07f, 3 + (size - d)); Camera.Main.Shake(3, 0.07f * (3 + (size - d))); } if (CurUser.IsAlive) { return; } Dungeon.Fail(Utils.Format(ResultDescriptions.WAND, name, Dungeon.Depth)); GLog.Negative("You killed yourself with your own Wand of Avalanche..."); }
protected internal override void Shatter(int cell) { PathFinder.BuildDistanceMap(cell, BArray.not(Level.losBlocking, null), Distance); var fire = (Fire)Dungeon.Level.Blobs[typeof(Fire)]; for (var i = 0; i < Level.Length; i++) { if (PathFinder.Distance[i] < int.MaxValue) { Freezing.Affect(i, fire); } } splash(cell); Sample.Instance.Play(Assets.SND_SHATTER); SetKnown(); }
protected internal override void Shatter(int cell) { PathFinder.BuildDistanceMap(cell, BArray.not(Level.losBlocking, null), DISTANCE); var procd = false; Blob[] blobs = { Dungeon.Level.Blobs[typeof(ToxicGas)], Dungeon.Level.Blobs[typeof(ParalyticGas)] }; foreach (var blob in blobs) { if (blob == null) { continue; } for (var i = 0; i < Level.Length; i++) { if (PathFinder.Distance[i] >= int.MaxValue) { continue; } var value = blob.Cur[i]; if (value <= 0) { continue; } blob.Cur[i] = 0; blob.Volume -= value; procd = true; CellEmitter.Get(i).Burst(Speck.Factory(Speck.DISCOVER), 1); } } var heroAffected = PathFinder.Distance[Dungeon.Hero.pos] < int.MaxValue; if (procd) { splash(cell); Sample.Instance.Play(Assets.SND_SHATTER); SetKnown(); if (heroAffected) { GLog.Positive(TXT_FRESHNESS); } } else { base.Shatter(cell); if (!heroAffected) { return; } GLog.Information(TXT_FRESHNESS); SetKnown(); } }
public override void Paint(Level level) { var w = GetWidth(); var h = GetHeight(); var old = Painter.Clip; Painter.Clip = null; Painter.Fill(level, this, Wall); Painter.Clip = old; Painter.FillEllipse(level, this, 3, Tile.FloorA); Painter.FillEllipse(level, this, (int)(Math.Min(w, h) / 2f - 2), Tile.FloorD); var r = GetCenterRect(); PaintTunnel(level, Tile.FloorA, r, true); PaintTunnel(level, Tile.FloorD, r); Pass((x, y) => { var t = level.Get(x, y); if (t != Tile.FloorD || Rnd.Chance(30)) { if (t == Tile.WallA && Rnd.Chance(10)) { Painter.Set(level, x, y, Tile.FloorA); } return; } var sz = Rnd.Int(2, 4); for (var xx = -sz; xx <= sz; xx++) { for (var yy = -sz; yy <= sz; yy++) { if (level.Get(x + xx, y + yy) != Tile.FloorD) { Painter.Set(level, x + xx, y + yy, Rnd.Chance(30) ? Tile.WallA : Tile.FloorA); } } } }); var array = new byte[w, h]; var oldArray = new byte[w, h]; Pass((x, y) => { var t = level.Get(x, y); if (t == Tile.FloorA && Rnd.Float() > 0.55f - (float)(Math.Cos(x / 16f) * 0.02f + Math.Cos(y / 16f) * 0.1f)) { t = Tile.WallA; Painter.Set(level, x, y, t); } var v = t == Tile.FloorA ? 0 : 1; if (t == Tile.FloorD) { v = 2; } array[x - Left, y - Top] = (byte)v; oldArray[x - Left, y - Top] = (byte)v; }); for (var i = 0; i < 5; i++) { for (var x = 0; x < w; x++) { for (var y = 0; y < h; y++) { var c = oldArray[x, y]; var n = 0; foreach (var d in MathUtils.AllDirections) { var xx = x + (int)d.X; var yy = y + (int)d.Y; if (xx < 0 || xx >= w || yy < 0 || yy >= h) { n++; continue; } if (oldArray[xx, yy] == 1) { n++; } } if (c != 2) { if (n < DeathCondition) { c = 0; } else if (n > BirthCondition) { c = 1; } } array[x, y] = c; } } for (var x = 0; x < w; x++) { for (var y = 0; y < h; y++) { oldArray[x, y] = array[x, y]; } } } Action <int, int> fill = null; var queue = new Queue <Dot>(); var m = 0; fill = (x, y) => { if (x < 0 || y < 0 || x >= w || y >= h) { return; } var v = array[x, y]; if (v == 1 || v == 3) { return; } m++; array[x, y] = 3; queue.Enqueue(new Dot(x - 1, y)); queue.Enqueue(new Dot(x + 1, y)); queue.Enqueue(new Dot(x, y - 1)); queue.Enqueue(new Dot(x, y + 1)); }; var painted = false; foreach (var dr in Connected.Values) { var st = new Dot(dr.X, dr.Y); if (dr.X == Left) { st = new Dot(dr.X + 1, dr.Y); } else if (dr.X == Right) { st = new Dot(dr.X - 1, dr.Y); } else if (dr.Y == Top) { st = new Dot(dr.X, dr.Y + 1); } else if (dr.Y == Bottom) { st = new Dot(dr.X, dr.Y - 1); } fill(st.X - Left, st.Y - Top); if (queue.Count != 0) { painted = true; break; } } if (!painted) { Log.Error("Did not spot a spot in the jungle room!"); Paint(level); return; } while (queue.Count > 0) { var d = queue.Dequeue(); fill(d.X, d.Y); } var start = 0; var ww = GetWidth(); var hh = GetHeight(); Func <int, int, int> toIndex = (x, y) => (x - Left) + (y - Top) * ww; foreach (var d in Connected.Values) { if (d.X == Left) { start = toIndex(d.X + 1, d.Y); } else if (d.X == Right) { start = toIndex(d.X - 1, d.Y); } else if (d.Y == Top) { start = toIndex(d.X, d.Y + 1); } else if (d.Y == Bottom) { start = toIndex(d.X, d.Y - 1); } } Pass((x, y) => { if (x > Left && x < Right && y > Top && y < Bottom) { Painter.Set(level, x, y, array[x - Left, y - Top] == 3 ? Floor : Wall); } }); var patch = new bool[ww * hh]; for (var y = 0; y < hh; y++) { for (var x = 0; x < ww; x++) { patch[y * ww + x] = !level.Get(Left + x, Top + y).IsPassable(); } } PathFinder.SetMapSize(ww, hh); PathFinder.BuildDistanceMap(start, BArray.Not(patch, null)); var valid = true; for (var i = 0; i < patch.Length; i++) { if (!patch[i] && PathFinder.Distance[i] == Int32.MaxValue) { valid = false; break; } } // level.Set(Left + start % ww, Top + start / ww, Tile.Cobweb); PathFinder.SetMapSize(level.Width, level.Height); if (!valid) { Log.Error("Failed to build path"); Paint(level); return; } patch = Patch.GenerateWithNoise(w, h, Rnd.Float(10000), 0.25f, 0.1f); if (Floor2 != Floor) { Pass((x, y) => { if (level.Get(x, y) == Floor && patch[(x - Left) + (y - Top) * w]) { Painter.Set(level, x, y, Floor2); } }); } }
protected void Setup(Level level, RoomDef room, float fill, int clustering, bool ensurePath) { Run.Level = level; var w = room.GetWidth() - 2; var h = room.GetHeight() - 2; if (ensurePath) { PathFinder.SetMapSize(w, h); var valid = false; var attempt = 0; do { Patch = BurningKnight.level.Patch.Generate(w, h, fill, clustering); var start = 0; foreach (var d in room.Connected.Values) { if (d.X == room.Left) { start = ToIndex(room, d.X + 1, d.Y); Patch[ToIndex(room, d.X + 1, d.Y)] = false; Patch[ToIndex(room, d.X + 2, d.Y)] = false; } else if (d.X == room.Right) { start = ToIndex(room, d.X - 1, d.Y); Patch[ToIndex(room, d.X - 1, d.Y)] = false; Patch[ToIndex(room, d.X - 2, d.Y)] = false; } else if (d.Y == room.Top) { start = ToIndex(room, d.X, d.Y + 1); Patch[ToIndex(room, d.X, d.Y + 1)] = false; Patch[ToIndex(room, d.X, d.Y + 2)] = false; } else if (d.Y == room.Bottom) { start = ToIndex(room, d.X, d.Y - 1); Patch[ToIndex(room, d.X, d.Y - 1)] = false; Patch[ToIndex(room, d.X, d.Y - 2)] = false; } } PathFinder.BuildDistanceMap(start, BArray.Not(Patch, null)); valid = true; for (var i = 0; i < Patch.Length; i++) { if (!Patch[i] && PathFinder.Distance[i] == Int32.MaxValue) { valid = false; break; } } if (!valid && fill > 0.1f) { fill -= 0.01f; } } while (attempt++ < 1000 && !valid); if (!valid) { Log.Error("Failed to generate patch"); for (var i = 0; i < Patch.Length; i++) { Patch[i] = false; } } PathFinder.SetMapSize(level.Width, level.Height); } else { Patch = BurningKnight.level.Patch.Generate(w, h, fill, clustering); } }
public override void Paint(Level level, RoomDef room, Rect inside) { var fill = 0.25f + (room.GetWidth() * room.GetHeight()) / 1024f; var s = Rnd.Chance(); bool[] oldPatch = null; if (s) { Setup(level, room, fill, 4, true); CleanDiagonalEdges(room); PaintPatch(level, room, Tiles.RandomSolid()); oldPatch = ArrayUtils.Clone(Patch); } SimplePaint(level, room); if (s) { PathFinder.SetMapSize(room.GetWidth() - 2, room.GetHeight() - 2); var start = 0; foreach (var d in room.Connected.Values) { if (d.X == room.Left) { start = ToIndex(room, d.X + 1, d.Y); } else if (d.X == room.Right) { start = ToIndex(room, d.X - 1, d.Y); } else if (d.Y == room.Top) { start = ToIndex(room, d.X, d.Y + 1); } else if (d.Y == room.Bottom) { start = ToIndex(room, d.X, d.Y - 1); } } for (var i = 0; i < Patch.Length; i++) { if (oldPatch[i]) { Patch[i] = true; } } PathFinder.BuildDistanceMap(start, BArray.Not(Patch, null)); var valid = true; for (var i = 0; i < Patch.Length; i++) { if (!Patch[i] && PathFinder.Distance[i] == Int32.MaxValue) { valid = false; break; } } PathFinder.SetMapSize(level.Width, level.Height); if (!valid) { Painter.Fill(level, room, 1, Tiles.RandomFloor()); SimplePaint(level, room); } } }