/// <summary> /// Spawns treasure chests in treasure room. /// </summary> private void SpawnTreasureChests() { var region = this.Regions.Last(); var rnd = RandomProvider.Get(); for (int i = 0; i < _treasureChests.Count; ++i) { var pos = new Generation.Position(this.Generator.Floors.Last().MazeGenerator.EndPos); pos.X *= Dungeon.TileSize; pos.Y *= Dungeon.TileSize; pos.X += Dungeon.TileSize / 2; pos.Y += (int)(Dungeon.TileSize * 2.5f); var placement = _treasurePlacementProvider.GetPosition(); pos.X += placement[0]; pos.Y += placement[1]; var rotation = MabiMath.DegreeToRadian(placement[2]); var prop = _treasureChests[i]; prop.RegionId = region.Id; prop.Info.X = pos.X; prop.Info.Y = pos.Y; prop.Info.Direction = rotation; region.AddProp(prop); } }
public DungeonFloor(DungeonGenerator dungeonGenerator, DungeonFloorData floorData, bool isLastFloor, DungeonFloor prevFloor) { _pos = new Position(0, 0); _startPos = new Position(0, 0); _startDirection = Direction.Down; this.Width = 1; this.Height = 1; this.MazeGenerator = new MazeGenerator(); this.Sections = new List<DungeonFloorSection>(); _dungeonGenerator = dungeonGenerator; _branchProbability = floorData.Branch; _coverageFactor = floorData.Coverage; this.IsLastFloor = isLastFloor; _prevFloor = prevFloor; this.HasBossRoom = floorData.HasBoss; this.Statue = floorData.Statue; this.CalculateSize(floorData); this.InitRoomtraits(); this.GenerateMaze(floorData); this.GenerateRooms(floorData); this.InitSections(floorData); }
public MazeGenerator() { _currentPos = new Position(0, 0); this.StartPos = new Position(0, 0); this.EndPos = new Position(0, 0); this.Rooms = new List<List<MazeRoomInternal>>(); this.CriticalPath = new List<MazeMove>(); }
private bool CreateSubPathRecursive(Position pos) { var room = GetRoom(pos); var maze_room = this.MazeGenerator.GetRoom(pos); for (int direction = 0; direction < 4; direction++) { if (maze_room.GetPassageType(direction) == 2) { var biased_pos = pos.GetBiasedPosition(direction); if (room != null) room.Link(direction, LinkType.To); this.CreateSubPathRecursive(biased_pos); } } return true; }
private List<MazeMove> CreateCriticalPath(int crit_path_min, int crit_path_max) { while (true) { this.MazeGenerator.SetSize(this.Width, this.Height); this.SetRandomPathPosition(); if (this.MazeGenerator.GenerateCriticalPath(_dungeonGenerator.RngMaze, crit_path_min, crit_path_max)) { _startPos = this.MazeGenerator.StartPos; if (this.SetTraits(_startPos, this.MazeGenerator.StartDirection, (int)DungeonBlockType.StairsUp)) break; } this.MazeGenerator = new MazeGenerator(); this.InitRoomtraits(); } return this.MazeGenerator.CriticalPath; }
private void SetRoomTypes() { for (int y = 0; y < this.MazeGenerator.Height; ++y) { for (int x = 0; x < this.MazeGenerator.Width; ++x) { var pos = new Position(x, y); var room = this.MazeGenerator.GetRoom(pos); var roomTrait = this.GetRoom(pos); if (this.MazeGenerator.StartPos.X == x && this.MazeGenerator.StartPos.Y == y) roomTrait.RoomType = RoomType.Start; else if (this.MazeGenerator.EndPos.X == x && this.MazeGenerator.EndPos.Y == y) roomTrait.RoomType = RoomType.End; else if (room.Visited) roomTrait.RoomType = RoomType.Alley; } } }
private bool SetTraits(Position pos, int direction, int doorType) { var biased_pos = pos.GetBiasedPosition(direction); if ((biased_pos.X >= 0) && (biased_pos.Y >= 0)) { if ((biased_pos.X < this.Width) && (biased_pos.Y < this.Height)) { if (!this.MazeGenerator.IsFree(biased_pos)) return false; this.MazeGenerator.MarkReservedPosition(biased_pos); } } var room = this.GetRoom(pos); if (room.IsLinked(direction)) throw new Exception("Room in direction isn't linked"); if (room.GetDoorType(direction) != 0) throw new Exception(); LinkType linkType; if (doorType == (int)DungeonBlockType.StairsDown) linkType = LinkType.To; else if (doorType == (int)DungeonBlockType.StairsUp) linkType = LinkType.From; else throw new Exception("Invalid door_type"); room.Link(direction, linkType); room.SetDoorType(direction, doorType); return true; }
/// <summary> /// Adds boss to list of bosses to spawn. /// </summary> /// <param name="raceId"></param> /// <param name="amount"></param> public void AddBoss(int raceId, int amount = 1) { var rnd = RandomProvider.Get(); var end = this.Generator.Floors.Last().MazeGenerator.EndPos; var endX = end.X * TileSize + TileSize / 2; var endY = end.Y * TileSize + TileSize / 2; var regionId = this.Regions.Last().Id; for (int i = 0; i < amount; ++i) { var pos = new Position(endX, endY + TileSize / 2); pos = pos.GetRandomInRange(TileSize / 2, rnd); var npc = new NPC(raceId); npc.Death += this.OnBossDeath; npc.Spawn(regionId, pos.X, pos.Y); Send.SpawnEffect(SpawnEffect.Monster, regionId, pos.X, pos.Y, npc, npc); if (npc.AI != null) npc.AI.Activate(0); } Interlocked.Add(ref _bossesRemaining, amount); }
public void MarkReservedPosition(Position pos) { MazeRoomInternal room = Rooms[pos.X][pos.Y]; if (!room.Visited) room.IsReserved = true; }
public bool IsRoomInDirectionFree(Position pos, int direction) { var dirPos = pos.GetBiasedPosition(direction); if ((0 <= dirPos.X) && (dirPos.X < Width) && (0 <= dirPos.Y) && (dirPos.Y < Height)) return !Rooms[dirPos.X][dirPos.Y].Occupied; return false; }
public bool IsFree(Position pos) { return !this.Rooms[pos.X][pos.Y].Occupied; }
public MazeRoomInternal GetRoom(Position pos) { return this.GetRoom(pos.X, pos.Y); }
private void UndoMove(int count = 1) { for (int i = 0; i < count; i++) { var move = this.CriticalPath[this.CriticalPath.Count - 1]; this.CriticalPath.Remove(this.CriticalPath[this.CriticalPath.Count - 1]); var current_room = this.GetRoom(move.PosFrom); var next_room = this.GetRoom(move.PosTo); var oppositeDirection = Direction.GetOppositeDirection(move.Direction); if (next_room.Visited) { current_room.Directions[move.Direction] = 0; next_room.Directions[oppositeDirection] = 0; next_room.VisitedCount = 0; next_room.IsOnCriticalPath = false; _counter -= 1; } _currentPos = _currentPos.GetBiasedPosition(oppositeDirection); } }
private bool MakeMove(int direction) { if (this.IsRoomInDirectionFree(_currentPos, direction)) { var nextPos = _currentPos.GetBiasedPosition(direction); var currentRoom = this.GetRoom(_currentPos); var nextRoom = this.GetRoom(nextPos); var move = new MazeMove(_currentPos, nextPos, direction); this.CriticalPath.Add(move); _counter++; nextRoom.VisitedCount = _counter; nextRoom.IsOnCriticalPath = true; currentRoom.Directions[direction] = 1; nextRoom.Directions[Direction.GetOppositeDirection(direction)] = 2; _currentPos = nextPos; return true; } return false; }
private int Sub(Position pos) { if (this.GetRoom(pos) != null) { var count = 1; for (int iDir = 0; iDir < 4; iDir++) { var room = this.GetRoom(pos.GetBiasedPosition(iDir)); if (room != null && !room.Occupied) count += 1; } return count; } return 0; }
public void SetPathPosition(Position pos) { if ((this.Width > pos.X) && (this.Height > pos.Y)) { MazeRoomInternal room; for (int y = 0; y < Height; y++) { for (int x = 0; x < Width; x++) { room = Rooms[x][y]; room.Directions = new int[4]; room.VisitedCount = 0; } } this.CriticalPath = new List<MazeMove>(); this.StartPos = new Position(0, 0); _currentPos = new Position(0, 0); this.EndPos.X = pos.X; this.EndPos.Y = pos.Y; _currentPos.X = pos.X; _currentPos.Y = pos.Y; _counter = 1; room = Rooms[pos.X][pos.Y]; room.VisitedCount = _counter; room.IsOnCriticalPath = true; } }
/// <summary> /// Initiates floor, creating puzzles and props. /// </summary> /// <param name="iRegion"></param> public void InitFloorRegion(int iRegion) { this.CreatePuzzles(iRegion); var region = this.Regions[iRegion]; var floor = this.Generator.Floors[iRegion - 1]; var gen = floor.MazeGenerator; var floorData = this.Data.Floors[iRegion - 1]; var iPrevRegion = iRegion - 1; var iNextRegion = iRegion + 1; var startTile = gen.StartPos; var startPos = new Generation.Position(startTile.X * Dungeon.TileSize + Dungeon.TileSize / 2, startTile.Y * Dungeon.TileSize + Dungeon.TileSize / 2); var startRoomTrait = floor.GetRoom(startTile); var startRoomIncomingDirection = startRoomTrait.GetIncomingDirection(); var endTile = gen.EndPos; var endPos = new Generation.Position(endTile.X * Dungeon.TileSize + Dungeon.TileSize / 2, endTile.Y * Dungeon.TileSize + Dungeon.TileSize / 2); var endRoomTrait = floor.GetRoom(endTile); var endRoomDirection = 0; for (int dir = 0; dir < 4; ++dir) { if (endRoomTrait.Links[dir] == LinkType.To) { endRoomDirection = dir; break; } } // Create upstairs prop var stairsBlock = this.Data.Style.Get(DungeonBlockType.StairsUp, startRoomIncomingDirection); var stairs = new Prop(stairsBlock.PropId, region.Id, startPos.X, startPos.Y, MabiMath.DegreeToRadian(stairsBlock.Rotation), 1, 0, "single"); stairs.Info.Color1 = floorData.Color1; stairs.Info.Color2 = floorData.Color1; stairs.Info.Color3 = floorData.Color3; region.AddProp(stairs); // Create portal prop leading to prev floor var portalBlock = this.Data.Style.Get(DungeonBlockType.PortalUp, startRoomIncomingDirection); var portal = new Prop(portalBlock.PropId, region.Id, startPos.X, startPos.Y, MabiMath.DegreeToRadian(portalBlock.Rotation), 1, 0, "single", "_upstairs", Localization.Get("<mini>TO</mini> Upstairs")); portal.Info.Color1 = floorData.Color1; portal.Info.Color2 = floorData.Color1; portal.Info.Color3 = floorData.Color3; portal.Behavior = (cr, pr) => { // Indoor_RDungeon_EB marks the end position on the prev floor. var clientEvent = this.Regions[iPrevRegion].GetClientEvent("Indoor_RDungeon_EB"); if (clientEvent == null) { Log.Error("Event 'Indoor_RDungeon_EB' not found while trying to warp to '{0}'.", this.Regions[iPrevRegion].Name); return; } // Warp to prev region var regionId = this.Regions[iPrevRegion].Id; var x = (int)clientEvent.Data.X; var y = (int)clientEvent.Data.Y; cr.Warp(regionId, x, y); }; region.AddProp(portal); // Create save statue if (floorData.Statue) { var saveStatue = new Prop(this.Data.SaveStatuePropId, region.Id, startPos.X, startPos.Y, MabiMath.DegreeToRadian(stairsBlock.Rotation + 180), 1, 0, "single"); saveStatue.Info.Color1 = floorData.Color1; saveStatue.Info.Color2 = floorData.Color1; saveStatue.Info.Color3 = floorData.Color3; saveStatue.Behavior = (cr, pr) => { cr.DungeonSaveLocation = cr.GetLocation(); Send.Notice(cr, Localization.Get("You have memorized this location.")); // Scroll message var msg = string.Format("You're currently on Floor {0} of {1}. ", iRegion, this.Data.EngName); Send.Notice(cr, NoticeType.Top, ScrollMessageDuration, msg + this.GetPlayerListScrollMessage()); }; region.AddProp(saveStatue); } // Spawn boss or downstair props // TODO: There is one dungeon that has two boss rooms. if (floor.IsLastFloor) { // Create door to treasure room _bossExitDoor = new Prop(this.Data.BossExitDoorId, region.Id, endPos.X, endPos.Y + Dungeon.TileSize / 2, Rotation(Direction.Up), 1, 0, "closed"); _bossExitDoor.Info.Color1 = floorData.Color1; _bossExitDoor.Info.Color2 = floorData.Color1; _bossExitDoor.Info.Color3 = floorData.Color3; region.AddProp(_bossExitDoor); // Get or create boss door if (endRoomTrait.PuzzleDoors[Direction.Down] == null) { Log.Warning("Dungeon.InitFloorRegion: No locked place in last section of '{0}'.", this.Name); _bossDoor = new Door(this.Data.BossDoorId, region.Id, endPos.X, endPos.Y - Dungeon.TileSize, Direction.Up, DungeonBlockType.BossDoor, "", "closed"); _bossDoor.Info.Color1 = floorData.Color1; _bossDoor.Info.Color2 = floorData.Color1; _bossDoor.Info.Color3 = floorData.Color3; _bossDoor.Behavior = (cr, pr) => { _bossDoor.Open(); }; _bossDoor.Behavior += this.BossDoorBehavior; _bossDoor.UpdateShapes(); endRoomTrait.SetPuzzleDoor(_bossDoor, Direction.Down); // making sure another open dummy door won't be added here region.AddProp(_bossDoor); } else { _bossDoor = endRoomTrait.PuzzleDoors[Direction.Down]; if (_bossDoor.State == "open") { Log.Warning("Dungeon.InitFloorRegion: Boss door was left open, closing. Dungeon: '{0}'.", this.Name); _bossDoor.Close(endRoomTrait.X, endRoomTrait.Y); } } // Create exit statue var exitStatue = new Prop(this.Data.LastStatuePropId, region.Id, endPos.X, endPos.Y + Dungeon.TileSize * 2, Rotation(Direction.Up), 1, 0, "single"); exitStatue.Info.Color1 = floorData.Color1; exitStatue.Info.Color2 = floorData.Color1; exitStatue.Info.Color3 = floorData.Color3; exitStatue.Extensions.AddSilent(new ConfirmationPropExtension("GotoLobby", "_LT[code.standard.msg.dungeon_exit_notice_msg]", "_LT[code.standard.msg.dungeon_exit_notice_title]", "haskey(chest)")); exitStatue.Behavior = (cr, pr) => { ChannelServer.Instance.Events.OnPlayerClearedDungeon(cr, this); cr.Warp(this.Data.Exit); }; region.AddProp(exitStatue); } else { // Create downstairs prop var stairsDownBlock = this.Data.Style.Get(DungeonBlockType.StairsDown, endRoomDirection); var stairsDown = new Prop(stairsDownBlock.PropId, region.Id, endPos.X, endPos.Y, MabiMath.DegreeToRadian(stairsDownBlock.Rotation), 1, 0, "single"); stairsDown.Info.Color1 = floorData.Color1; stairsDown.Info.Color2 = floorData.Color1; stairsDown.Info.Color3 = floorData.Color3; region.AddProp(stairsDown); // Create portal leading to the next floor var portalDownBlock = this.Data.Style.Get(DungeonBlockType.PortalDown, endRoomDirection); var portalDown = new Prop(portalDownBlock.PropId, region.Id, endPos.X, endPos.Y, MabiMath.DegreeToRadian(portalDownBlock.Rotation), 1, 0, "single", "_downstairs", Localization.Get("<mini>TO</mini> Downstairs")); portalDown.Info.Color1 = floorData.Color1; portalDown.Info.Color2 = floorData.Color1; portalDown.Info.Color3 = floorData.Color3; portalDown.Behavior = (cr, pr) => { // Indoor_RDungeon_SB marks the start position on the next floor. var clientEvent = this.Regions[iNextRegion].GetClientEvent("Indoor_RDungeon_SB"); if (clientEvent == null) { Log.Error("Event 'Indoor_RDungeon_SB' not found while trying to warp to '{0}'.", this.Regions[iNextRegion].Name); return; } // Warp to next floor var regionId = this.Regions[iNextRegion].Id; var x = (int)clientEvent.Data.X; var y = (int)clientEvent.Data.Y; cr.Warp(regionId, x, y); }; region.AddProp(portalDown); } // Place dummy doors for (int x = 0; x < floor.MazeGenerator.Width; ++x) { for (int y = 0; y < floor.MazeGenerator.Height; ++y) { var room = floor.MazeGenerator.GetRoom(x, y); var roomTrait = floor.GetRoom(x, y); var isRoom = (roomTrait.RoomType >= RoomType.Start); if (!room.Visited || !isRoom) { continue; } for (var dir = 0; dir < 4; ++dir) { // Skip stairs if (roomTrait.RoomType == RoomType.Start && dir == startRoomIncomingDirection) { continue; } if (roomTrait.RoomType == RoomType.End && dir == endRoomDirection) { continue; } if (roomTrait.Links[dir] == LinkType.None) { continue; } if (roomTrait.PuzzleDoors[dir] == null) { var doorX = x * Dungeon.TileSize + Dungeon.TileSize / 2; var doorY = y * Dungeon.TileSize + Dungeon.TileSize / 2; var doorBlock = this.Data.Style.Get(DungeonBlockType.Door, dir); var doorProp = new Prop(doorBlock.PropId, region.Id, doorX, doorY, MabiMath.DegreeToRadian(doorBlock.Rotation), state: "open"); doorProp.Info.Color1 = floorData.Color1; doorProp.Info.Color2 = floorData.Color2; doorProp.Info.Color3 = floorData.Color3; region.AddProp(doorProp); } else if (roomTrait.PuzzleDoors[dir].EntityId == 0) { // Add doors from failed puzzles roomTrait.PuzzleDoors[dir].Info.Region = region.Id; region.AddProp(roomTrait.PuzzleDoors[dir]); } } } } }
private void InitRoomtraits() { _rooms = new List<List<RoomTrait>>(); for (int x = 0; x < this.Width; x++) { var row = new List<RoomTrait>(); for (int y = 0; y < this.Height; y++) row.Add(new RoomTrait(x, y)); _rooms.Add(row); } for (int y = 0; y < this.Height; y++) { for (int x = 0; x < this.Width; x++) { for (int direction = 0; direction < 4; direction++) { var biased_pos = new Position(x, y).GetBiasedPosition(direction); if ((biased_pos.X >= 0) && (biased_pos.Y >= 0)) if ((biased_pos.X < this.Width) && (biased_pos.Y < this.Height)) _rooms[x][y].SetNeighbor(direction, _rooms[biased_pos.X][biased_pos.Y]); } } } }
/// <summary> /// Initiates floor, creating puzzles and props. /// </summary> /// <param name="iRegion"></param> public void InitFloorRegion(int iRegion) { this.CreatePuzzles(iRegion); var region = this.Regions[iRegion]; var floor = this.Generator.Floors[iRegion - 1]; var gen = floor.MazeGenerator; var floorData = this.Data.Floors[iRegion - 1]; var iPrevRegion = iRegion - 1; var iNextRegion = iRegion + 1; var startTile = gen.StartPos; var startPos = new Generation.Position(startTile.X * Dungeon.TileSize + Dungeon.TileSize / 2, startTile.Y * Dungeon.TileSize + Dungeon.TileSize / 2); var startRoomTrait = floor.GetRoom(startTile); var startRoomIncomingDirection = startRoomTrait.GetIncomingDirection(); var endTile = gen.EndPos; var endPos = new Generation.Position(endTile.X * Dungeon.TileSize + Dungeon.TileSize / 2, endTile.Y * Dungeon.TileSize + Dungeon.TileSize / 2); var endRoomTrait = floor.GetRoom(endTile); var endRoomDirection = 0; for (int dir = 0; dir < 4; ++dir) { if (endRoomTrait.Links[dir] == LinkType.To) { endRoomDirection = dir; break; } } // Create upstairs prop var stairsBlock = this.Data.Style.Get(DungeonBlockType.StairsUp, startRoomIncomingDirection); var stairs = new Prop(stairsBlock.PropId, region.Id, startPos.X, startPos.Y, MabiMath.DegreeToRadian(stairsBlock.Rotation), 1, 0, "single"); stairs.Info.Color1 = floorData.Color1; stairs.Info.Color2 = floorData.Color1; stairs.Info.Color3 = floorData.Color3; region.AddProp(stairs); // Create portal prop leading to prev floor var portalBlock = this.Data.Style.Get(DungeonBlockType.PortalUp, startRoomIncomingDirection); var portal = new Prop(portalBlock.PropId, region.Id, startPos.X, startPos.Y, MabiMath.DegreeToRadian(portalBlock.Rotation), 1, 0, "single", "_upstairs", Localization.Get("<mini>TO</mini> Upstairs")); portal.Info.Color1 = floorData.Color1; portal.Info.Color2 = floorData.Color1; portal.Info.Color3 = floorData.Color3; portal.Behavior = (cr, pr) => { // Indoor_RDungeon_EB marks the end position on the prev floor. var clientEvent = this.Regions[iPrevRegion].GetClientEvent("Indoor_RDungeon_EB"); if (clientEvent == null) { Log.Error("Event 'Indoor_RDungeon_EB' not found while trying to warp to '{0}'.", this.Regions[iPrevRegion].Name); return; } // Warp to prev region var regionId = this.Regions[iPrevRegion].Id; var x = (int)clientEvent.Data.X; var y = (int)clientEvent.Data.Y; cr.Warp(regionId, x, y); }; region.AddProp(portal); // Create save statue var saveStatue = new Prop(this.Data.SaveStatuePropId, region.Id, startPos.X, startPos.Y, MabiMath.DegreeToRadian(stairsBlock.Rotation + 180), 1, 0, "single"); saveStatue.Info.Color1 = floorData.Color1; saveStatue.Info.Color2 = floorData.Color1; saveStatue.Info.Color3 = floorData.Color3; saveStatue.Behavior = (cr, pr) => { cr.DungeonSaveLocation = cr.GetLocation(); Send.Notice(cr, Localization.Get("You have memorized this location.")); // Scroll message var msg = string.Format("You're currently on Floor {0} of {1}. ", iRegion, this.Data.EngName); Send.Notice(cr, NoticeType.Top, ScrollMessageDuration, msg + this.GetPlayerListScrollMessage()); }; region.AddProp(saveStatue); // Spawn boss or downstair props // TODO: There is one dungeon that has two boss rooms. if (floor.IsLastFloor) { // Create door to treasure room _bossExitDoor = new Prop(this.Data.BossExitDoorId, region.Id, endPos.X, endPos.Y + Dungeon.TileSize / 2, Rotation(Direction.Up), 1, 0, "closed"); _bossExitDoor.Info.Color1 = floorData.Color1; _bossExitDoor.Info.Color2 = floorData.Color1; _bossExitDoor.Info.Color3 = floorData.Color3; region.AddProp(_bossExitDoor); // Get or create boss door if (endRoomTrait.PuzzleDoors[Direction.Down] == null) { Log.Warning("Dungeon.InitFloorRegion: No locked place in last section of '{0}'.", this.Name); _bossDoor = new Door(this.Data.BossDoorId, region.Id, endPos.X, endPos.Y - Dungeon.TileSize, Direction.Up, DungeonBlockType.BossDoor, "", "closed"); _bossDoor.Info.Color1 = floorData.Color1; _bossDoor.Info.Color2 = floorData.Color1; _bossDoor.Info.Color3 = floorData.Color3; _bossDoor.Behavior = (cr, pr) => { _bossDoor.Open(); }; _bossDoor.Behavior += this.BossDoorBehavior; _bossDoor.UpdateShapes(); endRoomTrait.PuzzleDoors[Direction.Down] = _bossDoor; // making sure another open dummy door won't be added here region.AddProp(_bossDoor); } else { _bossDoor = endRoomTrait.PuzzleDoors[Direction.Down]; } // Create exit statue var exitStatue = new Prop(this.Data.LastStatuePropId, region.Id, endPos.X, endPos.Y + Dungeon.TileSize * 2, Rotation(Direction.Up), 1, 0, "single"); exitStatue.Info.Color1 = floorData.Color1; exitStatue.Info.Color2 = floorData.Color1; exitStatue.Info.Color3 = floorData.Color3; exitStatue.Extensions.AddSilent(new ConfirmationPropExtension("GotoLobby", "_LT[code.standard.msg.dungeon_exit_notice_msg]", "_LT[code.standard.msg.dungeon_exit_notice_title]", "haskey(chest)")); exitStatue.Behavior = (cr, pr) => { cr.Warp(this.Data.Exit); }; region.AddProp(exitStatue); } else { // Create downstairs prop var stairsDownBlock = this.Data.Style.Get(DungeonBlockType.StairsDown, endRoomDirection); var stairsDown = new Prop(stairsDownBlock.PropId, region.Id, endPos.X, endPos.Y, MabiMath.DegreeToRadian(stairsDownBlock.Rotation), 1, 0, "single"); stairsDown.Info.Color1 = floorData.Color1; stairsDown.Info.Color2 = floorData.Color1; stairsDown.Info.Color3 = floorData.Color3; region.AddProp(stairsDown); // Create portal leading to the next floor var portalDownBlock = this.Data.Style.Get(DungeonBlockType.PortalDown, endRoomDirection); var portalDown = new Prop(portalDownBlock.PropId, region.Id, endPos.X, endPos.Y, MabiMath.DegreeToRadian(portalDownBlock.Rotation), 1, 0, "single", "_downstairs", Localization.Get("<mini>TO</mini> Downstairs")); portalDown.Info.Color1 = floorData.Color1; portalDown.Info.Color2 = floorData.Color1; portalDown.Info.Color3 = floorData.Color3; portalDown.Behavior = (cr, pr) => { // Indoor_RDungeon_SB marks the start position on the next floor. var clientEvent = this.Regions[iNextRegion].GetClientEvent("Indoor_RDungeon_SB"); if (clientEvent == null) { Log.Error("Event 'Indoor_RDungeon_SB' not found while trying to warp to '{0}'.", this.Regions[iNextRegion].Name); return; } // Warp to next floor var regionId = this.Regions[iNextRegion].Id; var x = (int)clientEvent.Data.X; var y = (int)clientEvent.Data.Y; cr.Warp(regionId, x, y); }; region.AddProp(portalDown); } // Place dummy doors for (int x = 0; x < floor.MazeGenerator.Width; ++x) { for (int y = 0; y < floor.MazeGenerator.Height; ++y) { var room = floor.MazeGenerator.GetRoom(x, y); var roomTrait = floor.GetRoom(x, y); var isRoom = (roomTrait.RoomType >= RoomType.Start); if (!room.Visited || !isRoom) continue; for (var dir = 0; dir < 4; ++dir) { // Skip stairs if (roomTrait.RoomType == RoomType.Start && dir == startRoomIncomingDirection) continue; if (roomTrait.RoomType == RoomType.End && dir == endRoomDirection) continue; if (roomTrait.Links[dir] == LinkType.None) continue; if (roomTrait.PuzzleDoors[dir] == null) { var doorX = x * Dungeon.TileSize + Dungeon.TileSize / 2; var doorY = y * Dungeon.TileSize + Dungeon.TileSize / 2; var doorBlock = this.Data.Style.Get(DungeonBlockType.Door, dir); var doorProp = new Prop(doorBlock.PropId, region.Id, doorX, doorY, MabiMath.DegreeToRadian(doorBlock.Rotation), state: "open"); doorProp.Info.Color1 = floorData.Color1; doorProp.Info.Color2 = floorData.Color2; doorProp.Info.Color3 = floorData.Color3; region.AddProp(doorProp); } else if (roomTrait.PuzzleDoors[dir].EntityId == 0) { // Add doors from failed puzzles roomTrait.PuzzleDoors[dir].Info.Region = region.Id; region.AddProp(roomTrait.PuzzleDoors[dir]); } } } } }
public RoomTrait GetRoom(Position pos) { return this.GetRoom(pos.X, pos.Y); }
private bool GenerateSubPathSub2(Position pos) { var room = this.GetRoom(pos); if (room != null) { for (int i = 0; i < 4; i++) { if (room.GetPassageType(i) == 0) { if (this.IsRoomInDirectionFree(pos, i)) return true; } } } return false; }