public void DisposeDungeon(CLRScriptBase script) { foreach (RandomDungeonArea area in AreasOfDungeon) { area.ClearArea(script); if (!DungeonStore.CachedAreas.ContainsKey(area.TemplateAreaId)) { DungeonStore.CachedAreas.Add(area.TemplateAreaId, new List <uint>()); } DungeonStore.CachedAreas[area.TemplateAreaId].Add(area.AreaId); } AreasOfDungeon.Clear(); }
public RandomDungeon(string areaPrefix, int areasToGenerate, int cr, string name, CLRScriptBase script) { CR = cr; DungeonStore.FindAvailableAreas(areaPrefix); List <RandomDungeonArea> sourceAreas = new List <RandomDungeonArea>(); if (areasToGenerate > 1) { foreach (RandomDungeonArea area in DungeonStore.AvailableAreas[areaPrefix]) { if (area.AreaExits.Count <= areasToGenerate && area.AreaExits.Count > 1) { sourceAreas.Add(area); } } } else { foreach (RandomDungeonArea area in DungeonStore.AvailableAreas[areaPrefix]) { if (area.AreaExits.Count == 1) { sourceAreas.Add(area); } } } RandomDungeonArea template = sourceAreas[rnd.Next(sourceAreas.Count)]; RandomDungeonArea toAdd = new RandomDungeonArea(); toAdd.TemplateAreaId = template.AreaId; toAdd.DungeonName = name; toAdd.AreaExits = new List <ExitDirection>(); toAdd.AreaExits.AddRange(template.AreaExits); toAdd.DungeonExit = toAdd.AreaExits[rnd.Next(toAdd.AreaExits.Count)]; toAdd.AreaExits.Remove(toAdd.DungeonExit); toAdd.X = areasToGenerate + 1; toAdd.Y = areasToGenerate + 1; toAdd.Z = areasToGenerate + 1; toAdd.CR = cr; areasToGenerate -= toAdd.AreaExits.Count; areasToGenerate -= 1; AreasOfDungeon.Add(toAdd); List <RandomDungeonArea> areasNeedingAdjacentAreas = new List <RandomDungeonArea>(); areasNeedingAdjacentAreas.Add(toAdd); while (areasNeedingAdjacentAreas.Count > 0) { // Randomly select one of our bare ends to build out from. RandomDungeonArea toExpand = areasNeedingAdjacentAreas[rnd.Next(areasNeedingAdjacentAreas.Count)]; // Build a temporary collection of exit directions from this area, but // don't count the directions that already have adjacent areas. List <ExitDirection> NextAreaDirections = new List <ExitDirection>(); NextAreaDirections.AddRange(toExpand.AreaExits); foreach (ExitDirection used in toExpand.AdjacentAreas.Keys) { NextAreaDirections.Remove(used); } if (NextAreaDirections.Count == 0) { // If that's all of the exits, then this area shouldn't actually be on the list // of candidates to expand. areasNeedingAdjacentAreas.Remove(toExpand); continue; } // Pick a random direction out of those available and set the new area's coordinates // appropriately. ExitDirection nextAreaDirection = NextAreaDirections[rnd.Next(NextAreaDirections.Count)]; toAdd = new RandomDungeonArea(); _setAreaCoordinates(toExpand, toAdd, nextAreaDirection); // Scan for adjacent areas, and determine the necessary parts of the target area. Dictionary <ExitDirection, bool> necessaryBorders = new Dictionary <ExitDirection, bool>(); Dictionary <ExitDirection, RandomDungeonArea> adjacentToBe = new Dictionary <ExitDirection, RandomDungeonArea>(); _buildBorders(necessaryBorders, adjacentToBe, toAdd); // If we can't generate more areas, order the new areas to not open up any more exits that we'd have to // attach areas to. Future additions will just be attaching things to dangling ATs. if (areasToGenerate <= 0) { _sealBorders(necessaryBorders); } // Now that we know where the area is and what borders it has to maintain, we // loop through the areas that are available and build a list of all of the ones // that fit the restrictions of the area's location. sourceAreas.Clear(); foreach (RandomDungeonArea area in DungeonStore.AvailableAreas[areaPrefix]) { bool areaUseful = true; foreach (KeyValuePair <ExitDirection, bool> dir in necessaryBorders) { if (dir.Value) { if (!area.AreaExits.Contains(dir.Key)) { areaUseful = false; } } if (!dir.Value) { if (area.AreaExits.Contains(dir.Key)) { areaUseful = false; } } if (!areaUseful) { break; } } if (areaUseful) { sourceAreas.Add(area); } } if (sourceAreas.Count >= 1) { // If we have more at least one area that fits the bill, we'll try to use that, so that // the dungeon feels as connected and continuous as possible. template = sourceAreas[rnd.Next(sourceAreas.Count)]; toAdd.TemplateAreaId = template.AreaId; toAdd.DungeonName = name; toAdd.AreaExits.AddRange(template.AreaExits); toAdd.CR = cr; foreach (KeyValuePair <ExitDirection, RandomDungeonArea> adj in adjacentToBe) { toAdd.AdjacentAreas.Add(adj.Key, adj.Value); switch (adj.Key) { case ExitDirection.North: adj.Value.AdjacentAreas.Add(ExitDirection.South, toAdd); break; case ExitDirection.South: adj.Value.AdjacentAreas.Add(ExitDirection.North, toAdd); break; case ExitDirection.East: adj.Value.AdjacentAreas.Add(ExitDirection.West, toAdd); break; case ExitDirection.West: adj.Value.AdjacentAreas.Add(ExitDirection.East, toAdd); break; case ExitDirection.Up: adj.Value.AdjacentAreas.Add(ExitDirection.Down, toAdd); break; case ExitDirection.Down: adj.Value.AdjacentAreas.Add(ExitDirection.Up, toAdd); break; } } areasToGenerate -= (toAdd.AreaExits.Count - toAdd.AdjacentAreas.Count); AreasOfDungeon.Add(toAdd); areasNeedingAdjacentAreas.Add(toAdd); } else { // But if no area fits the bill, we loop over each of the exits we're expecting and // attach the dead end area with the appropriate exit to them. foreach (KeyValuePair <ExitDirection, RandomDungeonArea> adj in adjacentToBe) { int X = toAdd.X; int Y = toAdd.Y; int Z = toAdd.Z; switch (adj.Key) { case ExitDirection.North: template = getSingleExitArea(ExitDirection.South, areaPrefix); break; case ExitDirection.South: template = getSingleExitArea(ExitDirection.North, areaPrefix); break; case ExitDirection.East: template = getSingleExitArea(ExitDirection.West, areaPrefix); break; case ExitDirection.West: template = getSingleExitArea(ExitDirection.East, areaPrefix); break; case ExitDirection.Up: template = getSingleExitArea(ExitDirection.Down, areaPrefix); break; case ExitDirection.Down: template = getSingleExitArea(ExitDirection.Up, areaPrefix); break; } toAdd = new RandomDungeonArea(); toAdd.X = X; toAdd.Y = Y; toAdd.Z = Z; toAdd.TemplateAreaId = template.AreaId; toAdd.DungeonName = name; toAdd.AreaExits.AddRange(template.AreaExits); toAdd.AdjacentAreas.Add(adj.Key, adj.Value); switch (adj.Key) { case ExitDirection.North: adj.Value.AdjacentAreas.Add(ExitDirection.South, toAdd); break; case ExitDirection.South: adj.Value.AdjacentAreas.Add(ExitDirection.North, toAdd); break; case ExitDirection.East: adj.Value.AdjacentAreas.Add(ExitDirection.West, toAdd); break; case ExitDirection.West: adj.Value.AdjacentAreas.Add(ExitDirection.East, toAdd); break; case ExitDirection.Up: adj.Value.AdjacentAreas.Add(ExitDirection.Down, toAdd); break; case ExitDirection.Down: adj.Value.AdjacentAreas.Add(ExitDirection.Up, toAdd); break; } areasToGenerate -= (toAdd.AreaExits.Count - toAdd.AdjacentAreas.Count); AreasOfDungeon.Add(toAdd); areasNeedingAdjacentAreas.Add(toAdd); } } } }