TrinityCore
FollowMovementGenerator.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
19#include "Creature.h"
20#include "CreatureAI.h"
21#include "MoveSpline.h"
22#include "MoveSplineInit.h"
23#include "Optional.h"
24#include "PathGenerator.h"
25#include "Pet.h"
26#include "Unit.h"
27#include "Util.h"
28
29static void DoMovementInform(Unit* owner, Unit* target)
30{
31 if (owner->GetTypeId() != TYPEID_UNIT)
32 return;
33
34 if (CreatureAI* AI = owner->ToCreature()->AI())
35 AI->MovementInform(FOLLOW_MOTION_TYPE, target->GetGUID().GetCounter());
36}
37
39 : AbstractFollower(ASSERT_NOTNULL(target)), _range(range), _angle(angle), _checkTimer(CHECK_INTERVAL)
40{
45 if (duration)
46 _duration.emplace(*duration);
47}
49
50static bool PositionOkay(Unit* owner, Unit* target, float range, Optional<ChaseAngle> angle = {})
51{
52 if (owner->GetExactDistSq(target) > square(owner->GetCombatReach() + target->GetCombatReach() + range))
53 return false;
54
55 return !angle || angle->IsAngleOkay(target->GetRelativeAngle(owner));
56}
57
59{
62
63 owner->StopMoving();
64 UpdatePetSpeed(owner);
65 _path = nullptr;
66 _lastTargetPosition.reset();
67}
68
70{
72
73 Initialize(owner);
74}
75
77{
78 // owner might be dead or gone
79 if (!owner || !owner->IsAlive())
80 return false;
81
82 // our target might have gone away
83 Unit* const target = GetTarget();
84 if (!target || !target->IsInWorld())
85 return false;
86
87 if (_duration)
88 {
89 _duration->Update(diff);
90 if (_duration->Passed())
91 {
92 owner->StopMoving();
93 DoMovementInform(owner, target);
94 return false;
95 }
96 }
97
99 {
100 _path = nullptr;
101 owner->StopMoving();
102 _lastTargetPosition.reset();
103 return true;
104 }
105
106 float range = _range;
107 if (Creature* cOwner = owner->ToCreature())
108 if (cOwner->IsIgnoringChaseRange())
109 range = 0.0f;
110
111 _checkTimer.Update(diff);
112 if (_checkTimer.Passed())
113 {
116 {
118 _path = nullptr;
119 owner->StopMoving();
120 _lastTargetPosition.reset();
121 DoMovementInform(owner, target);
122 return true;
123 }
124 }
125
126 if (owner->HasUnitState(UNIT_STATE_FOLLOW_MOVE) && owner->movespline->Finalized())
127 {
129 _path = nullptr;
131 DoMovementInform(owner, target);
132 }
133
134 if (!_lastTargetPosition || _lastTargetPosition->GetExactDistSq(target->GetPosition()) > 0.0f)
135 {
137 if (owner->HasUnitState(UNIT_STATE_FOLLOW_MOVE) || !PositionOkay(owner, target, range + FOLLOW_RANGE_TOLERANCE))
138 {
139 if (!_path)
140 _path = std::make_unique<PathGenerator>(owner);
141
142 float x, y, z;
143
144 // select angle
145 float tAngle;
146 float const curAngle = target->GetRelativeAngle(owner);
147 if (_angle.IsAngleOkay(curAngle))
148 tAngle = curAngle;
149 else
150 {
151 float const diffUpper = Position::NormalizeOrientation(curAngle - _angle.UpperBound());
152 float const diffLower = Position::NormalizeOrientation(_angle.LowerBound() - curAngle);
153 if (diffUpper < diffLower)
154 tAngle = _angle.UpperBound();
155 else
156 tAngle = _angle.LowerBound();
157 }
158
159 target->GetNearPoint(owner, x, y, z, range, target->ToAbsoluteAngle(tAngle));
160
161 if (owner->IsHovering())
162 owner->UpdateAllowedPositionZ(x, y, z);
163
164 // pets are allowed to "cheat" on pathfinding when following their master
165 bool allowShortcut = false;
166 if (Pet* oPet = owner->ToPet())
167 {
168 if (target->GetGUID() == oPet->GetOwnerGUID())
169 allowShortcut = true;
170 }
171
172 bool success = _path->CalculatePath(x, y, z, allowShortcut);
173 if (!success || (_path->GetPathType() & PATHFIND_NOPATH))
174 {
175 owner->StopMoving();
176 return true;
177 }
178
181
182 Movement::MoveSplineInit init(owner);
183 init.MovebyPath(_path->GetPath());
184 init.SetWalk(target->IsWalking());
185 init.SetFacing(target->GetOrientation());
186 init.Launch();
187 }
188 }
189 return true;
190}
191
193{
197}
198
199void FollowMovementGenerator::Finalize(Unit* owner, bool active, bool/* movementInform*/)
200{
202 if (active)
203 {
205 UpdatePetSpeed(owner);
206 }
207}
208
210{
211 if (Pet* oPet = owner->ToPet())
212 {
213 if (!GetTarget() || GetTarget()->GetGUID() == owner->GetOwnerGUID())
214 {
215 oPet->UpdateSpeed(MOVE_RUN);
216 oPet->UpdateSpeed(MOVE_WALK);
217 oPet->UpdateSpeed(MOVE_SWIM);
218 }
219 }
220}
uint32_t uint32
Definition: Define.h:142
#define ASSERT_NOTNULL(pointer)
Definition: Errors.h:84
static bool PositionOkay(Unit *owner, Unit *target, float range, Optional< ChaseAngle > angle={})
static void DoMovementInform(Unit *owner, Unit *target)
#define FOLLOW_RANGE_TOLERANCE
@ MOTION_MODE_DEFAULT
@ MOTION_PRIORITY_NORMAL
@ FOLLOW_MOTION_TYPE
@ MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING
@ MOVEMENTGENERATOR_FLAG_DEACTIVATED
@ MOVEMENTGENERATOR_FLAG_FINALIZED
@ MOVEMENTGENERATOR_FLAG_TRANSITORY
@ MOVEMENTGENERATOR_FLAG_INFORM_ENABLED
@ MOVEMENTGENERATOR_FLAG_INITIALIZED
@ TYPEID_UNIT
Definition: ObjectGuid.h:40
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
@ PATHFIND_NOPATH
Definition: PathGenerator.h:47
@ MOVE_SWIM
Definition: UnitDefines.h:120
@ MOVE_RUN
Definition: UnitDefines.h:118
@ MOVE_WALK
Definition: UnitDefines.h:117
@ UNIT_STATE_NOT_MOVE
Definition: Unit.h:300
@ UNIT_STATE_FOLLOW
Definition: Unit.h:264
@ UNIT_STATE_FOLLOW_MOVE
Definition: Unit.h:282
T square(T x)
Definition: Util.h:103
CreatureAI * AI() const
Definition: Creature.h:214
bool Update(Unit *, uint32) override
void Finalize(Unit *, bool, bool) override
Optional< TimeTracker > _duration
FollowMovementGenerator(Unit *target, float range, ChaseAngle angle, Optional< Milliseconds > duration)
void Initialize(Unit *) override
Optional< Position > _lastTargetPosition
std::unique_ptr< PathGenerator > _path
static constexpr uint32 CHECK_INTERVAL
void Deactivate(Unit *) override
void AddFlag(uint16 const flag)
bool HasFlag(uint16 const flag) const
void RemoveFlag(uint16 const flag)
void SetWalk(bool enable)
void SetFacing(float angle)
void MovebyPath(PointsArray const &path, int32 pointId=0)
LowType GetCounter() const
Definition: ObjectGuid.h:293
static Creature * ToCreature(Object *o)
Definition: Object.h:219
bool IsInWorld() const
Definition: Object.h:154
TypeID GetTypeId() const
Definition: Object.h:173
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
Definition: Pet.h:40
Definition: Unit.h:627
void ClearUnitState(uint32 f)
Definition: Unit.h:733
virtual bool IsMovementPreventedByCasting() const
Definition: Unit.cpp:3119
Pet * ToPet()
Definition: Unit.h:1750
ObjectGuid GetOwnerGUID() const override
Definition: Unit.h:1170
bool IsAlive() const
Definition: Unit.h:1164
float GetCombatReach() const override
Definition: Unit.h:694
void StopMoving()
Definition: Unit.cpp:10049
void AddUnitState(uint32 f)
Definition: Unit.h:731
bool IsHovering() const
Definition: Unit.h:1137
bool HasUnitState(const uint32 f) const
Definition: Unit.h:732
std::unique_ptr< Movement::MoveSpline > movespline
Definition: Unit.h:1766
bool IsWalking() const
Definition: Unit.h:1136
void UpdateAllowedPositionZ(float x, float y, float &z, float *groundZ=nullptr) const
Definition: Object.cpp:1371
void GetNearPoint(WorldObject const *searcher, float &x, float &y, float &z, float distance2d, float absAngle) const
Definition: Object.cpp:3368
Unit * GetTarget() const
float UpperBound() const
float LowerBound() const
bool IsAngleOkay(float relativeAngle) const
float GetRelativeAngle(float x, float y) const
Definition: Position.h:136
static float NormalizeOrientation(float o)
Definition: Position.cpp:135
float ToAbsoluteAngle(float relAngle) const
Definition: Position.h:133
constexpr void GetPosition(float &x, float &y) const
Definition: Position.h:81
constexpr float GetExactDistSq(float x, float y, float z) const
Definition: Position.h:110
constexpr float GetOrientation() const
Definition: Position.h:79
void Update(int32 diff)
Definition: Timer.h:121
bool Passed() const
Definition: Timer.h:131
void Reset(int32 expiry)
Definition: Timer.h:136