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{
44 ScriptResult = std::move(scriptResult);
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->IsInDist(target, owner->GetCombatReach() + target->GetCombatReach() + range))
53 return false;
54
55 return !angle || angle->IsAngleOkay(target->GetRelativeAngle(owner));
56}
57
68
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 || _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 // pets are allowed to "cheat" on pathfinding when following their master
162 bool allowShortcut = false;
163 if (Pet* oPet = owner->ToPet())
164 {
165 if (target->GetGUID() == oPet->GetOwnerGUID())
166 allowShortcut = true;
167 }
168
169 bool success = _path->CalculatePath(x, y, z, allowShortcut);
170 if (!success || (_path->GetPathType() & PATHFIND_NOPATH))
171 {
172 owner->StopMoving();
173 return true;
174 }
175
178
179 Movement::MoveSplineInit init(owner);
180 init.MovebyPath(_path->GetPath());
182 init.SetWalk(target->IsWalking());
183 init.SetFacing(target->GetOrientation());
184 init.Launch();
185 }
186 }
187 return true;
188}
189
196
197void FollowMovementGenerator::Finalize(Unit* owner, bool active, bool movementInform)
198{
200 if (active)
201 {
203 UpdatePetSpeed(owner);
204 if (movementInform)
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}
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:74
static bool PositionOkay(Unit *owner, Unit *target, float range, Optional< ChaseAngle > angle={})
static void DoMovementInform(Unit *owner, Unit *target)
#define FOLLOW_RANGE_TOLERANCE
@ 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:320
@ UNIT_STATE_FOLLOW
Definition Unit.h:284
@ UNIT_STATE_FOLLOW_MOVE
Definition Unit.h:302
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:235
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:647
void ClearUnitState(uint32 f)
Definition Unit.h:756
virtual bool IsMovementPreventedByCasting() const
Definition Unit.cpp:3283
Pet * ToPet()
Definition Unit.h:1838
ObjectGuid GetOwnerGUID() const override
Definition Unit.h:1211
void StopMoving(bool force=false)
Definition Unit.cpp:10753
bool IsAlive() const
Definition Unit.h:1205
float GetCombatReach() const override
Definition Unit.h:717
void AddUnitState(uint32 f)
Definition Unit.h:754
bool HasUnitState(const uint32 f) const
Definition Unit.h:755
std::unique_ptr< Movement::MoveSpline > movespline
Definition Unit.h:1854
bool IsWalking() const
Definition Unit.h:1165
void GetNearPoint(WorldObject const *searcher, float &x, float &y, float &z, float distance2d, float absAngle) const
Definition Object.cpp:2719
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