AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
CreatureGroup Class Reference

#include "CreatureGroups.h"

Public Types

typedef std::map< Creature *, FormationInfoCreatureGroupMemberType
 

Public Member Functions

 CreatureGroup (uint32 id)
 
 ~CreatureGroup ()
 
CreatureGetLeader () const
 
uint32 GetId () const
 
bool IsEmpty () const
 
bool IsFormed () const
 
const CreatureGroupMemberTypeGetMembers () const
 
void AddMember (Creature *member)
 
void RemoveMember (Creature *member)
 
void FormationReset (bool dismiss, bool initMotionMaster)
 
void LeaderMoveTo (float x, float y, float z, bool run)
 
void MemberEngagingTarget (Creature *member, Unit *target)
 
UnitGetNewTargetForMember (Creature *member)
 
void MemberEvaded (Creature *member)
 
void RespawnFormation (bool force=false)
 
bool IsFormationInCombat ()
 
bool IsAnyMemberAlive (bool ignoreLeader=false)
 

Private Attributes

Creaturem_leader
 
CreatureGroupMemberType m_members
 
uint32 m_groupID
 
bool m_Formed
 

Detailed Description

Member Typedef Documentation

◆ CreatureGroupMemberType

Constructor & Destructor Documentation

◆ CreatureGroup()

CreatureGroup::CreatureGroup ( uint32  id)
inlineexplicit
95: m_leader(nullptr), m_groupID(id), m_Formed(false) {}
bool m_Formed
Definition: CreatureGroups.h:123
Creature * m_leader
Definition: CreatureGroups.h:119
uint32 m_groupID
Definition: CreatureGroups.h:122

◆ ~CreatureGroup()

CreatureGroup::~CreatureGroup ( )
inline
96{}

Member Function Documentation

◆ AddMember()

void CreatureGroup::AddMember ( Creature member)
168{
169 LOG_DEBUG("entities.unit", "CreatureGroup::AddMember: Adding unit {}.", member->GetGUID().ToString());
170
171 //Check if it is a leader
172 if (member->GetSpawnId() == m_groupID)
173 {
174 LOG_DEBUG("entities.unit", "Unit {} is formation leader. Adding group.", member->GetGUID().ToString());
175 m_leader = member;
176 }
177
178 m_members[member] = sFormationMgr->CreatureGroupMap.find(member->GetSpawnId())->second;
179 member->SetFormation(this);
180}
#define LOG_DEBUG(filterType__,...)
Definition: Log.h:171
#define sFormationMgr
Definition: CreatureGroups.h:126
ObjectGuid::LowType GetSpawnId() const
Definition: Creature.h:67
void SetFormation(CreatureGroup *formation)
Definition: Creature.h:347
CreatureGroupMemberType m_members
Definition: CreatureGroups.h:120
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:106
std::string ToString() const
Definition: ObjectGuid.cpp:47

References Object::GetGUID(), Creature::GetSpawnId(), LOG_DEBUG, m_groupID, m_leader, m_members, Creature::SetFormation(), sFormationMgr, and ObjectGuid::ToString().

Referenced by FormationMgr::AddCreatureToGroup().

◆ FormationReset()

void CreatureGroup::FormationReset ( bool  dismiss,
bool  initMotionMaster 
)
335{
336 if (m_members.size() && !(m_members.begin()->second.HasGroupFlag(std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_FOLLOW_LEADER))))
337 {
338 return;
339 }
340
341 for (auto const& itr : m_members)
342 {
343 Creature* member = itr.first;
344 if (member && member != m_leader && member->IsAlive())
345 {
346 if (initMotionMaster)
347 {
348 if (dismiss)
349 {
350 member->GetMotionMaster()->Initialize();
351 }
352 else
353 {
354 member->GetMotionMaster()->MoveIdle();
355 }
356 LOG_DEBUG("entities.unit", "Set {} movement for member {}", dismiss ? "default" : "idle", member->GetGUID().ToString());
357 }
358 }
359 }
360 m_Formed = !dismiss;
361}
Definition: Creature.h:46
MotionMaster * GetMotionMaster()
Definition: Unit.h:2262
bool IsAlive() const
Definition: Unit.h:1808
void Initialize()
Definition: MotionMaster.cpp:72
void MoveIdle()
Definition: MotionMaster.cpp:231

References Object::GetGUID(), Unit::GetMotionMaster(), MotionMaster::Initialize(), Unit::IsAlive(), LOG_DEBUG, m_Formed, m_leader, m_members, MotionMaster::MoveIdle(), and ObjectGuid::ToString().

Referenced by Creature::Motion_Initialize(), and Creature::setDeathState().

◆ GetId()

uint32 CreatureGroup::GetId ( ) const
inline

◆ GetLeader()

◆ GetMembers()

const CreatureGroupMemberType & CreatureGroup::GetMembers ( ) const
inline
104{ return m_members; }

References m_members.

◆ GetNewTargetForMember()

Unit * CreatureGroup::GetNewTargetForMember ( Creature member)
234{
235 uint8 const groupAI = sFormationMgr->CreatureGroupMap[member->GetSpawnId()].groupAI;
236 if (!(groupAI & std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_ACQUIRE_NEW_TARGET_ON_EVADE)))
237 {
238 return nullptr;
239 }
240
241 if (member == m_leader)
242 {
243 if (!(groupAI & std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_MEMBER_ASSIST_LEADER)))
244 {
245 return nullptr;
246 }
247 }
248 else if (!(groupAI & std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_LEADER_ASSIST_MEMBER)))
249 {
250 return nullptr;
251 }
252
253 for (auto const& itr : m_members)
254 {
255 Creature* pMember = itr.first;
256 if (!pMember)
257 {
258 continue;
259 }
260
261 if (pMember == member || !pMember->IsAlive() || !pMember->GetVictim())
262 {
263 continue;
264 }
265
266 if (pMember == m_leader && !(groupAI & std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_MEMBER_ASSIST_LEADER)))
267 {
268 continue;
269 }
270
271 if (member->IsValidAttackTarget(pMember->GetVictim()))
272 {
273 return pMember->GetVictim();
274 }
275 }
276
277 return nullptr;
278}
std::uint8_t uint8
Definition: Define.h:110
Unit * GetVictim() const
Definition: Unit.h:1386
bool IsValidAttackTarget(Unit const *target, SpellInfo const *bySpell=nullptr) const
Definition: Unit.cpp:13776

References Creature::GetSpawnId(), Unit::GetVictim(), Unit::IsAlive(), Unit::IsValidAttackTarget(), m_leader, m_members, and sFormationMgr.

◆ IsAnyMemberAlive()

bool CreatureGroup::IsAnyMemberAlive ( bool  ignoreLeader = false)
461{
462 for (auto const& itr : m_members)
463 {
464 if (itr.first && itr.first->IsAlive())
465 {
466 if (!ignoreLeader || itr.first != m_leader)
467 {
468 return true;
469 }
470 }
471 }
472
473 return false;
474}

References m_leader, and m_members.

◆ IsEmpty()

bool CreatureGroup::IsEmpty ( ) const
inline
101{ return m_members.empty(); }

References m_members.

Referenced by FormationMgr::RemoveCreatureFromGroup().

◆ IsFormationInCombat()

bool CreatureGroup::IsFormationInCombat ( )
448{
449 for (auto const& itr : m_members)
450 {
451 if (itr.first && itr.first->IsInCombat())
452 {
453 return true;
454 }
455 }
456
457 return false;
458}

References m_members.

◆ IsFormed()

bool CreatureGroup::IsFormed ( ) const
inline
102{ return m_Formed; }

References m_Formed.

Referenced by Creature::Motion_Initialize(), and npc_cameron::UpdateAI().

◆ LeaderMoveTo()

void CreatureGroup::LeaderMoveTo ( float  x,
float  y,
float  z,
bool  run 
)

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.

364{
367 if (!m_leader)
368 {
369 return;
370 }
371
372 float pathDist = m_leader->GetExactDist(x, y, z);
373 float pathAngle = std::atan2(m_leader->GetPositionY() - y, m_leader->GetPositionX() - x);
374
375 for (auto const& itr : m_members)
376 {
377 Creature* member = itr.first;
378 FormationInfo const& pFormationInfo = itr.second;
379 if (member == m_leader || !member->IsAlive() || member->GetVictim() || !pFormationInfo.HasGroupFlag(std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_FOLLOW_LEADER)))
380 {
381 continue;
382 }
383
384 // Xinef: If member is stunned / rooted etc don't allow to move him
386 {
387 continue;
388 }
389
390 // Xinef: this should be automatized, if turn angle is greater than PI/2 (90�) we should swap formation angle
391 float followAngle = pFormationInfo.follow_angle;
392 if (static_cast<float>(M_PI) - std::fabs(std::fabs(m_leader->GetOrientation() - pathAngle) - static_cast<float>(M_PI)) > static_cast<float>(M_PI)* 0.5f)
393 {
394 // pussywizard: in both cases should be 2*M_PI - follow_angle
395 // pussywizard: also, GetCurrentWaypointID() returns 0..n-1, while point_1 must be > 0, so +1
396 // pussywizard: db table waypoint_data shouldn't have point id 0 and shouldn't have any gaps for this to work!
397 // if (m_leader->GetCurrentWaypointID()+1 == pFormationInfo->point_1 || m_leader->GetCurrentWaypointID()+1 == itr->second->point_2)
398 followAngle = Position::NormalizeOrientation(pFormationInfo.follow_angle + static_cast<float>(M_PI)); //(2 * M_PI) - itr->second->follow_angle;
399 }
400
401 float const followDist = pFormationInfo.follow_dist;
402
403 float dx = x + std::cos(followAngle + pathAngle) * followDist;
404 float dy = y + std::sin(followAngle + pathAngle) * followDist;
405 float dz = z;
406
409 member->UpdateGroundPositionZ(dx, dy, dz);
410
412 // pussywizard: setting the same movementflags is not enough, spline decides whether leader walks/runs, so spline param is now passed as "run" parameter to this function
413 if (run && member->IsWalking())
414 {
416 }
417 else if (!run && !member->IsWalking())
418 {
420 }
421
422 // xinef: if we move members to position without taking care of sizes, we should compare distance without sizes
423 // xinef: change members speed basing on distance - if too far speed up, if too close slow down
425 float const speedRate = m_leader->GetSpeedRate(mtype) * member->GetExactDist(dx, dy, dz) / pathDist;
426
427 if (speedRate > 0.01f) // don't move if speed rate is too low
428 {
429 member->SetSpeedRate(mtype, speedRate);
430 member->GetMotionMaster()->MovePoint(0, dx, dy, dz);
431 member->SetHomePosition(dx, dy, dz, pathAngle);
432 }
433 }
434}
@ MOVEMENTFLAG_WALKING
Definition: Unit.h:560
@ UNIT_STATE_NOT_MOVE
Definition: Unit.h:371
UnitMoveType
Definition: Unit.h:377
void NormalizeMapCoord(float &c)
Definition: GridDefines.h:208
UnitMoveType SelectSpeedType(uint32 moveFlags)
Definition: MoveSplineInit.cpp:29
void SetHomePosition(float x, float y, float z, float o)
Definition: Creature.h:328
Definition: CreatureGroups.h:51
float follow_dist
Definition: CreatureGroups.h:63
float follow_angle
Definition: CreatureGroups.h:64
bool HasGroupFlag(uint16 flag) const
Definition: CreatureGroups.h:69
void UpdateGroundPositionZ(float x, float y, float &z) const
Definition: Object.cpp:1530
float GetExactDist(float x, float y, float z) const
Definition: Position.h:178
static float NormalizeOrientation(float o)
Definition: Position.h:233
float GetOrientation() const
Definition: Position.h:120
float GetPositionX() const
Definition: Position.h:117
float GetPositionY() const
Definition: Position.h:118
uint32 GetUnitMovementFlags() const
Definition: Unit.h:2275
void SetUnitMovementFlags(uint32 f)
Definition: Unit.h:2276
void AddUnitMovementFlag(uint32 f)
Definition: Unit.h:2272
float GetSpeedRate(UnitMoveType mtype) const
Definition: Unit.h:2248
void SetSpeedRate(UnitMoveType mtype, float rate)
Definition: Unit.h:2250
bool HasUnitState(const uint32 f) const
Definition: Unit.h:1398
void RemoveUnitMovementFlag(uint32 f)
Definition: Unit.h:2273
bool IsWalking() const
Definition: Unit.h:2379
void MovePoint(uint32 id, const Position &pos, bool generatePath=true, bool forceDestination=true)
Definition: MotionMaster.h:210

References Unit::AddUnitMovementFlag(), FormationInfo::follow_angle, FormationInfo::follow_dist, Position::GetExactDist(), Unit::GetMotionMaster(), Position::GetOrientation(), Position::GetPositionX(), Position::GetPositionY(), Unit::GetSpeedRate(), Unit::GetUnitMovementFlags(), Unit::GetVictim(), FormationInfo::HasGroupFlag(), Unit::HasUnitState(), Unit::IsAlive(), Unit::IsWalking(), m_leader, m_members, MOVEMENTFLAG_WALKING, MotionMaster::MovePoint(), Acore::NormalizeMapCoord(), Position::NormalizeOrientation(), Unit::RemoveUnitMovementFlag(), Movement::SelectSpeedType(), Creature::SetHomePosition(), Unit::SetSpeedRate(), Unit::SetUnitMovementFlags(), UNIT_STATE_NOT_MOVE, and WorldObject::UpdateGroundPositionZ().

Referenced by RandomMovementGenerator< T >::_setRandomLocation(), and WaypointMovementGenerator< Creature >::StartMove().

◆ MemberEngagingTarget()

void CreatureGroup::MemberEngagingTarget ( Creature member,
Unit target 
)
194{
195 uint8 const groupAI = sFormationMgr->CreatureGroupMap[member->GetSpawnId()].groupAI;
196 if (member == m_leader)
197 {
198 if (!(groupAI & std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_MEMBER_ASSIST_LEADER)))
199 {
200 return;
201 }
202 }
203 else if (!(groupAI & std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_LEADER_ASSIST_MEMBER)))
204 {
205 return;
206 }
207
208 for (auto const& itr : m_members)
209 {
210 Creature* pMember = itr.first;
211 if (!pMember)
212 {
213 continue;
214 }
215
216 if (pMember == member || !pMember->IsAlive() || pMember->GetVictim())
217 {
218 continue;
219 }
220
221 if (pMember == m_leader && !(groupAI & std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_LEADER_ASSIST_MEMBER)))
222 {
223 continue;
224 }
225
226 if (pMember->IsValidAttackTarget(target) && pMember->AI())
227 {
228 pMember->AI()->AttackStart(target);
229 }
230 }
231}
virtual void AttackStart(Unit *)
Definition: UnitAI.cpp:28
CreatureAI * AI() const
Definition: Creature.h:135

References Creature::AI(), UnitAI::AttackStart(), Creature::GetSpawnId(), Unit::GetVictim(), Unit::IsAlive(), Unit::IsValidAttackTarget(), m_leader, m_members, and sFormationMgr.

◆ MemberEvaded()

void CreatureGroup::MemberEvaded ( Creature member)
281{
282 uint8 const groupAI = sFormationMgr->CreatureGroupMap[member->GetSpawnId()].groupAI;
283 if (!(groupAI & std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_EVADE_MASK)))
284 {
285 return;
286 }
287
288 for (auto const& itr : m_members)
289 {
290 Creature* pMember = itr.first;
291 // This should never happen
292 if (!pMember)
293 {
294 continue;
295 }
296
297 if (pMember == member || pMember->IsInEvadeMode() || !itr.second.HasGroupFlag(std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_EVADE_MASK)))
298 {
299 continue;
300 }
301
302 if (itr.second.HasGroupFlag(std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_EVADE_TOGETHER)))
303 {
304 if (!pMember->IsAlive() || !pMember->IsInCombat())
305 {
306 continue;
307 }
308
309 if (pMember->IsAIEnabled)
310 {
311 if (CreatureAI* pMemberAI = pMember->AI())
312 {
313 pMemberAI->EnterEvadeMode();
314 }
315 }
316 }
317 else
318 {
319 if (pMember->IsAlive())
320 {
321 continue;
322 }
323
324 if (itr.second.HasGroupFlag(std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_DONT_RESPAWN_LEADER_ON_EVADE)) && pMember == m_leader)
325 {
326 continue;
327 }
328
329 pMember->Respawn();
330 }
331 }
332}
Definition: CreatureAI.h:70
void Respawn(bool force=false)
Definition: Creature.cpp:2005
bool IsInEvadeMode() const
Definition: Creature.h:129
bool IsAIEnabled
Definition: Unit.h:2350
bool IsInCombat() const
Definition: Unit.h:1688

References Creature::AI(), Creature::GetSpawnId(), Unit::IsAIEnabled, Unit::IsAlive(), Unit::IsInCombat(), Creature::IsInEvadeMode(), m_leader, m_members, Creature::Respawn(), and sFormationMgr.

◆ RemoveMember()

void CreatureGroup::RemoveMember ( Creature member)
183{
184 if (m_leader == member)
185 {
186 m_leader = nullptr;
187 }
188
189 m_members.erase(member);
190 member->SetFormation(nullptr);
191}

References m_leader, m_members, and Creature::SetFormation().

Referenced by FormationMgr::RemoveCreatureFromGroup().

◆ RespawnFormation()

void CreatureGroup::RespawnFormation ( bool  force = false)
437{
438 for (auto const& itr : m_members)
439 {
440 if (itr.first && !itr.first->IsAlive())
441 {
442 itr.first->Respawn(force);
443 }
444 }
445}

References m_members.

Member Data Documentation

◆ m_Formed

bool CreatureGroup::m_Formed
private

Referenced by FormationReset(), and IsFormed().

◆ m_groupID

uint32 CreatureGroup::m_groupID
private

Referenced by AddMember(), and GetId().

◆ m_leader

◆ m_members