コード例 #1
0
        void SetTargetLocation(T owner)
        {
            if (owner == null || !owner.IsAlive())
            {
                return;
            }

            if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting())
            {
                AddFlag(MovementGeneratorFlags.Interrupted);
                owner.StopMoving();
                _path = null;
                return;
            }

            Position destination = new (owner.GetPosition());

            GetPoint(owner, destination);

            // Add LOS check for target point
            if (!owner.IsWithinLOS(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()))
            {
                _timer.Reset(200);
                return;
            }

            if (_path == null)
            {
                _path = new PathGenerator(owner);
                _path.SetPathLengthLimit(30.0f);
            }

            bool result = _path.CalculatePath(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ());

            if (!result || _path.GetPathType().HasFlag(PathType.NoPath) || _path.GetPathType().HasFlag(PathType.Shortcut) || _path.GetPathType().HasFlag(PathType.FarFromPoly))
            {
                _timer.Reset(100);
                return;
            }

            owner.AddUnitState(UnitState.FleeingMove);

            MoveSplineInit init = new(owner);

            init.MovebyPath(_path.GetPath());
            init.SetWalk(false);
            int traveltime = init.Launch();

            _timer.Reset(traveltime + RandomHelper.URand(800, 1500));
        }
コード例 #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);
        }
コード例 #3
0
        void SetRandomLocation(Creature owner)
        {
            if (owner == null)
            {
                return;
            }

            if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting())
            {
                _interrupt = true;
                owner.StopMoving();
                return;
            }

            owner.AddUnitState(UnitState.RoamingMove);

            Position position = new Position(_reference);
            float    distance = RandomHelper.FRand(0.0f, 1.0f) * _wanderDistance;
            float    angle    = RandomHelper.FRand(0.0f, 1.0f) * MathF.PI * 2.0f;

            owner.MovePositionToFirstCollision(ref position, distance, angle);

            uint resetTimer = RandomHelper.randChance(50) ? RandomHelper.URand(5000, 10000) : RandomHelper.URand(1000, 2000);

            if (_path == null)
            {
                _path = new PathGenerator(owner);
            }

            _path.SetPathLengthLimit(30.0f);
            bool result = _path.CalculatePath(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ());

            if (!result || _path.GetPathType().HasAnyFlag(PathType.NoPath))
            {
                _timer.Reset(100);
                return;
            }

            MoveSplineInit init = new MoveSplineInit(owner);

            init.MovebyPath(_path.GetPath());
            init.SetWalk(true);
            int traveltime = init.Launch();

            _timer.Reset(traveltime + resetTimer);

            // Call for creature group update
            owner.SignalFormationMovement(position);
        }
コード例 #4
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);
        }
コード例 #5
0
        public void MoveCharge(PathGenerator path, float speed = SPEED_CHARGE, Unit target = null, SpellEffectExtraData spellEffectExtraData = null)
        {
            Vector3 dest = path.GetActualEndPosition();

            MoveCharge(dest.X, dest.Y, dest.Z, SPEED_CHARGE, EventId.ChargePrepath);

            // Charge movement is not started when using EVENT_CHARGE_PREPATH
            MoveSplineInit init = new MoveSplineInit(_owner);

            init.MovebyPath(path.GetPath());
            init.SetVelocity(speed);
            if (target != null)
            {
                init.SetFacing(target);
            }
            if (spellEffectExtraData != null)
            {
                init.SetSpellEffectExtraData(spellEffectExtraData);
            }
            init.Launch();
        }
コード例 #6
0
        public void SetTargetLocation(T owner, bool updateDestination)
        {
            if (!IsTargetValid() || !GetTarget().IsInWorld)
            {
                return;
            }

            if (!owner || !owner.IsAlive())
            {
                return;
            }


            if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting() || HasLostTarget(owner))
            {
                _interrupt = true;
                owner.StopMoving();
                return;
            }

            if (owner.IsTypeId(TypeId.Unit) && !GetTarget().IsInAccessiblePlaceFor(owner.ToCreature()))
            {
                owner.ToCreature().SetCannotReachTarget(true);
                return;
            }

            float x, y, z;

            if (updateDestination || _path == null)
            {
                if (_offset == 0)
                {
                    if (GetTarget().IsWithinDistInMap(owner, SharedConst.ContactDistance))
                    {
                        return;
                    }

                    // to nearest contact position
                    GetTarget().GetContactPoint(owner, out x, out y, out z);
                }
                else
                {
                    float distance = _offset + 1.0f;
                    float size     = owner.GetCombatReach();

                    if (owner.IsPet() && GetTarget().GetTypeId() == TypeId.Player)
                    {
                        distance = 1.0f;
                        size     = 1.0f;
                    }

                    if (GetTarget().IsWithinDistInMap(owner, distance))
                    {
                        return;
                    }

                    GetTarget().GetClosePoint(out x, out y, out z, size, _offset, _angle);
                }
            }
            else
            {
                // the destination has not changed, we just need to refresh the path (usually speed change)
                var end = _path.GetEndPosition();
                x = end.X;
                y = end.Y;
                z = end.Z;
            }

            if (_path == null)
            {
                _path = new PathGenerator(owner);
            }

            // allow pets to use shortcut if no path found when following their master
            bool forceDest = owner.IsTypeId(TypeId.Unit) && owner.IsPet() && owner.HasUnitState(UnitState.Follow);

            bool result = _path.CalculatePath(x, y, z, forceDest);

            if (!result && Convert.ToBoolean(_path.GetPathType() & PathType.NoPath))
            {
                // Can't reach target
                _recalculateTravel = true;
                if (owner.IsTypeId(TypeId.Unit))
                {
                    owner.ToCreature().SetCannotReachTarget(true);
                }
                return;
            }

            _targetReached     = false;
            _recalculateTravel = false;
            _speedChanged      = false;

            AddUnitStateMove(owner);

            if (owner.IsTypeId(TypeId.Unit))
            {
                owner.ToCreature().SetCannotReachTarget(false);
            }

            MoveSplineInit init = new MoveSplineInit(owner);

            init.MovebyPath(_path.GetPath());
            init.SetWalk(EnableWalking());
            // Using the same condition for facing target as the one that is used for SetInFront on movement end
            // - applies to ChaseMovementGenerator mostly
            if (_angle == 0.0f)
            {
                init.SetFacing(GetTarget());
            }

            init.Launch();
        }
コード例 #7
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);
        }
コード例 #8
0
ファイル: TargetMovement.cs プロジェクト: uvbs/CypherCore
        public void _setTargetLocation(T owner, bool updateDestination)
        {
            if (!Reftarget.IsValid() || !Target.IsInWorld)
            {
                return;
            }

            if (owner.HasUnitState(UnitState.NotMove))
            {
                return;
            }

            if (owner.IsMovementPreventedByCasting())
            {
                return;
            }

            if (owner.IsTypeId(TypeId.Unit) && !Target.IsInAccessiblePlaceFor(owner.ToCreature()))
            {
                owner.ToCreature().SetCannotReachTarget(true);
                return;
            }

            if (owner.IsTypeId(TypeId.Unit) && owner.ToCreature().IsFocusing(null, true))
            {
                return;
            }

            float x, y, z;

            if (updateDestination || i_path == null)
            {
                if (offset == 0)
                {
                    if (Target.IsWithinDistInMap(owner, SharedConst.ContactDistance))
                    {
                        return;
                    }

                    // to nearest contact position
                    Target.GetContactPoint(owner, out x, out y, out z);
                }
                else
                {
                    float dist = 0;
                    float size = 0;

                    // Pets need special handling.
                    // We need to subtract GetObjectSize() because it gets added back further down the chain
                    //  and that makes pets too far away. Subtracting it allows pets to properly
                    //  be (GetCombatReach() + i_offset) away.
                    // Only applies when i_target is pet's owner otherwise pets and mobs end up
                    //   doing a "dance" while fighting
                    if (owner.IsPet() && Target.IsTypeId(TypeId.Player))
                    {
                        dist = 1.0f; // target.GetCombatReach();
                        size = 1.0f; // target.GetCombatReach() - target.GetObjectSize();
                    }
                    else
                    {
                        dist = offset + 1.0f;
                        size = owner.GetObjectSize();
                    }

                    if (Target.IsWithinDistInMap(owner, dist))
                    {
                        return;
                    }

                    // to at i_offset distance from target and i_angle from target facing
                    Target.GetClosePoint(out x, out y, out z, size, offset, angle);
                }
            }
            else
            {
                // the destination has not changed, we just need to refresh the path (usually speed change)
                var end = i_path.GetEndPosition();
                x = end.X;
                y = end.Y;
                z = end.Z;
            }

            if (i_path == null)
            {
                i_path = new PathGenerator(owner);
            }

            // allow pets to use shortcut if no path found when following their master
            bool forceDest = (owner.IsTypeId(TypeId.Unit) && owner.IsPet() &&
                              owner.HasUnitState(UnitState.Follow));

            bool result = i_path.CalculatePath(x, y, z, forceDest);

            if (!result && Convert.ToBoolean(i_path.GetPathType() & PathType.NoPath))
            {
                // Can't reach target
                recalculateTravel = true;
                if (owner.IsTypeId(TypeId.Unit))
                {
                    owner.ToCreature().SetCannotReachTarget(true);
                }
                return;
            }

            _addUnitStateMove(owner);
            targetReached     = false;
            recalculateTravel = false;
            owner.AddUnitState(UnitState.Chase);
            if (owner.IsTypeId(TypeId.Unit))
            {
                owner.ToCreature().SetCannotReachTarget(false);
            }

            MoveSplineInit init = new MoveSplineInit(owner);

            init.MovebyPath(i_path.GetPath());
            init.SetWalk(EnableWalking());
            // Using the same condition for facing target as the one that is used for SetInFront on movement end
            // - applies to ChaseMovementGenerator mostly
            if (angle == 0.0f)
            {
                init.SetFacing(Target);
            }

            init.Launch();
        }
コード例 #9
0
        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);
        }
コード例 #10
0
        public override bool DoUpdate(T owner, uint diff)
        {
            if (!owner || !owner.IsAlive())
            {
                return(false);
            }

            if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting())
            {
                AddFlag(MovementGeneratorFlags.Interrupted);
                owner.StopMoving();
                _path = null;
                return(true);
            }
            else
            {
                RemoveFlag(MovementGeneratorFlags.Interrupted);
            }

            // waiting for next move
            _timer.Update(diff);
            if ((HasFlag(MovementGeneratorFlags.SpeedUpdatePending) && !owner.MoveSpline.Finalized()) || (_timer.Passed() && owner.MoveSpline.Finalized()))
            {
                RemoveFlag(MovementGeneratorFlags.Transitory);

                Position destination = new(_reference);
                float    distance    = (float)(4.0f * RandomHelper.FRand(0.0f, 1.0f) - 2.0f);
                float    angle       = RandomHelper.FRand(0.0f, 1.0f) * MathF.PI * 2.0f;
                owner.MovePositionToFirstCollision(destination, distance, angle);

                // Check if the destination is in LOS
                if (!owner.IsWithinLOS(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()))
                {
                    // Retry later on
                    _timer.Reset(200);
                    return(true);
                }

                if (_path == null)
                {
                    _path = new PathGenerator(owner);
                    _path.SetPathLengthLimit(30.0f);
                }

                bool result = _path.CalculatePath(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ());
                if (!result || _path.GetPathType().HasFlag(PathType.NoPath) || _path.GetPathType().HasFlag(PathType.Shortcut) || _path.GetPathType().HasFlag(PathType.FarFromPoly))
                {
                    _timer.Reset(100);
                    return(true);
                }

                owner.AddUnitState(UnitState.ConfusedMove);

                MoveSplineInit init = new(owner);
                init.MovebyPath(_path.GetPath());
                init.SetWalk(true);
                int traveltime = init.Launch();
                _timer.Reset(traveltime + RandomHelper.URand(800, 1500));
            }

            return(true);
        }
コード例 #11
0
ファイル: RandomMovement.cs プロジェクト: Tithand/CypherCore
        void SetRandomLocation(Creature owner)
        {
            if (owner == null)
            {
                return;
            }

            if (owner.HasUnitState(UnitState.NotMove | UnitState.LostControl) || owner.IsMovementPreventedByCasting())
            {
                AddFlag(MovementGeneratorFlags.Interrupted);
                owner.StopMoving();
                _path = null;
                return;
            }

            Position position = new(_reference);
            float    distance = RandomHelper.FRand(0.0f, 1.0f) * _wanderDistance;
            float    angle    = RandomHelper.FRand(0.0f, 1.0f) * MathF.PI * 2.0f;

            owner.MovePositionToFirstCollision(position, distance, angle);

            uint resetTimer = RandomHelper.randChance(50) ? RandomHelper.URand(5000, 10000) : RandomHelper.URand(1000, 2000);

            if (_path == null)
            {
                _path = new PathGenerator(owner);
                _path.SetPathLengthLimit(30.0f);
            }

            bool result = _path.CalculatePath(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ());

            if (!result || _path.GetPathType().HasAnyFlag(PathType.NoPath) || _path.GetPathType().HasAnyFlag(PathType.Shortcut))
            {
                _timer.Reset(100);
                return;
            }

            owner.AddUnitState(UnitState.RoamingMove);

            bool walk = true;

            switch (owner.GetMovementTemplate().GetRandom())
            {
            case CreatureRandomMovementType.CanRun:
                walk = owner.IsWalking();
                break;

            case CreatureRandomMovementType.AlwaysRun:
                walk = false;
                break;

            default:
                break;
            }

            MoveSplineInit init = new(owner);

            init.MovebyPath(_path.GetPath());
            init.SetWalk(walk);
            int traveltime = init.Launch();

            _timer.Reset(traveltime + resetTimer);

            // Call for creature group update
            owner.SignalFormationMovement(position);
        }
コード例 #12
0
        void SetRandomLocation(Creature owner)
        {
            if (owner == null)
            {
                return;
            }

            if (owner.HasUnitState(UnitState.NotMove | UnitState.LostControl) || owner.IsMovementPreventedByCasting())
            {
                AddFlag(MovementGeneratorFlags.Interrupted);
                owner.StopMoving();
                _path = null;
                return;
            }

            Position position = new(_reference);
            float    distance = RandomHelper.FRand(0.0f, _wanderDistance);
            float    angle    = RandomHelper.FRand(0.0f, MathF.PI * 2.0f);

            owner.MovePositionToFirstCollision(position, distance, angle);

            // Check if the destination is in LOS
            if (!owner.IsWithinLOS(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ()))
            {
                // Retry later on
                _timer.Reset(200);
                return;
            }

            if (_path == null)
            {
                _path = new PathGenerator(owner);
                _path.SetPathLengthLimit(30.0f);
            }

            bool result = _path.CalculatePath(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ());

            if (!result || _path.GetPathType().HasFlag(PathType.NoPath) || _path.GetPathType().HasFlag(PathType.Shortcut) || _path.GetPathType().HasFlag(PathType.FarFromPoly))
            {
                _timer.Reset(100);
                return;
            }

            RemoveFlag(MovementGeneratorFlags.Transitory | MovementGeneratorFlags.TimedPaused);

            owner.AddUnitState(UnitState.RoamingMove);

            bool walk = true;

            switch (owner.GetMovementTemplate().GetRandom())
            {
            case CreatureRandomMovementType.CanRun:
                walk = owner.IsWalking();
                break;

            case CreatureRandomMovementType.AlwaysRun:
                walk = false;
                break;

            default:
                break;
            }

            MoveSplineInit init = new(owner);

            init.MovebyPath(_path.GetPath());
            init.SetWalk(walk);
            int splineDuration = init.Launch();

            --_wanderSteps;
            if (_wanderSteps != 0) // Creature has yet to do steps before pausing
            {
                _timer.Reset(splineDuration);
            }
            else
            {
                // Creature has made all its steps, time for a little break
                _timer.Reset(splineDuration + RandomHelper.URand(4, 10) * Time.InMilliseconds); // Retails seems to use rounded numbers so we do as well
                _wanderSteps = RandomHelper.URand(2, 10);
            }

            // Call for creature group update
            owner.SignalFormationMovement();
        }