private void UpdateMove(long tick) { if (MovementSpeed == 0 || _unit != null && _unit.IsDisabled || _unit != null && _unit.IsStaggered) { return; } long deltaMs = tick - _moveStartTime; uint newWorldPosX = (uint)Point2D.Lerp(_startWorldPos.X, _destWorldPos.X, GetMoveFactor(deltaMs)); uint newWorldPosY = (uint)Point2D.Lerp(_startWorldPos.Y, _destWorldPos.Y, GetMoveFactor(deltaMs)); Zone_Info destZone = _unit.Region.GetZone((ushort)(newWorldPosX >> 12), (ushort)(newWorldPosY >> 12)); if (destZone == null) { return; } ushort pinX = _unit.Zone.CalculPin(newWorldPosX, true); ushort pinY = _unit.Zone.CalculPin(newWorldPosY, false); ushort pinZ = (ushort)Point2D.Lerp(_startWorldPos.Z, _destWorldPos.Z, GetMoveFactor(deltaMs)); _unit.SetPosition(pinX, pinY, pinZ, _unit.Heading, destZone.ZoneId); if (tick > _moveStartTime + _moveDuration) { if (MoveState == EMoveState.Move) { MoveState = EMoveState.None; } _moveDuration = 0; } }
// Recall state just moves the target repeatedly towards its owner without sending any state updates // TODO: Move towards offset position (back-rear) private void UpdateRecall(long tick) { long deltaMs = tick - _lastRecallMove; _lastRecallMove = tick; // Stationary pets should not perform any moves if (MovementSpeed == 0) { return; } if (_nextRecallSend < tick) { _nextRecallSend = tick + 7500; UpdateMovementState(null); } Vector2 destVect = new Vector2(_unit.WorldPosition.X - FollowTarget.WorldPosition.X, _unit.WorldPosition.Y - FollowTarget.WorldPosition.Y); float distance = destVect.Magnitude; // Within tolerance for recall move if (distance < 60) { Pet pet = _unit as Pet; if (pet != null && pet.IsHeeling) { pet.IsHeeling = false; pet.AiInterface.Debugger?.SendClientMessage("[MR]: Successfully recalled. No longer ignoring enemies."); } return; } // Total time required to move fully towards the target _moveDuration = (distance / _totalSpeed) * 1000; // Lerp alpha is capped to 1, so the move will never overshoot the target uint newWorldPosX = (uint)Point2D.Lerp(_unit.WorldPosition.X, FollowTarget.WorldPosition.X, GetMoveFactor(deltaMs)); uint newWorldPosY = (uint)Point2D.Lerp(_unit.WorldPosition.Y, FollowTarget.WorldPosition.Y, GetMoveFactor(deltaMs)); Zone_Info destZone = _unit.Region.GetZone((ushort)(newWorldPosX >> 12), (ushort)(newWorldPosY >> 12)); if (destZone == null) { return; } ushort pinX = _unit.Zone.CalculPin(newWorldPosX, true); ushort pinY = _unit.Zone.CalculPin(newWorldPosY, false); ushort pinZ = (ushort)Point2D.Lerp(_unit.WorldPosition.Z, FollowTarget.WorldPosition.Z, GetMoveFactor(deltaMs)); _unit.SetPosition(pinX, pinY, pinZ, _unit.Heading, destZone.ZoneId); }