TrinityCore
Loading...
Searching...
No Matches
SplineChainMovementGenerator.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 "Errors.h"
22#include "MotionMaster.h"
23#include "MovementDefines.h"
24#include "MoveSpline.h"
25#include "MoveSplineInit.h"
26#include "Log.h"
27#include "Unit.h"
28
29SplineChainMovementGenerator::SplineChainMovementGenerator(uint32 id, std::vector<SplineChainLink> const& chain, bool walk) : _id(id), _chain(chain), _chainSize(chain.size()), _walk(walk), _nextIndex(0), _nextFirstWP(0), _msToNext(0)
30{
34}
35
36SplineChainMovementGenerator::SplineChainMovementGenerator(SplineChainResumeInfo const& info) : _id(info.PointID), _chain(*info.Chain), _chainSize(info.Chain->size()), _walk(info.IsWalkMode), _nextIndex(info.SplineIndex), _nextFirstWP(info.PointIndex), _msToNext(info.TimeToNext)
37{
39
41 if (info.SplineIndex >= info.Chain->size())
43
45}
46
48{
49 uint32 nodeCount = path.size();
50 ASSERT(nodeCount > 1, "SplineChainMovementGenerator::SendPathSpline: Every path must have source & destination (size > 1)! (%s)", owner->GetGUID().ToString().c_str());
51
53
54 Movement::MoveSplineInit init(owner);
55 if (nodeCount > 2)
56 init.MovebyPath(path);
57 else
58 init.MoveTo(path[1], false, true);
59
60 if (velocity > 0.f)
61 init.SetVelocity(velocity);
62 init.SetWalk(_walk);
63 return init.Launch();
64}
65
67{
68 ASSERT(index < _chainSize, "SplineChainMovementGenerator::SendSplineFor: referenced index (%u) higher than path size (%u)!", index, _chainSize);
69 TC_LOG_DEBUG("movement.splinechain", "SplineChainMovementGenerator::SendSplineFor: sending spline on index: {}. ({})", index, owner->GetGUID().ToString());
70
71 SplineChainLink const& thisLink = _chain[index];
72 uint32 actualDuration = SendPathSpline(owner, thisLink.Velocity, thisLink.Points);
73 if (actualDuration != thisLink.ExpectedDuration)
74 {
75 TC_LOG_DEBUG("movement.splinechain", "SplineChainMovementGenerator::SendSplineFor: sent spline on index: {}, duration: {} ms. Expected duration: {} ms (delta {} ms). Adjusting. ({})", index, actualDuration, thisLink.ExpectedDuration, int32(actualDuration) - int32(thisLink.ExpectedDuration), owner->GetGUID().ToString());
76 duration = uint32(double(actualDuration) / double(thisLink.ExpectedDuration) * duration);
77 }
78 else
79 {
80 TC_LOG_DEBUG("movement.splinechain", "SplineChainMovementGenerator::SendSplineFor: sent spline on index {}, duration: {} ms. ({})", index, actualDuration, owner->GetGUID().ToString());
81 }
82}
83
85{
88
89 if (!_chainSize)
90 {
91 TC_LOG_ERROR("movement", "SplineChainMovementGenerator::Initialize: couldn't initialize generator, referenced spline is empty! ({})", owner->GetGUID().ToString());
92 return false;
93 }
94
96 {
97 TC_LOG_WARN("movement", "SplineChainMovementGenerator::Initialize: couldn't initialize generator, _nextIndex is >= _chainSize ({})", owner->GetGUID().ToString());
98 _msToNext = 0;
99 return false;
100 }
101
102 if (_nextFirstWP) // this is a resumed movegen that has to start with a partial spline
103 {
105 return false;
106
107 SplineChainLink const& thisLink = _chain[_nextIndex];
108 if (_nextFirstWP >= thisLink.Points.size())
109 {
110 TC_LOG_ERROR("movement.splinechain", "SplineChainMovementGenerator::Initialize: attempted to resume spline chain from invalid resume state, _nextFirstWP >= path size (_nextIndex: {}, _nextFirstWP: {}). ({})", _nextIndex, _nextFirstWP, owner->GetGUID().ToString());
111 _nextFirstWP = thisLink.Points.size() - 1;
112 }
113
114 Movement::PointsArray partial(thisLink.Points.begin() + (_nextFirstWP-1), thisLink.Points.end());
115 SendPathSpline(owner, thisLink.Velocity, partial);
116
117 TC_LOG_DEBUG("movement.splinechain", "SplineChainMovementGenerator::Initialize: resumed spline chain generator from resume state. ({})", owner->GetGUID().ToString());
118
119 ++_nextIndex;
120 if (_nextIndex >= _chainSize)
121 _msToNext = 0;
122 else if (!_msToNext)
123 _msToNext = 1;
124 _nextFirstWP = 0;
125 }
126 else
127 {
128 _msToNext = std::max(_chain[_nextIndex].TimeToNext, 1u);
130
131 ++_nextIndex;
132 if (_nextIndex >= _chainSize)
133 _msToNext = 0;
134 }
135 return true;
136}
137
139{
141
142 owner->StopMoving();
143 return Initialize(owner);
144}
145
147{
149 return false;
150
151 // _msToNext being zero here means we're on the final spline
152 if (!_msToNext)
153 {
154 if (owner->movespline->Finalized())
155 {
157 return false;
158 }
159 return true;
160 }
161
162 if (_msToNext <= diff)
163 {
164 // Send next spline
165 TC_LOG_DEBUG("movement.splinechain", "SplineChainMovementGenerator::Update: sending spline on index {} ({} ms late). ({})", _nextIndex, diff - _msToNext, owner->GetGUID().ToString());
166 _msToNext = std::max(_chain[_nextIndex].TimeToNext, 1u);
168 ++_nextIndex;
169 if (_nextIndex >= _chainSize)
170 {
171 // We have reached the final spline, once it finalizes we should also finalize the movegen (start checking on next update)
172 _msToNext = 0;
173 return true;
174 }
175 }
176 else
177 {
178 _msToNext -= diff;
179 if (owner->movespline->Finalized())
181 }
182
183 return true;
184}
185
191
192void SplineChainMovementGenerator::Finalize(Unit* owner, bool active, bool movementInform)
193{
195
196 if (active)
198
199 if (movementInform && HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED))
200 {
201 Creature* ownerCreature = owner->ToCreature();
202 if (CreatureAI* AI = ownerCreature ? ownerCreature->AI() : nullptr)
203 AI->MovementInform(SPLINE_CHAIN_MOTION_TYPE, _id);
204 }
205}
206
211
213{
214 if (!_nextIndex)
216
217 if (owner->movespline->Finalized())
218 {
221 else
222 return SplineChainResumeInfo();
223 }
224
226}
227
229{
230 std::function<bool(MovementGenerator const*)> criteria = [id](MovementGenerator const* movement) -> bool
231 {
232 if (movement->GetMovementGeneratorType() == SPLINE_CHAIN_MOTION_TYPE)
233 return (!id || static_cast<SplineChainMovementGenerator const*>(movement)->GetId() == *id);
234
235 return false;
236 };
237
238 if (MovementGenerator const* activeGenerator = owner->GetMotionMaster()->GetMovementGenerator(criteria))
239 info = static_cast<SplineChainMovementGenerator const*>(activeGenerator)->GetResumeInfo(owner);
240 else
241 info.Clear();
242}
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
#define ASSERT
Definition Errors.h:68
#define TC_LOG_WARN(filterType__,...)
Definition Log.h:162
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
@ MOTION_PRIORITY_NORMAL
MovementGeneratorType
@ SPLINE_CHAIN_MOTION_TYPE
@ MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING
@ MOVEMENTGENERATOR_FLAG_DEACTIVATED
@ MOVEMENTGENERATOR_FLAG_FINALIZED
@ MOVEMENTGENERATOR_FLAG_INFORM_ENABLED
@ MOVEMENTGENERATOR_FLAG_INITIALIZED
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
@ UNIT_STATE_ROAMING_MOVE
Definition Unit.h:243
@ UNIT_STATE_ROAMING
Definition Unit.h:224
CreatureAI * AI() const
Definition Creature.h:154
MovementGenerator * GetMovementGenerator(std::function< bool(MovementGenerator const *)> const &filter, MovementSlot slot=MOTION_SLOT_ACTIVE) const
void AddFlag(uint16 const flag)
bool HasFlag(uint16 const flag) const
void RemoveFlag(uint16 const flag)
void MoveTo(Vector3 const &destination, bool generatePath=true, bool forceDestination=false)
void SetWalk(bool enable)
void SetVelocity(float velocity)
void MovebyPath(PointsArray const &path, int32 pointId=0)
bool Finalized() const
Definition MoveSpline.h:121
int32 _currentSplineIdx() const
Definition MoveSpline.h:91
std::string ToString() const
static Creature * ToCreature(Object *o)
Definition Object.h:186
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
SplineChainMovementGenerator(uint32 id, std::vector< SplineChainLink > const &chain, bool walk=false)
std::vector< SplineChainLink > const & _chain
void SendSplineFor(Unit *owner, uint32 index, uint32 &duration)
void Finalize(Unit *, bool, bool) override
static void GetResumeInfo(SplineChainResumeInfo &info, Unit const *owner, Optional< uint32 > id={})
MovementGeneratorType GetMovementGeneratorType() const override
uint32 SendPathSpline(Unit *owner, float velocity, Movement::PointsArray const &path) const
Definition Unit.h:769
void ClearUnitState(uint32 f)
Definition Unit.h:877
Movement::MoveSpline * movespline
Definition Unit.h:1804
void StopMoving(bool force=false)
Definition Unit.cpp:10312
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
void AddUnitState(uint32 f)
Definition Unit.h:875
std::vector< Vector3 > PointsArray
std::vector< SplineChainLink > const * Chain
Definition SplineChain.h:43