TrinityCore
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{
35}
36
37SplineChainMovementGenerator::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)
38{
41
43 if (info.SplineIndex >= info.Chain->size())
45
47}
48
50{
51 uint32 nodeCount = path.size();
52 ASSERT(nodeCount > 1, "SplineChainMovementGenerator::SendPathSpline: Every path must have source & destination (size > 1)! (%s)", owner->GetGUID().ToString().c_str());
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;
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;
100 }
101
102 if (_nextFirstWP) // this is a resumed movegen that has to start with a partial spline
103 {
105 return;
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
115 Movement::PointsArray partial(thisLink.Points.begin() + (_nextFirstWP-1), thisLink.Points.end());
116 SendPathSpline(owner, thisLink.Velocity, partial);
117
118 TC_LOG_DEBUG("movement.splinechain", "SplineChainMovementGenerator::Initialize: resumed spline chain generator from resume state. ({})", owner->GetGUID().ToString());
119
120 ++_nextIndex;
121 if (_nextIndex >= _chainSize)
122 _msToNext = 0;
123 else if (!_msToNext)
124 _msToNext = 1;
125 _nextFirstWP = 0;
126 }
127 else
128 {
129 _msToNext = std::max(_chain[_nextIndex].TimeToNext, 1u);
131
132 ++_nextIndex;
133 if (_nextIndex >= _chainSize)
134 _msToNext = 0;
135 }
136}
137
139{
141
142 owner->StopMoving();
143 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 _msToNext -= diff;
178
179 return true;
180}
181
183{
186}
187
188void SplineChainMovementGenerator::Finalize(Unit* owner, bool active, bool movementInform)
189{
191
192 if (active)
194
195 if (movementInform && HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED))
196 {
197 Creature* ownerCreature = owner->ToCreature();
198 if (CreatureAI* AI = ownerCreature ? ownerCreature->AI() : nullptr)
199 AI->MovementInform(SPLINE_CHAIN_MOTION_TYPE, _id);
200 }
201}
202
204{
206}
207
209{
210 if (!_nextIndex)
212
213 if (owner->movespline->Finalized())
214 {
217 else
218 return SplineChainResumeInfo();
219 }
220
221 return SplineChainResumeInfo(_id, &_chain, _walk, uint8(_nextIndex - 1), uint8(owner->movespline->_currentSplineIdx()), _msToNext);
222}
223
225{
226 std::function<bool(MovementGenerator const*)> criteria = [id](MovementGenerator const* movement) -> bool
227 {
228 if (movement->GetMovementGeneratorType() == SPLINE_CHAIN_MOTION_TYPE)
229 return (!id || static_cast<SplineChainMovementGenerator const*>(movement)->GetId() == *id);
230
231 return false;
232 };
233
234 if (MovementGenerator const* activeGenerator = owner->GetMotionMaster()->GetMovementGenerator(criteria))
235 info = static_cast<SplineChainMovementGenerator const*>(activeGenerator)->GetResumeInfo(owner);
236 else
237 info.Clear();
238}
uint8_t uint8
Definition: Define.h:144
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
#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_MODE_DEFAULT
@ 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:278
@ UNIT_STATE_ROAMING
Definition: Unit.h:259
CreatureAI * AI() const
Definition: Creature.h:214
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)
std::string ToString() const
Definition: ObjectGuid.cpp:554
static Creature * ToCreature(Object *o)
Definition: Object.h:219
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
SplineChainMovementGenerator(uint32 id, std::vector< SplineChainLink > const &chain, bool walk=false)
std::vector< SplineChainLink > const & _chain
bool Update(Unit *, uint32) override
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:627
void ClearUnitState(uint32 f)
Definition: Unit.h:733
MotionMaster * GetMotionMaster()
Definition: Unit.h:1652
void StopMoving()
Definition: Unit.cpp:10049
void AddUnitState(uint32 f)
Definition: Unit.h:731
std::unique_ptr< Movement::MoveSpline > movespline
Definition: Unit.h:1766
std::vector< Vector3 > PointsArray
constexpr std::size_t size()
Definition: UpdateField.h:796
std::vector< SplineChainLink > const * Chain
Definition: SplineChain.h:43