public void LeaderMoveTo(float x, float y, float z) { //! To do: This should probably get its own movement generator or use WaypointMovementGenerator. //! If the leader's path is known, member's path can be plotted as well using formation offsets. if (!m_leader) { return; } float pathangle = (float)Math.Atan2(m_leader.GetPositionY() - y, m_leader.GetPositionX() - x); foreach (var pair in m_members) { Creature member = pair.Key; if (member == m_leader || !member.IsAlive() || member.GetVictim() || !pair.Value.groupAI.HasAnyFlag((uint)GroupAIFlags.IdleInFormation)) { continue; } if (pair.Value.point_1 != 0) { if (m_leader.GetCurrentWaypointID() == pair.Value.point_1 - 1 || m_leader.GetCurrentWaypointID() == pair.Value.point_2 - 1) { pair.Value.follow_angle = (float)Math.PI * 2 - pair.Value.follow_angle; } } float angle = pair.Value.follow_angle; float dist = pair.Value.follow_dist; float dx = x + (float)Math.Cos(angle + pathangle) * dist; float dy = y + (float)Math.Sin(angle + pathangle) * dist; float dz = z; GridDefines.NormalizeMapCoord(ref dx); GridDefines.NormalizeMapCoord(ref dy); if (!member.IsFlying()) { member.UpdateGroundPositionZ(dx, dy, ref dz); } if (member.IsWithinDist(m_leader, dist + 5.0f)) { member.SetUnitMovementFlags(m_leader.GetUnitMovementFlags()); } else { member.SetWalk(false); } member.GetMotionMaster().MovePoint(0, dx, dy, dz); member.SetHomePosition(dx, dy, dz, pathangle); } }