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]);
}
}
}
}
// Set up entered floor event.
region.PlayerEntered += (creature, prevRegionId) => this.Script.OnPlayerEnteredFloor(this, creature, iRegion);
}