TrinityCore
Loading...
Searching...
No Matches
FlightPathMovementGenerator.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 "DBCStores.h"
20#include "Log.h"
21#include "MapManager.h"
22#include "MovementDefines.h"
23#include "MoveSpline.h"
24#include "MoveSplineInit.h"
25#include "ObjectMgr.h"
26#include "Player.h"
27
28#define FLIGHT_TRAVEL_UPDATE 100
29#define TIMEDIFF_NEXT_WP 250
30#define SKIP_SPLINE_POINT_DISTANCE_SQ (40.f * 40.f)
31#define PLAYER_FLIGHT_SPEED 32.0f
32
45
50
51bool FlightPathMovementGenerator::GetResetPosition(Unit* /*owner*/, float& x, float& y, float& z)
52{
54 x = node->Loc.X;
55 y = node->Loc.Y;
56 z = node->Loc.Z;
57 return true;
58}
59
69
71{
73
74 owner->CombatStopWithPets();
76
77 uint32 end = GetPathAtMapEnd();
78 uint32 currentNodeId = GetCurrentNode();
79
80 if (currentNodeId == end)
81 {
82 TC_LOG_DEBUG("movement.flightpath", "FlightPathMovementGenerator::DoReset: trying to start a flypath from the end point. {}", owner->GetDebugInfo());
83 return false;
84 }
85
86 Movement::MoveSplineInit init(owner);
87 // Providing a starting vertex since the taxi paths do not provide such
88 init.Path().push_back(G3D::Vector3(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ()));
89 for (uint32 i = currentNodeId; i != end; ++i)
90 {
91 G3D::Vector3 vertice(_path[i]->Loc.X, _path[i]->Loc.Y, _path[i]->Loc.Z);
92 init.Path().push_back(vertice);
93 }
95 init.SetFly();
97 init.Launch();
98 return true;
99}
100
102{
103 if (!owner)
104 return false;
105
106 // skipping the first spline path point because it's our starting point and not a taxi path point
107 uint32 pointId = owner->movespline->currentPathIdx() <= 0 ? 0 : owner->movespline->currentPathIdx() - 1;
108 if (pointId > _currentNode && _currentNode < _path.size() - 1)
109 {
110 bool departureEvent = true;
111 do
112 {
113 ASSERT(_currentNode < _path.size(), "Point Id: %u\n%s", pointId, owner->GetDebugInfo().c_str());
114
115 DoEventIfAny(owner, _path[_currentNode], departureEvent);
116 while (!_pointsForPathSwitch.empty() && _pointsForPathSwitch.front().PathIndex <= _currentNode)
117 {
118 _pointsForPathSwitch.pop_front();
120 if (!_pointsForPathSwitch.empty())
121 {
123 owner->ModifyMoney(-_pointsForPathSwitch.front().Cost);
124 }
125 }
126
127 if (pointId == _currentNode)
128 break;
129
132
133 _currentNode += departureEvent ? 1 : 0;
134 departureEvent = !departureEvent;
135 } while (_currentNode < _path.size() - 1);
136 }
137
138 if (_currentNode >= (_path.size() - 1))
139 {
141 return false;
142 }
143 return true;
144}
145
150
151void FlightPathMovementGenerator::DoFinalize(Player* owner, bool active, bool/* movementInform*/)
152{
154 if (!active)
155 return;
156
157 uint32 taxiNodeId = owner->m_taxi.GetTaxiDestination();
159 owner->Dismount();
161
162 if (owner->m_taxi.empty())
163 {
164 // update z position to ground and orientation for landing point
165 // this prevent cheating with landing point at lags
166 // when client side flight end early in comparison server side
167 owner->StopMoving();
168
169 // When the player reaches the last flight point, teleport to destination taxi node location
170 if (TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(taxiNodeId))
171 {
172 owner->SetFallInformation(0, node->Pos.Z);
173 owner->TeleportTo(node->ContinentID, node->Pos.X, node->Pos.Y, node->Pos.Z, owner->GetOrientation());
174 }
175 }
176
178}
179
181{
182 if (_currentNode >= _path.size())
183 return _path.size();
184
185 uint32 curMapId = _path[_currentNode]->ContinentID;
186 for (uint32 itr = _currentNode; itr < _path.size(); ++itr)
187 {
188 if (_path[itr]->ContinentID != curMapId)
189 return itr;
190 }
191
192 return _path.size();
193}
194
196{
197 return p1->ContinentID != p2->ContinentID || std::pow(p1->Loc.X - p2->Loc.X, 2) + std::pow(p1->Loc.Y - p2->Loc.Y, 2) > SKIP_SPLINE_POINT_DISTANCE_SQ;
198}
199
201{
202 _pointsForPathSwitch.clear();
203 std::deque<uint32> const& taxi = owner->m_taxi.GetPath();
204 float discount = owner->GetReputationPriceDiscount(owner->m_taxi.GetFlightMasterFactionTemplate());
205 for (uint32 src = 0, dst = 1; dst < taxi.size(); src = dst++)
206 {
207 uint32 path, cost;
208 sObjectMgr->GetTaxiPath(taxi[src], taxi[dst], path, cost);
209 if (path >= sTaxiPathNodesByPath.size())
210 return;
211
212 TaxiPathNodeList const& nodes = sTaxiPathNodesByPath[path];
213 if (!nodes.empty())
214 {
215 TaxiPathNodeEntry const* start = nodes[0];
216 TaxiPathNodeEntry const* end = nodes[nodes.size() - 1];
217 bool passedPreviousSegmentProximityCheck = false;
218 for (uint32 i = 0; i < nodes.size(); ++i)
219 {
220 if (passedPreviousSegmentProximityCheck || !src || _path.empty() || IsNodeIncludedInShortenedPath(_path[_path.size() - 1], nodes[i]))
221 {
222 if ((!src || (IsNodeIncludedInShortenedPath(start, nodes[i]) && i >= 2)) &&
223 (dst == taxi.size() - 1 || (IsNodeIncludedInShortenedPath(end, nodes[i]) && i < nodes.size() - 1)))
224 {
225 passedPreviousSegmentProximityCheck = true;
226 _path.push_back(nodes[i]);
227 }
228 }
229 else
230 {
231 _path.pop_back();
232 --_pointsForPathSwitch.back().PathIndex;
233 }
234 }
235 }
236
237 _pointsForPathSwitch.push_back({ uint32(_path.size() - 1), int32(ceil(cost * discount)) });
238 }
239}
240
242{
243 if (_path.empty() || _currentNode >= _path.size())
244 return;
245
247 for (size_t i = _currentNode + 1; i < _path.size(); ++i)
248 {
249 if (_path[i]->ContinentID != map0)
250 {
251 _currentNode = i;
252 return;
253 }
254 }
255}
256
258{
259 ASSERT(node, "%s", owner->GetDebugInfo().c_str());
260
261 if (uint32 eventid = departure ? node->DepartureEventID : node->ArrivalEventID)
262 {
263 TC_LOG_DEBUG("maps.script", "FlightPathMovementGenerator::DoEventIfAny: taxi {} event {} of node {} of path {} for player {}", departure ? "departure" : "arrival", eventid, node->NodeIndex, node->PathID, owner->GetName());
264 owner->GetMap()->ScriptsStart(sEventScripts, eventid, owner, owner);
265 }
266}
267
269{
274 uint32 nodeCount = _path.size();
275 ASSERT(nodeCount, "FlightPathMovementGenerator::InitEndGridInfo() called with empty _path");
276 _endMapId = _path[nodeCount - 1]->ContinentID;
277 if (nodeCount < 3)
279 else
280 _preloadTargetNode = nodeCount - 3;
281 _endGridX = _path[nodeCount - 1]->Loc.X;
282 _endGridY = _path[nodeCount - 1]->Loc.Y;
283}
284
286{
287 // Used to preload the final grid where the flightmaster is
288 Map* endMap = sMapMgr->FindBaseNonInstanceMap(_endMapId);
289
290 // Load the grid
291 if (endMap)
292 {
293 TC_LOG_DEBUG("movement.flightpath", "FlightPathMovementGenerator::PreloadEndGrid: preloading grid ({}, {}) for map {} at node index {}/{}", _endGridX, _endGridY, _endMapId, _preloadTargetNode, uint32(_path.size() - 1));
294 endMap->LoadGrid(_endGridX, _endGridY);
295 }
296 else
297 TC_LOG_DEBUG("movement.flightpath", "FlightPathMovementGenerator::PreloadEndGrid: unable to determine map to preload flightmaster grid");
298}
299
301{
302 if (index >= _path.size())
303 return 0;
304
305 return _path[index]->PathID;
306}
307
309{
310 std::stringstream sstr;
311 sstr << std::boolalpha
314 << "Start Path Id: " << GetPathId(0)
315 << " Path Size: " << _path.size()
316 << " HasArrived: " << HasArrived()
317 << " End Grid X: " << _endGridX
318 << " End Grid Y: " << _endGridY
319 << " End Map Id: " << _endMapId
320 << " Preloaded Target Node: " << _preloadTargetNode;
321 return sstr.str();
322}
@ ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING
Definition DBCEnums.h:188
TaxiPathNodesByPath sTaxiPathNodesByPath
DBCStorage< TaxiNodesEntry > sTaxiNodesStore(TaxiNodesEntryfmt)
std::vector< TaxiPathNodeEntry const * > TaxiPathNodeList
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
#define ASSERT
Definition Errors.h:68
#define PLAYER_FLIGHT_SPEED
bool IsNodeIncludedInShortenedPath(TaxiPathNodeEntry const *p1, TaxiPathNodeEntry const *p2)
#define SKIP_SPLINE_POINT_DISTANCE_SQ
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define sMapMgr
Definition MapManager.h:211
@ MOTION_PRIORITY_HIGHEST
MovementGeneratorType
@ FLIGHT_MOTION_TYPE
@ MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING
@ MOVEMENTGENERATOR_FLAG_DEACTIVATED
@ MOVEMENTGENERATOR_FLAG_FINALIZED
@ MOVEMENTGENERATOR_FLAG_INFORM_ENABLED
@ MOVEMENTGENERATOR_FLAG_INITIALIZED
ScriptMapMap sEventScripts
Definition ObjectMgr.cpp:60
#define sObjectMgr
Definition ObjectMgr.h:1721
@ PLAYER_FLAGS_TAXI_BENCHMARK
Definition Player.h:361
@ UNIT_FLAG_ON_TAXI
@ UNIT_FLAG_REMOVE_CLIENT_CONTROL
@ UNIT_STATE_IN_FLIGHT
Definition Unit.h:228
@ PLAYER_FLAGS
float _endGridY
X coord of last node location.
bool GetResetPosition(Unit *owner, float &x, float &y, float &z) override
uint32 _preloadTargetNode
map Id of last node location
std::string GetDebugInfo() const override
void DoEventIfAny(Player *owner, TaxiPathNodeEntry const *node, bool departure)
MovementGeneratorType GetMovementGeneratorType() const override
std::deque< TaxiNodeChangeInfo > _pointsForPathSwitch
uint32 _endMapId
Y coord of last node location.
Definition Map.h:281
void ScriptsStart(std::map< uint32, std::multimap< uint32, ScriptInfo > > const &scripts, uint32 id, Object *source, Object *target)
Put scripts in the execution queue.
void LoadGrid(float x, float y)
Definition Map.cpp:578
void AddFlag(uint16 const flag)
void RemoveFlag(uint16 const flag)
virtual std::string GetDebugInfo() const
void SetFirstPointId(int32 pointId)
void SetVelocity(float velocity)
int32 currentPathIdx() const
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition Object.cpp:775
virtual std::string GetDebugInfo() const
std::deque< uint32 > const & GetPath() const
Definition PlayerTaxi.h:74
FactionTemplateEntry const * GetFlightMasterFactionTemplate() const
bool empty() const
Definition PlayerTaxi.h:75
uint32 NextTaxiDestination()
Definition PlayerTaxi.h:68
uint32 GetTaxiDestination() const
Definition PlayerTaxi.h:66
void ClearTaxiDestinations()
Definition PlayerTaxi.h:63
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1=0, uint32 miscValue2=0, WorldObject *ref=nullptr)
Definition Player.cpp:24940
bool ModifyMoney(int32 amount, bool sendError=true)
Definition Player.cpp:22339
float GetReputationPriceDiscount(Creature const *creature) const
Definition Player.cpp:23175
void SetFallInformation(uint32 time, float z)
Definition Player.cpp:24853
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition Player.cpp:1524
PlayerTaxi m_taxi
Definition Player.h:985
std::string GetDebugInfo() const override
Definition Player.cpp:26504
Definition Unit.h:769
Movement::MoveSpline * movespline
Definition Unit.h:1804
void StopMoving(bool force=false)
Definition Unit.cpp:10312
void Dismount()
Definition Unit.cpp:8234
void SetUnitFlag(UnitFlags flags)
Definition Unit.h:954
void RemoveUnitFlag(UnitFlags flags)
Definition Unit.h:955
void CombatStopWithPets(bool includingCast=false)
Definition Unit.cpp:5710
Map * GetMap() const
Definition Object.h:449
std::string const & GetName() const
Definition Object.h:382
float GetPositionZ() const
Definition Position.h:81
float GetOrientation() const
Definition Position.h:82
float GetPositionX() const
Definition Position.h:79
float GetPositionY() const
Definition Position.h:80
DBCPosition3D Loc