private bool CreateEnergyTanks( Random rng, out String result) { bool success = true; result = SuccessMessages.GENERAL_SUCCESS; for (RoomIndexIterator iterator = new RoomIndexIterator(m_roomGrid); success && iterator.Valid; iterator.Next()) { RoomIndex roomIndex = iterator.Current; RoomLayout room = GetRoomByIndex(roomIndex); RoomTemplate roomTemplate = m_roomTemplateSet.GetTemplateByName(room.static_room_data.room_template_name); foreach (EnergyTankTemplate energyTankTemplate in roomTemplate.EnergyTankTemplates) { //TODO: CreateEnergyTanks - Scale back energy tank distribution based on difficulty EnergyTank energyTank = EnergyTank.CreateEnergyTank(room.room_key, energyTankTemplate); room.energyTanks.Add(energyTank); } } return(success); }
private bool SelectRoomTemplates(Random rng, out string result) { List <RoomTemplate> filteredRoomTemplates = new List <RoomTemplate>(); bool success = true; result = SuccessMessages.GENERAL_SUCCESS; for (RoomIndexIterator iterator = new RoomIndexIterator(m_roomGrid); success && iterator.Valid; iterator.Next()) { RoomIndex roomIndex = iterator.Current; RoomLayout room = GetRoomByIndex(roomIndex); filteredRoomTemplates.Clear(); m_roomTemplateSet.GetTemplatesWithPortalBitmask(room.portalRoomSideBitmask, filteredRoomTemplates); if (filteredRoomTemplates.Count > 0) { RoomTemplate roomTemplate = filteredRoomTemplates[rng.Next(filteredRoomTemplates.Count)]; room.static_room_data.room_template_name = roomTemplate.TemplateName; } else { result = ErrorMessages.MISSING_ROOM_TEMPLATE; success = false; } } return(success); }
private bool CreateMobSpawners( Random rng, out String result) { bool success = true; result = SuccessMessages.GENERAL_SUCCESS; for (RoomIndexIterator iterator = new RoomIndexIterator(m_roomGrid); success && iterator.Valid; iterator.Next()) { RoomIndex roomIndex = iterator.Current; RoomLayout room = GetRoomByIndex(roomIndex); RoomTemplate roomTemplate = m_roomTemplateSet.GetTemplateByName(room.static_room_data.room_template_name); foreach (MobSpawnerTemplate mobSpawnerTemplate in roomTemplate.MobSpawnerTemplates) { MobSpawner spawner = MobSpawner.CreateMobSpawner( room.room_key, mobSpawnerTemplate, m_mobSpawnTableSet, rng); // Don't bother adding mob spawners that don't have any spawns left if (spawner.RemainingSpawnCount > 0) { room.mobSpawners.Add(spawner); } } } return(success); }
private void ComputeConnectivityIdToRoomIndexMap( UnionFind <RoomIndex> roomUnion, Dictionary <int, List <RoomIndex> > connectivityIdToRoomIndexMap) { IList <RoomIndex> roomIndices = GetRoomIndexList(); foreach (RoomIndex roomIndex in roomIndices) { RoomLayout room = GetRoomByIndex(roomIndex); int connectivityId = room.connectivity_id; List <RoomIndex> connectedRooms = null; if (connectivityIdToRoomIndexMap.TryGetValue(connectivityId, out connectedRooms)) { connectedRooms.Add(roomIndex); } else { connectedRooms = new List <RoomIndex>(); connectedRooms.Add(roomIndex); connectivityIdToRoomIndexMap.Add(connectivityId, connectedRooms); } } }
public RoomLayout TryGetRoomByIndex(RoomIndex roomIndex) { RoomLayout room = null; int roomXIndex = roomIndex.X; int roomYIndex = roomIndex.Y; int roomZIndex = roomIndex.Z; if (roomXIndex >= 0 && roomXIndex < m_roomGrid.GetLength(0) && roomYIndex >= 0 && roomYIndex < m_roomGrid.GetLength(1) && roomZIndex >= 0 && roomZIndex < m_roomGrid.GetLength(2)) { room = m_roomGrid[roomXIndex, roomYIndex, roomZIndex]; } return(room); }
public void ApplyLayout( DungeonLayout layout) { // Copy over all the rooms in the layout into the world for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid); iterator.Valid; iterator.Next()) { DungeonLayout.RoomIndex roomIndex = iterator.Current; RoomLayout room = layout.GetRoomByIndex(roomIndex); RoomTemplate roomTemplate = layout.LayoutRoomTemplateSet.GetTemplateByName(room.static_room_data.room_template_name); room.runtime_nav_mesh = new NavMesh(room.room_key, roomTemplate.NavMeshTemplate); m_rooms.Add(room.room_key, room); } }
public IList <RoomIndex> GetRoomIndexListForFloor(int z_index) { List <RoomIndex> indices = new List <RoomIndex>(); for (int y_index = 0; y_index < m_roomGrid.GetLength(1); y_index++) { for (int x_index = 0; x_index < m_roomGrid.GetLength(0); x_index++) { RoomLayout room = m_roomGrid[x_index, y_index, z_index]; if (room != null) { indices.Add(new RoomIndex(x_index, y_index, z_index)); } } } return(indices); }
private void RemoveRoomFromGrid(RoomIndex roomIndex) { RoomLayout room = GetRoomByIndex(roomIndex); // Neighbor on the +x side if (room.RoomHasPortalOnSide(MathConstants.eSignedDirection.positive_x)) { RoomLayout posXRoom = GetRoomByIndex(roomIndex.Offset(1, 0, 0)); // No more room on the -x side posXRoom.RoomFlagPortalOnSide(MathConstants.eSignedDirection.negative_x, false); } // Neighbor on the -x side if (room.RoomHasPortalOnSide(MathConstants.eSignedDirection.negative_x)) { RoomLayout negXRoom = GetRoomByIndex(roomIndex.Offset(-1, 0, 0)); // No more room on the +x side negXRoom.RoomFlagPortalOnSide(MathConstants.eSignedDirection.positive_x, false); } // Neighbor on the +y side if (room.RoomHasPortalOnSide(MathConstants.eSignedDirection.positive_y)) { RoomLayout posYRoom = GetRoomByIndex(roomIndex.Offset(0, 1, 0)); // No more room on the -y side posYRoom.RoomFlagPortalOnSide(MathConstants.eSignedDirection.negative_y, false); } // Neighbor on the -y side if (room.RoomHasPortalOnSide(MathConstants.eSignedDirection.negative_y)) { RoomLayout negYRoom = GetRoomByIndex(roomIndex.Offset(0, -1, 0)); // No more room on the +y side negYRoom.RoomFlagPortalOnSide(MathConstants.eSignedDirection.positive_y, false); } // Stomp this room m_roomGrid[roomIndex.X, roomIndex.Y, roomIndex.Z] = null; }
private bool CanRemoveRoomFromGrid(RoomIndex roomIndex) { RoomLayout room = GetRoomByIndex(roomIndex); bool canRemoveRoom = true; // Can't remove this room if it contains stairs // Or we are neighboring a room that contains stairs if (!room.RoomHasStairs) { RoomKey roomKey = GetRoomKeyForRoomIndex(roomIndex); // Can't remove the origin room because that's where the player is spawned in a new game canRemoveRoom = !(roomKey.x == 0 && roomKey.y == 0 && roomKey.z == 0); if (canRemoveRoom && room.RoomHasPortalOnSide(MathConstants.eSignedDirection.positive_x)) { canRemoveRoom &= !GetRoomByIndex(roomIndex.Offset(1, 0, 0)).RoomHasStairs; } if (canRemoveRoom && room.RoomHasPortalOnSide(MathConstants.eSignedDirection.negative_x)) { canRemoveRoom &= !GetRoomByIndex(roomIndex.Offset(-1, 0, 0)).RoomHasStairs; } if (canRemoveRoom && room.RoomHasPortalOnSide(MathConstants.eSignedDirection.positive_y)) { canRemoveRoom &= !GetRoomByIndex(roomIndex.Offset(0, 1, 0)).RoomHasStairs; } if (canRemoveRoom && room.RoomHasPortalOnSide(MathConstants.eSignedDirection.negative_y)) { canRemoveRoom &= !GetRoomByIndex(roomIndex.Offset(0, -1, 0)).RoomHasStairs; } } else { canRemoveRoom = false; } return(canRemoveRoom); }
private void FilterIsolatedRooms( Dictionary <int, List <RoomIndex> > connectivityIdToRoomIndexMap) { for (RoomIndexIterator iterator = new RoomIndexIterator(m_roomGrid); iterator.Valid; iterator.Next()) { RoomIndex roomIndex = iterator.Current; RoomLayout room = GetRoomByIndex(roomIndex); if (room.RoomIsIsolated) { List <RoomIndex> connectedSet = connectivityIdToRoomIndexMap[room.connectivity_id]; // Remove the room from the connectivity set connectivityIdToRoomIndexMap.Remove(room.connectivity_id); // Remove the room from the room grid m_roomGrid[roomIndex.X, roomIndex.Y, roomIndex.Z] = null; } } }
private Portal CreateTeleporterPortal( Random rng, RoomIndex roomIndex) { Portal portal = null; RoomLayout room = GetRoomByIndex(roomIndex); RoomTemplate roomTemplate = m_roomTemplateSet.GetTemplateByName(room.static_room_data.room_template_name); List <PortalTemplate> teleporterTemplates = roomTemplate.PortalTemplates.Where(t => t.PortalType == ePortalType.teleporter).ToList(); if (teleporterTemplates.Count > 0) { RoomKey roomKey = GetRoomKeyForRoomIndex(roomIndex); PortalTemplate portalTemplate = teleporterTemplates[rng.Next(teleporterTemplates.Count)]; portal = new Portal(); portal.bounding_box = portalTemplate.BoundingBox; portal.room_side = portalTemplate.PortalRoomSide; portal.portal_type = portalTemplate.PortalType; portal.room_x = roomKey.x; portal.room_y = roomKey.y; portal.room_z = roomKey.z; // This is a temp ID for the purpose of portal connection. // A new ID will get assigned when inserting this portal into the DB. portal.portal_id = m_nextPortalId; ++m_nextPortalId; // This get sets in the next pass portal.target_portal_id = -1; // Add the new portal to the room room.portals.Add(portal); } return(portal); }
private bool CreateNormalPortals(out string result) { bool success = true; result = SuccessMessages.GENERAL_SUCCESS; // Create portals in each room for (RoomIndexIterator iterator = new RoomIndexIterator(m_roomGrid); iterator.Valid; iterator.Next()) { RoomIndex roomIndex = iterator.Current; RoomKey roomKey = GetRoomKeyForRoomIndex(roomIndex); RoomLayout room = GetRoomByIndex(roomIndex); RoomTemplate roomTemplate = m_roomTemplateSet.GetTemplateByName(room.static_room_data.room_template_name); foreach (PortalTemplate portalTemplate in roomTemplate.PortalTemplates) { if (portalTemplate.PortalType != ePortalType.teleporter) { Portal portal = new Portal(); portal.bounding_box = portalTemplate.BoundingBox; portal.room_side = portalTemplate.PortalRoomSide; portal.room_x = roomKey.x; portal.room_y = roomKey.y; portal.room_z = roomKey.z; portal.portal_type = portalTemplate.PortalType; // This is a temp ID for the purpose of portal connection. // A new ID will get assigned when inserting this portal into the DB. portal.portal_id = m_nextPortalId; ++m_nextPortalId; // This get sets in the next pass portal.target_portal_id = -1; room.portals.Add(portal); } } } // Connect neighboring portals for (RoomIndexIterator iterator = new RoomIndexIterator(m_roomGrid); success && iterator.Valid; iterator.Next()) { RoomIndex roomIndex = iterator.Current; RoomLayout room = GetRoomByIndex(roomIndex); foreach (Portal portal in room.portals) { MathConstants.eSignedDirection opposingRoomSide = RoomKey.GetOpposingRoomSide(portal.room_side); RoomIndex opposingRoomIndex = roomIndex.GetOpposingRoomIndex(portal.room_side); RoomLayout opposingRoom = GetRoomByIndex(opposingRoomIndex); Portal opposingPortal = opposingRoom.portals.Find(p => p.room_side == opposingRoomSide); if (opposingPortal != null) { portal.target_portal_id = opposingPortal.portal_id; opposingPortal.target_portal_id = portal.portal_id; } else { result = ErrorMessages.DUNGEON_LAYOUT_ERROR; success = false; break; } } } return(success); }
private void JoinAdjacentDisjointRoomSets( Dictionary <int, List <RoomIndex> > connectivityIdToRoomIndexMap) { // Look for any null room that neighboring at least two disjoint sets of rooms for (RoomIndexIterator iterator = new RoomIndexIterator(m_roomGrid, RoomIndexIterator.eIterationType.nullRooms); iterator.Valid; iterator.Next()) { RoomIndex nullRoomIndex = iterator.Current; RoomIndex[] neighboringIndices = new RoomIndex[4] { nullRoomIndex.Offset(1, 0, 0), nullRoomIndex.Offset(-1, 0, 0), nullRoomIndex.Offset(0, 1, 0), nullRoomIndex.Offset(0, -1, 0) }; MathConstants.eSignedDirection[] neighborSideFlags = new MathConstants.eSignedDirection[4] { MathConstants.eSignedDirection.positive_x, MathConstants.eSignedDirection.negative_x, MathConstants.eSignedDirection.positive_y, MathConstants.eSignedDirection.negative_y }; bool createNewRoom = false; TypedFlags <MathConstants.eSignedDirection> nullRoomNeighborFlags = new TypedFlags <MathConstants.eSignedDirection>(); int lastConnectivityId = -1; for (int side_index = 0; side_index < 4; ++side_index) { MathConstants.eSignedDirection neighborSide = neighborSideFlags[side_index]; RoomIndex neighborRoomIndex = neighboringIndices[side_index]; // See if an adjacent room exists on this side RoomLayout neighborRoom = TryGetRoomByIndex(neighborRoomIndex); if (neighborRoom != null) { // Record that a neighboring room was found in this side nullRoomNeighborFlags.Set(neighborSide, true); // See if the neighboring room is actually disjoint from a previous neighbor // we have found on another side (different connectivity_id) int roomConnectivityId = neighborRoom.connectivity_id; if (lastConnectivityId != -1 && roomConnectivityId != lastConnectivityId) { List <RoomIndex> roomSet = connectivityIdToRoomIndexMap[roomConnectivityId]; List <RoomIndex> lastRoomSet = connectivityIdToRoomIndexMap[lastConnectivityId]; // Make the connectivity ids match for rooms in both sets roomSet.ForEach(rIndex => GetRoomByIndex(rIndex).connectivity_id = lastConnectivityId); // Merge the rooms in the set into the previous set lastRoomSet.AddRange(roomSet); // Remove the set connectivityIdToRoomIndexMap.Remove(roomConnectivityId); // Since we have merged two adjacent sets we now need a new room // to bridge the disjoin sets createNewRoom = true; } // Keep track of the last valid connectivity we found for the next iteration lastConnectivityId = neighborRoom.connectivity_id; } } if (createNewRoom) { // Create a new room at the null room index location RoomLayout newRoom = new RoomLayout(GetRoomKeyForRoomIndex(nullRoomIndex)); // Record which neighbors the null room has newRoom.portalRoomSideBitmask = nullRoomNeighborFlags; // All neighbors should have the same connectivity id now // so just get the connectivity id from the last valid neighbor newRoom.connectivity_id = lastConnectivityId; // Finally store the new room in the room grid m_roomGrid[nullRoomIndex.X, nullRoomIndex.Y, nullRoomIndex.Z] = newRoom; // Add the new room to the connectivity set it's helping to bridge { List <RoomIndex> lastRoomSet = connectivityIdToRoomIndexMap[lastConnectivityId]; lastRoomSet.Add(new RoomIndex(nullRoomIndex)); } // Tell all neighboring rooms about the new room adjacent to it for (int side_index = 0; side_index < 4; ++side_index) { MathConstants.eSignedDirection neighborSide = neighborSideFlags[side_index]; RoomIndex neighborRoomIndex = neighboringIndices[side_index]; // See if an adjacent room exists on this side if (newRoom.portalRoomSideBitmask.Test(neighborSide)) { RoomLayout neighborRoom = GetRoomByIndex(neighborRoomIndex); MathConstants.eSignedDirection opposingNeighborSide = RoomKey.GetOpposingRoomSide(neighborSide); neighborRoom.RoomFlagPortalOnSide(opposingNeighborSide, true); } } } } }
private void ComputeRoomConnectivity(UnionFind <RoomIndex> roomUnion) { IList <RoomIndex> roomIndices = GetRoomIndexList(); roomUnion = new UnionFind <RoomIndex>(); // Add all of the rooms into the union foreach (RoomIndex roomIndex in roomIndices) { roomUnion.AddElement(roomIndex); } // Start connecting to our neighbors foreach (RoomIndex roomIndex in roomIndices) { RoomLayout room = GetRoomByIndex(roomIndex); // Union with the neighbor on the +x side if (room.RoomHasPortalOnSide(MathConstants.eSignedDirection.positive_x)) { roomUnion.Union(roomIndex, roomIndex.Offset(1, 0, 0)); } // Union with the neighbor on the -x side if (room.RoomHasPortalOnSide(MathConstants.eSignedDirection.negative_x)) { roomUnion.Union(roomIndex, roomIndex.Offset(-1, 0, 0)); } // Union with the neighbor on the +y side if (room.RoomHasPortalOnSide(MathConstants.eSignedDirection.positive_y)) { roomUnion.Union(roomIndex, roomIndex.Offset(0, 1, 0)); } // Union with the neighbor on the -y side if (room.RoomHasPortalOnSide(MathConstants.eSignedDirection.negative_y)) { roomUnion.Union(roomIndex, roomIndex.Offset(0, -1, 0)); } // Union with the neighbor on the +z side if (room.RoomHasPortalOnSide(MathConstants.eSignedDirection.positive_z)) { roomUnion.Union(roomIndex, roomIndex.Offset(0, 0, 1)); } // Union with the neighbor on the -z side if (room.RoomHasPortalOnSide(MathConstants.eSignedDirection.negative_z)) { roomUnion.Union(roomIndex, roomIndex.Offset(0, 0, -1)); } } // Store the final connectivity id on the room foreach (RoomIndex roomIndex in roomIndices) { RoomLayout room = GetRoomByIndex(roomIndex); room.connectivity_id = roomUnion.FindRootIndex(roomIndex); } }
private int CreateFullyConnectedRoomGrid( Random rng) { int lateralRoomCount = m_worldTemplate.DungeonLateralRoomCount; int floorCount = m_worldTemplate.DungeonFloorCount; int totalRoomCount = lateralRoomCount * lateralRoomCount * floorCount; m_roomGrid = new RoomLayout[lateralRoomCount, lateralRoomCount, floorCount]; m_minRoomKey = new RoomKey(m_gameId, -lateralRoomCount / 2, -lateralRoomCount / 2, 0); // Fully connect the rooms on each floor, but leave each floor unconnected initially for (RoomIndexIterator iterator = new RoomIndexIterator(m_roomGrid, RoomIndexIterator.eIterationType.allRooms); iterator.Valid; iterator.Next()) { RoomIndex roomIndex = iterator.Current; RoomKey roomKey = new RoomKey( m_gameId, roomIndex.X - lateralRoomCount / 2, roomIndex.Y - lateralRoomCount / 2, roomIndex.Z); RoomLayout room = new RoomLayout(roomKey); if (roomIndex.X > 0) { room.RoomFlagPortalOnSide(MathConstants.eSignedDirection.negative_x, true); } if (roomIndex.X < lateralRoomCount - 1) { room.RoomFlagPortalOnSide(MathConstants.eSignedDirection.positive_x, true); } if (roomIndex.Y > 0) { room.RoomFlagPortalOnSide(MathConstants.eSignedDirection.negative_y, true); } if (roomIndex.Y < lateralRoomCount - 1) { room.RoomFlagPortalOnSide(MathConstants.eSignedDirection.positive_y, true); } m_roomGrid[roomIndex.X, roomIndex.Y, roomIndex.Z] = room; } // Randomly add stairs connecting each floor for (int z_index = 0; z_index < floorCount - 1; z_index++) { Range <int> stairsRange = m_worldTemplate.StairsPerFloor; IList <RoomIndex> randomRoomIndices = GetRoomIndexListForFloor(z_index); int desiredStairsCount = RNGUtilities.RandomInt(rng, stairsRange.Min, stairsRange.Max); int currentStairsCount = 0; RNGUtilities.DeterministicKnuthShuffle(rng, randomRoomIndices); foreach (RoomIndex roomIndex in randomRoomIndices) { Room room = m_roomGrid[roomIndex.X, roomIndex.Y, roomIndex.Z]; Room roomAbove = m_roomGrid[roomIndex.X, roomIndex.Y, roomIndex.Z + 1]; // Only consider rooms of the configuration X+X-Y+Y- to add stairs to // because we only have rooms with stairs for the templates // X+X-Y+Y-Z+ and X+X-Y+Y-Z- // We do this so that we can get away with 18 room templates rather than 64 if (room.RoomHasAllPossibleDoors && !room.RoomHasStairs) { room.RoomFlagPortalOnSide(MathConstants.eSignedDirection.positive_z, true); roomAbove.RoomFlagPortalOnSide(MathConstants.eSignedDirection.negative_z, true); ++currentStairsCount; } if (currentStairsCount >= desiredStairsCount) { break; } } } return(totalRoomCount); }