TrinityCore
Loading...
Searching...
No Matches
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
28static void DoMovementInform(Unit* owner, Unit* target)
29{
30 if (owner->GetTypeId() != TYPEID_UNIT)
31 return;
32
33 if (CreatureAI* AI = owner->ToCreature()->AI())
34 AI->MovementInform(FOLLOW_MOTION_TYPE, target->GetGUID().GetCounter());
35}
36
38 bool ignoreTargetWalk /*= false*/, Scripting::v2::ActionResultSetter<MovementStopReason>&& scriptResult /*= {}*/)
39 : AbstractFollower(ASSERT_NOTNULL(target)), _range(range), _angle(angle), _ignoreTargetWalk(ignoreTargetWalk), _checkTimer(CHECK_INTERVAL)
40{
45 ScriptResult = std::move(scriptResult);
46 if (duration)
47 _duration.emplace(*duration);
48}
50
51static bool PositionOkay(Unit* owner, Unit* target, float range, Optional<ChaseAngle> angle = {})
52{
53 if (!owner->IsInDist(target, owner->GetCombatReach() + target->GetCombatReach() + range))
54 return false;
55
56 return !angle || angle->IsAngleOkay(target->GetRelativeAngle(owner));
57}
58
69
76
78{
79 // owner might be dead or gone
80 if (!owner || !owner->IsAlive())
81 return false;
82
83 // our target might have gone away
84 Unit* const target = GetTarget();
85 if (!target || !target->IsInWorld())
86 return false;
87
88 if (_duration)
89 {
90 _duration->Update(diff);
91 if (_duration->Passed())
92 {
93 owner->StopMoving();
94 DoMovementInform(owner, target);
95 return false;
96 }
97 }
98
100 {
101 _path = nullptr;
102 owner->StopMoving();
103 _lastTargetPosition.reset();
104 return true;
105 }
106
107 float range = _range;
108 if (Creature* cOwner = owner->ToCreature())
109 if (cOwner->IsIgnoringChaseRange())
110 range = 0.0f;
111
112 _checkTimer.Update(diff);
113 if (_checkTimer.Passed())
114 {
117 {
119 _path = nullptr;
120 owner->StopMoving();
121 _lastTargetPosition.reset();
122 DoMovementInform(owner, target);
123 return true;
124 }
125 }
126
127 if (owner->HasUnitState(UNIT_STATE_FOLLOW_MOVE) && owner->movespline->Finalized())
128 {
130 _path = nullptr;
132 DoMovementInform(owner, target);
133 }
134
135 if (!_lastTargetPosition || _lastTargetPosition->GetExactDistSq(target->GetPosition()) > 0.0f)
136 {
138 if (owner->HasUnitState(UNIT_STATE_FOLLOW_MOVE) || !PositionOkay(owner, target, range + FOLLOW_RANGE_TOLERANCE))
139 {
140 if (!_path)
141 _path = std::make_unique<PathGenerator>(owner);
142
143 float x, y, z;
144
145 // select angle
146 float tAngle;
147 float const curAngle = target->GetRelativeAngle(owner);
148 if (!_angle || _angle->IsAngleOkay(curAngle))
149 tAngle = curAngle;
150 else
151 {
152 float const diffUpper = Position::NormalizeOrientation(curAngle - _angle->UpperBound());
153 float const diffLower = Position::NormalizeOrientation(_angle->LowerBound() - curAngle);
154 if (diffUpper < diffLower)
155 tAngle = _angle->UpperBound();
156 else
157 tAngle = _angle->LowerBound();
158 }
159
160 target->GetNearPoint(owner, x, y, z, range, target->ToAbsoluteAngle(tAngle));
161
162 if (owner->IsHovering())
163 owner->UpdateAllowedPositionZ(x, y, z);
164
165 // pets are allowed to "cheat" on pathfinding when following their master
166 bool allowShortcut = false;
167 if (Pet* oPet = owner->ToPet())
168 {
169 if (target->GetGUID() == oPet->GetOwnerGUID())
170 allowShortcut = true;
171 }
172
173 bool success = _path->CalculatePath(x, y, z, allowShortcut);
174 if (!success || (_path->GetPathType() & PATHFIND_NOPATH))
175 {
176 owner->StopMoving();
177 return true;
178 }
179
182
183 Movement::MoveSplineInit init(owner);
184 init.MovebyPath(_path->GetPath());
186 init.SetWalk(target->IsWalking());
187 init.SetFacing(target->GetOrientation());
188 init.Launch();
189 }
190 }
191 return true;
192}
193
200
201void FollowMovementGenerator::Finalize(Unit* owner, bool active, bool movementInform)
202{
204 if (active)
205 {
207 UpdatePetSpeed(owner);
208 if (movementInform)
210 }
211}
212
214{
215 if (Pet* oPet = owner->ToPet())
216 {
217 if (!GetTarget() || GetTarget()->GetGUID() == owner->GetOwnerGUID())
218 {
219 oPet->UpdateSpeed(MOVE_RUN);
220 oPet->UpdateSpeed(MOVE_WALK);
221 oPet->UpdateSpeed(MOVE_SWIM);
222 }
223 }
224}
static bool PositionOkay(Unit *owner, Unit *target, Optional< float > minDistance, Optional< float > maxDistance, Optional< ChaseAngle > angle)
static void DoMovementInform(Unit *owner, Unit *target)
uint32_t uint32
Definition Define.h:154
#define ASSERT_NOTNULL(pointer)
Definition Errors.h:82
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:43
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
@ PATHFIND_NOPATH
@ MOVE_SWIM
@ MOVE_RUN
@ MOVE_WALK
@ UNIT_STATE_NOT_MOVE
Definition Unit.h:306
@ UNIT_STATE_FOLLOW
Definition Unit.h:270
@ UNIT_STATE_FOLLOW_MOVE
Definition Unit.h:288
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
bool IsInWorld() const
Definition BaseEntity.h:158
TypeID GetTypeId() const
Definition BaseEntity.h:166
CreatureAI * AI() const
Definition Creature.h:228
bool Update(Unit *, uint32) override
Optional< ChaseAngle const > _angle
void Finalize(Unit *, bool, bool) override
FollowMovementGenerator(Unit *target, float range, Optional< ChaseAngle > angle, Optional< Milliseconds > duration, bool ignoreTargetWalk=false, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
Optional< TimeTracker > _duration
Optional< Position > _lastTargetPosition
std::unique_ptr< PathGenerator > _path
static constexpr uint32 CHECK_INTERVAL
void SetScriptResult(MovementStopReason reason)
void AddFlag(uint16 const flag)
Scripting::v2::ActionResultSetter< MovementStopReason > ScriptResult
bool HasFlag(uint16 const flag) const
void RemoveFlag(uint16 const flag)
void SetWalk(bool enable)
void MovebyPath(std::span< Vector3 const > path, int32 pointId=0)
void SetFacing(float angle)
LowType GetCounter() const
Definition ObjectGuid.h:336
Creature * ToCreature()
Definition Object.h:121
Definition Pet.h:40
Definition Unit.h:635
void ClearUnitState(uint32 f)
Definition Unit.h:744
virtual bool IsMovementPreventedByCasting() const
Definition Unit.cpp:3261
Pet * ToPet()
Definition Unit.h:1822
ObjectGuid GetOwnerGUID() const override
Definition Unit.h:1191
bool IsAlive() const
Definition Unit.h:1185
float GetCombatReach() const override
Definition Unit.h:705
void StopMoving()
Definition Unit.cpp:10680
void AddUnitState(uint32 f)
Definition Unit.h:742
bool IsHovering() const
Definition Unit.h:1151
bool HasUnitState(const uint32 f) const
Definition Unit.h:743
std::unique_ptr< Movement::MoveSpline > movespline
Definition Unit.h:1838
bool IsWalking() const
Definition Unit.h:1150
void UpdateAllowedPositionZ(float x, float y, float &z, float *groundZ=nullptr) const
Definition Object.cpp:711
void GetNearPoint(WorldObject const *searcher, float &x, float &y, float &z, float distance2d, float absAngle) const
Definition Object.cpp:2714
Unit * GetTarget() const
float GetRelativeAngle(float x, float y) const
Definition Position.h:147
static float NormalizeOrientation(float o)
Definition Position.cpp:207
float ToAbsoluteAngle(float relAngle) const
Definition Position.h:144
constexpr void GetPosition(float &x, float &y) const
Definition Position.h:92
constexpr bool IsInDist(float x, float y, float z, float dist) const
Definition Position.h:155
constexpr float GetOrientation() const
Definition Position.h:90
void Update(int32 diff)
Definition Timer.h:121
bool Passed() const
Definition Timer.h:131
void Reset(int32 expiry)
Definition Timer.h:136