private void PlaceDoors(Room r) { foreach (var n in r.Connected.Keys.ToList()) { var door = r.Connected[n]; if (door != null) { continue; } var i = r.Intersect(n); if (i.Width() == 0) { door = new Room.Door(i.Left, Random.Int(i.Top + 1, i.Bottom)); } else { door = new Room.Door(Random.Int(i.Left + 1, i.Right), i.Top); } if (r.Connected.ContainsKey(n)) { r.Connected[n] = door; } else { r.Connected.Add(n, door); } n.Connected[r] = door; } }
private static void PaintBurned(Level level, Room room) { for (var i = room.Top + 1; i < room.Bottom; i++) { for (var j = room.Left + 1; j < room.Right; j++) { var t = Terrain.EMBERS; switch (Random.Int(5)) { case 0: t = Terrain.EMPTY; break; case 1: t = Terrain.FIRE_TRAP; break; case 2: t = Terrain.SECRET_FIRE_TRAP; break; case 3: t = Terrain.INACTIVE_TRAP; break; } level.map[i * Level.Width + j] = t; } } }
protected internal virtual void PaintDoors(Room r) { foreach (var n in r.Connected.Keys) { if (JoinRooms(r, n)) { continue; } var d = r.Connected[n]; var door = d.X + d.Y * Width; switch (d.Type) { case levels.Room.Door.DoorType.EMPTY: map[door] = Terrain.EMPTY; break; case levels.Room.Door.DoorType.TUNNEL: map[door] = TunnelTile(); break; case levels.Room.Door.DoorType.REGULAR: if (Dungeon.Depth <= 1) { map[door] = Terrain.DOOR; } else { var localSecret = (Dungeon.Depth < 6 ? Random.Int(12 - Dungeon.Depth) : Random.Int(6)) == 0; map[door] = localSecret ? Terrain.SECRET_DOOR : Terrain.DOOR; if (localSecret) { SecretDoors++; } } break; case levels.Room.Door.DoorType.UNLOCKED: map[door] = Terrain.DOOR; break; case levels.Room.Door.DoorType.HIDDEN: map[door] = Terrain.SECRET_DOOR; break; case levels.Room.Door.DoorType.BARRICADE: map[door] = Random.Int(3) == 0 ? Terrain.BOOKSHELF : Terrain.BARRICADE; break; case levels.Room.Door.DoorType.LOCKED: map[door] = Terrain.LOCKED_DOOR; break; } } }
protected internal override void CreateItems() { #if DEBUG return; #endif var nItems = 3; while (Random.Float() < 0.3f) { nItems++; } for (var i = 0; i < nItems; i++) { Heap.Type type; switch (Random.Int(20)) { case 0: type = Heap.Type.Skeleton; break; case 1: case 2: case 3: case 4: type = Heap.Type.Chest; break; default: type = Heap.Type.Heap; break; } Drop(Generator.Random(), RandomDropCell()).HeapType = type; } foreach (var itemToSpawn in itemsToSpawn) { var cell = RandomDropCell(); if (itemToSpawn is ScrollOfUpgrade) { while (map[cell] == Terrain.FIRE_TRAP || map[cell] == Terrain.SECRET_FIRE_TRAP) { cell = RandomDropCell(); } } Drop(itemToSpawn, cell).HeapType = Heap.Type.Heap; } var item = Bones.Get(); if (item != null) { Drop(item, RandomDropCell()).HeapType = Heap.Type.Skeleton; } }
protected internal virtual void PlaceTraps() { var numberOfTraps = NumberOfTraps(); var trapChances = TrapChances(); for (var i = 0; i < numberOfTraps; i++) { var trapPos = Random.Int(Length); if (map[trapPos] != Terrain.EMPTY) { continue; } switch (Random.Chances(trapChances)) { case 0: map[trapPos] = Terrain.SECRET_TOXIC_TRAP; break; case 1: map[trapPos] = Terrain.SECRET_FIRE_TRAP; break; case 2: map[trapPos] = Terrain.SECRET_PARALYTIC_TRAP; break; case 3: map[trapPos] = Terrain.SECRET_POISON_TRAP; break; case 4: map[trapPos] = Terrain.SECRET_ALARM_TRAP; break; case 5: map[trapPos] = Terrain.SECRET_LIGHTNING_TRAP; break; case 6: map[trapPos] = Terrain.SECRET_GRIPPING_TRAP; break; case 7: map[trapPos] = Terrain.SECRET_SUMMONING_TRAP; break; } } }
public virtual void Damage(int dmg, object src) { if (HP <= 0) { return; } buffs.Buff.Detach <Frost>(this); var srcClass = src.GetType(); if (Immunities().Contains(srcClass)) { dmg = 0; } else if (Resistances().Contains(srcClass)) { dmg = Random.IntRange(0, dmg); } if (Buff <Paralysis>() != null) { if (Random.Int(dmg) >= Random.Int(HP)) { buffs.Buff.Detach <Paralysis>(this); if (Dungeon.Visible[pos]) { GLog.Information(TxtOutOfParalysis, Name); } } } HP -= dmg; if (dmg > 0 || src is Character) { Sprite.ShowStatus(HP > HT / 2 ? CharSprite.Warning : CharSprite.Negative, dmg.ToString()); } if (HP <= 0) { Die(src); } }
private static void PaintFissure(Level level, Room room) { Fill(level, room.Left + 1, room.Top + 1, room.Width() - 1, room.Height() - 1, Terrain.EMPTY); for (var i = room.Top + 2; i < room.Bottom - 1; i++) { for (var j = room.Left + 2; j < room.Right - 1; j++) { var v = Math.Min(i - room.Top, room.Bottom - i); var h = Math.Min(j - room.Left, room.Right - j); if (Math.Min(v, h) > 2 || Random.Int(2) == 0) { Set(level, j, i, Terrain.CHASM); } } } }
private static void PaintGraveyard(Level level, Room room) { Fill(level, room.Left + 1, room.Top + 1, room.Width() - 1, room.Height() - 1, Terrain.GRASS); var w = room.Width() - 1; var h = room.Height() - 1; var nGraves = Math.Max(w, h) / 2; var index = Random.Int(nGraves); var shift = Random.Int(2); for (var i = 0; i < nGraves; i++) { var pos = w > h ? room.Left + 1 + shift + i * 2 + (room.Top + 2 + Random.Int(h - 2)) * Level.Width : (room.Left + 2 + Random.Int(w - 2)) + (room.Top + 1 + shift + i * 2) * Level.Width; level.Drop(i == index ? Generator.Random() : new Gold(), pos).HeapType = Heap.Type.Tomb; } }
protected internal virtual void Split(Rect rect) { var w = rect.Width(); var h = rect.Height(); if (w > MaxRoomSize && h < MinRoomSize) { var vw = Random.Int(rect.Left + 3, rect.Right - 3); Split(new Rect(rect.Left, rect.Top, vw, rect.Bottom)); Split(new Rect(vw, rect.Top, rect.Right, rect.Bottom)); } else if (h > MaxRoomSize && w < MinRoomSize) { var vh = Random.Int(rect.Top + 3, rect.Bottom - 3); Split(new Rect(rect.Left, rect.Top, rect.Right, vh)); Split(new Rect(rect.Left, vh, rect.Right, rect.Bottom)); } else if ((new System.Random(1).NextDouble() <= (MinRoomSize * MinRoomSize / rect.Square()) && w <= MaxRoomSize && h <= MaxRoomSize) || w < MinRoomSize || h < MinRoomSize) { Rooms.Add((Room) new Room().Set(rect)); } else { if (Random.Float() < (float)(w - 2) / (w + h - 4)) { var vw = Random.Int(rect.Left + 3, rect.Right - 3); Split(new Rect(rect.Left, rect.Top, vw, rect.Bottom)); Split(new Rect(vw, rect.Top, rect.Right, rect.Bottom)); } else { var vh = Random.Int(rect.Top + 3, rect.Bottom - 3); Split(new Rect(rect.Left, rect.Top, rect.Right, vh)); Split(new Rect(rect.Left, vh, rect.Right, rect.Bottom)); } } }
protected internal virtual void Paint() { foreach (var r in Rooms) { if (r.type != RoomType.NULL) { PlaceDoors(r); r.Paint(this, r); } else { if (feeling == Feeling.CHASM && Random.Int(2) == 0) { Painter.Fill(this, r, Terrain.WALL); } } } foreach (var r in Rooms) { PaintDoors(r); } }
public virtual void Wither() { Dungeon.Level.Uproot(Pos); Sprite.Kill(); if (Dungeon.Visible[Pos]) { CellEmitter.Get(Pos).Burst(LeafParticle.Factory, 6); } if (Dungeon.Hero.subClass != HeroSubClass.WARDEN) { return; } if (Random.Int(5) == 0) { Dungeon.Level.Drop(Generator.Random(Generator.Category.SEED), Pos).Sprite.Drop(); } if (Random.Int(5) == 0) { Dungeon.Level.Drop(new Dewdrop(), Pos).Sprite.Drop(); } }
private static void PaintBridge(Level level, Room room) { Fill(level, room.Left + 1, room.Top + 1, room.Width() - 1, room.Height() - 1, !Dungeon.BossLevel() && !Dungeon.BossLevel(Dungeon.Depth + 1) && Random.Int(3) == 0 ? Terrain.CHASM : Terrain.WATER); Point door1 = null; Point door2 = null; foreach (var p in room.Connected.Values) { if (door1 == null) { door1 = p; } else { door2 = p; } } if ((door1.X == room.Left && door2.X == room.Right) || (door1.X == room.Right && door2.X == room.Left)) { var s = room.Width() / 2; DrawInside(level, room, door1, s, Terrain.EMPTY_SP); DrawInside(level, room, door2, s, Terrain.EMPTY_SP); Fill(level, room.Center().X, Math.Min(door1.Y, door2.Y), 1, Math.Abs(door1.Y - door2.Y) + 1, Terrain.EMPTY_SP); } else if ((door1.Y == room.Top && door2.Y == room.Bottom) || (door1.Y == room.Bottom && door2.Y == room.Top)) { int s = room.Height() / 2; DrawInside(level, room, door1, s, Terrain.EMPTY_SP); DrawInside(level, room, door2, s, Terrain.EMPTY_SP); Fill(level, Math.Min(door1.X, door2.X), room.Center().Y, Math.Abs(door1.X - door2.X) + 1, 1, Terrain.EMPTY_SP); } else if (door1.X == door2.X) { Fill(level, door1.X == room.Left ? room.Left + 1 : room.Right - 1, Math.Min(door1.Y, door2.Y), 1, Math.Abs(door1.Y - door2.Y) + 1, Terrain.EMPTY_SP); } else if (door1.Y == door2.Y) { Fill(level, Math.Min(door1.X, door2.X), door1.Y == room.Top ? room.Top + 1 : room.Bottom - 1, Math.Abs(door1.X - door2.X) + 1, 1, Terrain.EMPTY_SP); } else if (door1.Y == room.Top || door1.Y == room.Bottom) { DrawInside(level, room, door1, Math.Abs(door1.Y - door2.Y), Terrain.EMPTY_SP); DrawInside(level, room, door2, Math.Abs(door1.X - door2.X), Terrain.EMPTY_SP); } else if (door1.X == room.Left || door1.X == room.Right) { DrawInside(level, room, door1, Math.Abs(door1.X - door2.X), Terrain.EMPTY_SP); DrawInside(level, room, door2, Math.Abs(door1.Y - door2.Y), Terrain.EMPTY_SP); } }
public static bool AsNeeded() { return(Random.Int(12 * (1 + ArcaneStyli)) < Depth); }
public override int NMobs() { return(2 + Dungeon.Depth % 5 + Random.Int(3)); }
protected internal virtual int NumberOfTraps() { return(Dungeon.Depth <= 1 ? 0 : Random.Int(1, Rooms.Count + Dungeon.Depth)); }
public override void Paint(Level level, Room room) { Fill(level, room, Terrain.WALL); foreach (var door in room.Connected.Values) { door.Set(Room.Door.DoorType.REGULAR); } if (!Dungeon.BossLevel() && Random.Int(5) == 0) { switch (Random.Int(6)) { case 0: if (level.feeling != Level.Feeling.GRASS) { if (Math.Min(room.Width(), room.Height()) >= 4 && Math.Max(room.Width(), room.Height()) >= 6) { PaintGraveyard(level, room); return; } } break; case 1: if (Dungeon.Depth > 1) { PaintBurned(level, room); return; } break; case 2: if (Math.Max(room.Width(), room.Height()) >= 4) { PaintStriped(level, room); return; } break; case 3: if (room.Width() >= 6 && room.Height() >= 6) { PaintStudy(level, room); return; } break; case 4: if (level.feeling != Level.Feeling.WATER) { if (room.Connected.Count == 2 && room.Width() >= 4 && room.Height() >= 4) { PaintBridge(level, room); return; } } break; case 5: if (!Dungeon.BossLevel() && !Dungeon.BossLevel(Dungeon.Depth + 1) && Math.Min(room.Width(), room.Height()) >= 5) { PaintFissure(level, room); return; } break; } } Fill(level, room, 1, Terrain.EMPTY); }
protected internal virtual void AssignRoomType() { var specialRooms = 0; foreach (var r in Rooms.Where(r => r.type == RoomType.NULL && r.Connected.Count == 1)) { if (Specials.Count > 0 && r.Width() > 3 && r.Height() > 3 && Random.Int(specialRooms * specialRooms + 2) == 0) { if (pitRoomNeeded) { r.type = RoomType.PIT; pitRoomNeeded = false; Specials.Remove(RoomType.ARMORY); Specials.Remove(RoomType.CRYPT); Specials.Remove(RoomType.LABORATORY); Specials.Remove(RoomType.LIBRARY); Specials.Remove(RoomType.STATUE); Specials.Remove(RoomType.TREASURY); Specials.Remove(RoomType.VAULT); Specials.Remove(RoomType.WEAK_FLOOR); } else if (Dungeon.Depth % 5 == 2 && Specials.Contains(RoomType.LABORATORY)) { r.type = RoomType.LABORATORY; } else if (Dungeon.Depth >= Dungeon.Transmutation && Specials.Contains(RoomType.MAGIC_WELL)) { r.type = RoomType.MAGIC_WELL; } else { var n = Specials.Count; r.type = Specials[Math.Min(Random.Int(n), Random.Int(n))]; if (r.type == RoomType.WEAK_FLOOR) { weakFloorCreated = true; } } levels.Room.UseType(r.type); Specials.Remove(r.type); specialRooms++; } else if (Random.Int(2) == 0) { var neigbours = r.Neigbours.Where(n => !r.Connected.ContainsKey(n) && !levels.Room.SPECIALS.Contains(n.type) && n.type != RoomType.PIT).ToList(); if (neigbours.Count > 1) { r.Connect(Random.Element(neigbours)); } } } var count = 0; foreach (var r in Rooms) { if (r.type != RoomType.NULL) { continue; } var connections = r.Connected.Count; switch (connections) { case 0: break; default: if (Random.Int(connections * connections) == 0) { r.type = RoomType.STANDARD; count++; } else { r.type = RoomType.TUNNEL; } break; } } while (count < 4) { var r = RandomRoom(RoomType.TUNNEL, 1); if (r == null) { continue; } r.type = RoomType.STANDARD; count++; } }