TrinityCore
RandomMovementGenerator.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 "MovementDefines.h"
22#include "MoveSpline.h"
23#include "MoveSplineInit.h"
24#include "PathGenerator.h"
25#include "Random.h"
26
27template<class T>
28RandomMovementGenerator<T>::RandomMovementGenerator(float distance, Optional<Milliseconds> duration) : _timer(0), _reference(), _wanderDistance(distance), _wanderSteps(0)
29{
34 if (duration)
35 _duration.emplace(*duration);
36}
37
39
40template<class T>
42{
43 return RANDOM_MOTION_TYPE;
44}
45
46template<class T>
48{
49 if (timer)
50 {
52 _timer.Reset(timer);
53 this->RemoveFlag(MOVEMENTGENERATOR_FLAG_PAUSED);
54 }
55 else
56 {
57 this->AddFlag(MOVEMENTGENERATOR_FLAG_PAUSED);
59 }
60}
61
62template<class T>
64{
65 if (overrideTimer)
66 _timer.Reset(overrideTimer);
67
68 this->RemoveFlag(MOVEMENTGENERATOR_FLAG_PAUSED);
69}
70
72
73template<class T>
75
76template<>
78{
81
82 if (!owner || !owner->IsAlive())
83 return;
84
85 _reference = owner->GetPosition();
86 owner->StopMoving();
87
88 if (_wanderDistance == 0.f)
89 _wanderDistance = owner->GetWanderDistance();
90
91 // Retail seems to let a creature walk 2 up to 10 splines before triggering a pause
92 _wanderSteps = urand(2, 10);
93
94 _timer.Reset(0);
95 _path = nullptr;
96}
97
98template<class T>
100
101template<>
103{
105
106 DoInitialize(owner);
107}
108
109template<class T>
111
112template<>
114{
115 if (!owner)
116 return;
117
119 {
121 owner->StopMoving();
122 _path = nullptr;
123 return;
124 }
125
126 Position position(_reference);
127 float distance = _wanderDistance > 0.1f ? frand(0.1f, _wanderDistance) : _wanderDistance;
128 float angle = frand(0.f, static_cast<float>(M_PI * 2));
129 owner->MovePositionToFirstCollision(position, distance, angle);
130
131 // Check if the destination is in LOS
132 if (!owner->IsWithinLOS(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ()))
133 {
134 // Retry later on
135 _timer.Reset(200);
136 return;
137 }
138
139 if (!_path)
140 {
141 _path = std::make_unique<PathGenerator>(owner);
142 _path->SetPathLengthLimit(30.0f);
143 }
144
145 bool result = _path->CalculatePath(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ());
146 // PATHFIND_FARFROMPOLY shouldn't be checked as creatures in water are most likely far from poly
147 if (!result || (_path->GetPathType() & PATHFIND_NOPATH)
148 || (_path->GetPathType() & PATHFIND_SHORTCUT)
149 /*|| (_path->GetPathType() & PATHFIND_FARFROMPOLY)*/)
150 {
151 _timer.Reset(100);
152 return;
153 }
154
155 if (_path->GetPathLength() < 0.1f)
156 {
157 // the path is too short for the spline system to be accepted. Let's try again soon.
158 _timer.Reset(500);
159 return;
160 }
161
163
165
166 bool walk = true;
167 switch (owner->GetMovementTemplate().GetRandom())
168 {
170 walk = owner->IsWalking();
171 break;
173 walk = false;
174 break;
175 default:
176 break;
177 }
178
179 Movement::MoveSplineInit init(owner);
180 init.MovebyPath(_path->GetPath());
181 init.SetWalk(walk);
182 int32 splineDuration = init.Launch();
183
184 --_wanderSteps;
185 if (_wanderSteps) // Creature has yet to do steps before pausing
186 _timer.Reset(splineDuration);
187 else
188 {
189 // Creature has made all its steps, time for a little break
190 _timer.Reset(splineDuration + urand(4, 10) * IN_MILLISECONDS); // Retails seems to use rounded numbers so we do as well
191 _wanderSteps = urand(2, 10);
192 }
193
194 // Call for creature group update
196}
197
198template<class T>
200{
201 return false;
202}
203
204template<>
206{
207 if (!owner || !owner->IsAlive())
208 return true;
209
211 return true;
212
213 if (_duration)
214 {
215 _duration->Update(diff);
216 if (_duration->Passed())
217 {
220 return false;
221 }
222 }
223
225 {
227 owner->StopMoving();
228 _path = nullptr;
229 return true;
230 }
231 else
233
234 _timer.Update(diff);
235 if ((HasFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING) && !owner->movespline->Finalized()) || (_timer.Passed() && owner->movespline->Finalized()))
236 SetRandomLocation(owner);
237
238 return true;
239}
240
241template<class T>
243
244template<>
246{
249}
250
251template<class T>
253
254template<>
255void RandomMovementGenerator<Creature>::DoFinalize(Creature* owner, bool active, bool movementInform)
256{
258 if (active)
259 {
261 owner->StopMoving();
262
263 // TODO: Research if this modification is needed, which most likely isnt
264 owner->SetWalk(false);
265 }
266
267 if (movementInform && HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED))
268 if (owner->IsAIEnabled())
270}
@ IN_MILLISECONDS
Definition: Common.h:35
#define M_PI
Definition: Common.h:115
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
@ MOTION_MODE_DEFAULT
@ MOTION_PRIORITY_NORMAL
MovementGeneratorType
@ RANDOM_MOTION_TYPE
@ MOVEMENTGENERATOR_FLAG_TIMED_PAUSED
@ MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING
@ MOVEMENTGENERATOR_FLAG_PAUSED
@ MOVEMENTGENERATOR_FLAG_DEACTIVATED
@ MOVEMENTGENERATOR_FLAG_FINALIZED
@ MOVEMENTGENERATOR_FLAG_TRANSITORY
@ MOVEMENTGENERATOR_FLAG_INTERRUPTED
@ MOVEMENTGENERATOR_FLAG_INFORM_ENABLED
@ MOVEMENTGENERATOR_FLAG_INITIALIZED
@ MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
@ PATHFIND_NOPATH
Definition: PathGenerator.h:47
@ PATHFIND_SHORTCUT
Definition: PathGenerator.h:45
float frand(float min, float max)
Definition: Random.cpp:55
uint32 urand(uint32 min, uint32 max)
Definition: Random.cpp:42
@ UNIT_STATE_NOT_MOVE
Definition: Unit.h:300
@ UNIT_STATE_ROAMING_MOVE
Definition: Unit.h:278
@ UNIT_STATE_LOST_CONTROL
Definition: Unit.h:296
@ UNIT_STATE_ROAMING
Definition: Unit.h:259
virtual void MovementInform(uint32, uint32)
Definition: CreatureAI.h:154
void SignalFormationMovement()
Definition: Creature.cpp:396
float GetWanderDistance() const
Definition: Creature.h:340
CreatureMovementData const & GetMovementTemplate() const
Definition: Creature.cpp:2939
CreatureAI * AI() const
Definition: Creature.h:214
bool IsMovementPreventedByCasting() const override
Definition: Creature.cpp:3551
void SetWalk(bool enable)
void MovebyPath(PointsArray const &path, int32 pointId=0)
Optional< TimeTracker > _duration
void Pause(uint32 timer) override
MovementGeneratorType GetMovementGeneratorType() const override
void DoFinalize(T *, bool, bool)
void Resume(uint32 overrideTimer) override
RandomMovementGenerator(float distance=0.0f, Optional< Milliseconds > duration={})
void ClearUnitState(uint32 f)
Definition: Unit.h:733
bool IsAlive() const
Definition: Unit.h:1164
void StopMoving()
Definition: Unit.cpp:10049
void AddUnitState(uint32 f)
Definition: Unit.h:731
bool IsAIEnabled() const
Definition: Unit.h:658
bool SetWalk(bool enable)
Definition: Unit.cpp:12707
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
bool IsWithinLOS(float x, float y, float z, LineOfSightChecks checks=LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags ignoreFlags=VMAP::ModelIgnoreFlags::Nothing) const
Definition: Object.cpp:1161
void MovePositionToFirstCollision(Position &pos, float dist, float angle)
Definition: Object.cpp:3482
CreatureRandomMovementType GetRandom() const
Definition: CreatureData.h:403
constexpr float GetPositionX() const
Definition: Position.h:76
constexpr float GetPositionY() const
Definition: Position.h:77
constexpr void GetPosition(float &x, float &y) const
Definition: Position.h:81
constexpr float GetPositionZ() const
Definition: Position.h:78