Beispiel #1
0
        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));
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
        }