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); } } } }