TrinityCore
MovementHandler.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
18#include "WorldSession.h"
19#include "Battleground.h"
20#include "Corpse.h"
21#include "DB2Stores.h"
23#include "GameTime.h"
24#include "Garrison.h"
25#include "InstanceLockMgr.h"
26#include "InstancePackets.h"
27#include "Log.h"
28#include "Map.h"
29#include "MapManager.h"
30#include "MiscPackets.h"
31#include "MovementPackets.h"
32#include "Player.h"
33#include "SpellInfo.h"
34#include "MotionMaster.h"
35#include "MovementGenerator.h"
36#include "MoveSpline.h"
37#include "Transport.h"
38#include "Vehicle.h"
39#include "SpellMgr.h"
40#include <boost/accumulators/statistics/variance.hpp>
41#include <boost/accumulators/accumulators.hpp>
42#include <boost/accumulators/statistics.hpp>
43#include <boost/circular_buffer.hpp>
44
46{
48}
49
51{
52 Player* player = GetPlayer();
53 // ignore unexpected far teleports
54 if (!player->IsBeingTeleportedFar())
55 return;
56
57 bool seamlessTeleport = player->IsBeingTeleportedSeamlessly();
58 player->SetSemaphoreTeleportFar(false);
59
60 // get the teleport destination
61 WorldLocation const& loc = player->GetTeleportDest();
62
63 // possible errors in the coordinate validity check
65 {
66 LogoutPlayer(false);
67 return;
68 }
69
70 // get the destination map entry, not the current one, this will fix homebind and reset greeting
71 MapEntry const* mEntry = sMapStore.LookupEntry(loc.GetMapId());
72
73 // reset instance validity, except if going to an instance inside an instance
74 if (player->m_InstanceValid == false && !mEntry->IsDungeon())
75 player->m_InstanceValid = true;
76
77 Map* oldMap = player->GetMap();
79 sMapMgr->FindMap(loc.GetMapId(), *GetPlayer()->GetTeleportDestInstanceId()) :
80 sMapMgr->CreateMap(loc.GetMapId(), GetPlayer());
81
83 if (TransportBase* transport = player->GetTransport())
84 transport->RemovePassenger(player);
85
86 if (player->IsInWorld())
87 {
88 TC_LOG_ERROR("network", "{} {} is still in world when teleported from map {} ({}) to new map {} ({})", player->GetGUID().ToString(), player->GetName(), oldMap->GetMapName(), oldMap->GetId(), newMap ? newMap->GetMapName() : "Unknown", loc.GetMapId());
89 oldMap->RemovePlayerFromMap(player, false);
90 }
91
92 // relocate the player to the teleport destination
93 // the CannotEnter checks are done in TeleporTo but conditions may change
94 // while the player is in transit, for example the map may get full
95 if (!newMap || newMap->CannotEnter(player))
96 {
97 TC_LOG_ERROR("network", "Map {} ({}) could not be created for player {} ({}), porting player to homebind", loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown", player->GetGUID().ToString(), player->GetName());
98 player->TeleportTo(player->m_homebind);
99 return;
100 }
101
102 float z = loc.GetPositionZ() + player->GetHoverOffset();
103 player->Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation());
104 player->SetFallInformation(0, player->GetPositionZ());
105
106 player->ResetMap();
107 player->SetMap(newMap);
108
110 resumeToken.SequenceIndex = player->m_movementCounter;
111 resumeToken.Reason = seamlessTeleport ? 2 : 1;
112 SendPacket(resumeToken.Write());
113
114 if (!seamlessTeleport)
116
117 // move player between transport copies on each map
118 if (Transport* newTransport = newMap->GetTransport(transportInfo.guid))
119 {
120 player->m_movementInfo.transport = transportInfo;
121 newTransport->AddPassenger(player);
122 }
123
124 if (!player->GetMap()->AddPlayerToMap(player, !seamlessTeleport))
125 {
126 TC_LOG_ERROR("network", "WORLD: failed to teleport player {} {} to map {} ({}) because of unknown reason!",
127 player->GetName(), player->GetGUID().ToString(), loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown");
128 player->ResetMap();
129 player->SetMap(oldMap);
130 player->TeleportTo(player->m_homebind);
131 return;
132 }
133
134 // battleground state prepare (in case join to BG), at relogin/tele player not invited
135 // only add to bg group and object, if the player was invited (else he entered through command)
136 if (player->InBattleground())
137 {
138 // cleanup setting if outdated
139 if (!mEntry->IsBattlegroundOrArena())
140 {
141 // We're not in BG
143 // reset destination bg team
144 player->SetBGTeam(TEAM_OTHER);
145 }
146 // join to bg case
147 else if (Battleground* bg = player->GetBattleground())
148 {
150 bg->AddPlayer(player, player->m_bgData.queueId);
151 }
152 }
153
154 if (!seamlessTeleport)
156 else
157 {
159 if (Garrison* garrison = player->GetGarrison())
160 garrison->SendRemoteInfo();
161 }
162
163 // flight fast teleport case
164 if (player->IsInFlight())
165 {
166 if (!player->InBattleground())
167 {
168 if (!seamlessTeleport)
169 {
170 // short preparations to continue flight
171 MovementGenerator* movementGenerator = player->GetMotionMaster()->GetCurrentMovementGenerator();
172 movementGenerator->Initialize(player);
173 }
174 return;
175 }
176
177 // battleground state prepare, stop flight
178 player->FinishTaxiFlight();
179 }
180
181 if (!player->IsAlive() && player->GetTeleportOptions() & TELE_REVIVE_AT_TELEPORT)
182 player->ResurrectPlayer(0.5f);
183
184 // resurrect character at enter into instance where his corpse exist after add to map
185 if (mEntry->IsDungeon() && !player->IsAlive())
186 {
187 if (player->GetCorpseLocation().GetMapId() == mEntry->ID)
188 {
189 player->ResurrectPlayer(0.5f);
190 player->SpawnCorpseBones();
191 }
192 }
193
194 if (mEntry->IsDungeon())
195 {
196 // check if this instance has a reset time and send it to player if so
197 MapDb2Entries entries{ mEntry->ID, newMap->GetDifficultyID() };
198 if (entries.MapDifficulty->HasResetSchedule())
199 {
201 raidInstanceMessage.Type = RAID_INSTANCE_WELCOME;
202 raidInstanceMessage.MapID = mEntry->ID;
203 raidInstanceMessage.DifficultyID = newMap->GetDifficultyID();
204 if (InstanceLock const* playerLock = sInstanceLockMgr.FindActiveInstanceLock(GetPlayer()->GetGUID(), entries))
205 {
206 raidInstanceMessage.Locked = !playerLock->IsExpired();
207 raidInstanceMessage.Extended = playerLock->IsExtended();
208 }
209 else
210 {
211 raidInstanceMessage.Locked = false;
212 raidInstanceMessage.Extended = false;
213 }
214 SendPacket(raidInstanceMessage.Write());
215 }
216
217 // check if instance is valid
218 if (!player->CheckInstanceValidity(false))
219 player->m_InstanceValid = false;
220 }
221
222 // update zone immediately, otherwise leave channel will cause crash in mtmap
223 uint32 newzone, newarea;
224 player->GetZoneAndAreaId(newzone, newarea);
225 player->UpdateZone(newzone, newarea);
226
227 // honorless target
228 if (player->pvpInfo.IsHostile)
229 player->CastSpell(player, 2479, true);
230
231 // in friendly area
232 else if (player->IsPvP() && !player->HasPlayerFlag(PLAYER_FLAGS_IN_PVP))
233 player->UpdatePvP(false, false);
234
235 // resummon pet
238
239 //lets process all delayed operations on successful teleport
240 player->ProcessDelayedOperations();
241}
242
244{
246 return;
247
248 WorldLocation const& loc = GetPlayer()->GetTeleportDest();
249
250 if (sMapStore.AssertEntry(loc.GetMapId())->IsDungeon())
251 {
253 updateLastInstance.MapID = loc.GetMapId();
254 SendPacket(updateLastInstance.Write());
255 }
256
258 packet.MapID = loc.GetMapId();
259 packet.Loc.Pos = loc;
261 SendPacket(packet.Write());
262
265}
266
268{
269 TC_LOG_DEBUG("network", "CMSG_MOVE_TELEPORT_ACK: Guid: {}, Sequence: {}, Time: {}", packet.MoverGUID.ToString(), packet.AckIndex, packet.MoveTime);
270
271 Player* plMover = _player->GetUnitBeingMoved()->ToPlayer();
272
273 if (!plMover || !plMover->IsBeingTeleportedNear())
274 return;
275
276 if (packet.MoverGUID != plMover->GetGUID())
277 return;
278
279 plMover->SetSemaphoreTeleportNear(false);
280
281 uint32 old_zone = plMover->GetZoneId();
282
283 WorldLocation const& dest = plMover->GetTeleportDest();
284
285 plMover->UpdatePosition(dest, true);
286 plMover->SetFallInformation(0, GetPlayer()->GetPositionZ());
287
288 uint32 newzone, newarea;
289 plMover->GetZoneAndAreaId(newzone, newarea);
290 plMover->UpdateZone(newzone, newarea);
291
292 // new zone
293 if (old_zone != newzone)
294 {
295 // honorless target
296 if (plMover->pvpInfo.IsHostile)
297 plMover->CastSpell(plMover, 2479, true);
298
299 // in friendly area
300 else if (plMover->IsPvP() && !plMover->HasPlayerFlag(PLAYER_FLAGS_IN_PVP))
301 plMover->UpdatePvP(false, false);
302 }
303
304 // resummon pet
306
307 //lets process all delayed operations on successful teleport
309}
310
312{
313 HandleMovementOpcode(packet.GetOpcode(), packet.Status);
314}
315
317{
318 Unit* mover = _player->GetUnitBeingMoved();
319
320 ASSERT(mover != nullptr); // there must always be a mover
321
322 Player* plrMover = mover->ToPlayer();
323
324 TC_LOG_TRACE("opcodes.movement", "HandleMovementOpcode Name {}: opcode {} {} Flags {} Flags2 {} Pos {}",
325 mover->GetName(), opcode, GetOpcodeNameForLogging(opcode),
326 movementInfo.flags, movementInfo.flags2, movementInfo.pos.ToString());
327
328 // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
329 if (plrMover && plrMover->IsBeingTeleported())
330 return;
331
332 GetPlayer()->ValidateMovementInfo(&movementInfo);
333
334 // prevent tampered movement data
335 if (movementInfo.guid != mover->GetGUID())
336 {
337 TC_LOG_ERROR("network", "HandleMovementOpcodes: guid error");
338 return;
339 }
340
341 if (!movementInfo.pos.IsPositionValid())
342 return;
343
344 if (!mover->movespline->Finalized())
345 return;
346
347 // stop some emotes at player move
348 if (plrMover && (plrMover->GetEmoteState() != 0))
350
351 /* handle special cases */
352 if (!movementInfo.transport.guid.IsEmpty())
353 {
354 // We were teleported, skip packets that were broadcast before teleport
355 if (movementInfo.pos.GetExactDist2d(mover) > SIZE_OF_GRIDS)
356 return;
357
358 // transports size limited
359 // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
360 if (fabs(movementInfo.transport.pos.GetPositionX()) > 75.0f || fabs(movementInfo.transport.pos.GetPositionY()) > 75.0f || fabs(movementInfo.transport.pos.GetPositionZ()) > 75.0f)
361 return;
362
363 if (!Trinity::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.transport.pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.transport.pos.GetPositionY(),
364 movementInfo.pos.GetPositionZ() + movementInfo.transport.pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.transport.pos.GetOrientation()))
365 return;
366
367 // if we boarded a transport, add us to it
368 if (plrMover)
369 {
370 if (!plrMover->GetTransport())
371 {
372 if (GameObject* go = plrMover->GetMap()->GetGameObject(movementInfo.transport.guid))
373 if (TransportBase* transport = go->ToTransportBase())
374 transport->AddPassenger(plrMover);
375 }
376 else if (plrMover->GetTransport()->GetTransportGUID() != movementInfo.transport.guid)
377 {
378 plrMover->GetTransport()->RemovePassenger(plrMover);
379 if (GameObject* go = plrMover->GetMap()->GetGameObject(movementInfo.transport.guid))
380 {
381 if (TransportBase* transport = go->ToTransportBase())
382 transport->AddPassenger(plrMover);
383 else
384 movementInfo.ResetTransport();
385 }
386 else
387 movementInfo.ResetTransport();
388 }
389 }
390
391 if (!mover->GetTransport() && !mover->GetVehicle())
392 movementInfo.transport.Reset();
393 }
394 else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave
395 plrMover->GetTransport()->RemovePassenger(plrMover);
396
397 // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
398 if (opcode == CMSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight())
399 plrMover->HandleFall(movementInfo);
400
401 // interrupt parachutes upon falling or landing in water
402 if (opcode == CMSG_MOVE_FALL_LAND || opcode == CMSG_MOVE_START_SWIM || opcode == CMSG_MOVE_SET_FLY)
404
405 if (opcode == CMSG_MOVE_SET_FLY || opcode == CMSG_MOVE_SET_ADV_FLY)
406 {
407 _player->UnsummonPetTemporaryIfAny(); // always do the pet removal on current client activeplayer only
409 }
410
411 /* process position-change */
412 movementInfo.guid = mover->GetGUID();
413 movementInfo.time = AdjustClientMovementTime(movementInfo.time);
414 mover->m_movementInfo = movementInfo;
415
416 // Some vehicles allow the passenger to turn by himself
417 if (Vehicle* vehicle = mover->GetVehicle())
418 {
419 if (VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(mover))
420 {
421 if (seat->Flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING)
422 {
423 if (movementInfo.pos.GetOrientation() != mover->GetOrientation())
424 {
425 mover->SetOrientation(movementInfo.pos.GetOrientation());
427 }
428 }
429 }
430 return;
431 }
432
433 mover->UpdatePosition(movementInfo.pos);
434
436 moveUpdate.Status = &mover->m_movementInfo;
437 mover->SendMessageToSet(moveUpdate.Write(), _player);
438
439 if (plrMover) // nothing is charmed, or player charmed
440 {
441 if (plrMover->IsSitState() && (movementInfo.flags & (MOVEMENTFLAG_MASK_MOVING | MOVEMENTFLAG_MASK_TURNING)))
443
444 plrMover->UpdateFallInformationIfNeed(movementInfo, opcode);
445
446 if (movementInfo.pos.GetPositionZ() < plrMover->GetMap()->GetMinHeight(plrMover->GetPhaseShift(), movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY()))
447 {
448 if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player)))
449 {
450 // NOTE: this is actually called many times while falling
451 // even after the player has been teleported away
453 if (plrMover->IsAlive())
454 {
455 TC_LOG_DEBUG("entities.player.falldamage", "FALLDAMAGE Below map. Map min height: {} , Player debug info:\n{}", plrMover->GetMap()->GetMinHeight(plrMover->GetPhaseShift(), movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY()), plrMover->GetDebugInfo());
457 plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
458 // player can be alive if GM/etc
459 // change the death state to CORPSE to prevent the death timer from
460 // starting in the next player update
461 if (plrMover->IsAlive())
462 plrMover->KillPlayer();
463 }
464 }
465 }
466 else
468
469 if (opcode == CMSG_MOVE_JUMP)
470 {
473 }
474 }
475}
476
478{
479
481
482 // now can skip not our packet
483 if (_player->GetGUID() != packet.Ack.Status.guid)
484 return;
485
486 /*----------------*/
487
488 // client ACK send one packet for mounted/run case and need skip all except last from its
489 // in other cases anti-cheat check can be fail in false case
490 UnitMoveType move_type;
491
492 static char const* const move_type_name[MAX_MOVE_TYPE] =
493 {
494 "Walk",
495 "Run",
496 "RunBack",
497 "Swim",
498 "SwimBack",
499 "TurnRate",
500 "Flight",
501 "FlightBack",
502 "PitchRate"
503 };
504
505 OpcodeClient opcode = packet.GetOpcode();
506 switch (opcode)
507 {
508
509 case CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; break;
510 case CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; break;
512 case CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; break;
518
519 default:
520 TC_LOG_ERROR("network", "WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: {}", opcode);
521 return;
522 }
523
524 // skip all forced speed changes except last and unexpected
525 // in run/mounted case used one ACK and it must be skipped. m_forced_speed_changes[MOVE_RUN] store both.
526 if (_player->m_forced_speed_changes[move_type] > 0)
527 {
528 --_player->m_forced_speed_changes[move_type];
529 if (_player->m_forced_speed_changes[move_type] > 0)
530 return;
531 }
532
533 if (!_player->GetTransport() && std::fabs(_player->GetSpeed(move_type) - packet.Speed) > 0.01f)
534 {
535 if (_player->GetSpeed(move_type) > packet.Speed) // must be greater - just correct
536 {
537 TC_LOG_ERROR("network", "{}SpeedChange player {} is NOT correct (must be {} instead {}), force set to correct value",
538 move_type_name[move_type], _player->GetName(), _player->GetSpeed(move_type), packet.Speed);
539 _player->SetSpeedRate(move_type, _player->GetSpeedRate(move_type));
540 }
541 else // must be lesser - cheating
542 {
543 TC_LOG_DEBUG("misc", "Player {} from account id {} kicked for incorrect speed (must be {} instead {})",
544 _player->GetName(), _player->GetSession()->GetAccountId(), _player->GetSpeed(move_type), packet.Speed);
545 _player->GetSession()->KickPlayer("WorldSession::HandleForceSpeedChangeAck Incorrect speed");
546 }
547 }
548}
549
551{
552 if (GetPlayer()->IsInWorld())
553 if (_player->GetUnitBeingMoved()->GetGUID() != packet.ActiveMover)
554 TC_LOG_DEBUG("network", "HandleSetActiveMoverOpcode: incorrect mover guid: mover is {} and should be {}" , packet.ActiveMover.ToString(), _player->GetUnitBeingMoved()->GetGUID().ToString());
555}
556
558{
559 GetPlayer()->ValidateMovementInfo(&movementAck.Ack.Status);
560
561 if (_player->m_unitMovedByMe->GetGUID() != movementAck.Ack.Status.guid)
562 return;
563
564 movementAck.Ack.Status.time = AdjustClientMovementTime(movementAck.Ack.Status.time);
565 _player->m_movementInfo = movementAck.Ack.Status;
566
568 updateKnockBack.Status = &_player->m_movementInfo;
569 _player->SendMessageToSet(updateKnockBack.Write(), false);
570}
571
573{
574 GetPlayer()->ValidateMovementInfo(&movementAck.Ack.Status);
575}
576
578{
579 if (!_player->IsAlive() || _player->IsInCombat())
580 return;
581
583}
584
586{
587 GetPlayer()->ValidateMovementInfo(&setCollisionHeightAck.Data.Status);
588}
589
591{
592 Unit* mover = _player->m_unitMovedByMe;
593 ASSERT(mover != nullptr);
594 _player->ValidateMovementInfo(&moveApplyMovementForceAck.Ack.Status);
595
596 // prevent tampered movement data
597 if (moveApplyMovementForceAck.Ack.Status.guid != mover->GetGUID())
598 {
599 TC_LOG_ERROR("network", "HandleMoveApplyMovementForceAck: guid error, expected {}, got {}",
600 mover->GetGUID().ToString(), moveApplyMovementForceAck.Ack.Status.guid.ToString());
601 return;
602 }
603
604 moveApplyMovementForceAck.Ack.Status.time = AdjustClientMovementTime(moveApplyMovementForceAck.Ack.Status.time);
605
607 updateApplyMovementForce.Status = &moveApplyMovementForceAck.Ack.Status;
608 updateApplyMovementForce.Force = &moveApplyMovementForceAck.Force;
609 mover->SendMessageToSet(updateApplyMovementForce.Write(), false);
610}
611
613{
614 Unit* mover = _player->m_unitMovedByMe;
615 ASSERT(mover != nullptr);
616 _player->ValidateMovementInfo(&moveRemoveMovementForceAck.Ack.Status);
617
618 // prevent tampered movement data
619 if (moveRemoveMovementForceAck.Ack.Status.guid != mover->GetGUID())
620 {
621 TC_LOG_ERROR("network", "HandleMoveRemoveMovementForceAck: guid error, expected {}, got {}",
622 mover->GetGUID().ToString(), moveRemoveMovementForceAck.Ack.Status.guid.ToString());
623 return;
624 }
625
626 moveRemoveMovementForceAck.Ack.Status.time = AdjustClientMovementTime(moveRemoveMovementForceAck.Ack.Status.time);
627
629 updateRemoveMovementForce.Status = &moveRemoveMovementForceAck.Ack.Status;
630 updateRemoveMovementForce.TriggerGUID = moveRemoveMovementForceAck.ID;
631 mover->SendMessageToSet(updateRemoveMovementForce.Write(), false);
632}
633
635{
636 Unit* mover = _player->m_unitMovedByMe;
637 ASSERT(mover != nullptr); // there must always be a mover
638 _player->ValidateMovementInfo(&setModMovementForceMagnitudeAck.Ack.Status);
639
640 // prevent tampered movement data
641 if (setModMovementForceMagnitudeAck.Ack.Status.guid != mover->GetGUID())
642 {
643 TC_LOG_ERROR("network", "HandleSetModMovementForceMagnitudeAck: guid error, expected {}, got {}",
644 mover->GetGUID().ToString(), setModMovementForceMagnitudeAck.Ack.Status.guid.ToString());
645 return;
646 }
647
648 // skip all except last
650 {
653 {
654 float expectedModMagnitude = 1.0f;
655 if (MovementForces const* movementForces = mover->GetMovementForces())
656 expectedModMagnitude = movementForces->GetModMagnitude();
657
658 if (std::fabs(expectedModMagnitude - setModMovementForceMagnitudeAck.Speed) > 0.01f)
659 {
660 TC_LOG_DEBUG("misc", "Player {} from account id {} kicked for incorrect movement force magnitude (must be {} instead {})",
661 _player->GetName(), _player->GetSession()->GetAccountId(), expectedModMagnitude, setModMovementForceMagnitudeAck.Speed);
662 _player->GetSession()->KickPlayer("WorldSession::HandleMoveSetModMovementForceMagnitudeAck Incorrect magnitude");
663 return;
664 }
665 }
666 }
667
668 setModMovementForceMagnitudeAck.Ack.Status.time = AdjustClientMovementTime(setModMovementForceMagnitudeAck.Ack.Status.time);
669
671 updateModMovementForceMagnitude.Status = &setModMovementForceMagnitudeAck.Ack.Status;
672 updateModMovementForceMagnitude.Speed = setModMovementForceMagnitudeAck.Speed;
673 mover->SendMessageToSet(updateModMovementForceMagnitude.Write(), false);
674}
675
677{
678 MovementInfo movementInfo = moveSplineDone.Status;
679 _player->ValidateMovementInfo(&movementInfo);
680
681 // in taxi flight packet received in 2 case:
682 // 1) end taxi path in far (multi-node) flight
683 // 2) switch from one map to other in case multim-map taxi path
684 // we need process only (1)
685
687 if (curDest)
688 {
689 TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest);
690
691 // far teleport case
692 if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE)
693 {
694 if (FlightPathMovementGenerator* flight = dynamic_cast<FlightPathMovementGenerator*>(GetPlayer()->GetMotionMaster()->GetCurrentMovementGenerator()))
695 {
696 bool shouldTeleport = curDestNode && curDestNode->ContinentID != GetPlayer()->GetMapId();
697 if (!shouldTeleport)
698 {
699 TaxiPathNodeEntry const* currentNode = flight->GetPath()[flight->GetCurrentNode()];
700 shouldTeleport = currentNode->Flags & TAXI_PATH_NODE_FLAG_TELEPORT;
701 }
702
703 if (shouldTeleport)
704 {
705 // short preparations to continue flight
706 flight->SetCurrentNodeAfterTeleport();
707 TaxiPathNodeEntry const* node = flight->GetPath()[flight->GetCurrentNode()];
708 flight->SkipCurrentNode();
709
710 GetPlayer()->TeleportTo(curDestNode->ContinentID, node->Loc.X, node->Loc.Y, node->Loc.Z, GetPlayer()->GetOrientation());
711 }
712 }
713 }
714
715 return;
716 }
717
718 // at this point only 1 node is expected (final destination)
719 if (GetPlayer()->m_taxi.GetPath().size() != 1)
720 return;
721
723 GetPlayer()->SetFallInformation(0, GetPlayer()->GetPositionZ());
724 if (GetPlayer()->pvpInfo.IsHostile)
725 GetPlayer()->CastSpell(GetPlayer(), 2479, true);
726}
727
729{
730 Unit* mover = GetPlayer()->m_unitMovedByMe;
731 if (!mover)
732 {
733 TC_LOG_WARN("entities.player", "WorldSession::HandleMoveTimeSkippedOpcode wrong mover state from the unit moved by {}", GetPlayer()->GetGUID().ToString());
734 return;
735 }
736
737 // prevent tampered movement data
738 if (moveTimeSkipped.MoverGUID != mover->GetGUID())
739 {
740 TC_LOG_WARN("entities.player", "WorldSession::HandleMoveTimeSkippedOpcode wrong guid from the unit moved by {}", GetPlayer()->GetGUID().ToString());
741 return;
742 }
743
744 mover->m_movementInfo.time += moveTimeSkipped.TimeSkipped;
745
747 moveSkipTime.MoverGUID = moveTimeSkipped.MoverGUID;
748 moveSkipTime.TimeSkipped = moveTimeSkipped.TimeSkipped;
749 mover->SendMessageToSet(moveSkipTime.Write(), _player);
750}
751
753{
754 if (_pendingTimeSyncRequests.count(timeSyncResponse.SequenceIndex) == 0)
755 return;
756
757 uint32 serverTimeAtSent = _pendingTimeSyncRequests.at(timeSyncResponse.SequenceIndex);
758 _pendingTimeSyncRequests.erase(timeSyncResponse.SequenceIndex);
759
760 // time it took for the request to travel to the client, for the client to process it and reply and for response to travel back to the server.
761 // we are going to make 2 assumptions:
762 // 1) we assume that the request processing time equals 0.
763 // 2) we assume that the packet took as much time to travel from server to client than it took to travel from client to server.
764 uint32 roundTripDuration = getMSTimeDiff(serverTimeAtSent, timeSyncResponse.GetReceivedTime());
765 uint32 lagDelay = roundTripDuration / 2;
766
767 /*
768 clockDelta = serverTime - clientTime
769 where
770 serverTime: time that was displayed on the clock of the SERVER at the moment when the client processed the SMSG_TIME_SYNC_REQUEST packet.
771 clientTime: time that was displayed on the clock of the CLIENT at the moment when the client processed the SMSG_TIME_SYNC_REQUEST packet.
772
773 Once clockDelta has been computed, we can compute the time of an event on server clock when we know the time of that same event on the client clock,
774 using the following relation:
775 serverTime = clockDelta + clientTime
776 */
777 int64 clockDelta = (int64)serverTimeAtSent + (int64)lagDelay - (int64)timeSyncResponse.ClientTime;
778 _timeSyncClockDeltaQueue->push_back(std::pair<int64, uint32>(clockDelta, roundTripDuration));
780}
781
783{
784 // implementation of the technique described here: https://web.archive.org/web/20180430214420/http://www.mine-control.com/zack/timesync/timesync.html
785 // to reduce the skew induced by dropped TCP packets that get resent.
786
787 using namespace boost::accumulators;
788
789 accumulator_set<uint32, features<tag::mean, tag::median, tag::variance(lazy)> > latencyAccumulator;
790
791 for (auto [_, roundTripDuration] : *_timeSyncClockDeltaQueue)
792 latencyAccumulator(roundTripDuration);
793
794 uint32 latencyMedian = static_cast<uint32>(std::round(median(latencyAccumulator)));
795 uint32 latencyStandardDeviation = static_cast<uint32>(std::round(sqrt(variance(latencyAccumulator))));
796
797 accumulator_set<int64, features<tag::mean> > clockDeltasAfterFiltering;
798 uint32 sampleSizeAfterFiltering = 0;
799 for (auto [clockDelta, roundTripDuration] : *_timeSyncClockDeltaQueue)
800 {
801 if (roundTripDuration < latencyStandardDeviation + latencyMedian) {
802 clockDeltasAfterFiltering(clockDelta);
803 sampleSizeAfterFiltering++;
804 }
805 }
806
807 if (sampleSizeAfterFiltering != 0)
808 {
809 int64 meanClockDelta = static_cast<int64>(std::round(mean(clockDeltasAfterFiltering)));
810 if (std::abs(meanClockDelta - _timeSyncClockDelta) > 25)
811 _timeSyncClockDelta = meanClockDelta;
812 }
813 else if (_timeSyncClockDelta == 0)
815}
816
818{
820 _player->SetTransportServerTime(GameTime::GetGameTimeMS() - moveInitActiveMoverComplete.Ticks);
821
823}
DB2Storage< MapEntry > sMapStore("Map.db2", &MapLoadInfo::Instance)
DB2Storage< TaxiNodesEntry > sTaxiNodesStore("TaxiNodes.db2", &TaxiNodesLoadInfo::Instance)
@ VEHICLE_SEAT_FLAG_ALLOW_TURNING
Definition: DBCEnums.h:2427
@ TAXI_PATH_NODE_FLAG_TELEPORT
Definition: DBCEnums.h:2152
int64_t int64
Definition: Define.h:137
uint32_t uint32
Definition: Define.h:142
#define ASSERT
Definition: Errors.h:68
#define SIZE_OF_GRIDS
Definition: GridDefines.h:40
#define sInstanceLockMgr
#define TC_LOG_WARN(filterType__,...)
Definition: Log.h:162
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:156
#define TC_LOG_TRACE(filterType__,...)
Definition: Log.h:153
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
#define sMapMgr
Definition: MapManager.h:184
@ FLIGHT_MOTION_TYPE
@ DAMAGE_FALL_TO_VOID
Definition: Player.h:823
@ NEW_WORLD_NORMAL
Definition: Player.h:773
@ NEW_WORLD_SEAMLESS
Definition: Player.h:774
@ TELE_REVIVE_AT_TELEPORT
Definition: Player.h:808
@ PLAYER_FLAGS_IN_PVP
Definition: Player.h:437
@ PLAYER_FLAGS_IS_OUT_OF_BOUNDS
Definition: Player.h:442
@ PLAYER_LOCAL_FLAG_OVERRIDE_TRANSPORT_SERVER_TIME
Definition: Player.h:491
@ RAID_INSTANCE_WELCOME
Definition: Player.h:782
@ EMOTE_ONESHOT_NONE
constexpr BattlegroundQueueTypeId BATTLEGROUND_QUEUE_NONE
@ TEAM_OTHER
@ BATTLEGROUND_TYPE_NONE
@ PROC_SPELL_PHASE_NONE
Definition: SpellMgr.h:262
@ PROC_SPELL_TYPE_MASK_ALL
Definition: SpellMgr.h:255
@ PROC_FLAG_JUMP
Definition: SpellMgr.h:176
@ PROC_FLAG_NONE
Definition: SpellMgr.h:135
@ PROC_HIT_NONE
Definition: SpellMgr.h:273
uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime)
Definition: Timer.h:40
UnitMoveType
Definition: UnitDefines.h:116
@ MOVE_FLIGHT
Definition: UnitDefines.h:123
@ MOVE_SWIM
Definition: UnitDefines.h:120
@ MOVE_TURN_RATE
Definition: UnitDefines.h:122
@ MOVE_FLIGHT_BACK
Definition: UnitDefines.h:124
@ MOVE_SWIM_BACK
Definition: UnitDefines.h:121
@ MOVE_RUN
Definition: UnitDefines.h:118
@ MOVE_PITCH_RATE
Definition: UnitDefines.h:125
@ MOVE_RUN_BACK
Definition: UnitDefines.h:119
@ MOVE_WALK
Definition: UnitDefines.h:117
@ UNIT_STAND_STATE_STAND
Definition: UnitDefines.h:42
@ MOVEMENTFLAG_MASK_MOVING
Definition: UnitDefines.h:389
@ MOVEMENTFLAG_MASK_TURNING
Definition: UnitDefines.h:393
#define MAX_MOVE_TYPE
Definition: UnitDefines.h:128
virtual bool HandlePlayerUnderMap(Player *)
Definition: Battleground.h:460
static bool IsValidMapCoord(uint32 mapid, float x, float y)
Definition: MapManager.h:82
Definition: Map.h:189
virtual void RemovePlayerFromMap(Player *, bool)
Definition: Map.cpp:945
virtual bool AddPlayerToMap(Player *player, bool initPlayer=true)
Definition: Map.cpp:415
virtual TransferAbortParams CannotEnter(Player *)
Definition: Map.h:320
float GetMinHeight(PhaseShift const &phaseShift, float x, float y)
Definition: Map.cpp:1747
GameObject * GetGameObject(ObjectGuid const &guid)
Definition: Map.cpp:3489
Difficulty GetDifficultyID() const
Definition: Map.h:324
uint32 GetId() const
Definition: Map.cpp:3228
char const * GetMapName() const
Definition: Map.cpp:1854
Transport * GetTransport(ObjectGuid const &guid)
Definition: Map.cpp:3499
MovementGenerator * GetCurrentMovementGenerator() const
virtual void Initialize(Unit *owner)=0
bool IsEmpty() const
Definition: ObjectGuid.h:319
std::string ToString() const
Definition: ObjectGuid.cpp:554
bool IsInWorld() const
Definition: Object.h:154
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
static Player * ToPlayer(Object *o)
Definition: Object.h:213
uint32 GetTaxiDestination() const
Definition: PlayerTaxi.h:73
void SetSemaphoreTeleportNear(bool semphsetting)
Definition: Player.h:2223
void SendInitialPacketsAfterAddToMap()
Definition: Player.cpp:24316
void ValidateMovementInfo(MovementInfo *mi)
Definition: Player.cpp:29539
bool m_InstanceValid
Definition: Player.h:2571
WorldLocation & GetTeleportDest()
Definition: Player.h:2216
void HandleFall(MovementInfo const &movementInfo)
Definition: Player.cpp:26678
void SetPlayerFlag(PlayerFlags flags)
Definition: Player.h:2738
void SetBGTeam(Team team)
Definition: Player.cpp:23603
bool IsBeingTeleportedFar() const
Definition: Player.h:2221
void SetPlayerLocalFlag(PlayerLocalFlags flags)
Definition: Player.h:2833
void RemovePlayerFlag(PlayerFlags flags)
Definition: Player.h:2739
uint32 EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
Definition: Player.cpp:634
void KillPlayer()
Definition: Player.cpp:4495
void SetBattlegroundId(uint32 val, BattlegroundTypeId bgTypeId, BattlegroundQueueTypeId queueId)
Definition: Player.cpp:25030
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, TeleportToOptions options=TELE_TO_NONE, Optional< uint32 > instanceId={})
Definition: Player.cpp:1250
uint8 m_movementForceModMagnitudeChanges
Definition: Player.h:2530
bool InBattleground() const
Definition: Player.h:2394
void SpawnCorpseBones(bool triggerSave=true)
Definition: Player.cpp:4598
void UpdateZone(uint32 newZone, uint32 newArea)
Definition: Player.cpp:7549
void SetFallInformation(uint32 time, float z)
Definition: Player.cpp:26672
void SendInitialPacketsBeforeAddToMap()
Definition: Player.cpp:24203
void ResetMap() override
Definition: Player.cpp:27560
WorldLocation m_homebind
Definition: Player.h:2503
WorldSession * GetSession() const
Definition: Player.h:2101
bool IsInvitedForBattlegroundInstance(uint32 instanceId) const
Definition: Player.cpp:25083
void UnsummonPetTemporaryIfAny()
Definition: Player.cpp:27165
void UpdateFallInformationIfNeed(MovementInfo const &minfo, uint16 opcode)
Definition: Player.cpp:27116
void UpdateVisibilityForPlayer()
Definition: Player.cpp:24085
void SetSemaphoreTeleportFar(bool semphsetting)
Definition: Player.h:2224
void ResummonBattlePetTemporaryUnSummonedIfAny()
Definition: Player.cpp:27214
WorldLocation GetCorpseLocation() const
Definition: Player.h:2164
Optional< uint32 > GetTeleportDestInstanceId() const
Definition: Player.h:2217
void FinishTaxiFlight()
Definition: Player.cpp:22706
Battleground * GetBattleground() const
Definition: Player.cpp:24976
void ProcessDelayedOperations()
Definition: Player.cpp:1507
bool UpdatePosition(float x, float y, float z, float orientation, bool teleport=false) override
Definition: Player.cpp:6273
uint32 GetTeleportOptions() const
Definition: Player.h:2218
PvPInfo pvpInfo
Definition: Player.h:1953
void SummonIfPossible(bool agree)
Definition: Player.cpp:25337
PlayerTaxi m_taxi
Definition: Player.h:1166
std::array< uint8, MAX_MOVE_TYPE > m_forced_speed_changes
Definition: Player.h:2529
bool IsBeingTeleportedNear() const
Definition: Player.h:2220
void SetTransportServerTime(int32 transportServerTime)
Definition: Player.h:2845
bool CheckInstanceValidity(bool)
Definition: Player.cpp:19821
Garrison * GetGarrison() const
Definition: Player.h:2710
void UnsummonBattlePetTemporaryIfAny(bool onFlyingMount=false)
Definition: Player.cpp:27199
uint32 GetBattlegroundId() const
Definition: Player.h:2396
bool IsBeingTeleportedSeamlessly() const
Definition: Player.h:2222
bool HasPlayerFlag(PlayerFlags flags) const
Definition: Player.h:2737
void UpdateObjectVisibility(bool forced=true) override
Definition: Player.cpp:24070
void SetMap(Map *map) override
Definition: Player.cpp:27572
std::string GetDebugInfo() const override
Definition: Player.cpp:30123
void SendMessageToSet(WorldPacket const *data, bool self) const override
Definition: Player.h:2151
void ResummonPetTemporaryUnSummonedIfAny()
Definition: Player.cpp:27180
void UpdatePvP(bool state, bool override=false)
Definition: Player.cpp:23360
void CleanupAfterTaxiFlight()
Definition: Player.cpp:22715
BGData m_bgData
Definition: Player.h:2897
bool IsBeingTeleported() const
Definition: Player.h:2219
void ResurrectPlayer(float restore_percent, bool applySickness=false)
Definition: Player.cpp:4408
virtual ObjectGuid GetTransportGUID() const =0
virtual TransportBase * RemovePassenger(WorldObject *passenger)=0
virtual void AddPassenger(WorldObject *passenger)=0
Definition: Unit.h:627
Vehicle * GetVehicle() const
Definition: Unit.h:1713
Unit * m_unitMovedByMe
Definition: Unit.h:1898
float GetSpeed(UnitMoveType mtype) const
Definition: Unit.cpp:8515
void SetStandState(UnitStandStateType state, uint32 animKitID=0)
Definition: Unit.cpp:10100
Emote GetEmoteState() const
Definition: Unit.h:851
bool IsPvP() const
Definition: Unit.h:873
MotionMaster * GetMotionMaster()
Definition: Unit.h:1652
MovementForces const * GetMovementForces() const
Definition: Unit.h:1153
bool IsAlive() const
Definition: Unit.h:1164
uint32 m_movementCounter
Incrementing counter used in movement packets.
Definition: Unit.h:1955
void SetEmoteState(Emote emote)
Definition: Unit.h:852
virtual bool UpdatePosition(float x, float y, float z, float ang, bool teleport=false)
Definition: Unit.cpp:12392
bool IsInFlight() const
Definition: Unit.h:1012
Unit * GetUnitBeingMoved() const
Definition: Unit.h:1230
float GetHoverOffset() const
Definition: Unit.h:1740
void RemoveAurasWithInterruptFlags(InterruptFlags flag, SpellInfo const *source=nullptr)
Definition: Unit.cpp:4101
float GetSpeedRate(UnitMoveType mtype) const
Definition: Unit.h:1644
void SetSpeedRate(UnitMoveType mtype, float rate)
Definition: Unit.cpp:8525
std::unique_ptr< Movement::MoveSpline > movespline
Definition: Unit.h:1766
static void ProcSkillsAndAuras(Unit *actor, Unit *actionTarget, ProcFlagsInit const &typeMaskActor, ProcFlagsInit const &typeMaskActionTarget, ProcFlagsSpellType spellTypeMask, ProcFlagsSpellPhase spellPhaseMask, ProcFlagsHit hitMask, Spell *spell, DamageInfo *damageInfo, HealInfo *healInfo)
Definition: Unit.cpp:5407
bool IsInCombat() const
Definition: Unit.h:1043
bool IsSitState() const
Definition: Unit.cpp:10085
constexpr uint32 GetMapId() const
Definition: Position.h:201
virtual void SendMessageToSet(WorldPacket const *data, bool self) const
Definition: Object.cpp:1744
Map * GetMap() const
Definition: Object.h:624
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2896
PhaseShift & GetPhaseShift()
Definition: Object.h:523
TransportBase * GetTransport() const
Definition: Object.h:750
std::string const & GetName() const
Definition: Object.h:555
uint32 GetZoneId() const
Definition: Object.h:545
MovementInfo m_movementInfo
Definition: Object.h:761
void GetZoneAndAreaId(uint32 &zoneid, uint32 &areaid) const
Definition: Object.h:547
OpcodeClient GetOpcode() const
Definition: Packet.h:68
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
void LogoutPlayer(bool save)
Log the player out
void HandleMovementOpcode(OpcodeClient opcode, MovementInfo &movementInfo)
void HandleTimeSyncResponse(WorldPackets::Misc::TimeSyncResponse &timeSyncResponse)
void HandleMoveWorldportAck()
int64 _timeSyncClockDelta
void HandleMoveApplyMovementForceAck(WorldPackets::Movement::MoveApplyMovementForceAck &moveApplyMovementForceAck)
std::map< uint32, uint32 > _pendingTimeSyncRequests
uint32 AdjustClientMovementTime(uint32 time) const
void HandleMovementAckMessage(WorldPackets::Movement::MovementAckMessage &movementAck)
void KickPlayer(std::string const &reason)
Kick a player out of the World.
void HandleMoveWorldportAckOpcode(WorldPackets::Movement::WorldPortResponse &packet)
void HandleMoveSplineDoneOpcode(WorldPackets::Movement::MoveSplineDone &moveSplineDone)
Player * GetPlayer() const
void HandleSetCollisionHeightAck(WorldPackets::Movement::MoveSetCollisionHeightAck &setCollisionHeightAck)
void HandleMovementOpcodes(WorldPackets::Movement::ClientPlayerMovement &packet)
void HandleMoveKnockBackAck(WorldPackets::Movement::MoveKnockBackAck &movementAck)
void ComputeNewClockDelta()
void HandleSetActiveMoverOpcode(WorldPackets::Movement::SetActiveMover &packet)
void HandleMoveSetModMovementForceMagnitudeAck(WorldPackets::Movement::MovementSpeedAck &setModMovementForceMagnitudeAck)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
uint32 GetAccountId() const
void HandleMoveTimeSkippedOpcode(WorldPackets::Movement::MoveTimeSkipped &moveTimeSkipped)
Player * _player
void HandleMoveRemoveMovementForceAck(WorldPackets::Movement::MoveRemoveMovementForceAck &moveRemoveMovementForceAck)
void HandleForceSpeedChangeAck(WorldPackets::Movement::MovementSpeedAck &packet)
std::unique_ptr< boost::circular_buffer< std::pair< int64, uint32 > > > _timeSyncClockDeltaQueue
void HandleMoveInitActiveMoverComplete(WorldPackets::Movement::MoveInitActiveMoverComplete &moveInitActiveMoverComplete)
void HandleSuspendTokenResponse(WorldPackets::Movement::SuspendTokenResponse &suspendTokenResponse)
void HandleSummonResponseOpcode(WorldPackets::Movement::SummonResponse &packet)
void HandleMoveTeleportAck(WorldPackets::Movement::MoveTeleportAck &packet)
OpcodeClient
Definition: Opcodes.h:46
std::string GetOpcodeNameForLogging(OpcodeClient opcode)
Lookup opcode name for human understandable logging.
Definition: Opcodes.cpp:2205
@ CMSG_MOVE_SET_ADV_FLY
Definition: Opcodes.h:539
@ CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK
Definition: Opcodes.h:521
@ CMSG_MOVE_START_SWIM
Definition: Opcodes.h:576
@ CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK
Definition: Opcodes.h:522
@ CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK
Definition: Opcodes.h:524
@ CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK
Definition: Opcodes.h:515
@ CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK
Definition: Opcodes.h:519
@ CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK
Definition: Opcodes.h:518
@ CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK
Definition: Opcodes.h:520
@ CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK
Definition: Opcodes.h:516
@ CMSG_MOVE_FALL_LAND
Definition: Opcodes.h:511
@ CMSG_MOVE_JUMP
Definition: Opcodes.h:533
@ CMSG_MOVE_SET_FLY
Definition: Opcodes.h:559
@ CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK
Definition: Opcodes.h:514
@ SMSG_MOVE_UPDATE_MOD_MOVEMENT_FORCE_MAGNITUDE
Definition: Opcodes.h:1639
uint32 GetGameTimeMS()
Definition: GameTime.cpp:49
std::string ToString(Type &&val, Params &&... params)
bool IsValidMapCoord(float c)
Definition: GridDefines.h:231
BattlegroundQueueTypeId queueId
Definition: Player.h:1015
bool IsBattlegroundOrArena() const
uint32 ID
bool IsDungeon() const
ObjectGuid guid
Definition: MovementInfo.h:30
void ResetTransport()
Definition: MovementInfo.h:129
uint32 flags
Definition: MovementInfo.h:31
struct MovementInfo::TransportInfo transport
uint32 flags2
Definition: MovementInfo.h:32
Position pos
Definition: MovementInfo.h:34
constexpr void SetOrientation(float orientation)
Definition: Position.h:71
constexpr float GetPositionX() const
Definition: Position.h:76
constexpr float GetPositionY() const
Definition: Position.h:77
float GetExactDist2d(const float x, const float y) const
Definition: Position.h:106
std::string ToString() const
Definition: Position.cpp:128
bool IsPositionValid() const
Definition: Position.cpp:42
constexpr void Relocate(float x, float y)
Definition: Position.h:63
constexpr float GetOrientation() const
Definition: Position.h:79
constexpr float GetPositionZ() const
Definition: Position.h:78
bool IsHostile
Definition: Player.h:348
DBCPosition3D Loc
TaggedPosition< Position::XYZO > Pos