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); } }
public void MemberAttackStart(Creature member, Unit target) { GroupAIFlags groupAI = (GroupAIFlags)FormationMgr.CreatureGroupMap[member.GetSpawnId()].groupAI; if (groupAI == 0) { return; } if (member == m_leader) { if (!groupAI.HasAnyFlag(GroupAIFlags.MembersAssistLeader)) { return; } } else if (!groupAI.HasAnyFlag(GroupAIFlags.LeaderAssistsMember)) { return; } foreach (var pair in m_members) { if (m_leader) // avoid crash if leader was killed and reset. { Log.outDebug(LogFilter.Unit, "GROUP ATTACK: group instance id {0} calls member instid {1}", m_leader.GetInstanceId(), member.GetInstanceId()); } Creature other = pair.Key; // Skip self if (other == member) { continue; } if (!other.IsAlive()) { continue; } if (other.GetVictim()) { continue; } if (((other != m_leader && groupAI.HasAnyFlag(GroupAIFlags.MembersAssistLeader)) || (other == m_leader && groupAI.HasAnyFlag(GroupAIFlags.LeaderAssistsMember))) && other.IsValidAttackTarget(target)) { other.GetAI().AttackStart(target); } } }
public void MemberEngagingTarget(Creature member, Unit target) { GroupAIFlags groupAI = (GroupAIFlags)FormationMgr.CreatureGroupMap[member.GetSpawnId()].groupAI; if (groupAI == 0) { return; } if (member == m_leader) { if (!groupAI.HasAnyFlag(GroupAIFlags.MembersAssistLeader)) { return; } } else if (!groupAI.HasAnyFlag(GroupAIFlags.LeaderAssistsMember)) { return; } foreach (var pair in m_members) { Creature other = pair.Key; // Skip self if (other == member) { continue; } if (!other.IsAlive()) { continue; } if (((other != m_leader && groupAI.HasAnyFlag(GroupAIFlags.MembersAssistLeader)) || (other == m_leader && groupAI.HasAnyFlag(GroupAIFlags.LeaderAssistsMember))) && other.IsValidAttackTarget(target)) { other.EngageWithTarget(target); } } }