Example #1
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));
        }