public static void FindAvailableAreas(string areaPrefix) { areaPrefix = areaPrefix.ToLower(); // I guess we already cached this one. Do nothing else. if (AvailableAreas.ContainsKey(areaPrefix)) { return; } AvailableAreas.Add(areaPrefix, new List <RandomDungeonArea>()); foreach (KeyValuePair <uint, ActiveArea> area in ALFA.Shared.Modules.InfoStore.ActiveAreas) { if (area.Value.Tag.Contains(areaPrefix)) { RandomDungeonArea genericArea = new RandomDungeonArea(); string north = area.Value.Tag.Substring(area.Value.Tag.Length - 6, 1); string east = area.Value.Tag.Substring(area.Value.Tag.Length - 5, 1); string south = area.Value.Tag.Substring(area.Value.Tag.Length - 4, 1); string west = area.Value.Tag.Substring(area.Value.Tag.Length - 3, 1); string up = area.Value.Tag.Substring(area.Value.Tag.Length - 2, 1); string down = area.Value.Tag.Substring(area.Value.Tag.Length - 1, 1); int n, e, s, w, u, d; if (Int32.TryParse(north, out n) && n == 1) { genericArea.AreaExits.Add(ExitDirection.North); } if (Int32.TryParse(east, out e) && e == 1) { genericArea.AreaExits.Add(ExitDirection.East); } if (Int32.TryParse(south, out s) && s == 1) { genericArea.AreaExits.Add(ExitDirection.South); } if (Int32.TryParse(west, out w) && w == 1) { genericArea.AreaExits.Add(ExitDirection.West); } if (Int32.TryParse(up, out u) && u == 1) { genericArea.AreaExits.Add(ExitDirection.Up); } if (Int32.TryParse(down, out d) && d == 1) { genericArea.AreaExits.Add(ExitDirection.Down); } genericArea.AreaId = area.Key; AvailableAreas[areaPrefix].Add(genericArea); } } }
public RandomDungeonArea GetEndArea() { int grabbedCR = -1; RandomDungeonArea ret = null; foreach (RandomDungeonArea area in AreasOfDungeon) { if (area.CR > grabbedCR) { ret = area; grabbedCR = area.CR; } } return(ret); }
public RandomDungeonArea GetCurrentArea(CLRScriptBase script) { uint currentArea = script.GetArea(script.OBJECT_SELF); RandomDungeonArea currentAreaObject = null; foreach (RandomDungeonArea area in AreasOfDungeon) { if (area.AreaId == currentArea) { currentAreaObject = area; break; } } return(currentAreaObject); }
public RandomDungeonArea GetAdjacentArea(CLRScriptBase script, ExitDirection exit, RandomDungeonArea CurrentArea) { int X = CurrentArea.X; int Y = CurrentArea.Y; int Z = CurrentArea.Z; switch (exit) { case ExitDirection.North: Y++; break; case ExitDirection.East: X++; break; case ExitDirection.South: Y--; break; case ExitDirection.West: X--; break; case ExitDirection.Up: Z++; break; case ExitDirection.Down: Z--; break; } RandomDungeonArea targetArea = null; foreach (RandomDungeonArea area in AreasOfDungeon) { if (area.X == X && area.Y == Y && area.Z == Z) { targetArea = area; break; } } return(targetArea); }
public void CorrectDungeonCR() { RandomDungeonArea start = GetEntranceArea(); List <RandomDungeonArea> remainingAreas = new List <RandomDungeonArea>(); remainingAreas.AddRange(AreasOfDungeon); remainingAreas.Remove(start); start.CR = 0; List <RandomDungeonArea> nextAreas = new List <RandomDungeonArea>(); List <RandomDungeonArea> lastAreas = new List <RandomDungeonArea>(); lastAreas.Add(start); int CRtoSet = 1; while (remainingAreas.Count > 0) { foreach (RandomDungeonArea lastArea in lastAreas) { foreach (RandomDungeonArea nextArea in lastArea.AdjacentAreas.Values) { if (remainingAreas.Contains(nextArea)) { nextArea.CR = CRtoSet; nextAreas.Add(nextArea); remainingAreas.Remove(nextArea); } } } if (nextAreas.Count == 0) { break; } lastAreas.Clear(); lastAreas.AddRange(nextAreas); nextAreas.Clear(); CRtoSet++; } int diff = 1 + CR - CRtoSet; // CRtoSet will always be 1 higher than the last area in the dungeon, because CRtoSet will increment on its way out. foreach (RandomDungeonArea area in AreasOfDungeon) { area.CR += diff; } }
private void _setAreaCoordinates(RandomDungeonArea toExpand, RandomDungeonArea toAdd, ExitDirection exit) { switch (exit) { case ExitDirection.North: toAdd.X = toExpand.X; toAdd.Y = toExpand.Y + 1; toAdd.Z = toExpand.Z; break; case ExitDirection.East: toAdd.X = toExpand.X + 1; toAdd.Y = toExpand.Y; toAdd.Z = toExpand.Z; break; case ExitDirection.South: toAdd.X = toExpand.X; toAdd.Y = toExpand.Y - 1; toAdd.Z = toExpand.Z; break; case ExitDirection.West: toAdd.X = toExpand.X - 1; toAdd.Y = toExpand.Y; toAdd.Z = toExpand.Z; break; case ExitDirection.Up: toAdd.X = toExpand.X; toAdd.Y = toExpand.Y; toAdd.Z = toExpand.Z + 1; break; case ExitDirection.Down: toAdd.X = toExpand.X; toAdd.Y = toExpand.Y; toAdd.Z = toExpand.Z - 1; break; } }
public Int32 ScriptMain([In] object[] ScriptParameters, [In] Int32 DefaultReturnCode) { int command = (int)ScriptParameters[0]; // ScriptParameterTypes[0] is typeof(int) string name = (string)ScriptParameters[1]; int state = (int)ScriptParameters[2]; string template = (string)ScriptParameters[3]; Infestation infest = null; switch ((Command)command) { case Command.InitializeInfestations: if (!QuestStore.InfestationGrowthCounterStarted) { Infestation.InitializeInfestations(this); DelayCommand(HoursToSeconds(24), delegate { QuestStore.GrowAllInfestations(this); }); } break; case Command.CreateInfestation: new Infestation(name, template, state, this); break; case Command.GrowInfestation: infest = QuestStore.GetInfestation(name); if (infest != null) { infest.GrowInfestation(this); } else { SendMessageToAllDMs(NoInfest); } break; case Command.AddSpawnToInfestation: infest = QuestStore.GetInfestation(name); if (infest != null) { infest.AddSpawn(state, template); } else { SendMessageToAllDMs(NoInfest); } break; case Command.RemoveSpawnFromInfestation: infest = QuestStore.GetInfestation(name); if (infest != null) { if (!infest.RemoveSpawn(state, template)) { SendMessageToAllDMs(NoSpawn); } } else { SendMessageToAllDMs(NoInfest); } break; case Command.SetInfestationFecundity: infest = QuestStore.GetInfestation(name); if (infest != null) { infest.Fecundity = state; infest.Save(); } else { SendMessageToAllDMs(NoInfest); } break; case Command.SpawnCreatureFromInfestation: infest = QuestStore.GetInfestation(name); if (infest != null) { infest.SpawnOneAtTier(this); } break; case Command.DegradeAreaInfestation: infest = QuestStore.GetInfestation(name); if (infest != null) { uint degradedInfestationArea = GetArea(OBJECT_SELF); string degradedInfestationTag = GetTag(degradedInfestationArea); if (infest.InfestedAreaLevels.ContainsKey(degradedInfestationTag)) { if (infest.InfestedAreaLevels[degradedInfestationTag] <= 1) { infest.ClearArea(degradedInfestationTag, ALFA.Shared.Modules.InfoStore.ActiveAreas[degradedInfestationArea], this); infest.Save(); } else { infest.ChangeAreaLevel(degradedInfestationTag, ALFA.Shared.Modules.InfoStore.ActiveAreas[degradedInfestationArea], infest.InfestedAreaLevels[degradedInfestationTag] - 1, this); infest.Save(); } } } break; case Command.AddBossMonsterToInfestation: infest = QuestStore.GetInfestation(name); if (infest != null) { infest.AddBoss(template); } break; case Command.RemoveBossMonsterFromInfestation: infest = QuestStore.GetInfestation(name); if (infest != null) { infest.RemoveBoss(template); } break; case Command.PopulateInfestationGUIScreen: string infestName = GetLocalString(GetArea(OBJECT_SELF), Infestation.InfestNameVar); infest = QuestStore.GetInfestation(infestName); if (infest != null) { infest.PopulateGUI(OBJECT_SELF, this); } break; case Command.UpgradeInfestationCreatureTier: infest = QuestStore.GetInfestation(name); if (infest != null) { if (!infest.Spawns.ContainsKey(state)) { SendMessageToAllDMs("No spawns found at that tier."); } else if (infest.Spawns[state].Count <= 1) { SendMessageToAllDMs("Cannot upgrade tier for " + template + " as there are too few creatures at that tier."); } else if (!infest.Spawns[state].Contains(template)) { SendMessageToAllDMs(template + " does not exist at that tier."); } else { infest.AddSpawn(state + 1, template); infest.RemoveSpawn(state, template); } } break; case Command.DowngradeInfestationCreatureTier: infest = QuestStore.GetInfestation(name); if (infest != null) { if (state <= 1) { SendMessageToAllDMs("Creature is already at the minimum tier."); } else if (!infest.Spawns.ContainsKey(state)) { SendMessageToAllDMs("No spawns found at that tier."); } else if (infest.Spawns[state].Count <= 1 && infest.Spawns.ContainsKey(state + 1) && infest.Spawns[state + 1].Count > 0) { SendMessageToAllDMs("Cannot downgrade tier for " + template + " as there are creatures at the next tier."); } else if (!infest.Spawns[state].Contains(template)) { SendMessageToAllDMs(template + " does not exist at that tier."); } else { infest.AddSpawn(state - 1, template); infest.RemoveSpawn(state, template); } } break; case Command.PrintInfestations: foreach (Infestation inf in QuestStore.LoadedInfestations) { SendMessageToAllDMs(inf.ToString()); } break; case Command.InstanceDungeon: if (DungeonStore.Dungeons.ContainsKey(name)) { return(0); } DungeonStore.FindAvailableAreas(template); RandomDungeon dung = new RandomDungeon(template, state, state, name, this); dung.retLoc = GetLocation(OBJECT_SELF); dung.CorrectDungeonCR(); DungeonStore.Dungeons.Add(name, dung); break; case Command.EnterDungeon: if (DungeonStore.Dungeons.ContainsKey(name)) { RandomDungeon dungeon = DungeonStore.Dungeons[name]; RandomDungeonArea enter = dungeon.GetEntranceArea(); enter.LoadArea(this); enter.TransitionToArea(this, enter.DungeonExit); } break; case Command.DungeonTransitionNorth: if (DungeonStore.Dungeons.ContainsKey(name)) { RandomDungeon dungeon = DungeonStore.Dungeons[name]; RandomDungeonArea current = dungeon.GetCurrentArea(this); if (current == null) { return(0); } if (current.DungeonExit == ExitDirection.North) { JumpToLocation(dungeon.retLoc); return(0); } RandomDungeonArea target = dungeon.GetAdjacentArea(this, ExitDirection.North, current); if (target == null) { SendMessageToPC(OBJECT_SELF, "This appears to be a dead end."); return(0); } if (!target.LoadArea(this)) { SendMessageToPC(OBJECT_SELF, "I cannot load that area, so this is effectively a dead end."); return(0); } target.TransitionToArea(this, ExitDirection.South); } break; case Command.DungeonTransitionEast: if (DungeonStore.Dungeons.ContainsKey(name)) { RandomDungeon dungeon = DungeonStore.Dungeons[name]; RandomDungeonArea current = dungeon.GetCurrentArea(this); if (current == null) { return(0); } if (current.DungeonExit == ExitDirection.East) { JumpToLocation(dungeon.retLoc); return(0); } RandomDungeonArea target = dungeon.GetAdjacentArea(this, ExitDirection.East, current); if (target == null) { SendMessageToPC(OBJECT_SELF, "This appears to be a dead end."); return(0); } if (!target.LoadArea(this)) { SendMessageToPC(OBJECT_SELF, "I cannot load that area, so this is effectively a dead end."); return(0); } target.TransitionToArea(this, ExitDirection.West); } break; case Command.DungeonTransitionSouth: if (DungeonStore.Dungeons.ContainsKey(name)) { RandomDungeon dungeon = DungeonStore.Dungeons[name]; RandomDungeonArea current = dungeon.GetCurrentArea(this); if (current == null) { return(0); } if (current.DungeonExit == ExitDirection.South) { JumpToLocation(dungeon.retLoc); return(0); } RandomDungeonArea target = dungeon.GetAdjacentArea(this, ExitDirection.South, current); if (target == null) { SendMessageToPC(OBJECT_SELF, "This appears to be a dead end."); return(0); } if (!target.LoadArea(this)) { SendMessageToPC(OBJECT_SELF, "I cannot load that area, so this is effectively a dead end."); return(0); } target.TransitionToArea(this, ExitDirection.North); } break; case Command.DungeonTransitionWest: if (DungeonStore.Dungeons.ContainsKey(name)) { RandomDungeon dungeon = DungeonStore.Dungeons[name]; RandomDungeonArea current = dungeon.GetCurrentArea(this); if (current == null) { return(0); } if (current.DungeonExit == ExitDirection.West) { JumpToLocation(dungeon.retLoc); return(0); } RandomDungeonArea target = dungeon.GetAdjacentArea(this, ExitDirection.West, current); if (target == null) { SendMessageToPC(OBJECT_SELF, "This appears to be a dead end."); return(0); } if (!target.LoadArea(this)) { SendMessageToPC(OBJECT_SELF, "I cannot load that area, so this is effectively a dead end."); return(0); } target.TransitionToArea(this, ExitDirection.East); } break; case Command.DungeonTransitionUp: if (DungeonStore.Dungeons.ContainsKey(name)) { RandomDungeon dungeon = DungeonStore.Dungeons[name]; RandomDungeonArea current = dungeon.GetCurrentArea(this); if (current == null) { return(0); } if (current.DungeonExit == ExitDirection.Up) { JumpToLocation(dungeon.retLoc); return(0); } RandomDungeonArea target = dungeon.GetAdjacentArea(this, ExitDirection.Up, current); if (target == null) { SendMessageToPC(OBJECT_SELF, "This appears to be a dead end."); return(0); } if (!target.LoadArea(this)) { SendMessageToPC(OBJECT_SELF, "I cannot load that area, so this is effectively a dead end."); return(0); } target.TransitionToArea(this, ExitDirection.Down); } break; case Command.DungeonTransitionDown: if (DungeonStore.Dungeons.ContainsKey(name)) { RandomDungeon dungeon = DungeonStore.Dungeons[name]; RandomDungeonArea current = dungeon.GetCurrentArea(this); if (current == null) { return(0); } if (current.DungeonExit == ExitDirection.Down) { JumpToLocation(dungeon.retLoc); return(0); } RandomDungeonArea target = dungeon.GetAdjacentArea(this, ExitDirection.Down, current); if (target == null) { SendMessageToPC(OBJECT_SELF, "This appears to be a dead end."); return(0); } if (!target.LoadArea(this)) { SendMessageToPC(OBJECT_SELF, "I cannot load that area, so this is effectively a dead end."); return(0); } target.TransitionToArea(this, ExitDirection.Up); } break; case Command.AddDungeonSpawn: if (!DungeonStore.DungeonSpawns.ContainsKey(name)) { DungeonStore.DungeonSpawns.Add(name, new Dictionary <int, List <string> >()); } if (!DungeonStore.DungeonSpawns[name].ContainsKey(state)) { DungeonStore.DungeonSpawns[name].Add(state, new List <string>()); } DungeonStore.DungeonSpawns[name][state].Add(template); break; case Command.RemoveDungeonSpawn: if (DungeonStore.DungeonSpawns.ContainsKey(name) && DungeonStore.DungeonSpawns[name].ContainsKey(state) && DungeonStore.DungeonSpawns[name][state].Contains(template)) { DungeonStore.DungeonSpawns[name][state].Remove(template); } break; case Command.SetDungeonSpawnType: if (DungeonStore.Dungeons.ContainsKey(name)) { foreach (RandomDungeonArea area in DungeonStore.Dungeons[name].AreasOfDungeon) { area.SpawnType = template; } } break; case Command.DisposeDungeon: if (DungeonStore.Dungeons.ContainsKey(name)) { RandomDungeon toDispose = DungeonStore.Dungeons[name]; toDispose.DisposeDungeon(this); DungeonStore.Dungeons.Remove(name); } break; case Command.AddDungeonTrap: if (!DungeonStore.DungeonTraps.ContainsKey(name)) { DungeonStore.DungeonTraps.Add(name, new Dictionary <int, List <string> >()); } if (!DungeonStore.DungeonTraps[name].ContainsKey(state)) { DungeonStore.DungeonTraps[name].Add(state, new List <string>()); } DungeonStore.DungeonTraps[name][state].Add(template); break; case Command.RemoveDungeonTrap: if (DungeonStore.DungeonTraps.ContainsKey(name) && DungeonStore.DungeonTraps[name].ContainsKey(state) && DungeonStore.DungeonTraps[name][state].Contains(template)) { DungeonStore.DungeonTraps[name][state].Remove(template); } break; case Command.SetDungeonTrapType: if (DungeonStore.Dungeons.ContainsKey(name)) { foreach (RandomDungeonArea area in DungeonStore.Dungeons[name].AreasOfDungeon) { area.TrapType = template; } } break; case Command.SetDungeonQuestObjective: if (DungeonStore.Dungeons.ContainsKey(name)) { DungeonStore.Dungeons[name].GetEndArea().Quest = template; } break; case Command.PrintDungeons: foreach (KeyValuePair <string, RandomDungeon> dungeon in DungeonStore.Dungeons) { SendMessageToAllDMs(dungeon.Key); foreach (RandomDungeonArea area in dungeon.Value.AreasOfDungeon) { SendMessageToAllDMs(GetName(area.TemplateAreaId) + "(" + area.TemplateAreaId + ") : " + GetName(area.AreaId) + "(" + area.AreaId + ") CR " + area.CR + "(" + area.X + "," + area.Y + "," + area.Z + ")"); } } break; } return(0); }
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); } } } }
private void _buildBorders(Dictionary <ExitDirection, bool> necessaryBorders, Dictionary <ExitDirection, RandomDungeonArea> adjacentToBe, RandomDungeonArea toAdd) { foreach (RandomDungeonArea area in AreasOfDungeon) { if (area.X == toAdd.X && area.Y == toAdd.Y && area.Z == toAdd.Z + 1) { // Area is above the new area. if (area.AreaExits.Contains(ExitDirection.Down)) { necessaryBorders.Add(ExitDirection.Up, true); adjacentToBe.Add(ExitDirection.Up, area); } else if (!necessaryBorders.ContainsKey(ExitDirection.Up)) { // This location might have double end caps in it. necessaryBorders.Add(ExitDirection.Up, false); } } else if (area.X == toAdd.X && area.Y == toAdd.Y && area.Z == toAdd.Z - 1) { if (area.AreaExits.Contains(ExitDirection.Up)) { necessaryBorders.Add(ExitDirection.Down, true); adjacentToBe.Add(ExitDirection.Down, area); } else if (!necessaryBorders.ContainsKey(ExitDirection.Down)) { necessaryBorders.Add(ExitDirection.Down, false); } } else if (area.X == toAdd.X + 1 && area.Y == toAdd.Y && area.Z == toAdd.Z) { if (area.AreaExits.Contains(ExitDirection.West)) { necessaryBorders.Add(ExitDirection.East, true); adjacentToBe.Add(ExitDirection.East, area); } else if (!necessaryBorders.ContainsKey(ExitDirection.East)) { necessaryBorders.Add(ExitDirection.East, false); } } else if (area.X == toAdd.X - 1 && area.Y == toAdd.Y && area.Z == toAdd.Z) { if (area.AreaExits.Contains(ExitDirection.East)) { necessaryBorders.Add(ExitDirection.West, true); adjacentToBe.Add(ExitDirection.West, area); } else if (!necessaryBorders.ContainsKey(ExitDirection.West)) { necessaryBorders.Add(ExitDirection.West, false); } } else if (area.X == toAdd.X && area.Y == toAdd.Y + 1 && area.Z == toAdd.Z) { if (area.AreaExits.Contains(ExitDirection.South)) { necessaryBorders.Add(ExitDirection.North, true); adjacentToBe.Add(ExitDirection.North, area); } else if (!necessaryBorders.ContainsKey(ExitDirection.North)) { necessaryBorders.Add(ExitDirection.North, false); } } else if (area.X == toAdd.X && area.Y == toAdd.Y - 1 && area.Z == toAdd.Z) { if (area.AreaExits.Contains(ExitDirection.North)) { necessaryBorders.Add(ExitDirection.South, true); adjacentToBe.Add(ExitDirection.South, area); } else if (!necessaryBorders.ContainsKey(ExitDirection.South)) { necessaryBorders.Add(ExitDirection.South, false); } } } }
public static void FindAvailableAreas(string areaPrefix) { areaPrefix = areaPrefix.ToLower(); // I guess we already cached this one. Do nothing else. if (AvailableAreas.ContainsKey(areaPrefix)) { return; } AvailableAreas.Add(areaPrefix, new List<RandomDungeonArea>()); foreach (KeyValuePair<uint, ActiveArea> area in ALFA.Shared.Modules.InfoStore.ActiveAreas) { if(area.Value.Tag.Contains(areaPrefix)) { RandomDungeonArea genericArea = new RandomDungeonArea(); string north = area.Value.Tag.Substring(area.Value.Tag.Length - 6, 1); string east = area.Value.Tag.Substring(area.Value.Tag.Length - 5, 1); string south = area.Value.Tag.Substring(area.Value.Tag.Length - 4, 1); string west = area.Value.Tag.Substring(area.Value.Tag.Length - 3, 1); string up = area.Value.Tag.Substring(area.Value.Tag.Length - 2, 1); string down = area.Value.Tag.Substring(area.Value.Tag.Length - 1, 1); int n, e, s, w, u, d; if (Int32.TryParse(north, out n) && n == 1) genericArea.AreaExits.Add(ExitDirection.North); if (Int32.TryParse(east, out e) && e == 1) genericArea.AreaExits.Add(ExitDirection.East); if (Int32.TryParse(south, out s) && s == 1) genericArea.AreaExits.Add(ExitDirection.South); if (Int32.TryParse(west, out w) && w == 1) genericArea.AreaExits.Add(ExitDirection.West); if (Int32.TryParse(up, out u) && u == 1) genericArea.AreaExits.Add(ExitDirection.Up); if (Int32.TryParse(down, out d) && d == 1) genericArea.AreaExits.Add(ExitDirection.Down); genericArea.AreaId = area.Key; AvailableAreas[areaPrefix].Add(genericArea); } } }
public RandomDungeonArea GetAdjacentArea(CLRScriptBase script, ExitDirection exit, RandomDungeonArea CurrentArea) { int X = CurrentArea.X; int Y = CurrentArea.Y; int Z = CurrentArea.Z; switch(exit) { case ExitDirection.North: Y++; break; case ExitDirection.East: X++; break; case ExitDirection.South: Y--; break; case ExitDirection.West: X--; break; case ExitDirection.Up: Z++; break; case ExitDirection.Down: Z--; break; } RandomDungeonArea targetArea = null; foreach(RandomDungeonArea area in AreasOfDungeon) { if(area.X == X && area.Y == Y && area.Z == Z) { targetArea = area; break; } } return targetArea; }
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); } } } }
private void _buildBorders(Dictionary<ExitDirection, bool> necessaryBorders, Dictionary<ExitDirection, RandomDungeonArea> adjacentToBe, RandomDungeonArea toAdd) { foreach (RandomDungeonArea area in AreasOfDungeon) { if (area.X == toAdd.X && area.Y == toAdd.Y && area.Z == toAdd.Z + 1) { // Area is above the new area. if (area.AreaExits.Contains(ExitDirection.Down)) { necessaryBorders.Add(ExitDirection.Up, true); adjacentToBe.Add(ExitDirection.Up, area); } else if (!necessaryBorders.ContainsKey(ExitDirection.Up)) { // This location might have double end caps in it. necessaryBorders.Add(ExitDirection.Up, false); } } else if (area.X == toAdd.X && area.Y == toAdd.Y && area.Z == toAdd.Z - 1) { if (area.AreaExits.Contains(ExitDirection.Up)) { necessaryBorders.Add(ExitDirection.Down, true); adjacentToBe.Add(ExitDirection.Down, area); } else if (!necessaryBorders.ContainsKey(ExitDirection.Down)) { necessaryBorders.Add(ExitDirection.Down, false); } } else if (area.X == toAdd.X + 1 && area.Y == toAdd.Y && area.Z == toAdd.Z) { if (area.AreaExits.Contains(ExitDirection.West)) { necessaryBorders.Add(ExitDirection.East, true); adjacentToBe.Add(ExitDirection.East, area); } else if (!necessaryBorders.ContainsKey(ExitDirection.East)) { necessaryBorders.Add(ExitDirection.East, false); } } else if (area.X == toAdd.X - 1 && area.Y == toAdd.Y && area.Z == toAdd.Z) { if (area.AreaExits.Contains(ExitDirection.East)) { necessaryBorders.Add(ExitDirection.West, true); adjacentToBe.Add(ExitDirection.West, area); } else if (!necessaryBorders.ContainsKey(ExitDirection.West)) { necessaryBorders.Add(ExitDirection.West, false); } } else if (area.X == toAdd.X && area.Y == toAdd.Y + 1 && area.Z == toAdd.Z) { if (area.AreaExits.Contains(ExitDirection.South)) { necessaryBorders.Add(ExitDirection.North, true); adjacentToBe.Add(ExitDirection.North, area); } else if (!necessaryBorders.ContainsKey(ExitDirection.North)) { necessaryBorders.Add(ExitDirection.North, false); } } else if (area.X == toAdd.X && area.Y == toAdd.Y - 1 && area.Z == toAdd.Z) { if (area.AreaExits.Contains(ExitDirection.North)) { necessaryBorders.Add(ExitDirection.South, true); adjacentToBe.Add(ExitDirection.South, area); } else if (!necessaryBorders.ContainsKey(ExitDirection.South)) { necessaryBorders.Add(ExitDirection.South, false); } } } }