/// <summary> /// Solves the maze BFS. /// </summary> /// <param name="name">The name.</param> /// <returns>Solution</returns> public Solution <Position> solveMazeBFS(string name) { modelData.mutexBfs.WaitOne(); Solution <Position> solution = null; // Check if the maze exist. if (modelData.Mazes.ContainsKey(name)) { ISearchable <Position> mazeObjectAdapter = new MazeAdapter(modelData.Mazes[name]); ISearcher <Position> BFS = new BestFirstSearch <Position>(); // Check if the solution exist. if (modelData.BfsSolutions.ContainsKey(name)) { solution = modelData.BfsSolutions[name]; } else { // Calculate the solution. solution = BFS.Search(mazeObjectAdapter); modelData.BfsSolutions.Add(name, solution); } } State <Position> .StatePool.Clear(); modelData.mutexBfs.ReleaseMutex(); return(solution); }
/// <summary> /// Follow the Monsters target to it's position. /// </summary> /// <param name="targetSession">The TargetSession to follow</param> private void FollowTarget(ClientSession targetSession) { if (IsMoving) { if (!Path.Any() && targetSession != null) { short xoffset = (short)ServerManager.Instance.RandomNumber(-1, 1); short yoffset = (short)ServerManager.Instance.RandomNumber(-1, 1); try { List <Node> list = BestFirstSearch.TracePath(new Node() { X = MapX, Y = MapY }, targetSession.Character.BrushFire, targetSession.Character.MapInstance.Map.Grid); Path = list; } catch (Exception ex) { Logger.Log.Error($"Pathfinding using Pathfinder failed. Map: {MapId} StartX: {MapX} StartY: {MapY} TargetX: {(short)(targetSession.Character.PositionX + xoffset)} TargetY: {(short)(targetSession.Character.PositionY + yoffset)}", ex); RemoveTarget(); } } if (targetSession == null || MapId != targetSession.Character.MapInstance.Map.MapId) { RemoveTarget(); } } }
private static void Main(string[] args) { // the maze size 100x100 int col = 100; int row = 100; // create maze with DFSMazeGenerator DFSMazeGenerator generator = new DFSMazeGenerator(); Maze maze = generator.Generate(col, row); // print the maze Console.Write(maze.ToString()); // adapt the maze and solve it with BFS ISearchable <Position> adapter = new MazeAdapter(maze); ISearcher <Position> bfsSearcher = new BestFirstSearch <Position>(); bfsSearcher.Search(adapter); int bfsNumOfStases = bfsSearcher.GetNumberOfNodesEvaluated(); // solve the maze with DFS ISearcher <Position> dfsSearcher = new DepthFirstSearch <Position>(); dfsSearcher.Search(adapter); int dfsNumOfStases = dfsSearcher.GetNumberOfNodesEvaluated(); // print the num of evalueted nodes for BFS and DFS Console.WriteLine("number of BFS states:" + bfsNumOfStases); Console.WriteLine("number of DFS states:" + dfsNumOfStases); Console.Read(); }
/// <summary> /// Solves the specified maze. /// </summary> /// <param name="name">The name.</param> /// <param name="algorithmNumber">The algorithm number.</param> /// <returns>Solution.</returns> public Solution solve(string name, int algorithmNumber) { var maze = DictionaryOfMazes[name]; var searchableMaze = new SearchableMaze(maze); if (DictionaryOfMazesAndSolutions.ContainsKey(searchableMaze)) { return(DictionaryOfMazesAndSolutions[searchableMaze]); } Solution solution; ISearcher searchAlgorithm = null; switch (algorithmNumber) { case 0: searchAlgorithm = new BestFirstSearch <PointState>(); break; case 1: searchAlgorithm = new DepthFirstSearch <PointState>(); break; } solution = searchAlgorithm.search(searchableMaze); EvaluateNodes = searchAlgorithm.getNumberOfNodesEvaluated(); DictionaryOfMazesAndSolutions.Add(searchableMaze, solution); return(solution); }
public void UpdateBushFire() { BrushFire = BestFirstSearch.LoadBrushFire(new GridPos() { X = PositionX, Y = PositionY }, Owner.MapInstance.Map.Grid); }
public LinkedList <string> calcFastestWay(string source, string dest) { BestFirstSearch bfs = new BestFirstSearch(); bfs.BuildGraph(); bfs.Search(source, dest, "time"); return(bfs.path); }
/// <summary> /// Remove the current Target from Npc. /// </summary> internal void RemoveTarget() { Target = null; Path = BestFirstSearch.FindPath(new Node { X = MapX, Y = MapY }, new Node { X = FirstX, Y = FirstY }, MapInstance.Map.Grid); // Path To origins }
static void Main(string[] args) { Console.BufferWidth = 300; Console.BufferHeight = 240; Console.WindowWidth = 180; Console.WriteLine("Press any key to start..."); Console.ReadKey(); FileStream mapFileStream = File.Open("Maps/vadim_maze.cmap", FileMode.Open, FileAccess.Read); ConsoleMap map = ConsoleMapGenerator.FromText(mapFileStream, 'S', 'E', 'X', '.'); _map = map; InitArrays(2); Vector2Int start = map.DefaultStart; Vector2Int stop = map.DefaultStop; _start = start; _stop = stop; Vector2Int scale = new Vector2Int(4, 2); int spacing = 4; InitConsoleDrawer(map, scale, spacing, start, stop, 0); InitConsoleDrawer(map, scale, spacing, start, stop, 1); Console.SetCursorPosition(0, map.Height * scale.Y); AStarAlgorithm aStarTest = new AStarAlgorithm(); var path = aStarTest.GetPath(_map, start, stop, NeighbourMode.SideOnly); if (path != null) { Console.WriteLine("Path was found"); DrawPath(path, 0); } _contestants[0] = new BestFirstSearch(); _contestants[0].OnCellViewedEvent += OnCellUpdated; _contestants[1] = new AStarAlgorithm(); _contestants[1].OnCellViewedEvent += OnCellUpdated; StartPathFinder(0); StartPathFinder(1); while (_runningTasks > 0) { Thread.Sleep(100); } Console.WriteLine("Press any key to exit..."); Console.ReadKey(); }
public MazeModel() { _mazes = new Dictionary <string, Maze>(); _games = new Dictionary <string, GameController>(); _solutions = new Dictionary <string, MazeSolution>(); _generator = new DFSMazeGenerator(); _algorithms = new ISearcher <Position> [2]; _algorithms[0] = new BestFirstSearch <Position>(); _algorithms[1] = new DepthFirstSearch <Position>(); }
/// <summary> /// Follow the Monsters target to it's position. /// </summary> /// <param name="targetSession">The TargetSession to follow</param> private void FollowTarget(ClientSession targetSession) { if (IsMoving) { short maxDistance = 22; int distance = 0; if (!Path.Any() && targetSession != null) { short xoffset = (short)ServerManager.Instance.RandomNumber(-1, 1); short yoffset = (short)ServerManager.Instance.RandomNumber(-1, 1); try { List <Node> list = BestFirstSearch.TracePath(new Node() { X = MapX, Y = MapY }, targetSession.Character.BrushFire, targetSession.Character.MapInstance.Map.Grid); Path = list; } catch (Exception ex) { Logger.Log.Error($"Pathfinding using Pathfinder failed. Map: {MapId} StartX: {MapX} StartY: {MapY} TargetX: {(short)(targetSession.Character.PositionX + xoffset)} TargetY: {(short)(targetSession.Character.PositionY + yoffset)}", ex); RemoveTarget(); } } if (Monster != null && DateTime.Now > LastMove && Monster.Speed > 0 && Path.Any()) { int maxindex = Path.Count > Monster.Speed / 2 ? Monster.Speed / 2 : Path.Count; short mapX = Path.ElementAt(maxindex - 1).X; short mapY = Path.ElementAt(maxindex - 1).Y; double waitingtime = Map.GetDistance(new MapCell { X = mapX, Y = mapY }, new MapCell { X = MapX, Y = MapY }) / (double)Monster.Speed; MapInstance.Broadcast(new BroadcastPacket(null, $"mv 3 {MapMonsterId} {mapX} {mapY} {Monster.Speed}", ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY)); LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime); Observable.Timer(TimeSpan.FromMilliseconds((int)((waitingtime > 1 ? 1 : waitingtime) * 1000))).Subscribe(x => { MapX = mapX; MapY = mapY; }); distance = (int)Path.First().F; Path.RemoveRange(0, maxindex); } if (targetSession == null || MapId != targetSession.Character.MapInstance.Map.MapId || distance > maxDistance) { RemoveTarget(); } } }
/// <summary> /// Remove the current Target from Monster. /// </summary> internal void RemoveTarget() { GetNearestOponent(); if (Target != null) { Path.Clear(); return; } Path = BestFirstSearch.FindPath(new Node { X = MapX, Y = MapY }, new Node { X = FirstX, Y = FirstY }, MapInstance.Map.Grid); // Path To origins }
/// <summary> /// Remove the current Target from Npc. /// </summary> internal void RemoveTarget() { if (Target != -1) { Path.Clear(); Target = -1; //return to origin Path = BestFirstSearch.FindPath(new Node { X = MapX, Y = MapY }, new Node { X = FirstX, Y = FirstY }, MapInstance.Map.Grid); } }
public static void CompareSolvers() { DFSMazeGenerator generator = new DFSMazeGenerator(); Maze m = generator.Generate(5, 6); Console.WriteLine(m.ToString()); BestFirstSearch <CellType> bfs = new BestFirstSearch <CellType>(); DFS <CellType> dfs = new DFS <CellType>(); Solution <CellType> SolBFS = bfs.search(m); Solution <CellType> SolDFS = dfs.search(m); Console.ReadLine(); }
public IHttpActionResult SolveMaze(MazeName NameParam) { try { Searcher <Position> algorithm = new BestFirstSearch <Position>(new StateComparerByCost <Position>()); Solution <State <Position> > sol = this.mazeModel.Solve(NameParam.Name, algorithm); MazeSolutionAdapter solutionAdapter = new MazeSolutionAdapter(sol); return(Ok(JObject.Parse(solutionAdapter.ToJson(NameParam.Name)))); } catch (ArgumentException) { // Content bla bla BadRequest blabla return(NotFound()); } }
/// <summary> /// Compares the solvers. /// </summary> public static void CompareSolvers() { DFSMazeGenerator generator = new DFSMazeGenerator(); Maze maze = generator.Generate(10, 10); //Console.WriteLine(maze); ISearchable <Position> mazeAdapter = new MazeAdapter(maze); ISearcher <Position> bfs = new BestFirstSearch <Position>(); ISearcher <Position> dfs = new Dfs <Position>(); Solution <Position> solution = bfs.Search(mazeAdapter); Console.WriteLine("bfs sol:" + solution.EvaluatedNodes); Console.WriteLine(mazeAdapter.ToString(solution)); solution = dfs.Search(mazeAdapter); Console.WriteLine("dfs sol:" + solution.EvaluatedNodes); Console.WriteLine(mazeAdapter.ToString(solution)); }
internal static Node <TFactor, TStep> Run <TFactor, TStep>(this HeuristicSearchBase <TFactor, TStep> source) { Debug.WriteLine($"Searching path between {source.From} and {source.To} with {source.AlgorithmName}..."); var lastNode = default(Node <TFactor, TStep>); var observerFactory = source.AlgorithmObserverFactory; var observer = observerFactory != null?observerFactory.Create(source) : null; switch (source.AlgorithmName) { case nameof(AStar): lastNode = observer == null?AStar.Run(source) : AStar.Run(source, observer); break; case nameof(BestFirstSearch): lastNode = observer == null?BestFirstSearch.Run(source) : BestFirstSearch.Run(source, observer); break; case nameof(IterativeDeepeningAStar): lastNode = observer == null?IterativeDeepeningAStar.Run(source) : IterativeDeepeningAStar.Run(source, observer); break; case nameof(RecursiveBestFirstSearch): lastNode = observer == null?RecursiveBestFirstSearch.Run(source) : RecursiveBestFirstSearch.Run(source, observer); break; default: var algorithm = HeuristicSearch.RegisteredAlgorithms[source.AlgorithmName](source.AlgorithmName); if (algorithm is IObservableAlgorithm && observer != null) { lastNode = (algorithm as IObservableAlgorithm).Run(source, observer); } else { lastNode = algorithm.Run(source); } break; } return(lastNode); }
public override IEnumerator <TFactor> GetEnumerator() { Debug.WriteLine($"Searching path between {From} and {To} with {AlgorithmName}..."); var lastNode = default(Node <TFactor, TStep>); switch (AlgorithmName) { case nameof(AStar): lastNode = AStar.Run(this); break; case nameof(BestFirstSearch): lastNode = BestFirstSearch.Run(this); break; case nameof(IterativeDeepeningAStar): lastNode = IterativeDeepeningAStar.Run(this); break; case nameof(RecursiveBestFirstSearch): lastNode = RecursiveBestFirstSearch.Run(this); break; default: lastNode = HeuristicSearch.RegisteredAlgorithms[AlgorithmName](AlgorithmName).Run(this); break; } if (lastNode == null) // Solution not found { return(Enumerable.Empty <TFactor>().GetEnumerator()); } if (IsReversed) { return(lastNode.EnumerateReverseFactors().GetEnumerator()); } else { return(lastNode.TraceBack().EnumerateFactors().GetEnumerator()); } }
static void Main(string[] args) { Console.WriteLine("THE START !!"); ISearcher <int> ser = new BestFirstSearch <int>(); Dictionary <State <int>, List <State <int> > > Adj = new Dictionary <State <int>, List <State <int> > >(); State <int> one = new State <int>(1); State <int> two = new State <int>(2); State <int> three = new State <int>(3); State <int> four = new State <int>(4); State <int> five = new State <int>(5); State <int> six = new State <int>(6); State <int> seven = new State <int>(7); Adj[one] = new List <State <int> > { two, three }; Adj[two] = new List <State <int> > { four, five }; Adj[three] = new List <State <int> > { two, six }; Adj[four] = new List <State <int> >(); Adj[five] = new List <State <int> > { six }; Adj[six] = new List <State <int> > { seven }; Adj[seven] = new List <State <int> > { three }; TestSearchable <int> test1 = new TestSearchable <int>(one, six, Adj); Solution <int> sol = ser.search(test1); printSol(sol); Console.ReadLine(); }
/// <summary> /// Follow the Monsters target to it's position. /// </summary> /// <param name="targetSession">The TargetSession to follow</param> private void FollowTarget() { if (Monster == null || !IsAlive || HasBuff(CardType.Move, (byte)AdditionalTypes.Move.MovementImpossible) || !IsMoving) { return; } if (!Target?.IsTargetable(SessionType()) ?? true) { RemoveTarget(); return; } if (!Path.Any() && Target.MapInstance != null) { Path = BestFirstSearch.TracePath(new Node() { X = MapX, Y = MapY }, Target.GetBrushFire(), MapInstance.Map.Grid); } Move(); // follow the target }
public override IEnumerator <TResult> GetEnumerator() { Debug.WriteLine($"Searching path between {From} and {To} with {AlgorithmName}..."); switch (AlgorithmName) { case nameof(AStar): return(AStar.Run(this).GetEnumerator()); case nameof(BestFirstSearch): return(BestFirstSearch.Run(this).GetEnumerator()); case nameof(RecursiveBestFirstSearch): return(RecursiveBestFirstSearch.Run(this).GetEnumerator()); case nameof(IterativeDeepeningAStar): return(IterativeDeepeningAStar.Run(this).GetEnumerator()); } return(base.GetEnumerator()); }
/// <summary> /// Runs this instance. /// </summary> public static void Run() { var dfsMazeGenerator = new DFSMazeGenerator(); var MyMaze = dfsMazeGenerator.Generate(20, 20); var s = MyMaze.ToString(); Console.WriteLine(s); var SM = new SearchableMaze(MyMaze); Console.WriteLine("Start:" + new PointState(MyMaze.InitialPos)); Console.WriteLine("Goal:" + new PointState(MyMaze.GoalPos)); var DFS = new DepthFirstSearch <PointState>(); var solutionDFS = DFS.search(SM); Console.WriteLine("The solution path by DFS is:"); foreach (var state in solutionDFS.Path) { Console.WriteLine(state.ToString()); } Console.WriteLine("The DFS algorithm treated " + DFS.evaluatedNodes + " nodes."); Console.WriteLine(); var BFS = new BestFirstSearch <PointState>(); var solution = BFS.search(SM); Console.WriteLine("The solution path by BFS is:"); foreach (var state in solution.Path) { Console.WriteLine(state.ToString()); } Console.WriteLine("The BFS algorithm treated " + BFS.evaluatedNodes + " nodes."); Console.WriteLine(); }
// Algorithms public void Best_First_Search_Alg() { Clear(); List <Field> fieldList = new List <Field>(); foreach (Field field in fieldArray) { field.prevField = null; field.visited = false; field.distance = int.MaxValue; field.fDistance = 0; if (field.finish) { continue; } if (!field.wall) { field.hDistance = field.point.Distance_To(finishPoint); } fieldList.Add(field); if (!field.wall && !field.start && !field.finish) { btnArray[field.point.row, field.point.col].Background = Brushes.White; } } var fieldToVisit = new List <Field>(fieldList); BestFirstSearch alg = new BestFirstSearch(fieldToVisit); thr = new Thread(() => alg.Algorithm()); thr.Start(); }
public void RunEvent(EventContainer evt, ClientSession session = null, MapMonster monster = null) { if (evt != null) { if (session != null) { evt.MapInstance = session.CurrentMapInstance; switch (evt.EventActionType) { #region EventForUser case EventActionType.NPCDIALOG: session.SendPacket(session.Character.GenerateNpcDialog((int)evt.Parameter)); break; case EventActionType.SENDPACKET: session.SendPacket((string)evt.Parameter); break; #endregion } } if (evt.MapInstance != null) { switch (evt.EventActionType) { #region EventForUser case EventActionType.NPCDIALOG: case EventActionType.SENDPACKET: if (session == null) { evt.MapInstance.Sessions.ToList().ForEach(e => RunEvent(evt, e)); } break; #endregion #region MapInstanceEvent case EventActionType.REGISTEREVENT: Tuple <string, List <EventContainer> > even = (Tuple <string, List <EventContainer> >)evt.Parameter; switch (even.Item1) { case "OnCharacterDiscoveringMap": even.Item2.ForEach(s => evt.MapInstance.OnCharacterDiscoveringMapEvents.Add(new Tuple <EventContainer, List <long> >(s, new List <long>()))); break; case "OnMoveOnMap": evt.MapInstance.OnMoveOnMapEvents.AddRange(even.Item2); break; case "OnMapClean": evt.MapInstance.OnMapClean.AddRange(even.Item2); break; case "OnLockerOpen": evt.MapInstance.UnlockEvents.AddRange(even.Item2); break; } break; case EventActionType.REGISTERWAVE: evt.MapInstance.WaveEvents.Add((EventWave)evt.Parameter); break; case EventActionType.SETAREAENTRY: ZoneEvent even2 = (ZoneEvent)evt.Parameter; evt.MapInstance.OnAreaEntryEvents.Add(even2); break; case EventActionType.REMOVEMONSTERLOCKER: EventContainer evt2 = (EventContainer)evt.Parameter; if (evt.MapInstance.InstanceBag.MonsterLocker.Current > 0) { evt.MapInstance.InstanceBag.MonsterLocker.Current--; } if (evt.MapInstance.InstanceBag.MonsterLocker.Current == 0 && evt.MapInstance.InstanceBag.ButtonLocker.Current == 0) { evt.MapInstance.UnlockEvents.ForEach(s => RunEvent(s)); evt.MapInstance.UnlockEvents.RemoveAll(s => s != null); } break; case EventActionType.REMOVEBUTTONLOCKER: evt2 = (EventContainer)evt.Parameter; if (evt.MapInstance.InstanceBag.ButtonLocker.Current > 0) { evt.MapInstance.InstanceBag.ButtonLocker.Current--; } if (evt.MapInstance.InstanceBag.MonsterLocker.Current == 0 && evt.MapInstance.InstanceBag.ButtonLocker.Current == 0) { evt.MapInstance.UnlockEvents.ForEach(s => RunEvent(s)); evt.MapInstance.UnlockEvents.RemoveAll(s => s != null); } break; case EventActionType.EFFECT: short evt3 = (short)evt.Parameter; if (monster != null) { monster.LastEffect = DateTime.Now; evt.MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Monster, monster.MapMonsterId, evt3)); } break; case EventActionType.CONTROLEMONSTERINRANGE: if (monster != null) { Tuple <short, byte, List <EventContainer> > evnt = (Tuple <short, byte, List <EventContainer> >)evt.Parameter; List <MapMonster> MapMonsters = evt.MapInstance.GetListMonsterInRange(monster.MapX, monster.MapY, evnt.Item2); if (evnt.Item1 != 0) { MapMonsters.RemoveAll(s => s.MonsterVNum != evnt.Item1); } MapMonsters.ForEach(s => evnt.Item3.ForEach(e => RunEvent(e, monster: s))); } break; case EventActionType.ONTARGET: if (monster.MoveEvent?.InZone(monster.MapX, monster.MapY) == true) { monster.MoveEvent = null; monster.Path = new List <Node>(); ((List <EventContainer>)evt.Parameter).ForEach(s => RunEvent(s, monster: monster)); } break; case EventActionType.MOVE: ZoneEvent evt4 = (ZoneEvent)evt.Parameter; if (monster != null) { monster.MoveEvent = evt4; monster.Path = BestFirstSearch.FindPathJagged(new Node { X = monster.MapX, Y = monster.MapY }, new Node { X = evt4.X, Y = evt4.Y }, evt.MapInstance?.Map.JaggedGrid); } break; case EventActionType.CLOCK: evt.MapInstance.InstanceBag.Clock.TotalSecondsAmount = Convert.ToInt32(evt.Parameter); evt.MapInstance.InstanceBag.Clock.SecondsRemaining = Convert.ToInt32(evt.Parameter); break; case EventActionType.SETMONSTERLOCKERS: evt.MapInstance.InstanceBag.MonsterLocker.Current = Convert.ToByte(evt.Parameter); evt.MapInstance.InstanceBag.MonsterLocker.Initial = Convert.ToByte(evt.Parameter); break; case EventActionType.SETBUTTONLOCKERS: evt.MapInstance.InstanceBag.ButtonLocker.Current = Convert.ToByte(evt.Parameter); evt.MapInstance.InstanceBag.ButtonLocker.Initial = Convert.ToByte(evt.Parameter); break; case EventActionType.SCRIPTEND: switch (evt.MapInstance.MapInstanceType) { case MapInstanceType.TimeSpaceInstance: evt.MapInstance.InstanceBag.EndState = (byte)evt.Parameter; ClientSession client = evt.MapInstance.Sessions.FirstOrDefault(); if (client != null) { Guid MapInstanceId = ServerManager.GetBaseMapInstanceIdByMapId(client.Character.MapId); MapInstance map = ServerManager.GetMapInstance(MapInstanceId); ScriptedInstance si = map.ScriptedInstances.Find(s => s.PositionX == client.Character.MapX && s.PositionY == client.Character.MapY); byte penalty = 0; if (penalty > (client.Character.Level - si.LevelMinimum) * 2) { penalty = penalty > 100 ? (byte)100 : penalty; client.SendPacket(client.Character.GenerateSay(string.Format(Language.Instance.GetMessageFromKey("TS_PENALTY"), penalty), 10)); } int point = evt.MapInstance.InstanceBag.Point * (100 - penalty) / 100; string perfection = string.Empty; perfection += evt.MapInstance.InstanceBag.MonstersKilled >= si.MonsterAmount ? 1 : 0; perfection += evt.MapInstance.InstanceBag.NpcsKilled == 0 ? 1 : 0; perfection += evt.MapInstance.InstanceBag.RoomsVisited >= si.RoomAmount ? 1 : 0; evt.MapInstance.Broadcast($"score {evt.MapInstance.InstanceBag.EndState} {point} 27 47 18 {si.DrawItems.Count} {evt.MapInstance.InstanceBag.MonstersKilled} {si.NpcAmount - evt.MapInstance.InstanceBag.NpcsKilled} {evt.MapInstance.InstanceBag.RoomsVisited} {perfection} 1 1"); } break; case MapInstanceType.RaidInstance: evt.MapInstance.InstanceBag.EndState = (byte)evt.Parameter; client = evt.MapInstance.Sessions.FirstOrDefault(); if (client != null) { Group grp = client?.Character?.Group; if (grp == null) { return; } if (evt.MapInstance.InstanceBag.EndState == 1 && evt.MapInstance.Monsters.Any(s => s.IsBoss)) { foreach (ClientSession sess in grp.Characters.Where(s => s.CurrentMapInstance.Monsters.Any(e => e.IsBoss))) { foreach (Gift gift in grp?.Raid?.GiftItems) { const byte rare = 0; // TODO: add random rarity for some object sess.Character.GiftAdd(gift.VNum, gift.Amount, rare, 0, gift.Design, gift.IsRandomRare); } } foreach (MapMonster mon in evt.MapInstance.Monsters) { mon.CurrentHp = 0; evt.MapInstance.Broadcast(StaticPacketHelper.Out(UserType.Monster, mon.MapMonsterId)); evt.MapInstance.RemoveMonster(mon); } Logger.LogUserEvent("RAID_SUCCESS", grp.Characters.ElementAt(0).Character.Name, $"RaidId: {grp.GroupId}"); ServerManager.Instance.Broadcast(UserInterfaceHelper.GenerateMsg(string.Format(Language.Instance.GetMessageFromKey("RAID_SUCCEED"), grp?.Raid?.Label, grp.Characters.ElementAt(0).Character.Name), 0)); } Observable.Timer(TimeSpan.FromSeconds(evt.MapInstance.InstanceBag.EndState == 1 ? 30 : 0)).Subscribe(o => { ClientSession[] grpmembers = new ClientSession[40]; grp.Characters.CopyTo(grpmembers); foreach (ClientSession targetSession in grpmembers) { if (targetSession != null) { if (targetSession.Character.Hp <= 0) { targetSession.Character.Hp = 1; targetSession.Character.Mp = 1; } targetSession.SendPacket(Character.GenerateRaidBf(evt.MapInstance.InstanceBag.EndState)); targetSession.SendPacket(targetSession.Character.GenerateRaid(1, true)); targetSession.SendPacket(targetSession.Character.GenerateRaid(2, true)); grp.LeaveGroup(targetSession); } } ServerManager.Instance.GroupList.RemoveAll(s => s.GroupId == grp.GroupId); ServerManager.Instance.GroupsThreadSafe.Remove(grp.GroupId); evt.MapInstance.Dispose(); }); } break; case MapInstanceType.Act4Morcos: case MapInstanceType.Act4Hatus: case MapInstanceType.Act4Calvina: case MapInstanceType.Act4Berios: client = evt.MapInstance.Sessions.FirstOrDefault(); if (client != null) { Family fam = evt.MapInstance.Sessions.FirstOrDefault(s => s?.Character?.Family != null)?.Character.Family; if (fam != null) { fam.Act4Raid.Portals.RemoveAll(s => s.DestinationMapInstanceId.Equals(fam.Act4RaidBossMap.MapInstanceId)); short destX = 38; short destY = 179; short rewardVNum = 882; switch (evt.MapInstance.MapInstanceType) { //Morcos is default case MapInstanceType.Act4Hatus: destX = 18; destY = 10; rewardVNum = 185; break; case MapInstanceType.Act4Calvina: destX = 25; destY = 7; rewardVNum = 942; break; case MapInstanceType.Act4Berios: destX = 16; destY = 25; rewardVNum = 999; break; } int count = evt.MapInstance.Sessions.Count(s => s?.Character != null); foreach (ClientSession sess in evt.MapInstance.Sessions) { if (sess?.Character != null) { sess.Character.GiftAdd(rewardVNum, 1, forceRandom: true, minRare: 1, design: 255); sess.Character.GenerateFamilyXp(10000 / count); } } Logger.LogEvent("FAMILYRAID_SUCCESS", $"[fam.Name]FamilyRaidId: {evt.MapInstance.MapInstanceType.ToString()}"); //TODO: Famlog CommunicationServiceClient.Instance.SendMessageToCharacter(new SCSCharacterMessage { DestinationCharacterId = fam.FamilyId, SourceCharacterId = client.Character.CharacterId, SourceWorldId = ServerManager.Instance.WorldId, Message = UserInterfaceHelper.GenerateMsg(Language.Instance.GetMessageFromKey("FAMILYRAID_SUCCESS"), 0), Type = MessageType.Family }); //ServerManager.Instance.Broadcast(UserInterfaceHelper.Instance.GenerateMsg(string.Format(Language.Instance.GetMessageFromKey("FAMILYRAID_SUCCESS"), grp?.Raid?.Label, grp.Characters.ElementAt(0).Character.Name), 0)); Observable.Timer(TimeSpan.FromSeconds(30)).Subscribe(o => { foreach (ClientSession targetSession in evt.MapInstance.Sessions.ToArray()) { if (targetSession != null) { if (targetSession.Character.Hp <= 0) { targetSession.Character.Hp = 1; targetSession.Character.Mp = 1; } ServerManager.Instance.ChangeMapInstance(targetSession.Character.CharacterId, fam.Act4Raid.MapInstanceId, destX, destY); } } evt.MapInstance.Dispose(); }); } } break; case MapInstanceType.CaligorInstance: FactionType winningFaction = CaligorRaid.AngelDamage > CaligorRaid.DemonDamage ? FactionType.Angel : FactionType.Demon; foreach (ClientSession sess in evt.MapInstance.Sessions) { if (sess?.Character != null) { if (CaligorRaid.RemainingTime > 2400) { if (sess.Character.Faction == winningFaction) { sess.Character.GiftAdd(302, 1, 0, 0, 51); } else { sess.Character.GiftAdd(302, 1, 0, 0, 51); } } else { if (sess.Character.Faction == winningFaction) { sess.Character.GiftAdd(302, 1, 0, 0, 51); } else { sess.Character.GiftAdd(302, 1, 0, 0, 51); } } sess.Character.GiftAdd(1244, 50); sess.Character.GiftAdd(1134, 1); sess.Character.GenerateFamilyXp(500); } } evt.MapInstance.Broadcast(UserInterfaceHelper.GenerateCHDM(ServerManager.GetNpc(2305).MaxHP, CaligorRaid.AngelDamage, CaligorRaid.DemonDamage, CaligorRaid.RemainingTime)); break; } break; case EventActionType.MAPCLOCK: evt.MapInstance.Clock.TotalSecondsAmount = Convert.ToInt32(evt.Parameter); evt.MapInstance.Clock.SecondsRemaining = Convert.ToInt32(evt.Parameter); break; case EventActionType.STARTCLOCK: Tuple <List <EventContainer>, List <EventContainer> > eve = (Tuple <List <EventContainer>, List <EventContainer> >)evt.Parameter; evt.MapInstance.InstanceBag.Clock.StopEvents = eve.Item1; evt.MapInstance.InstanceBag.Clock.TimeoutEvents = eve.Item2; evt.MapInstance.InstanceBag.Clock.StartClock(); evt.MapInstance.Broadcast(evt.MapInstance.InstanceBag.Clock.GetClock()); break; case EventActionType.TELEPORT: Tuple <short, short, short, short> tp = (Tuple <short, short, short, short>)evt.Parameter; List <Character> characters = evt.MapInstance.GetCharactersInRange(tp.Item1, tp.Item2, 5).ToList(); characters.ForEach(s => { s.PositionX = tp.Item3; s.PositionY = tp.Item4; evt.MapInstance?.Broadcast(s.Session, s.GenerateTp(), ReceiverType.Group); }); break; case EventActionType.STOPCLOCK: evt.MapInstance.InstanceBag.Clock.StopClock(); evt.MapInstance.Broadcast(evt.MapInstance.InstanceBag.Clock.GetClock()); break; case EventActionType.STARTMAPCLOCK: eve = (Tuple <List <EventContainer>, List <EventContainer> >)evt.Parameter; evt.MapInstance.Clock.StopEvents = eve.Item1; evt.MapInstance.Clock.TimeoutEvents = eve.Item2; evt.MapInstance.Clock.StartClock(); evt.MapInstance.Broadcast(evt.MapInstance.Clock.GetClock()); break; case EventActionType.STOPMAPCLOCK: evt.MapInstance.Clock.StopClock(); evt.MapInstance.Broadcast(evt.MapInstance.Clock.GetClock()); break; case EventActionType.SPAWNPORTAL: evt.MapInstance.CreatePortal((Portal)evt.Parameter); break; case EventActionType.REFRESHMAPITEMS: evt.MapInstance.MapClear(); break; case EventActionType.NPCSEFFECTCHANGESTATE: evt.MapInstance.Npcs.ForEach(s => s.EffectActivated = (bool)evt.Parameter); break; case EventActionType.CHANGEPORTALTYPE: Tuple <int, PortalType> param = (Tuple <int, PortalType>)evt.Parameter; Portal portal = evt.MapInstance.Portals.Find(s => s.PortalId == param.Item1); if (portal != null) { portal.Type = (short)param.Item2; } break; case EventActionType.CHANGEDROPRATE: evt.MapInstance.DropRate = (int)evt.Parameter; break; case EventActionType.CHANGEXPRATE: evt.MapInstance.XpRate = (int)evt.Parameter; break; case EventActionType.DISPOSEMAP: evt.MapInstance.Dispose(); break; case EventActionType.SPAWNBUTTON: evt.MapInstance.SpawnButton((MapButton)evt.Parameter); break; case EventActionType.UNSPAWNMONSTERS: evt.MapInstance.DespawnMonster((int)evt.Parameter); break; case EventActionType.SPAWNMONSTER: evt.MapInstance.SummonMonster((MonsterToSummon)evt.Parameter); break; case EventActionType.SPAWNMONSTERS: evt.MapInstance.SummonMonsters((List <MonsterToSummon>)evt.Parameter); break; case EventActionType.REFRESHRAIDGOAL: ClientSession cl = evt.MapInstance.Sessions.FirstOrDefault(); if (cl?.Character != null) { ServerManager.Instance.Broadcast(cl, cl.Character?.Group?.GeneraterRaidmbf(cl), ReceiverType.Group); ServerManager.Instance.Broadcast(cl, UserInterfaceHelper.GenerateMsg(Language.Instance.GetMessageFromKey("NEW_MISSION"), 0), ReceiverType.Group); } break; case EventActionType.SPAWNNPC: evt.MapInstance.SummonNpc((NpcToSummon)evt.Parameter); break; case EventActionType.SPAWNNPCS: evt.MapInstance.SummonNpcs((List <NpcToSummon>)evt.Parameter); break; case EventActionType.DROPITEMS: evt.MapInstance.DropItems((List <Tuple <short, int, short, short> >)evt.Parameter); break; case EventActionType.THROWITEMS: Tuple <int, short, byte, int, int> parameters = (Tuple <int, short, byte, int, int>)evt.Parameter; if (monster != null) { parameters = new Tuple <int, short, byte, int, int>(monster.MapMonsterId, parameters.Item2, parameters.Item3, parameters.Item4, parameters.Item5); } evt.MapInstance.ThrowItems(parameters); break; case EventActionType.SPAWNONLASTENTRY: Character lastincharacter = evt.MapInstance.Sessions.OrderByDescending(s => s.RegisterTime).FirstOrDefault()?.Character; List <MonsterToSummon> summonParameters = new List <MonsterToSummon>(); MapCell hornSpawn = new MapCell { X = lastincharacter?.PositionX ?? 154, Y = lastincharacter?.PositionY ?? 140 }; long hornTarget = lastincharacter?.CharacterId ?? -1; summonParameters.Add(new MonsterToSummon(Convert.ToInt16(evt.Parameter), hornSpawn, hornTarget, true)); evt.MapInstance.SummonMonsters(summonParameters); break; #endregion } } } }
/// <summary> /// Run Event /// </summary> /// <param name="evt">Event Container</param> /// <param name="session">Character Session that run the event</param> /// <param name="monster">Monster that run the event</param> public void RunEvent(EventContainer evt, ClientSession session = null, MapMonster monster = null) { if (session != null) { evt.MapInstance = session.CurrentMapInstance; switch (evt.EventActionType) { #region EventForUser case EventActionType.NPCDIALOG: session.SendPacket(session.Character.GenerateNpcDialog((int)evt.Parameter)); break; case EventActionType.SENDPACKET: session.SendPacket((string)evt.Parameter); break; #endregion } } if (evt.MapInstance == null) { return; } switch (evt.EventActionType) { #region EventForUser case EventActionType.NPCDIALOG: case EventActionType.SENDPACKET: if (session == null) { evt.MapInstance.Sessions.ToList().ForEach(e => { RunEvent(evt, e); }); } break; #endregion #region MapInstanceEvent case EventActionType.REGISTEREVENT: Tuple <string, ConcurrentBag <EventContainer> > even = (Tuple <string, ConcurrentBag <EventContainer> >)evt.Parameter; switch (even.Item1) { case "OnCharacterDiscoveringMap": even.Item2.ToList().ForEach(s => evt.MapInstance.OnCharacterDiscoveringMapEvents.Add(new Tuple <EventContainer, List <long> >(s, new List <long>()))); break; case "OnMoveOnMap": evt.MapInstance.OnMoveOnMapEvents.AddRange(even.Item2); break; case "OnMapClean": evt.MapInstance.OnMapClean.AddRange(even.Item2); break; case "OnLockerOpen": even.Item2.ToList().ForEach(s => evt.MapInstance.InstanceBag.UnlockEvents.Add(s)); break; } break; case EventActionType.REGISTERWAVE: evt.MapInstance.WaveEvents.Add((EventWave)evt.Parameter); break; case EventActionType.SETAREAENTRY: ZoneEvent even2 = (ZoneEvent)evt.Parameter; evt.MapInstance.OnAreaEntryEvents.Add(even2); break; case EventActionType.REMOVEMONSTERLOCKER: if (evt.MapInstance.InstanceBag.MonsterLocker.Current > 0) { evt.MapInstance.InstanceBag.MonsterLocker.Current--; } if (evt.MapInstance.InstanceBag.MonsterLocker.Current == 0 && evt.MapInstance.InstanceBag.ButtonLocker.Current == 0) { evt.MapInstance.InstanceBag.UnlockEvents.ToList().ForEach(s => RunEvent(s)); evt.MapInstance.InstanceBag.UnlockEvents.Clear(); } break; case EventActionType.REMOVEBUTTONLOCKER: if (evt.MapInstance.InstanceBag.ButtonLocker.Current > 0) { evt.MapInstance.InstanceBag.ButtonLocker.Current--; } if (evt.MapInstance.InstanceBag.MonsterLocker.Current == 0 && evt.MapInstance.InstanceBag.ButtonLocker.Current == 0) { evt.MapInstance.InstanceBag.UnlockEvents.ToList().ForEach(s => RunEvent(s)); evt.MapInstance.InstanceBag.UnlockEvents.Clear(); } break; case EventActionType.EFFECT: short evt3 = (short)evt.Parameter; if (monster != null && (DateTime.Now - monster.LastEffect).TotalSeconds >= 5) { evt.MapInstance.Broadcast(monster.GenerateEff(evt3)); monster.ShowEffect(); } break; case EventActionType.CONTROLEMONSTERINRANGE: if (monster != null) { Tuple <short, byte, ConcurrentBag <EventContainer> > evnt = (Tuple <short, byte, ConcurrentBag <EventContainer> >)evt.Parameter; List <MapMonster> mapMonsters = evt.MapInstance.GetListMonsterInRange(monster.MapX, monster.MapY, evnt.Item2); if (evnt.Item1 != 0) { mapMonsters.RemoveAll(s => s.MonsterVNum != evnt.Item1); } mapMonsters.ForEach(s => evnt.Item3.ToList().ForEach(e => RunEvent(e, monster: s))); } break; case EventActionType.ONTARGET: if (monster?.MoveEvent != null && monster.MoveEvent.InZone(monster.MapX, monster.MapY)) { ((ConcurrentBag <EventContainer>)evt.Parameter).ToList().ForEach(s => RunEvent(s, monster: monster)); } break; case EventActionType.MOVE: ZoneEvent evt4 = (ZoneEvent)evt.Parameter; if (monster != null) { monster.FirstX = evt4.X; monster.FirstY = evt4.Y; monster.MoveEvent = evt4; monster.Path = BestFirstSearch.FindPath(new Node { X = monster.MapX, Y = monster.MapY }, new Node { X = evt4.X, Y = evt4.Y }, evt.MapInstance?.Map.Grid); } break; case EventActionType.CLOCK: evt.MapInstance.InstanceBag.Clock.BasesSecondRemaining = Convert.ToInt32(evt.Parameter); evt.MapInstance.InstanceBag.Clock.DeciSecondRemaining = Convert.ToInt32(evt.Parameter); break; case EventActionType.SETMONSTERLOCKERS: evt.MapInstance.InstanceBag.MonsterLocker.Current = Convert.ToByte(evt.Parameter); evt.MapInstance.InstanceBag.MonsterLocker.Initial = Convert.ToByte(evt.Parameter); break; case EventActionType.SETBUTTONLOCKERS: evt.MapInstance.InstanceBag.ButtonLocker.Current = Convert.ToByte(evt.Parameter); evt.MapInstance.InstanceBag.ButtonLocker.Initial = Convert.ToByte(evt.Parameter); break; case EventActionType.SCRIPTEND: switch (evt.MapInstance.MapInstanceType) { case MapInstanceType.TimeSpaceInstance: evt.MapInstance.InstanceBag.EndState = (byte)evt.Parameter; ClientSession client = evt.MapInstance.Sessions.FirstOrDefault(); if (client != null) { Guid mapInstanceId = ServerManager.Instance.GetBaseMapInstanceIdByMapId(client.Character.MapId); MapInstance map = ServerManager.Instance.GetMapInstance(mapInstanceId); ScriptedInstance si = map.ScriptedInstances.FirstOrDefault(s => s.PositionX == client.Character.MapX && s.PositionY == client.Character.MapY); byte penalty = 0; if (si != null && penalty > (client.Character.Level - si.LevelMinimum) * 2) { penalty = penalty > 100 ? (byte)100 : penalty; client.SendPacket(client.Character.GenerateSay(string.Format(Language.Instance.GetMessageFromKey("TS_PENALTY"), penalty), 10)); } int point = evt.MapInstance.InstanceBag.Point * (100 - penalty) / 100; string perfection = string.Empty; perfection += si != null && evt.MapInstance.InstanceBag.MonstersKilled >= si.MonsterAmount ? 1 : 0; perfection += evt.MapInstance.InstanceBag.NpcsKilled == 0 ? 1 : 0; perfection += si != null && evt.MapInstance.InstanceBag.RoomsVisited >= si.RoomAmount ? 1 : 0; if (si != null) { evt.MapInstance.Broadcast( $"score {evt.MapInstance.InstanceBag.EndState} {point} 27 47 18 {si.DrawItems.Count()} {evt.MapInstance.InstanceBag.MonstersKilled} {si.NpcAmount - evt.MapInstance.InstanceBag.NpcsKilled} {evt.MapInstance.InstanceBag.RoomsVisited} {perfection} 1 1"); } } break; case MapInstanceType.RaidInstance: evt.MapInstance.InstanceBag.EndState = (byte)evt.Parameter; client = evt.MapInstance.Sessions.FirstOrDefault(); List <ClientSession> toBan = new List <ClientSession>(); if (client != null) { Group grp = client.Character?.Group; if (grp == null) { return; } if (evt.MapInstance.InstanceBag.EndState == 1 && evt.MapInstance.Monsters.Any(s => s.IsBoss && !s.IsAlive)) { foreach (ClientSession sess in grp.Characters.Replace(s => s.CurrentMapInstance.Monsters.Any(e => e.IsBoss))) { // TODO REMOTE THAT FOR PUBLIC RELEASE if (grp.Characters.Count(s => s.IpAddress.Equals(sess.IpAddress)) > 2) { toBan.Add(sess); continue; } if (grp.Raid?.GiftItems == null) { continue; } if (grp.Raid.Reputation > 0) { sess.Character.GetReput(grp.Raid.Reputation); } if (sess.Character.Dignity < 0) { sess.Character.Dignity += 100; } else { sess.Character.Dignity = 100; } if (sess.Character.Level > grp.Raid.LevelMaximum) { // RAID CERTIFICATE sess.Character.GiftAdd(2320, 1); } else { foreach (Gift gift in grp.Raid?.GiftItems) { sbyte rare = 0; if (gift.IsRandomRare) { rare = (sbyte)ServerManager.Instance.RandomNumber(-2, 7); } //TODO add random rarity for some object sess.Character.GiftAdd(gift.VNum, gift.Amount, gift.Design, rare: rare); } } } // Remove monster when raid is over foreach (MapMonster e in evt.MapInstance.Monsters.Where(s => !s.IsBoss)) { evt.MapInstance.DespawnMonster(e.MonsterVNum); } evt.MapInstance.WaveEvents.Clear(); ServerManager.Instance.Broadcast(UserInterfaceHelper.Instance.GenerateMsg( string.Format(Language.Instance.GetMessageFromKey("RAID_SUCCEED"), grp.Raid?.Label, grp.Characters.ElementAt(0).Character.Name), 0)); Observable.Timer(TimeSpan.FromSeconds(evt.MapInstance.InstanceBag.EndState == 1 ? 30 : 0)).Subscribe(obj => { ClientSession[] grpmembers = new ClientSession[40]; grp.Characters.ToList().CopyTo(grpmembers); List <MapInstance> mapinstances = new List <MapInstance>(); foreach (ClientSession targetSession in grpmembers) { if (targetSession == null) { continue; } if (targetSession.Character.Hp <= 0) { targetSession.Character.Hp = 1; targetSession.Character.Mp = 1; } targetSession.SendPacket(targetSession.Character.GenerateRaidBf(evt.MapInstance.InstanceBag.EndState)); targetSession.SendPacket(targetSession.Character.GenerateRaid(1, true)); targetSession.SendPacket(targetSession.Character.GenerateRaid(2, true)); if (!mapinstances.Any(s => s.MapInstanceId == targetSession?.CurrentMapInstance.MapInstanceId && s.MapInstanceType == MapInstanceType.RaidInstance)) { mapinstances.Add(targetSession.CurrentMapInstance); } grp.LeaveGroup(targetSession); } ServerManager.Instance.GroupList.RemoveAll(s => s.GroupId == grp.GroupId); ServerManager.Instance.GroupsThreadSafe.TryRemove(grp.GroupId, out Group _); mapinstances.ForEach(s => s.Dispose()); }); } } break; } break; case EventActionType.MAPCLOCK: evt.MapInstance.Clock.BasesSecondRemaining = Convert.ToInt32(evt.Parameter); evt.MapInstance.Clock.DeciSecondRemaining = Convert.ToInt32(evt.Parameter); break; case EventActionType.STARTCLOCK: Tuple <List <EventContainer>, List <EventContainer> > eve = (Tuple <List <EventContainer>, List <EventContainer> >)evt.Parameter; if (eve != null) { evt.MapInstance.InstanceBag.Clock.StopEvents = eve.Item2; evt.MapInstance.InstanceBag.Clock.TimeoutEvents = eve.Item1; evt.MapInstance.InstanceBag.Clock.StartClock(); evt.MapInstance.Broadcast(evt.MapInstance.InstanceBag.Clock.GetClock()); } break; case EventActionType.TELEPORT: Tuple <short, short, short, short> tp = (Tuple <short, short, short, short>)evt.Parameter; List <Character> characters = evt.MapInstance.GetCharactersInRange(tp.Item1, tp.Item2, 5).ToList(); characters.ForEach(s => { s.PositionX = tp.Item3; s.PositionY = tp.Item4; evt.MapInstance?.Broadcast(s.Session, s.GenerateTp(), ReceiverType.Group); }); break; case EventActionType.STOPCLOCK: evt.MapInstance.InstanceBag.Clock.StopClock(); evt.MapInstance.Broadcast(evt.MapInstance.InstanceBag.Clock.GetClock()); break; case EventActionType.STARTMAPCLOCK: eve = (Tuple <List <EventContainer>, List <EventContainer> >)evt.Parameter; if (eve != null) { evt.MapInstance.Clock.StopEvents = eve.Item2; evt.MapInstance.Clock.TimeoutEvents = eve.Item1; evt.MapInstance.Clock.StartClock(); evt.MapInstance.Broadcast(evt.MapInstance.Clock.GetClock()); } break; case EventActionType.STOPMAPCLOCK: evt.MapInstance.Clock.StopClock(); evt.MapInstance.Broadcast(evt.MapInstance.Clock.GetClock()); break; case EventActionType.SPAWNPORTAL: evt.MapInstance.CreatePortal((Portal)evt.Parameter); break; case EventActionType.REFRESHMAPITEMS: evt.MapInstance.MapClear(); break; case EventActionType.NPCSEFFECTCHANGESTATE: evt.MapInstance.Npcs.ForEach(s => s.EffectActivated = (bool)evt.Parameter); break; case EventActionType.CHANGEPORTALTYPE: Tuple <int, PortalType> param = (Tuple <int, PortalType>)evt.Parameter; Portal portal = evt.MapInstance.Portals.FirstOrDefault(s => s.PortalId == param.Item1); if (portal != null) { portal.Type = (short)param.Item2; } break; case EventActionType.CHANGEDROPRATE: evt.MapInstance.DropRate = (int)evt.Parameter; break; case EventActionType.CHANGEXPRATE: evt.MapInstance.XpRate = (int)evt.Parameter; break; case EventActionType.DISPOSEMAP: evt.MapInstance.Dispose(); break; case EventActionType.SPAWNBUTTON: evt.MapInstance.SpawnButton((MapButton)evt.Parameter); break; case EventActionType.UNSPAWNMONSTERS: evt.MapInstance.DespawnMonster((int)evt.Parameter); break; case EventActionType.SPAWNMONSTERS: evt.MapInstance.SummonMonsters(((ConcurrentBag <MonsterToSummon>)evt.Parameter).ToList()); break; case EventActionType.REFRESHRAIDGOAL: ClientSession cl = evt.MapInstance.Sessions.FirstOrDefault(); if (cl?.Character != null) { ServerManager.Instance.Broadcast(cl, cl.Character?.Group?.GeneraterRaidmbf(), ReceiverType.Group); ServerManager.Instance.Broadcast(cl, UserInterfaceHelper.Instance.GenerateMsg(Language.Instance.GetMessageFromKey("NEW_MISSION"), 0), ReceiverType.Group); } break; case EventActionType.SPAWNNPCS: evt.MapInstance.SummonNpcs((List <NpcToSummon>)evt.Parameter); break; case EventActionType.DROPITEMS: evt.MapInstance.DropItems((List <Tuple <short, int, short, short> >)evt.Parameter); break; case EventActionType.THROWITEMS: Tuple <int, short, byte, int, int> parameters = (Tuple <int, short, byte, int, int>)evt.Parameter; if (monster != null) { parameters = new Tuple <int, short, byte, int, int>(monster.MapMonsterId, parameters.Item2, parameters.Item3, parameters.Item4, parameters.Item5); } evt.MapInstance.ThrowItems(parameters); break; case EventActionType.SPAWNONLASTENTRY: Character lastincharacter = evt.MapInstance.Sessions.OrderByDescending(s => s.RegisterTime).FirstOrDefault()?.Character; List <MonsterToSummon> summonParameters = new List <MonsterToSummon>(); MapCell hornSpawn = new MapCell { X = lastincharacter?.PositionX ?? 154, Y = lastincharacter?.PositionY ?? 140 }; long hornTarget = lastincharacter?.CharacterId ?? -1; summonParameters.Add(new MonsterToSummon(Convert.ToInt16(evt.Parameter), hornSpawn, hornTarget, true)); evt.MapInstance.SummonMonsters(summonParameters); break; #endregion } }
private void npcLife() { // Respawn if (CurrentHp <= 0 && ShouldRespawn != null && !ShouldRespawn.Value) { MapInstance.RemoveNpc(this); MapInstance.Broadcast(GenerateOut()); } if (!IsAlive && ShouldRespawn != null && ShouldRespawn.Value) { double timeDeath = (DateTime.Now - Death).TotalSeconds; if (timeDeath >= Npc.RespawnTime / 10d) { Respawn(); } } if (LastProtectedEffect.AddMilliseconds(6000) <= DateTime.Now) { LastProtectedEffect = DateTime.Now; if (IsMate || IsProtected) { MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, 825), MapX, MapY); } } double time = (DateTime.Now - LastEffect).TotalMilliseconds; if (EffectDelay > 0) { if (time > EffectDelay) { if (Effect > 0 && EffectActivated) { MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, Effect), MapX, MapY); } LastEffect = DateTime.Now; } } time = (DateTime.Now - LastMove).TotalMilliseconds; if (Target == -1 && IsMoving && Npc.Speed > 0 && time > _movetime && !HasBuff(CardType.Move, (byte)AdditionalTypes.Move.MovementImpossible)) { _movetime = ServerManager.RandomNumber(500, 3000); int maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count; if (maxindex < 1) { maxindex = 1; } if (Path.Count == 0 || Path.Count >= maxindex && maxindex > 0 && Path[maxindex - 1] == null) { short xoffset = (short)ServerManager.RandomNumber(-1, 1); short yoffset = (short)ServerManager.RandomNumber(-1, 1); MapCell moveToPosition = new MapCell { X = FirstX, Y = FirstY }; if (RunToX != 0 || RunToY != 0) { moveToPosition = new MapCell { X = RunToX, Y = RunToY }; _movetime = ServerManager.RandomNumber(300, 1200); } Path = BestFirstSearch.FindPathJagged(new GridPos { X = MapX, Y = MapY }, new GridPos { X = (short)ServerManager.RandomNumber(moveToPosition.X - 3, moveToPosition.X + 3), Y = (short)ServerManager.RandomNumber(moveToPosition.Y - 3, moveToPosition.Y + 3) }, MapInstance.Map.JaggedGrid); maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count; } if (DateTime.Now > LastMove && Npc.Speed > 0 && Path.Count > 0) { byte speedIndex = (byte)(Npc.Speed / 2.5 < 1 ? 1 : Npc.Speed / 2.5); maxindex = Path.Count > speedIndex ? speedIndex : Path.Count; short mapX = (short)ServerManager.RandomNumber(Path[maxindex - 1].X - 1, Path[maxindex - 1].X + 1); short mapY = (short)_random.Next(Path[maxindex - 1].Y - 1, Path[maxindex - 1].Y + 1); //short mapX = Path[maxindex - 1].X; //short mapY = Path[maxindex - 1].Y; double waitingtime = Map.GetDistance(new MapCell { X = mapX, Y = mapY }, new MapCell { X = MapX, Y = MapY }) / (double)Npc.Speed; MapInstance.Broadcast(new BroadcastPacket(null, PacketFactory.Serialize(StaticPacketHelper.Move(UserType.Npc, MapNpcId, mapX, mapY, Npc.Speed)), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY)); LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime); Observable.Timer(TimeSpan.FromMilliseconds((int)((waitingtime > 1 ? 1 : waitingtime) * 1000))).Subscribe(x => { MapX = mapX; MapY = mapY; }); Path.RemoveRange(0, maxindex); } } if (Target == -1) { if (IsHostile && Shop == null) { MapMonster monster = MapInstance.GetMonsterInRangeList(MapX, MapY, (byte)(Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange)).Where(s => BattleEntity.CanAttackEntity(s.BattleEntity)).FirstOrDefault(); ClientSession session = MapInstance.Sessions.FirstOrDefault(s => BattleEntity.CanAttackEntity(s.Character.BattleEntity) && MapInstance == s.Character.MapInstance && Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = s.Character.PositionX, Y = s.Character.PositionY }) < Npc.NoticeRange); if (monster != null) { Target = monster.MapMonsterId; } if (session?.Character != null) { Target = session.Character.CharacterId; } } } else if (Target != -1) { MapMonster monster = MapInstance.Monsters.Find(s => s.MapMonsterId == Target); if (monster == null || monster.CurrentHp < 1) { Target = -1; return; } NpcMonsterSkill npcMonsterSkill = null; if (ServerManager.RandomNumber(0, 10) > 8) { npcMonsterSkill = Skills.Where(s => (DateTime.Now - s.LastSkillUse).TotalMilliseconds >= 100 * s.Skill.Cooldown).OrderBy(rnd => _random.Next()).FirstOrDefault(); } int hitmode = 0; bool onyxWings = false; int damage = DamageHelper.Instance.CalculateDamage(new BattleEntity(this), new BattleEntity(monster), npcMonsterSkill?.Skill, ref hitmode, ref onyxWings); if (monster.Monster.BCards.Find(s => s.Type == (byte)CardType.LightAndShadow && s.SubType == (byte)AdditionalTypes.LightAndShadow.InflictDamageToMP) is BCard card) { int reduce = damage / 100 * card.FirstData; if (monster.CurrentMp < reduce) { reduce = (int)monster.CurrentMp; monster.CurrentMp = 0; } else { monster.DecreaseMp(reduce); } damage -= reduce; } int distance = Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = monster.MapX, Y = monster.MapY }); if (monster.CurrentHp > 0 && ((npcMonsterSkill != null && distance < npcMonsterSkill.Skill.Range) || distance <= Npc.BasicRange) && !HasBuff(CardType.SpecialAttack, (byte)AdditionalTypes.SpecialAttack.NoAttack)) { if (((DateTime.Now - LastSkill).TotalMilliseconds >= 1000 + (Npc.BasicCooldown * 200) /* && Skills.Count == 0*/) || npcMonsterSkill != null) { if (npcMonsterSkill != null) { npcMonsterSkill.LastSkillUse = DateTime.Now; MapInstance.Broadcast(StaticPacketHelper.CastOnTarget(UserType.Npc, MapNpcId, UserType.Monster, Target, npcMonsterSkill.Skill.CastAnimation, npcMonsterSkill.Skill.CastEffect, npcMonsterSkill.Skill.SkillVNum)); } if (npcMonsterSkill != null && npcMonsterSkill.Skill.CastEffect != 0) { MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, Effect)); } monster.BattleEntity.GetDamage(damage, BattleEntity); lock (monster.DamageList) { if (!monster.DamageList.Any(s => s.Key.MapEntityId == MapNpcId)) { monster.AddToAggroList(BattleEntity); } } MapInstance.Broadcast(npcMonsterSkill != null ? StaticPacketHelper.SkillUsed(UserType.Npc, MapNpcId, 3, Target, npcMonsterSkill.SkillVNum, npcMonsterSkill.Skill.Cooldown, npcMonsterSkill.Skill.AttackAnimation, npcMonsterSkill.Skill.Effect, 0, 0, monster.CurrentHp > 0, (int)((float)monster.CurrentHp / (float)monster.MaxHp * 100), damage, hitmode, 0) : StaticPacketHelper.SkillUsed(UserType.Npc, MapNpcId, 3, Target, 0, Npc.BasicCooldown, 11, Npc.BasicSkill, 0, 0, monster.CurrentHp > 0, (int)((float)monster.CurrentHp / (float)monster.MaxHp * 100), damage, hitmode, 0)); LastSkill = DateTime.Now; if (npcMonsterSkill?.Skill.TargetType == 1 && npcMonsterSkill?.Skill.HitType == 2) { IEnumerable <ClientSession> clientSessions = MapInstance.Sessions?.Where(s => s.Character.IsInRange(MapX, MapY, npcMonsterSkill.Skill.TargetRange)); IEnumerable <Mate> mates = MapInstance.GetListMateInRange(MapX, MapY, npcMonsterSkill.Skill.TargetRange); foreach (BCard skillBcard in npcMonsterSkill.Skill.BCards) { if (skillBcard.Type == 25 && skillBcard.SubType == 1 && new Buff((short)skillBcard.SecondData, Npc.Level)?.Card?.BuffType == BuffType.Good) { if (clientSessions != null) { foreach (ClientSession clientSession in clientSessions) { if (clientSession.Character != null) { if (!BattleEntity.CanAttackEntity(clientSession.Character.BattleEntity)) { skillBcard.ApplyBCards(clientSession.Character.BattleEntity, BattleEntity); } } } } if (mates != null) { foreach (Mate mate in mates) { if (!BattleEntity.CanAttackEntity(mate.BattleEntity)) { skillBcard.ApplyBCards(mate.BattleEntity, BattleEntity); } } } } } } if (monster.CurrentHp < 1 && monster.SetDeathStatement()) { monster.RunDeathEvent(); RemoveTarget(); } } } else { int maxdistance = Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange; if (IsMoving && !HasBuff(CardType.Move, (byte)AdditionalTypes.Move.MovementImpossible)) { const short maxDistance = 5; int maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count; if (maxindex < 1) { maxindex = 1; } if ((Path.Count == 0 && distance >= 1 && distance < maxDistance) || (Path.Count >= maxindex && maxindex > 0 && Path[maxindex - 1] == null)) { short xoffset = (short)ServerManager.RandomNumber(-1, 1); short yoffset = (short)ServerManager.RandomNumber(-1, 1); //go to monster Path = BestFirstSearch.FindPathJagged(new GridPos { X = MapX, Y = MapY }, new GridPos { X = (short)(monster.MapX + xoffset), Y = (short)(monster.MapY + yoffset) }, MapInstance.Map.JaggedGrid); maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count; } if (DateTime.Now > LastMove && Npc.Speed > 0 && Path.Count > 0) { byte speedIndex = (byte)(Npc.Speed / 2.5 < 1 ? 1 : Npc.Speed / 2.5); maxindex = Path.Count > speedIndex ? speedIndex : Path.Count; //short mapX = (short)ServerManager.RandomNumber(Path[maxindex - 1].X - 1, Path[maxindex - 1].X + 1); //short mapY = (short)_random.Next(Path[maxindex - 1].Y - 1, Path[maxindex - 1].Y + 1); short mapX = Path[maxindex - 1].X; short mapY = Path[maxindex - 1].Y; double waitingtime = Map.GetDistance(new MapCell { X = mapX, Y = mapY }, new MapCell { X = MapX, Y = MapY }) / (double)Npc.Speed; MapInstance.Broadcast(new BroadcastPacket(null, PacketFactory.Serialize(StaticPacketHelper.Move(UserType.Npc, MapNpcId, mapX, mapY, Npc.Speed)), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY)); LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime); Observable.Timer(TimeSpan.FromMilliseconds((int)((waitingtime > 1 ? 1 : waitingtime) * 1000))).Subscribe(x => { MapX = mapX; MapY = mapY; }); Path.RemoveRange(0, maxindex); } if (Target != -1 && (MapId != monster.MapId || distance > maxDistance)) { RemoveTarget(); } } } } }
private void NpcLife() { double time = (DateTime.Now - LastEffect).TotalMilliseconds; if (time > EffectDelay) { if (IsMate || IsProtected) { MapInstance.Broadcast(GenerateEff(825), MapX, MapY); } if (Effect > 0 && EffectActivated) { MapInstance.Broadcast(GenerateEff(Effect), MapX, MapY); } LastEffect = DateTime.Now; } time = (DateTime.Now - LastMove).TotalMilliseconds; if (IsMoving && Npc.Speed > 0 && time > _movetime) { _movetime = ServerManager.Instance.RandomNumber(500, 3000); byte point = (byte)ServerManager.Instance.RandomNumber(2, 4); byte fpoint = (byte)ServerManager.Instance.RandomNumber(0, 2); byte xpoint = (byte)ServerManager.Instance.RandomNumber(fpoint, point); byte ypoint = (byte)(point - xpoint); short mapX = FirstX; short mapY = FirstY; if (MapInstance.Map.GetFreePosition(ref mapX, ref mapY, xpoint, ypoint)) { double value = (xpoint + ypoint) / (double)(2 * Npc.Speed); Observable.Timer(TimeSpan.FromMilliseconds(1000 * value)) .Subscribe( x => { MapX = mapX; MapY = mapY; }); LastMove = DateTime.Now.AddSeconds(value); MapInstance.Broadcast(new BroadcastPacket(null, GenerateMv2(), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY)); } } if (Target == -1) { if (IsHostile && Shop == null) { MapMonster monster = MapInstance.Monsters.FirstOrDefault(s => MapInstance == s.MapInstance && Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = s.MapX, Y = s.MapY }) < (Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange)); ClientSession session = MapInstance.Sessions.FirstOrDefault(s => MapInstance == s.Character.MapInstance && Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = s.Character.PositionX, Y = s.Character.PositionY }) < Npc.NoticeRange); if (monster != null && session != null) { Target = monster.MapMonsterId; } } } else if (Target != -1) { MapMonster monster = MapInstance.Monsters.FirstOrDefault(s => s.MapMonsterId == Target); if (monster == null || monster.CurrentHp < 1) { Target = -1; return; } NpcMonsterSkill npcMonsterSkill = null; if (ServerManager.Instance.RandomNumber(0, 10) > 8) { npcMonsterSkill = Npc.Skills.Where(s => (DateTime.Now - s.LastSkillUse).TotalMilliseconds >= 100 * s.Skill.Cooldown).OrderBy(rnd => _random.Next()).FirstOrDefault(); } const short damage = 100; int distance = Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = monster.MapX, Y = monster.MapY }); if (monster.CurrentHp > 0 && (npcMonsterSkill != null && distance < npcMonsterSkill.Skill.Range || distance <= Npc.BasicRange)) { if ((DateTime.Now - LastEffect).TotalMilliseconds >= 1000 + Npc.BasicCooldown * 200 && !Npc.Skills.Any() || npcMonsterSkill != null) { if (npcMonsterSkill != null) { npcMonsterSkill.LastSkillUse = DateTime.Now; MapInstance.Broadcast($"ct 2 {MapNpcId} 3 {Target} {npcMonsterSkill.Skill.CastAnimation} {npcMonsterSkill.Skill.CastEffect} {npcMonsterSkill.Skill.SkillVNum}"); } if (npcMonsterSkill != null && npcMonsterSkill.Skill.CastEffect != 0) { MapInstance.Broadcast(GenerateEff(Effect)); } monster.CurrentHp -= damage; MapInstance.Broadcast(npcMonsterSkill != null ? $"su 2 {MapNpcId} 3 {Target} {npcMonsterSkill.SkillVNum} {npcMonsterSkill.Skill.Cooldown} {npcMonsterSkill.Skill.AttackAnimation} {npcMonsterSkill.Skill.Effect} 0 0 {(monster.CurrentHp > 0 ? 1 : 0)} {(int)((double)monster.CurrentHp / monster.Monster.MaxHP * 100)} {damage} 0 0" : $"su 2 {MapNpcId} 3 {Target} 0 {Npc.BasicCooldown} 11 {Npc.BasicSkill} 0 0 {(monster.CurrentHp > 0 ? 1 : 0)} {(int)((double)monster.CurrentHp / monster.Monster.MaxHP * 100)} {damage} 0 0"); LastEffect = DateTime.Now; if (monster.CurrentHp < 1) { RemoveTarget(); monster.IsAlive = false; monster.LastMove = DateTime.Now; monster.CurrentHp = 0; monster.CurrentMp = 0; monster.Death = DateTime.Now; Target = -1; } } } else { int maxdistance = Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange; if (IsMoving) { const short maxDistance = 5; if (!Path.Any() && distance > 1 && distance < maxDistance) { short xoffset = (short)ServerManager.Instance.RandomNumber(-1, 1); short yoffset = (short)ServerManager.Instance.RandomNumber(-1, 1); //go to monster Path = BestFirstSearch.FindPath(new GridPos { X = MapX, Y = MapY }, new GridPos { X = (short)(monster.MapX + xoffset), Y = (short)(monster.MapY + yoffset) }, MapInstance.Map.Grid); } if (DateTime.Now > LastMove && Npc.Speed > 0 && Path.Any()) { int maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count; maxindex = maxindex < 1 ? 1 : maxindex; short mapX = (short)Path.ElementAt(maxindex - 1).X; short mapY = (short)Path.ElementAt(maxindex - 1).Y; double waitingtime = Map.GetDistance(new MapCell { X = mapX, Y = mapY }, new MapCell { X = MapX, Y = MapY }) / (double)Npc.Speed; MapInstance.Broadcast(new BroadcastPacket(null, $"mv 2 {MapNpcId} {mapX} {mapY} {Npc.Speed}", ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY)); LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime); Observable.Timer(TimeSpan.FromMilliseconds((int)((waitingtime > 1 ? 1 : waitingtime) * 1000))) .Subscribe( x => { MapX = mapX; MapY = mapY; }); Path.RemoveRange(0, maxindex > Path.Count ? Path.Count : maxindex); } if (Target != -1 && (MapId != monster.MapId || distance > maxDistance)) { RemoveTarget(); } } } } }
private void npcLife() { double time = (DateTime.Now - LastEffect).TotalMilliseconds; if (time > EffectDelay) { if (IsMate || IsProtected) { MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, 825), MapX, MapY); } if (Effect > 0 && EffectActivated) { MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, Effect), MapX, MapY); } LastEffect = DateTime.Now; } time = (DateTime.Now - LastMove).TotalMilliseconds; if (IsMoving && Npc.Speed > 0 && time > _movetime) { _movetime = ServerManager.RandomNumber(500, 3000); byte point = (byte)ServerManager.RandomNumber(2, 4); byte fpoint = (byte)ServerManager.RandomNumber(0, 2); byte xpoint = (byte)ServerManager.RandomNumber(fpoint, point); byte ypoint = (byte)(point - xpoint); short mapX = FirstX; short mapY = FirstY; if (MapInstance.Map.GetFreePosition(ref mapX, ref mapY, xpoint, ypoint)) { double value = (xpoint + ypoint) / (double)(2 * Npc.Speed); Observable.Timer(TimeSpan.FromMilliseconds(1000 * value)).Subscribe(x => { MapX = mapX; MapY = mapY; }); LastMove = DateTime.Now.AddSeconds(value); MapInstance.Broadcast(new BroadcastPacket(null, PacketFactory.Serialize(StaticPacketHelper.Move(UserType.Npc, MapNpcId, MapX, MapY, Npc.Speed)), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY)); } } if (Target == -1) { if (IsHostile && Shop == null) { MapMonster monster = MapInstance.Monsters.Find(s => MapInstance == s.MapInstance && Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = s.MapX, Y = s.MapY }) < (Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange)); ClientSession session = MapInstance.Sessions.FirstOrDefault(s => MapInstance == s.Character.MapInstance && Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = s.Character.PositionX, Y = s.Character.PositionY }) < Npc.NoticeRange); if (monster != null && session != null) { Target = monster.MapMonsterId; } } } else if (Target != -1) { MapMonster monster = MapInstance.Monsters.Find(s => s.MapMonsterId == Target); if (monster == null || monster.CurrentHp < 1) { Target = -1; return; } NpcMonsterSkill npcMonsterSkill = null; if (ServerManager.RandomNumber(0, 10) > 8) { npcMonsterSkill = Npc.Skills.Where(s => (DateTime.Now - s.LastSkillUse).TotalMilliseconds >= 100 * s.Skill.Cooldown).OrderBy(rnd => _random.Next()).FirstOrDefault(); } int hitmode = 0; bool onyxWings = false; int damage = DamageHelper.Instance.CalculateDamage(new BattleEntity(this), new BattleEntity(monster), npcMonsterSkill?.Skill, ref hitmode, ref onyxWings); if (monster.Monster.BCards.Find(s => s.Type == (byte)CardType.LightAndShadow && s.SubType == (byte)AdditionalTypes.LightAndShadow.InflictDamageToMP) is BCard card) { int reduce = damage / 100 * card.FirstData; if (monster.CurrentMp < reduce) { monster.CurrentMp = 0; } else { monster.CurrentMp -= reduce; } } int distance = Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = monster.MapX, Y = monster.MapY }); if (monster.CurrentHp > 0 && ((npcMonsterSkill != null && distance < npcMonsterSkill.Skill.Range) || distance <= Npc.BasicRange)) { if (((DateTime.Now - LastEffect).TotalMilliseconds >= 1000 + (Npc.BasicCooldown * 200) && Npc.Skills.Count == 0) || npcMonsterSkill != null) { if (npcMonsterSkill != null) { npcMonsterSkill.LastSkillUse = DateTime.Now; MapInstance.Broadcast(StaticPacketHelper.CastOnTarget(UserType.Npc, MapNpcId, 3, Target, npcMonsterSkill.Skill.CastAnimation, npcMonsterSkill.Skill.CastEffect, npcMonsterSkill.Skill.SkillVNum)); } if (npcMonsterSkill != null && npcMonsterSkill.Skill.CastEffect != 0) { MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, Effect)); } monster.CurrentHp -= damage; MapInstance.Broadcast(npcMonsterSkill != null ? StaticPacketHelper.SkillUsed(UserType.Npc, MapNpcId, 3, Target, npcMonsterSkill.SkillVNum, npcMonsterSkill.Skill.Cooldown, npcMonsterSkill.Skill.AttackAnimation, npcMonsterSkill.Skill.Effect, 0, 0, monster.CurrentHp > 0, (int)((float)monster.CurrentHp / (float)monster.Monster.MaxHP * 100), damage, hitmode, 0) : StaticPacketHelper.SkillUsed(UserType.Npc, MapNpcId, 3, Target, 0, Npc.BasicCooldown, 11, Npc.BasicSkill, 0, 0, monster.CurrentHp > 0, (int)((float)monster.CurrentHp / (float)monster.Monster.MaxHP * 100), damage, hitmode, 0)); LastEffect = DateTime.Now; if (monster.CurrentHp < 1) { RemoveTarget(); monster.IsAlive = false; monster.LastMove = DateTime.Now; monster.CurrentHp = 0; monster.CurrentMp = 0; monster.Death = DateTime.Now; Target = -1; } } } else { int maxdistance = Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange; if (IsMoving) { const short maxDistance = 5; int maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count; if (maxindex < 1) { maxindex = 1; } if ((Path.Count == 0 && distance >= 1 && distance < maxDistance) || (Path.Count >= maxindex && maxindex > 0 && Path[maxindex - 1] == null)) { short xoffset = (short)ServerManager.RandomNumber(-1, 1); short yoffset = (short)ServerManager.RandomNumber(-1, 1); //go to monster Path = BestFirstSearch.FindPathJagged(new GridPos { X = MapX, Y = MapY }, new GridPos { X = (short)(monster.MapX + xoffset), Y = (short)(monster.MapY + yoffset) }, MapInstance.Map.JaggedGrid); maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count; } if (DateTime.Now > LastMove && Npc.Speed > 0 && Path.Count > 0) { short mapX = Path[maxindex - 1].X; short mapY = Path[maxindex - 1].Y; double waitingtime = Map.GetDistance(new MapCell { X = mapX, Y = mapY }, new MapCell { X = MapX, Y = MapY }) / (double)Npc.Speed; MapInstance.Broadcast(new BroadcastPacket(null, PacketFactory.Serialize(StaticPacketHelper.Move(UserType.Npc, MapNpcId, MapX, MapY, Npc.Speed)), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY)); LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime); Observable.Timer(TimeSpan.FromMilliseconds((int)((waitingtime > 1 ? 1 : waitingtime) * 1000))).Subscribe(x => { MapX = mapX; MapY = mapY; }); Path.RemoveRange(0, maxindex); } if (Target != -1 && (MapId != monster.MapId || distance > maxDistance)) { RemoveTarget(); } } } } }
public List <GridPos> PathSearch(GridPos cell1, GridPos cell2) { return(BestFirstSearch.findPath(cell1, cell2, Grid)); }
/// <summary> /// Follow the Monsters target to it's position. /// </summary> /// <param name="targetSession">The TargetSession to follow</param> private void followTarget(ClientSession targetSession) { if (IsMoving && !_noMove) { const short maxDistance = 22; int distance = Map.GetDistance(new MapCell() { X = targetSession.Character.PositionX, Y = targetSession.Character.PositionY }, new MapCell() { X = MapX, Y = MapY }); if (targetSession != null) { if (targetSession.Character.LastMonsterAggro.AddSeconds(5) < DateTime.Now || targetSession.Character.BrushFire == null) { targetSession.Character.UpdateBushFire(); } targetSession.Character.LastMonsterAggro = DateTime.Now; } if (Path.Count == 0 && targetSession != null) { short xoffset = (short)ServerManager.Instance.RandomNumber(-1, 1); short yoffset = (short)ServerManager.Instance.RandomNumber(-1, 1); try { Path = BestFirstSearch.TracePath(new Node() { X = MapX, Y = MapY }, targetSession.Character.BrushFire, targetSession.Character.MapInstance.Map.Grid); } catch (Exception ex) { Logger.Error($"Pathfinding using Pathfinder failed. Map: {MapId} StartX: {MapX} StartY: {MapY} TargetX: {(short)(targetSession.Character.PositionX + xoffset)} TargetY: {(short)(targetSession.Character.PositionY + yoffset)}", ex); RemoveTarget(); } } if (Monster != null && DateTime.Now > LastMove && Monster.Speed > 0 && Path.Count > 0) { int maxindex = Path.Count > Monster.Speed / 2 ? Monster.Speed / 2 : Path.Count; short mapX = Path[maxindex - 1].X; short mapY = Path[maxindex - 1].Y; double waitingtime = Map.GetDistance(new MapCell { X = mapX, Y = mapY }, new MapCell { X = MapX, Y = MapY }) / (double)Monster.Speed; MapInstance.Broadcast(new BroadcastPacket(null, PacketFactory.Serialize(StaticPacketHelper.Move(UserType.Monster, MapMonsterId, mapX, mapY, Monster.Speed)), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY)); LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime); Observable.Timer(TimeSpan.FromMilliseconds((int)((waitingtime > 1 ? 1 : waitingtime) * 1000))).Subscribe(x => { MapX = mapX; MapY = mapY; }); distance = (int)Path[0].F; Path.RemoveRange(0, maxindex > Path.Count ? Path.Count : maxindex); } if (targetSession == null || MapId != targetSession.Character.MapInstance.Map.MapId || distance > (maxDistance) + 3) { RemoveTarget(); } } }
public Node[,] GetBrushFire() => BestFirstSearch.LoadBrushFire(new GridPos() { X = MapX, Y = MapY }, MapInstance.Map.Grid);