mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-03-15 13:35:08 +00:00
refactor(Core/Movement): follower management of references (#25060)
Co-authored-by: Shauren <shauren.trinity@gmail.com>
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Unit.h"
|
#include "Unit.h"
|
||||||
|
#include "AbstractFollower.h"
|
||||||
#include "AreaDefines.h"
|
#include "AreaDefines.h"
|
||||||
#include "ArenaSpectator.h"
|
#include "ArenaSpectator.h"
|
||||||
#include "Battlefield.h"
|
#include "Battlefield.h"
|
||||||
@@ -44,7 +45,6 @@
|
|||||||
#include "MoveSpline.h"
|
#include "MoveSpline.h"
|
||||||
#include "MoveSplineInit.h"
|
#include "MoveSplineInit.h"
|
||||||
#include "MovementGenerator.h"
|
#include "MovementGenerator.h"
|
||||||
#include "AbstractFollower.h"
|
|
||||||
#include "ObjectAccessor.h"
|
#include "ObjectAccessor.h"
|
||||||
#include "ObjectMgr.h"
|
#include "ObjectMgr.h"
|
||||||
#include "OutdoorPvP.h"
|
#include "OutdoorPvP.h"
|
||||||
@@ -5530,12 +5530,8 @@ void Unit::RemoveAreaAurasDueToLeaveWorld()
|
|||||||
|
|
||||||
void Unit::RemoveAllFollowers()
|
void Unit::RemoveAllFollowers()
|
||||||
{
|
{
|
||||||
while (auto* ref = m_FollowingRefMgr.getFirst())
|
while (!m_followingMe.empty())
|
||||||
{
|
(*m_followingMe.begin())->SetTarget(nullptr);
|
||||||
auto* source = ref->GetSource();
|
|
||||||
ref->delink();
|
|
||||||
source->SetTarget(nullptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::RemoveAllAuras()
|
void Unit::RemoveAllAuras()
|
||||||
|
|||||||
@@ -20,8 +20,6 @@
|
|||||||
|
|
||||||
#include "EnumFlag.h"
|
#include "EnumFlag.h"
|
||||||
#include "EventProcessor.h"
|
#include "EventProcessor.h"
|
||||||
#include "FollowerRefMgr.h"
|
|
||||||
#include "FollowerReference.h"
|
|
||||||
#include "HostileRefMgr.h"
|
#include "HostileRefMgr.h"
|
||||||
#include "ItemTemplate.h"
|
#include "ItemTemplate.h"
|
||||||
#include "MotionMaster.h"
|
#include "MotionMaster.h"
|
||||||
@@ -74,6 +72,7 @@ class MotionTransport;
|
|||||||
class Vehicle;
|
class Vehicle;
|
||||||
class TransportBase;
|
class TransportBase;
|
||||||
class SpellCastTargets;
|
class SpellCastTargets;
|
||||||
|
class AbstractFollower;
|
||||||
|
|
||||||
typedef std::list<Unit*> UnitList;
|
typedef std::list<Unit*> UnitList;
|
||||||
typedef std::list< std::pair<Aura*, uint8> > DispelChargesList;
|
typedef std::list< std::pair<Aura*, uint8> > DispelChargesList;
|
||||||
@@ -1881,9 +1880,9 @@ public:
|
|||||||
[[nodiscard]] bool IsInDisallowedMountForm() const;
|
[[nodiscard]] bool IsInDisallowedMountForm() const;
|
||||||
|
|
||||||
// Followers
|
// Followers
|
||||||
void AddFollower(FollowerReference* ref) { m_FollowingRefMgr.insertFirst(ref); }
|
void FollowerAdded(AbstractFollower* f) { m_followingMe.insert(f); }
|
||||||
|
void FollowerRemoved(AbstractFollower* f) { m_followingMe.erase(f); }
|
||||||
[[nodiscard]] virtual float GetFollowAngle() const { return static_cast<float>(M_PI / 2); }
|
[[nodiscard]] virtual float GetFollowAngle() const { return static_cast<float>(M_PI / 2); }
|
||||||
void RemoveFollower(FollowerReference* /*ref*/ ) { /* nothing to do yet */ }
|
|
||||||
void RemoveAllFollowers();
|
void RemoveAllFollowers();
|
||||||
|
|
||||||
// Pets, guardians, minions...
|
// Pets, guardians, minions...
|
||||||
@@ -2229,7 +2228,7 @@ private:
|
|||||||
// Manage all Units that are threatened by us
|
// Manage all Units that are threatened by us
|
||||||
HostileRefMgr m_HostileRefMgr;
|
HostileRefMgr m_HostileRefMgr;
|
||||||
|
|
||||||
FollowerRefMgr m_FollowingRefMgr;
|
std::unordered_set<AbstractFollower*> m_followingMe;
|
||||||
|
|
||||||
Unit* m_comboTarget;
|
Unit* m_comboTarget;
|
||||||
int8 m_comboPoints;
|
int8 m_comboPoints;
|
||||||
|
|||||||
@@ -20,9 +20,13 @@
|
|||||||
|
|
||||||
void AbstractFollower::SetTarget(Unit* unit)
|
void AbstractFollower::SetTarget(Unit* unit)
|
||||||
{
|
{
|
||||||
if (unit == GetTarget())
|
if (unit == _target)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
i_target.link(unit, this);
|
if (_target)
|
||||||
_target = i_target.getTarget();
|
_target->FollowerRemoved(this);
|
||||||
|
|
||||||
|
_target = unit;
|
||||||
|
if (_target)
|
||||||
|
_target->FollowerAdded(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,6 @@
|
|||||||
#ifndef ACORE_ABSTRACTFOLLOWER_H
|
#ifndef ACORE_ABSTRACTFOLLOWER_H
|
||||||
#define ACORE_ABSTRACTFOLLOWER_H
|
#define ACORE_ABSTRACTFOLLOWER_H
|
||||||
|
|
||||||
#include "FollowerReference.h"
|
|
||||||
|
|
||||||
class Unit;
|
class Unit;
|
||||||
|
|
||||||
class AbstractFollower
|
class AbstractFollower
|
||||||
@@ -29,15 +27,10 @@ public:
|
|||||||
virtual ~AbstractFollower() { SetTarget(nullptr); }
|
virtual ~AbstractFollower() { SetTarget(nullptr); }
|
||||||
|
|
||||||
void SetTarget(Unit* unit);
|
void SetTarget(Unit* unit);
|
||||||
Unit* GetTarget() const { return _target; }
|
[[nodiscard]] Unit* GetTarget() const { return _target; }
|
||||||
bool IsTargetValid() const { return i_target.isValid(); }
|
|
||||||
|
|
||||||
virtual void stopFollowing() { }
|
|
||||||
|
|
||||||
|
private:
|
||||||
Unit* _target = nullptr;
|
Unit* _target = nullptr;
|
||||||
|
|
||||||
protected:
|
|
||||||
FollowerReference i_target;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _FOLLOWERREFMANAGER
|
|
||||||
#define _FOLLOWERREFMANAGER
|
|
||||||
|
|
||||||
#include "RefMgr.h"
|
|
||||||
|
|
||||||
class Unit;
|
|
||||||
class AbstractFollower;
|
|
||||||
|
|
||||||
class FollowerRefMgr : public RefMgr<Unit, AbstractFollower>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "FollowerReference.h"
|
|
||||||
#include "AbstractFollower.h"
|
|
||||||
#include "Unit.h"
|
|
||||||
|
|
||||||
void FollowerReference::targetObjectBuildLink()
|
|
||||||
{
|
|
||||||
getTarget()->AddFollower(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FollowerReference::targetObjectDestroyLink()
|
|
||||||
{
|
|
||||||
getTarget()->RemoveFollower(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FollowerReference::sourceObjectDestroyLink()
|
|
||||||
{
|
|
||||||
GetSource()->stopFollowing();
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _FOLLOWERREFERENCE_H
|
|
||||||
#define _FOLLOWERREFERENCE_H
|
|
||||||
|
|
||||||
#include "Reference.h"
|
|
||||||
|
|
||||||
class AbstractFollower;
|
|
||||||
class Unit;
|
|
||||||
|
|
||||||
class FollowerReference : public Reference<Unit, AbstractFollower>
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
void targetObjectBuildLink() override;
|
|
||||||
void targetObjectDestroyLink() override;
|
|
||||||
void sourceObjectDestroyLink() override;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
@@ -85,7 +85,7 @@ void ChaseMovementGenerator<T>::DistanceYourself(T* owner, float distance)
|
|||||||
i_path = std::make_unique<PathGenerator>(owner);
|
i_path = std::make_unique<PathGenerator>(owner);
|
||||||
|
|
||||||
float x, y, z;
|
float x, y, z;
|
||||||
i_target->GetNearPoint(owner, x, y, z, owner->GetBoundaryRadius(), distance, i_target->GetAngle(owner));
|
GetTarget()->GetNearPoint(owner, x, y, z, owner->GetBoundaryRadius(), distance, GetTarget()->GetAngle(owner));
|
||||||
if (DispatchSplineToPosition(owner, x, y, z, false, false, 0.f, false, false))
|
if (DispatchSplineToPosition(owner, x, y, z, false, false, 0.f, false, false))
|
||||||
{
|
{
|
||||||
m_currentMode = CHASE_MODE_DISTANCING;
|
m_currentMode = CHASE_MODE_DISTANCING;
|
||||||
@@ -110,7 +110,7 @@ bool ChaseMovementGenerator<T>::DispatchSplineToPosition(T* owner, float x, floa
|
|||||||
|
|
||||||
// For pets, treat incomplete paths as failures to avoid clipping through geometry
|
// For pets, treat incomplete paths as failures to avoid clipping through geometry
|
||||||
// Players and Player-controlled units have more erratic movement, skip failure
|
// Players and Player-controlled units have more erratic movement, skip failure
|
||||||
if (cOwner && (cOwner->IsPet() || cOwner->IsControlledByPlayer()) && !i_target.getTarget()->IsCharmedOwnedByPlayerOrPlayer())
|
if (cOwner && (cOwner->IsPet() || cOwner->IsControlledByPlayer()) && !GetTarget()->IsCharmedOwnedByPlayerOrPlayer())
|
||||||
if (pathType & PATHFIND_INCOMPLETE)
|
if (pathType & PATHFIND_INCOMPLETE)
|
||||||
pathFailed = true;
|
pathFailed = true;
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ bool ChaseMovementGenerator<T>::DispatchSplineToPosition(T* owner, float x, floa
|
|||||||
{
|
{
|
||||||
if (cOwner)
|
if (cOwner)
|
||||||
{
|
{
|
||||||
cOwner->SetCannotReachTarget(i_target.getTarget()->GetGUID());
|
cOwner->SetCannotReachTarget(GetTarget()->GetGUID());
|
||||||
|
|
||||||
if (cOwner->IsPet() || cOwner->IsControlledByPlayer())
|
if (cOwner->IsPet() || cOwner->IsControlledByPlayer())
|
||||||
cOwner->AttackStop();
|
cOwner->AttackStop();
|
||||||
@@ -142,7 +142,7 @@ bool ChaseMovementGenerator<T>::DispatchSplineToPosition(T* owner, float x, floa
|
|||||||
Movement::MoveSplineInit init(owner);
|
Movement::MoveSplineInit init(owner);
|
||||||
init.MovebyPath(i_path->GetPath());
|
init.MovebyPath(i_path->GetPath());
|
||||||
if (target)
|
if (target)
|
||||||
init.SetFacing(i_target.getTarget());
|
init.SetFacing(GetTarget());
|
||||||
init.SetWalk(walk);
|
init.SetWalk(walk);
|
||||||
init.Launch();
|
init.Launch();
|
||||||
|
|
||||||
@@ -152,7 +152,7 @@ bool ChaseMovementGenerator<T>::DispatchSplineToPosition(T* owner, float x, floa
|
|||||||
template<class T>
|
template<class T>
|
||||||
bool ChaseMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
|
bool ChaseMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
|
||||||
{
|
{
|
||||||
if (!i_target.isValid() || !i_target->IsInWorld() || !owner->IsInMap(i_target.getTarget()))
|
if (!GetTarget() || !GetTarget()->IsInWorld() || !owner->IsInMap(GetTarget()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!owner || !owner->IsAlive())
|
if (!owner || !owner->IsAlive())
|
||||||
@@ -194,11 +194,11 @@ bool ChaseMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
|
|||||||
|
|
||||||
bool forceDest =
|
bool forceDest =
|
||||||
//(cOwner && (cOwner->isWorldBoss() || cOwner->IsDungeonBoss())) || // force for all bosses, even not in instances
|
//(cOwner && (cOwner->isWorldBoss() || cOwner->IsDungeonBoss())) || // force for all bosses, even not in instances
|
||||||
(i_target->IsPlayer() && i_target->ToPlayer()->IsGameMaster()) || // for .npc follow
|
(GetTarget()->IsPlayer() && GetTarget()->ToPlayer()->IsGameMaster()) || // for .npc follow
|
||||||
(owner->CanFly())
|
(owner->CanFly())
|
||||||
; // closes "bool forceDest", that way it is more appropriate, so we can comment out crap whenever we need to
|
; // closes "bool forceDest", that way it is more appropriate, so we can comment out crap whenever we need to
|
||||||
|
|
||||||
Unit* target = i_target.getTarget();
|
Unit* target = GetTarget();
|
||||||
|
|
||||||
bool mutualChase = IsMutualChase(owner, target);
|
bool mutualChase = IsMutualChase(owner, target);
|
||||||
bool const mutualTarget = target->GetVictim() == owner;
|
bool const mutualTarget = target->GetVictim() == owner;
|
||||||
@@ -414,7 +414,7 @@ void ChaseMovementGenerator<T>::MovementInform(T* owner)
|
|||||||
{
|
{
|
||||||
// Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle
|
// Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle
|
||||||
if (CreatureAI* AI = owner->ToCreature()->AI())
|
if (CreatureAI* AI = owner->ToCreature()->AI())
|
||||||
AI->MovementInform(CHASE_MOTION_TYPE, i_target.getTarget()->GetGUID().GetCounter());
|
AI->MovementInform(CHASE_MOTION_TYPE, GetTarget()->GetGUID().GetCounter());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CHASE_MODE_DISTANCING:
|
case CHASE_MODE_DISTANCING:
|
||||||
@@ -552,14 +552,14 @@ bool FollowMovementGenerator<T>::PositionOkay(Unit* target, bool isPlayerPet, bo
|
|||||||
template<class T>
|
template<class T>
|
||||||
bool FollowMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
|
bool FollowMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
|
||||||
{
|
{
|
||||||
if (!i_target.isValid() || !i_target->IsInWorld() || !owner->IsInMap(i_target.getTarget()))
|
if (!GetTarget() || !GetTarget()->IsInWorld() || !owner->IsInMap(GetTarget()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!owner || !owner->IsAlive())
|
if (!owner || !owner->IsAlive())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Creature* cOwner = owner->ToCreature();
|
Creature* cOwner = owner->ToCreature();
|
||||||
Unit* target = i_target.getTarget();
|
Unit* target = GetTarget();
|
||||||
|
|
||||||
// the owner might be unable to move (rooted or casting), or we have lost the target, pause movement
|
// the owner might be unable to move (rooted or casting), or we have lost the target, pause movement
|
||||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || (cOwner && owner->ToCreature()->IsMovementPreventedByCasting()))
|
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || (cOwner && owner->ToCreature()->IsMovementPreventedByCasting()))
|
||||||
@@ -580,7 +580,7 @@ bool FollowMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
|
|||||||
|
|
||||||
bool forceDest =
|
bool forceDest =
|
||||||
(followingMaster) || // allow pets following their master to cheat while generating paths
|
(followingMaster) || // allow pets following their master to cheat while generating paths
|
||||||
(i_target->IsPlayer() && i_target->ToPlayer()->IsGameMaster()) // for .npc follow
|
(GetTarget()->IsPlayer() && GetTarget()->ToPlayer()->IsGameMaster()) // for .npc follow
|
||||||
; // closes "bool forceDest", that way it is more appropriate, so we can comment out crap whenever we need to
|
; // closes "bool forceDest", that way it is more appropriate, so we can comment out crap whenever we need to
|
||||||
|
|
||||||
bool targetIsMoving = false;
|
bool targetIsMoving = false;
|
||||||
@@ -725,7 +725,7 @@ void FollowMovementGenerator<T>::MovementInform(T* owner)
|
|||||||
|
|
||||||
// Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle
|
// Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle
|
||||||
if (CreatureAI* AI = owner->ToCreature()->AI())
|
if (CreatureAI* AI = owner->ToCreature()->AI())
|
||||||
AI->MovementInform(FOLLOW_MOTION_TYPE, i_target.getTarget()->GetGUID().GetCounter());
|
AI->MovementInform(FOLLOW_MOTION_TYPE, GetTarget()->GetGUID().GetCounter());
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------//
|
//-----------------------------------------------//
|
||||||
|
|||||||
@@ -25,8 +25,6 @@
|
|||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
#include "Unit.h"
|
#include "Unit.h"
|
||||||
|
|
||||||
using TargetedMovementGeneratorBase = AbstractFollower;
|
|
||||||
|
|
||||||
enum ChaseMovementMode
|
enum ChaseMovementMode
|
||||||
{
|
{
|
||||||
CHASE_MODE_NORMAL, // chasing target
|
CHASE_MODE_NORMAL, // chasing target
|
||||||
|
|||||||
Reference in New Issue
Block a user