void MotionMaster::MoveSmoothPath(uint32 pointId, Position const* pathPoints, size_t pathSize, bool walk) { Movement::MoveSplineInit init(_owner); Movement::PointsArray path; path.reserve(pathSize); std::transform(pathPoints, pathPoints + pathSize, std::back_inserter(path), [](Position const& point) { return G3D::Vector3(point.GetPositionX(), point.GetPositionY(), point.GetPositionZ()); }); init.MovebyPath(path); init.SetSmooth(); init.SetWalk(walk); // This code is not correct // GenericMovementGenerator does not affect UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE // need to call PointMovementGenerator with various pointIds Mutate(new GenericMovementGenerator(std::move(init), EFFECT_MOTION_TYPE, pointId), MOTION_SLOT_ACTIVE); }
bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature) { if (!creature || !creature->IsAlive()) return false; if (!i_path || i_path->nodes.empty()) return false; bool transportPath = creature->GetTransport() != nullptr; if (IsArrivalDone) { if ((i_currentNode == i_path->nodes.size() - 1) && !repeating) // If that's our last waypoint { WaypointNode const &waypoint = i_path->nodes.at(i_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 { if (Transport* trans = creature->GetTransport()) { o -= trans->GetOrientation(); creature->SetTransportHomePosition(x, y, z, o); trans->CalculatePassengerPosition(x, y, z, &o); creature->SetHomePosition(x, y, z, o); } else transportPath = false; // else if (vehicle) - this should never happen, vehicle offsets are const } return false; } i_currentNode = (i_currentNode + 1) % i_path->nodes.size(); } float finalOrient = 0.0f; uint8 finalMove = WAYPOINT_MOVE_TYPE_WALK; Movement::PointsArray pathing; pathing.reserve((i_path->nodes.size() - i_currentNode) + 1); pathing.push_back(G3D::Vector3(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ())); for (uint32 i = i_currentNode; i < i_path->nodes.size(); ++i) { WaypointNode const &waypoint = i_path->nodes.at(i); pathing.push_back(G3D::Vector3(waypoint.x, waypoint.y, waypoint.z)); finalOrient = waypoint.orientation; finalMove = waypoint.moveType; if (waypoint.delay) break; } // if we have only 1 point, only current position, we shall return if (pathing.size() < 2) return false; IsArrivalDone = false; i_recalculateSpeed = false; creature->AddUnitState(UNIT_STATE_ROAMING_MOVE); Movement::MoveSplineInit init(creature); Movement::Location formationDest(i_path->nodes.at(i_currentNode).x, i_path->nodes.at(i_currentNode).y, i_path->nodes.at(i_currentNode).z, 0.0f); //! If creature is on transport, we assume waypoints set in DB are already transport offsets if (transportPath) { init.DisableTransportPathTransformations(); if (TransportBase* trans = creature->GetDirectTransport()) trans->CalculatePassengerPosition(formationDest.x, formationDest.y, formationDest.z, &formationDest.orientation); } init.MovebyPath(pathing, i_currentNode); switch (finalMove) { case WAYPOINT_MOVE_TYPE_LAND: init.SetAnimation(Movement::ToGround); break; case WAYPOINT_MOVE_TYPE_TAKEOFF: init.SetAnimation(Movement::ToFly); break; case WAYPOINT_MOVE_TYPE_RUN: init.SetWalk(false); break; case WAYPOINT_MOVE_TYPE_WALK: init.SetWalk(true); break; } if (finalOrient != 0.0f) init.SetFacing(finalOrient); init.Launch(); //Call for creature group update if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature) creature->GetFormation()->LeaderMoveTo(formationDest.x, formationDest.y, formationDest.z); return true; }