public static void WalkToXY_Tick(WorldObjectUnit obj) { if (obj.Walkpath == null) { return; } else if (obj.Walkpath.path_pos >= obj.Walkpath.path_len) { return; } else if (obj.Walkpath.path[obj.Walkpath.path_pos] == EDirection.None) { return; } else if ((int)obj.Walkpath.path[obj.Walkpath.path_pos] > 8) { return; } else { } // TODO: this is the point there the client seems to look laggy // eAthena sends before any movement the WalkOk() packet // and the client animates the move to the target location. // But if we attacked by a skill or w00tever, // eAthena updates the position (i think) // AND THIS is the all-known movement/position-reset. // // In future, we may test to send a WalkOk() Packet in every single step // So the client maybe display it more accurate.. EDirection dir = obj.Walkpath.path[obj.Walkpath.path_pos]; Point2D targetLoc = obj.Location.Point + dir.ToPoint2D(); ServerConsole.DebugLine("{0}: walk from {1} to {2} ({3})", obj, obj.Location.Point, targetLoc, dir); //obj.Map.DrawGat(); //Mapcache.Maps[obj.Map.Name].DrawGat(); if (obj.Map.CheckCell(targetLoc, ECollisionType.Walkable) == false) { // Target location is not walkable - recalc path! ServerConsole.DebugLine("WalkToXY_Tick: location {0} not walkable, recalc path..", targetLoc); WalkToXY(obj, obj.TargetLocation); return; } obj.Move(dir); obj.Walkpath.path_pos++; int speed = CalcWalkspeed(obj); // Next step? if (speed > 0) { obj.WalkTimer = Timer.DelayCall(TimeSpan.FromMilliseconds(speed), TimeSpan.Zero, 1, new TimerStateCallback<WorldObjectUnit>(WalkToXY_Tick), obj); } else { // No next step, target location reached, update target location // just to be sure.. obj.TargetLocation = obj.Location.Point; obj.Walkpath = null; ServerConsole.DebugLine("WalkToXY_Tick: finished moving to location {0}", obj.Location.Point); } }
public static void WalkToXY(WorldObjectUnit obj, Point2D targetLoc) { // Walking in process? if (obj.Walkpath != null || obj.WalkTimer != null) { // Stop and reset walking if (obj.WalkTimer != null) { obj.WalkTimer.Stop(); obj.WalkTimer = null; } obj.Walkpath = null; } obj.TargetLocation = targetLoc; if (obj.Location.Point == obj.TargetLocation) { return; } // Calc path WalkpathData wpd; if (PathHelper.SearchPath(out wpd, obj.Map, obj.Location.Point, obj.TargetLocation) == false) { ServerConsole.ErrorLine("Bad path, cancel moving"); //obj.Map.DrawGat(); return; } obj.Walkpath = wpd; // Player needs to notify clients about a successfull move if ((obj is Character)) { (obj as Character).Account.Netstate.Send(new WorldResponseWalkOK(obj as Character)); } // Get speed and start timer int speed = CalcWalkspeed(obj); if (speed > 0) { obj.WalkTimer = Timer.DelayCall(TimeSpan.FromMilliseconds(speed), TimeSpan.Zero, 1, new TimerStateCallback<WorldObjectUnit>(WalkToXY_Tick), obj); } }
private static int CalcWalkspeed(WorldObjectUnit obj) { // In final case, the speed comes from status and/or calculation.. int speed = Global.DEFAULT_WALK_SPEED; if (obj.Walkpath.path_pos >= obj.Walkpath.path_len) { speed = -1; } else if ((obj.Walkpath.path[obj.Walkpath.path_pos] & EDirection.Up) > 0) { } else { } return speed; }
public static bool check_distance_blxy(WorldObjectUnit bl, int x1, int y1, int distance) { return InRange((bl).X - (x1), (bl).Y - (y1), distance); }
public bool InRange(WorldObjectUnit obj, int range) { return(PathHelper.InRange(X - obj.X, Y - obj.Y, range)); }
private void Move(WorldObjectUnit obj, Point2D OldLocation) { this[OldLocation].DelUnit(obj); this[obj.Location].AddUnit(obj); }
public static bool check_distance_bl(WorldObjectUnit bl1, WorldObjectUnit bl2, int distance) { return InRange((bl1).X - (bl2).X, (bl1).Y - (bl2).Y, distance); }
private void Add(WorldObjectUnit obj) { this[obj.Location].AddUnit(obj); }
private void Remove(WorldObjectUnit obj) { this[obj.Location].DelUnit(obj); }
/// <summary> /// Locates a random spare cell around the object given, using range as max /// distance from that spot. Used for warping functions. Use range below 0 for whole map range. /// </summary> /// <param name="src">src can be null as long as flag&1</param> /// <param name="p">Source poition to use (if flag & 1), will also contain the new position</param> /// <param name="rx">Range width</param> /// <param name="ry">Range height</param> /// <param name="flag"> /// <para>&1 = random cell must be around given m,x,y, not around src</para> /// <PARA>&2 = the target should be able to walk to the target tile</para> /// <para>&4 = there shouldn't be any players around the target tile (use the no_spawn_on_player setting)</para> /// </param> /// <returns></returns> public bool SearchFreeCell(WorldObjectUnit src, ref Point2D p, int rx, int ry, int flag) { int tries, spawn = 0; int bx, by; int rx2 = 2 * rx + 1; int ry2 = 2 * ry + 1; if (src == null && ((flag & 1) != 1 || (flag & 2) != 2)) { ServerConsole.DebugLine("SearchFreeCell: Incorrect usage! When src is NULL, flag has to be &1 and can't have &2"); return false; } if ((flag & 1) == 1) { bx = p.X; by = p.Y; } else { bx = src.X; by = src.Y; } // No range? Return the target cell then.... if (rx == 0 && ry == 0) { p.X = bx; p.Y = by; return CheckCell(p, ECollisionType.Reachable); } // Calc max tries if (rx >= 0 && ry >= 0) { tries = rx2 * ry2; if (tries > 100) { tries = 100; } } else { tries = Width * Height; if (tries > 500) { tries = 500; } } Random rand = new Random(); while (tries-- > 0) { p.X = (rx >= 0 ? (rand.Next() % rx2 - rx + bx) : (rand.Next() % (Width - 2) + 1)); p.Y = (ry >= 0 ? (rand.Next() % ry2 - ry + by) : (rand.Next() % (Height - 2) + 1)); // Avoid picking the same target tile if (p.X == bx && p.Y == by) { continue; } if (CheckCell(p, ECollisionType.Reachable) == true) { if ((flag & 2) == 2 && src.CanReach(p, 1) == false) { continue; } if ((flag & 4) == 4) { // Limit of retries reached. if (spawn >= 100) { return false; } /* if (spawn++ < battle_config.no_spawn_on_player && map_foreachinarea(map_count_sub, m, *x-AREA_SIZE, *y-AREA_SIZE, *x+AREA_SIZE, *y+AREA_SIZE, BL_PC) ) continue; */ } return true; } } p.X = bx; p.Y = by; return false; }
public void OnMove(WorldObjectUnit obj, Point2D OldLocation) { Move(obj, OldLocation); }
public void OnLeave(WorldObjectUnit obj) { Remove(obj); }
public void OnEnter(WorldObjectUnit obj) { Add(obj); }
public bool InRange(WorldObjectUnit obj, int range) { return PathHelper.InRange(X - obj.X, Y - obj.Y, range); }