예제 #1
0
        void FormationMove(Creature creature)
        {
            if (path == null || path.nodes.Empty())
            {
                return;
            }

            bool transportPath = creature.GetTransport() != null;

            WaypointNode waypoint = path.nodes.LookupByIndex((int)currentNode);

            Position formationDest = new Position(waypoint.x, waypoint.y, waypoint.z, 0.0f);

            //! If creature is on transport, we assume waypoints set in DB are already transport offsets
            if (transportPath)
            {
                ITransport trans = creature.GetDirectTransport();
                if (trans != null)
                {
                    trans.CalculatePassengerPosition(ref formationDest.posX, ref formationDest.posY, ref formationDest.posZ, ref formationDest.Orientation);
                }
            }

            // Call for creature group update
            if (creature.GetFormation() != null && creature.GetFormation().getLeader() == creature)
            {
                creature.GetFormation().LeaderMoveTo(formationDest.posX, formationDest.posY, formationDest.posZ);
            }
        }
예제 #2
0
        public void SaveStayPosition()
        {
            //! At this point a new spline destination is enabled because of Unit.StopMoving()
            Vector3 stayPos = _unit.MoveSpline.FinalDestination();

            if (_unit.MoveSpline.onTransport)
            {
                float      o         = 0;
                ITransport transport = _unit.GetDirectTransport();
                if (transport != null)
                {
                    transport.CalculatePassengerPosition(ref stayPos.X, ref stayPos.Y, ref stayPos.Z, ref o);
                }
            }

            _stayX = stayPos.X;
            _stayY = stayPos.Y;
            _stayZ = stayPos.Z;
        }
예제 #3
0
        public override bool DoUpdate(T owner, uint diff)
        {
            if (!IsTargetValid() || !GetTarget().IsInWorld)
            {
                return(false);
            }

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

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

            if (_interrupt || _recalculateTravel)
            {
                _interrupt = false;
                SetTargetLocation(owner, true);
                return(true);
            }


            bool targetMoved = false;

            _timer.Update((int)diff);
            if (_timer.Passed())
            {
                _timer.Reset(100);

                float distance = owner.GetCombatReach() + WorldConfig.GetFloatValue(WorldCfg.RateTargetPosRecalculationRange);
                if (owner.IsPet() && (owner.GetCharmerOrOwnerGUID() == GetTarget().GetGUID()))
                {
                    distance = 1.0f; // pet following owner
                }
                Vector3 destination = owner.MoveSpline.FinalDestination();
                if (owner.MoveSpline.onTransport)
                {
                    float      o         = 0;
                    ITransport transport = owner.GetDirectTransport();
                    if (transport != null)
                    {
                        transport.CalculatePassengerPosition(ref destination.X, ref destination.Y, ref destination.Z, ref o);
                    }
                }

                // First check distance
                if (owner.IsTypeId(TypeId.Unit) && owner.ToCreature().CanFly())
                {
                    targetMoved = !GetTarget().IsWithinDist3d(destination.X, destination.Y, destination.Z, distance);
                }
                else
                {
                    targetMoved = !GetTarget().IsWithinDist2d(destination.X, destination.Y, distance);
                }


                // then, if the target is in range, check also Line of Sight.
                if (!targetMoved)
                {
                    targetMoved = !GetTarget().IsWithinLOSInMap(owner);
                }
            }

            if (targetMoved)
            {
                SetTargetLocation(owner, true);
            }
            else if (_speedChanged)
            {
                SetTargetLocation(owner, false);
            }

            if (!_targetReached && owner.MoveSpline.Finalized())
            {
                MovementInform(owner);
                if (_angle == 0.0f && !owner.HasInArc(0.01f, GetTarget()))
                {
                    owner.SetInFront(GetTarget());
                }

                if (!_targetReached)
                {
                    _targetReached = true;
                    ReachTarget(owner);
                }
            }

            return(true);
        }
예제 #4
0
        void StartMove(Creature owner, bool relaunch = false)
        {
            // sanity checks
            if (owner == null || !owner.IsAlive() || HasFlag(MovementGeneratorFlags.Finalized) || _path == null || _path.nodes.Empty() || (relaunch && (HasFlag(MovementGeneratorFlags.InformEnabled) || !HasFlag(MovementGeneratorFlags.Initialized))))
            {
                return;
            }

            if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting() || (owner.IsFormationLeader() && !owner.IsFormationLeaderMoveAllowed())) // if cannot move OR cannot move because of formation
            {
                _nextMoveTime.Reset(1000);                                                                                                                             // delay 1s
                return;
            }

            bool transportPath = !owner.GetTransGUID().IsEmpty();

            if (HasFlag(MovementGeneratorFlags.InformEnabled) && HasFlag(MovementGeneratorFlags.Initialized))
            {
                if (ComputeNextNode())
                {
                    Cypher.Assert(_currentNode < _path.nodes.Count, $"WaypointMovementGenerator.StartMove: tried to reference a node id ({_currentNode}) which is not included in path ({_path.id})");
                    // inform AI
                    CreatureAI ai = owner.GetAI();
                    if (ai != null)
                    {
                        ai.WaypointStarted(_path.nodes[_currentNode].id, _path.id);
                    }
                }
                else
                {
                    WaypointNode currentWaypoint = _path.nodes[_currentNode];
                    float        x = currentWaypoint.x;
                    float        y = currentWaypoint.y;
                    float        z = currentWaypoint.z;
                    float        o = owner.GetOrientation();

                    if (!transportPath)
                    {
                        owner.SetHomePosition(x, y, z, o);
                    }
                    else
                    {
                        Transport trans = owner.GetTransport();
                        if (trans)
                        {
                            o -= trans.GetOrientation();
                            owner.SetTransportHomePosition(x, y, z, o);
                            trans.CalculatePassengerPosition(ref x, ref y, ref z, ref o);
                            owner.SetHomePosition(x, y, z, o);
                        }
                        // else if (vehicle) - this should never happen, vehicle offsets are const
                    }

                    AddFlag(MovementGeneratorFlags.Finalized);
                    owner.UpdateCurrentWaypointInfo(0, 0);

                    // inform AI
                    CreatureAI ai = owner.GetAI();
                    if (ai != null)
                    {
                        ai.WaypointPathEnded(currentWaypoint.id, _path.id);
                    }
                    return;
                }
            }
            else if (!HasFlag(MovementGeneratorFlags.Initialized))
            {
                AddFlag(MovementGeneratorFlags.Initialized);

                // inform AI
                CreatureAI ai = owner.GetAI();
                if (ai != null)
                {
                    ai.WaypointStarted(_path.nodes[_currentNode].id, _path.id);
                }
            }

            Cypher.Assert(_currentNode < _path.nodes.Count, $"WaypointMovementGenerator.StartMove: tried to reference a node id ({_currentNode}) which is not included in path ({_path.id})");
            WaypointNode waypoint      = _path.nodes[_currentNode];
            Position     formationDest = new(waypoint.x, waypoint.y, waypoint.z, (waypoint.orientation != 0 && waypoint.delay != 0) ? waypoint.orientation : 0.0f);

            RemoveFlag(MovementGeneratorFlags.Transitory | MovementGeneratorFlags.InformEnabled | MovementGeneratorFlags.TimedPaused);

            owner.AddUnitState(UnitState.RoamingMove);

            MoveSplineInit init = new(owner);

            //! If creature is on transport, we assume waypoints set in DB are already transport offsets
            if (transportPath)
            {
                init.DisableTransportPathTransformations();
                ITransport trans = owner.GetDirectTransport();
                if (trans != null)
                {
                    float orientation = formationDest.GetOrientation();
                    trans.CalculatePassengerPosition(ref formationDest.posX, ref formationDest.posY, ref formationDest.posZ, ref orientation);
                    formationDest.SetOrientation(orientation);
                }
            }

            //! Do not use formationDest here, MoveTo requires transport offsets due to DisableTransportPathTransformations() call
            //! but formationDest contains global coordinates
            init.MoveTo(waypoint.x, waypoint.y, waypoint.z);

            //! Accepts angles such as 0.00001 and -0.00001, 0 must be ignored, default value in waypoint table
            if (waypoint.orientation != 0 && waypoint.delay != 0)
            {
                init.SetFacing(waypoint.orientation);
            }

            switch (waypoint.moveType)
            {
            case WaypointMoveType.Land:
                init.SetAnimation(AnimType.ToGround);
                break;

            case WaypointMoveType.Takeoff:
                init.SetAnimation(AnimType.ToFly);
                break;

            case WaypointMoveType.Run:
                init.SetWalk(false);
                break;

            case WaypointMoveType.Walk:
                init.SetWalk(true);
                break;
            }

            init.Launch();

            // inform formation
            owner.SignalFormationMovement(formationDest, waypoint.id, waypoint.moveType, (waypoint.orientation != 0 && waypoint.delay != 0));
        }
예제 #5
0
        public override bool DoUpdate(T owner, uint time_diff)
        {
            if (!Reftarget.IsValid() || !Target.IsInWorld)
            {
                return(false);
            }

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

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

            // prevent movement while casting spells with cast time or channel time
            if (owner.IsMovementPreventedByCasting())
            {
                if (!owner.IsStopped())
                {
                    owner.StopMoving();
                }
                return(true);
            }

            // prevent crash after creature killed pet
            if (_lostTarget(owner))
            {
                _clearUnitStateMove(owner);
                return(true);
            }

            bool targetMoved = false;

            recheckDistance.Update((int)time_diff);
            if (recheckDistance.Passed())
            {
                recheckDistance.Reset(100);
                //More distance let have better performance, less distance let have more sensitive reaction at target move.
                float allowed_dist = 0.0f;// owner.GetCombatReach() + WorldConfig.GetFloatValue(WorldCfg.RateTargetPosRecalculationRange);

                if (owner.IsPet() && (owner.GetCharmerOrOwnerGUID() == Target.GetGUID()))
                {
                    allowed_dist = 1.0f; // pet following owner
                }
                else
                {
                    allowed_dist = owner.GetCombatReach() + WorldConfig.GetFloatValue(WorldCfg.RateTargetPosRecalculationRange);
                }

                Vector3 dest = owner.MoveSpline.FinalDestination();
                if (owner.MoveSpline.onTransport)
                {
                    float      o         = 0;
                    ITransport transport = owner.GetDirectTransport();
                    if (transport != null)
                    {
                        transport.CalculatePassengerPosition(ref dest.X, ref dest.Y, ref dest.Z, ref o);
                    }
                }

                // First check distance
                if (owner.IsTypeId(TypeId.Unit) && (owner.ToCreature().CanFly() || owner.ToCreature().CanSwim()))
                {
                    targetMoved = !Target.IsWithinDist3d(dest.X, dest.Y, dest.Z, allowed_dist);
                }
                else
                {
                    targetMoved = !Target.IsWithinDist2d(dest.X, dest.Y, allowed_dist);
                }


                // then, if the target is in range, check also Line of Sight.
                if (!targetMoved)
                {
                    targetMoved = !Target.IsWithinLOSInMap(owner);
                }
            }

            if (recalculateTravel || targetMoved)
            {
                _setTargetLocation(owner, targetMoved);
            }

            if (owner.MoveSpline.Finalized())
            {
                MovementInform(owner);
                if (angle == 0.0f && !owner.HasInArc(0.01f, Target))
                {
                    owner.SetInFront(Target);
                }

                if (!targetReached)
                {
                    targetReached = true;
                    _reachTarget(owner);
                }
            }

            return(true);
        }
예제 #6
0
        bool StartMove(Creature creature)
        {
            if (path == null || path.Empty())
            {
                return(false);
            }

            if (Stopped())
            {
                return(true);
            }

            bool transportPath = creature.GetTransport() != null;

            if (isArrivalDone)
            {
                if ((currentNode == path.Count - 1) && !repeating) // If that's our last waypoint
                {
                    WaypointData waypoint = path.LookupByIndex((int)currentNode);

                    float x = waypoint.x;
                    float y = waypoint.y;
                    float z = waypoint.z;
                    float o = creature.GetOrientation();

                    if (!transportPath)
                    {
                        creature.SetHomePosition(x, y, z, o);
                    }
                    else
                    {
                        Transport trans = creature.GetTransport();
                        if (trans)
                        {
                            o -= trans.GetOrientation();
                            creature.SetTransportHomePosition(x, y, z, o);
                            trans.CalculatePassengerPosition(ref x, ref y, ref z, ref o);
                            creature.SetHomePosition(x, y, z, o);
                        }
                        else
                        {
                            transportPath = false;
                        }
                        // else if (vehicle) - this should never happen, vehicle offsets are const
                    }

                    creature.GetMotionMaster().Initialize();
                    return(false);
                }

                currentNode = (uint)((currentNode + 1) % path.Count);
            }

            var node = path.LookupByIndex((int)currentNode);

            isArrivalDone = false;

            creature.AddUnitState(UnitState.RoamingMove);

            Position       formationDest = new Position(node.x, node.y, node.z, (node.orientation != 0 && node.delay != 0) ? node.orientation : 0.0f);
            MoveSplineInit init          = new MoveSplineInit(creature);

            //! If creature is on transport, we assume waypoints set in DB are already transport offsets
            if (transportPath)
            {
                init.DisableTransportPathTransformations();
                ITransport trans = creature.GetDirectTransport();
                if (trans != null)
                {
                    float orientation = formationDest.GetOrientation();
                    trans.CalculatePassengerPosition(ref formationDest.posX, ref formationDest.posY, ref formationDest.posZ, ref orientation);
                    formationDest.SetOrientation(orientation);
                }
            }

            //! Do not use formationDest here, MoveTo requires transport offsets due to DisableTransportPathTransformations() call
            //! but formationDest contains global coordinates
            init.MoveTo(node.x, node.y, node.z);

            //! Accepts angles such as 0.00001 and -0.00001, 0 must be ignored, default value in waypoint table
            if (node.orientation != 0 && node.delay != 0)
            {
                init.SetFacing(node.orientation);
            }

            switch (node.moveType)
            {
            case WaypointMoveType.Land:
                init.SetAnimation(AnimType.ToGround);
                break;

            case WaypointMoveType.Takeoff:
                init.SetAnimation(AnimType.ToFly);
                break;

            case WaypointMoveType.Run:
                init.SetWalk(false);
                break;

            case WaypointMoveType.Walk:
                init.SetWalk(true);
                break;
            }

            init.Launch();

            //Call for creature group update
            if (creature.GetFormation() != null && creature.GetFormation().GetLeader() == creature)
            {
                creature.GetFormation().LeaderMoveTo(formationDest, node.id, (uint)node.moveType, (node.orientation != 0 && node.delay != 0) ? true : false);
            }

            return(true);
        }
예제 #7
0
        bool StartMove(Creature creature)
        {
            if (!creature || !creature.IsAlive())
            {
                return(false);
            }

            if (path == null || path.nodes.Empty())
            {
                return(false);
            }

            if (Stopped())
            {
                return(true);
            }

            bool transportPath = creature.GetTransport() != null;

            if (isArrivalDone)
            {
                if ((currentNode == path.nodes.Count - 1) && !repeating) // If that's our last waypoint
                {
                    WaypointNode waypoint = path.nodes.LookupByIndex((int)currentNode);

                    float x = waypoint.x;
                    float y = waypoint.y;
                    float z = waypoint.z;
                    float o = creature.GetOrientation();

                    if (!transportPath)
                    {
                        creature.SetHomePosition(x, y, z, o);
                    }
                    else
                    {
                        Transport trans = creature.GetTransport();
                        if (trans)
                        {
                            o -= trans.GetOrientation();
                            creature.SetTransportHomePosition(x, y, z, o);
                            trans.CalculatePassengerPosition(ref x, ref y, ref z, ref o);
                            creature.SetHomePosition(x, y, z, o);
                        }
                        else
                        {
                            transportPath = false;
                        }
                        // else if (vehicle) - this should never happen, vehicle offsets are const
                    }

                    return(false);
                }

                currentNode = (uint)((currentNode + 1) % path.nodes.Count);
            }

            float            finalOrient = 0.0f;
            WaypointMoveType finalMove   = WaypointMoveType.Walk;

            List <Vector3> pathing = new List <Vector3>();

            pathing.Add(new Vector3(creature.GetPositionX(), creature.GetPositionY(), creature.GetPositionZ()));
            for (int i = (int)currentNode; i < path.nodes.Count; ++i)
            {
                WaypointNode waypoint = path.nodes.LookupByIndex(i);

                pathing.Add(new Vector3(waypoint.x, waypoint.y, waypoint.z));

                finalOrient = waypoint.orientation;
                finalMove   = waypoint.moveType;

                if (waypoint.delay != 0)
                {
                    break;
                }
            }

            // if we have only 1 point, only current position, we shall return
            if (pathing.Count < 2)
            {
                return(false);
            }

            isArrivalDone    = false;
            recalculateSpeed = false;

            creature.AddUnitState(UnitState.RoamingMove);

            MoveSplineInit init          = new MoveSplineInit(creature);
            var            node          = path.nodes.LookupByIndex((int)currentNode);
            Position       formationDest = new Position(node.x, node.y, node.z, 0.0f);

            //! If creature is on transport, we assume waypoints set in DB are already transport offsets
            if (transportPath)
            {
                init.DisableTransportPathTransformations();
                ITransport trans = creature.GetDirectTransport();
                if (trans != null)
                {
                    trans.CalculatePassengerPosition(ref formationDest.posX, ref formationDest.posY, ref formationDest.posZ, ref formationDest.Orientation);
                }
            }

            init.MovebyPath(pathing.ToArray(), (int)currentNode);
            switch (finalMove)
            {
            case WaypointMoveType.Land:
                init.SetAnimation(AnimType.ToGround);
                break;

            case WaypointMoveType.Takeoff:
                init.SetAnimation(AnimType.ToFly);
                break;

            case WaypointMoveType.Run:
                init.SetWalk(false);
                break;

            case WaypointMoveType.Walk:
                init.SetWalk(true);
                break;
            }

            if (finalOrient != 0.0f)
            {
                init.SetFacing(finalOrient);
            }

            init.Launch();

            //Call for creature group update
            if (creature.GetFormation() != null && creature.GetFormation().getLeader() == creature)
            {
                creature.GetFormation().LeaderMoveTo(formationDest.posX, formationDest.posY, formationDest.posZ);
            }

            return(true);
        }
예제 #8
0
        bool StartMove(Creature creature)
        {
            if (!creature || !creature.IsAlive())
            {
                return(true);
            }

            if (_done || _path == null || _path.nodes.Empty())
            {
                return(true);
            }

            // if the owner is the leader of its formation, check members status
            if (creature.IsFormationLeader() && !creature.IsFormationLeaderMoveAllowed())
            {
                _nextMoveTime.Reset(1000);
                return(true);
            }

            bool transportPath = creature.GetTransport() != null;

            if (_isArrivalDone)
            {
                Cypher.Assert(_currentNode < _path.nodes.Count, $"WaypointMovementGenerator.StartMove: tried to reference a node id ({_currentNode}) which is not included in path ({_path.id})");
                WaypointNode lastWaypoint = _path.nodes.ElementAt(_currentNode);
                if ((_currentNode == _path.nodes.Count - 1) && !_repeating) // If that's our last waypoint
                {
                    float x = lastWaypoint.x;
                    float y = lastWaypoint.y;
                    float z = lastWaypoint.z;
                    float o = creature.GetOrientation();

                    if (!transportPath)
                    {
                        creature.SetHomePosition(x, y, z, o);
                    }
                    else
                    {
                        Transport trans = creature.GetTransport();
                        if (trans)
                        {
                            o -= trans.GetOrientation();
                            creature.SetTransportHomePosition(x, y, z, o);
                            trans.CalculatePassengerPosition(ref x, ref y, ref z, ref o);
                            creature.SetHomePosition(x, y, z, o);
                        }
                        else
                        {
                            transportPath = false;
                        }
                        // else if (vehicle) - this should never happen, vehicle offsets are const
                    }
                    _done = true;
                    creature.UpdateCurrentWaypointInfo(0, 0);

                    // inform AI
                    if (creature.IsAIEnabled)
                    {
                        creature.GetAI().WaypointPathEnded(lastWaypoint.id, _path.id);
                    }
                    return(true);
                }

                _currentNode = (_currentNode + 1) % _path.nodes.Count;

                // inform AI
                if (creature.IsAIEnabled)
                {
                    creature.GetAI().WaypointStarted(lastWaypoint.id, _path.id);
                }
            }

            Cypher.Assert(_currentNode < _path.nodes.Count, $"WaypointMovementGenerator.StartMove: tried to reference a node id ({_currentNode}) which is not included in path ({_path.id})");
            WaypointNode waypoint      = _path.nodes.ElementAt(_currentNode);
            Position     formationDest = new(waypoint.x, waypoint.y, waypoint.z, (waypoint.orientation != 0 && waypoint.delay != 0) ? waypoint.orientation : 0.0f);

            _isArrivalDone    = false;
            _recalculateSpeed = false;

            creature.AddUnitState(UnitState.RoamingMove);

            MoveSplineInit init = new(creature);

            //! If creature is on transport, we assume waypoints set in DB are already transport offsets
            if (transportPath)
            {
                init.DisableTransportPathTransformations();
                ITransport trans = creature.GetDirectTransport();
                if (trans != null)
                {
                    float orientation = formationDest.GetOrientation();
                    trans.CalculatePassengerPosition(ref formationDest.posX, ref formationDest.posY, ref formationDest.posZ, ref orientation);
                    formationDest.SetOrientation(orientation);
                }
            }

            //! Do not use formationDest here, MoveTo requires transport offsets due to DisableTransportPathTransformations() call
            //! but formationDest contains global coordinates
            init.MoveTo(waypoint.x, waypoint.y, waypoint.z);

            //! Accepts angles such as 0.00001 and -0.00001, 0 must be ignored, default value in waypoint table
            if (waypoint.orientation != 0 && waypoint.delay != 0)
            {
                init.SetFacing(waypoint.orientation);
            }

            switch (waypoint.moveType)
            {
            case WaypointMoveType.Land:
                init.SetAnimation(AnimType.ToGround);
                break;

            case WaypointMoveType.Takeoff:
                init.SetAnimation(AnimType.ToFly);
                break;

            case WaypointMoveType.Run:
                init.SetWalk(false);
                break;

            case WaypointMoveType.Walk:
                init.SetWalk(true);
                break;
            }

            init.Launch();

            // inform formation
            creature.SignalFormationMovement(formationDest, waypoint.id, waypoint.moveType, (waypoint.orientation != 0 && waypoint.delay != 0) ? true : false);
            return(true);
        }