void _setTargetLocation(T owner) { if (owner == null) { return; } if (owner.HasUnitState(UnitState.Root | UnitState.Stunned)) { return; } if (owner.IsMovementPreventedByCasting()) { owner.CastStop(); return; } owner.AddUnitState(UnitState.FleeingMove); float x, y, z; _getPoint(owner, out x, out y, out z); Position mypos = owner.GetPosition(); bool isInLOS = Global.VMapMgr.isInLineOfSight(owner.GetMapId(), mypos.posX, mypos.posY, mypos.posZ + 2.0f, x, y, z + 2.0f); if (!isInLOS) { i_nextCheckTime.Reset(200); return; } PathGenerator path = new PathGenerator(owner); path.SetPathLengthLimit(30.0f); bool result = path.CalculatePath(x, y, z); if (!result || path.GetPathType().HasAnyFlag(PathType.NoPath)) { i_nextCheckTime.Reset(100); return; } MoveSplineInit init = new MoveSplineInit(owner); init.MovebyPath(path.GetPath()); init.SetWalk(false); int traveltime = init.Launch(); i_nextCheckTime.Reset(traveltime + RandomHelper.URand(800, 1500)); }
public override bool DoUpdate(T owner, uint time_diff) { if (owner.HasUnitState(UnitState.Root | UnitState.Stunned | UnitState.Distracted)) { return(true); } if (i_nextMoveTime.Passed()) { // currently moving, update location owner.AddUnitState(UnitState.ConfusedMove); if (owner.MoveSpline.Finalized()) { i_nextMoveTime.Reset(RandomHelper.IRand(800, 1500)); } } else { // waiting for next move i_nextMoveTime.Update(time_diff); if (i_nextMoveTime.Passed()) { // start moving owner.AddUnitState(UnitState.ConfusedMove); float dest = (float)(4.0f * RandomHelper.NextDouble() - 2.0f); Position pos = new Position(i_x, i_y, i_z); owner.MovePositionToFirstCollision(ref pos, dest, 0.0f); PathGenerator path = new PathGenerator(owner); path.SetPathLengthLimit(30.0f); bool result = path.CalculatePath(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); if (!result || path.GetPathType().HasAnyFlag(PathType.NoPath)) { i_nextMoveTime.Reset(100); return(true); } MoveSplineInit init = new MoveSplineInit(owner); init.MovebyPath(path.GetPath()); init.SetWalk(true); init.Launch(); } } return(true); }
public void MoveTo(Vector3 dest, bool generatePath = true, bool forceDestination = false) { if (generatePath) { PathGenerator path = new PathGenerator(unit); bool result = path.CalculatePath(dest.X, dest.Y, dest.Z, forceDestination); if (result && !Convert.ToBoolean(path.GetPathType() & PathType.NoPath)) { MovebyPath(path.GetPath()); return; } } args.path_Idx_offset = 0; args.path = new Vector3[2]; TransportPathTransform transform = new TransportPathTransform(unit, args.TransformForTransport); args.path[1] = transform.Calc(dest); }
public override bool Update(Unit owner, uint diff) { // owner might be dead or gone (can we even get nullptr here?) if (!owner || !owner.IsAlive()) { return(false); } // our target might have gone away Unit target = _abstractFollower.GetTarget(); if (target == null || !target.IsInWorld) { return(false); } // the owner might be unable to move (rooted or casting), pause movement if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) { owner.StopMoving(); _lastTargetPosition = null; Creature cOwner = owner.ToCreature(); if (cOwner != null) { cOwner.SetCannotReachTarget(false); } return(true); } bool mutualChase = IsMutualChase(owner, target); float hitboxSum = owner.GetCombatReach() + target.GetCombatReach(); float minRange = _range.HasValue ? _range.Value.MinRange + hitboxSum : SharedConst.ContactDistance; float minTarget = (_range.HasValue ? _range.Value.MinTolerance : 0.0f) + hitboxSum; float maxRange = _range.HasValue ? _range.Value.MaxRange + hitboxSum : owner.GetMeleeRange(target); // melee range already includes hitboxes float maxTarget = _range.HasValue ? _range.Value.MaxTolerance + hitboxSum : SharedConst.ContactDistance + hitboxSum; ChaseAngle?angle = mutualChase ? null : _angle; // if we're already moving, periodically check if we're already in the expected range... if (owner.HasUnitState(UnitState.ChaseMove)) { if (_rangeCheckTimer > diff) { _rangeCheckTimer -= diff; } else { _rangeCheckTimer = RANGE_CHECK_INTERVAL; if (PositionOkay(owner, target, _movingTowards ? null : minTarget, _movingTowards ? maxTarget : null, angle)) { _path = null; owner.StopMoving(); owner.SetInFront(target); DoMovementInform(owner, target); return(true); } } } // if we're done moving, we want to clean up if (owner.HasUnitState(UnitState.ChaseMove) && owner.MoveSpline.Finalized()) { _path = null; Creature cOwner = owner.ToCreature(); if (cOwner != null) { cOwner.SetCannotReachTarget(false); } owner.ClearUnitState(UnitState.ChaseMove); owner.SetInFront(target); DoMovementInform(owner, target); } // if the target moved, we have to consider whether to adjust if (_lastTargetPosition == null || target.GetPosition() != _lastTargetPosition || mutualChase != _mutualChase) { _lastTargetPosition = new(target.GetPosition()); _mutualChase = mutualChase; if (owner.HasUnitState(UnitState.ChaseMove) || !PositionOkay(owner, target, minRange, maxRange, angle)) { Creature cOwner = owner.ToCreature(); // can we get to the target? if (cOwner != null && !target.IsInAccessiblePlaceFor(cOwner)) { cOwner.SetCannotReachTarget(true); cOwner.StopMoving(); _path = null; return(true); } // figure out which way we want to move bool moveToward = !owner.IsInDist(target, maxRange); // make a new path if we have to... if (_path == null || moveToward != _movingTowards) { _path = new PathGenerator(owner); } float x, y, z; bool shortenPath; // if we want to move toward the target and there's no fixed angle... if (moveToward && !angle.HasValue) { // ...we'll pathfind to the center, then shorten the path target.GetPosition(out x, out y, out z); shortenPath = true; } else { // otherwise, we fall back to nearpoint finding target.GetNearPoint(owner, out x, out y, out z, (moveToward ? maxTarget : minTarget) - hitboxSum, angle.HasValue ? target.ToAbsoluteAngle(angle.Value.RelativeAngle) : target.GetAbsoluteAngle(owner)); shortenPath = false; } if (owner.IsHovering()) { owner.UpdateAllowedPositionZ(x, y, ref z); } bool success = _path.CalculatePath(x, y, z, owner.CanFly()); if (!success || _path.GetPathType().HasAnyFlag(PathType.NoPath)) { if (cOwner) { cOwner.SetCannotReachTarget(true); } owner.StopMoving(); return(true); } if (shortenPath) { _path.ShortenPathUntilDist(target, maxTarget); } if (cOwner) { cOwner.SetCannotReachTarget(false); } owner.AddUnitState(UnitState.ChaseMove); bool walk = false; if (cOwner && !cOwner.IsPet()) { switch (cOwner.GetMovementTemplate().GetChase()) { case CreatureChaseMovementType.CanWalk: walk = owner.IsWalking(); break; case CreatureChaseMovementType.AlwaysWalk: walk = true; break; default: break; } } MoveSplineInit init = new(owner); init.MovebyPath(_path.GetPath()); init.SetWalk(walk); init.SetFacing(target); init.Launch(); } } // and then, finally, we're done for the tick return(true); }
public override bool Update(Unit owner, uint diff) { // owner might be dead or gone if (owner == null || !owner.IsAlive()) { return(false); } // our target might have gone away Unit target = _abstractFollower.GetTarget(); if (target == null || !target.IsInWorld) { return(false); } if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) { _path = null; owner.StopMoving(); _lastTargetPosition = null; return(true); } _checkTimer.Update((int)diff); if (_checkTimer.Passed()) { _checkTimer.Reset(CHECK_INTERVAL); if (HasFlag(MovementGeneratorFlags.InformEnabled) && PositionOkay(owner, target, _range, _angle)) { RemoveFlag(MovementGeneratorFlags.InformEnabled); _path = null; owner.StopMoving(); _lastTargetPosition = new(); DoMovementInform(owner, target); return(true); } } if (owner.HasUnitState(UnitState.FollowMove) && owner.MoveSpline.Finalized()) { RemoveFlag(MovementGeneratorFlags.InformEnabled); _path = null; owner.ClearUnitState(UnitState.FollowMove); DoMovementInform(owner, target); } if (_lastTargetPosition == null || _lastTargetPosition.GetExactDistSq(target.GetPosition()) > 0.0f) { _lastTargetPosition = new(target.GetPosition()); if (owner.HasUnitState(UnitState.FollowMove) || !PositionOkay(owner, target, _range + FOLLOW_RANGE_TOLERANCE)) { if (_path == null) { _path = new PathGenerator(owner); } float x, y, z; // select angle float tAngle; float curAngle = target.GetRelativeAngle(owner); if (_angle.IsAngleOkay(curAngle)) { tAngle = curAngle; } else { float diffUpper = Position.NormalizeOrientation(curAngle - _angle.UpperBound()); float diffLower = Position.NormalizeOrientation(_angle.LowerBound() - curAngle); if (diffUpper < diffLower) { tAngle = _angle.UpperBound(); } else { tAngle = _angle.LowerBound(); } } target.GetNearPoint(owner, out x, out y, out z, _range, target.ToAbsoluteAngle(tAngle)); if (owner.IsHovering()) { owner.UpdateAllowedPositionZ(x, y, ref z); } // pets are allowed to "cheat" on pathfinding when following their master bool allowShortcut = false; Pet oPet = owner.ToPet(); if (oPet != null) { if (target.GetGUID() == oPet.GetOwnerGUID()) { allowShortcut = true; } } bool success = _path.CalculatePath(x, y, z, allowShortcut); if (!success || _path.GetPathType().HasFlag(PathType.NoPath)) { owner.StopMoving(); return(true); } owner.AddUnitState(UnitState.FollowMove); AddFlag(MovementGeneratorFlags.InformEnabled); MoveSplineInit init = new(owner); init.MovebyPath(_path.GetPath()); init.SetWalk(target.IsWalking()); init.SetFacing(target.GetOrientation()); init.Launch(); } } return(true); }