diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index fed9b9ba7a..1c9276f137 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -1603,50 +1603,6 @@ void WorldSession::HandleInstanceLockResponse(WorldPacket& recvPacket) _player->SetPendingBind(0, 0); } -void WorldSession::HandleUpdateMissileTrajectory(WorldPacket& recvPacket) -{ - TC_LOG_DEBUG("network", "WORLD: CMSG_UPDATE_MISSILE_TRAJECTORY"); - - ObjectGuid guid; - uint32 spellId; - float elevation, speed; - float curX, curY, curZ; - float targetX, targetY, targetZ; - uint8 moveStop; - - recvPacket >> guid >> spellId >> elevation >> speed; - recvPacket >> curX >> curY >> curZ; - recvPacket >> targetX >> targetY >> targetZ; - recvPacket >> moveStop; - - Unit* caster = ObjectAccessor::GetUnit(*_player, guid); - Spell* spell = caster ? caster->GetCurrentSpell(CURRENT_GENERIC_SPELL) : nullptr; - if (!spell || spell->m_spellInfo->Id != spellId || !spell->m_targets.HasDst() || !spell->m_targets.HasSrc()) - { - recvPacket.rfinish(); - return; - } - - Position pos = *spell->m_targets.GetSrcPos(); - pos.Relocate(curX, curY, curZ); - spell->m_targets.ModSrc(pos); - - pos = *spell->m_targets.GetDstPos(); - pos.Relocate(targetX, targetY, targetZ); - spell->m_targets.ModDst(pos); - - spell->m_targets.SetElevation(elevation); - spell->m_targets.SetSpeed(speed); - - if (moveStop) - { - uint32 opcode; - recvPacket >> opcode; - recvPacket.SetOpcode(MSG_MOVE_STOP); // always set to MSG_MOVE_STOP in client SetOpcode - HandleMovementOpcodes(recvPacket); - } -} - void WorldSession::HandleViolenceLevel(WorldPacket& recvPacket) { uint8 violenceLevel; diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 2ad666fcb7..5f1ef97688 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -607,3 +607,21 @@ void WorldSession::HandleCancelQueuedSpellOpcode(WorldPackets::Spells::CancelQue mover->CancelPendingCastRequest(); } +void WorldSession::HandleUpdateMissileTrajectory(WorldPackets::Spells::UpdateMissileTrajectory& updateMissileTrajectory) +{ + Unit* caster = ObjectAccessor::GetUnit(*_player, updateMissileTrajectory.Guid); + Spell* spell = caster ? caster->GetCurrentSpell(CURRENT_GENERIC_SPELL) : nullptr; + if (!spell || spell->m_spellInfo->Id != updateMissileTrajectory.SpellID || !spell->m_targets.HasDst() || !spell->m_targets.HasSrc()) + return; + + Position pos = *spell->m_targets.GetSrcPos(); + pos.Relocate(updateMissileTrajectory.FirePos); + spell->m_targets.ModSrc(pos); + + pos = spell->m_targets.GetDstPos()->GetPosition(); + pos.Relocate(updateMissileTrajectory.ImpactPos); + spell->m_targets.ModDst(pos); + + spell->m_targets.SetElevation(updateMissileTrajectory.Pitch); + spell->m_targets.SetSpeed(updateMissileTrajectory.Speed); +} diff --git a/src/server/game/Server/Packets/SpellPackets.cpp b/src/server/game/Server/Packets/SpellPackets.cpp index ffa29913c0..395cdc0785 100644 --- a/src/server/game/Server/Packets/SpellPackets.cpp +++ b/src/server/game/Server/Packets/SpellPackets.cpp @@ -821,3 +821,163 @@ void WorldPackets::Spells::UseItem::Read() } } } + +void WorldPackets::Spells::UpdateMissileTrajectory::Read() +{ + _worldPacket >> FirePos.Pos.m_positionZ; + _worldPacket >> FirePos.Pos.m_positionX; + _worldPacket >> Pitch; + _worldPacket >> ImpactPos.Pos.m_positionX; + _worldPacket >> FirePos.Pos.m_positionY; + _worldPacket >> Speed; + _worldPacket >> ImpactPos.Pos.m_positionY; + _worldPacket >> MoveMsgID; + _worldPacket >> SpellID; + _worldPacket >> ImpactPos.Pos.m_positionZ; + + Guid[5] = _worldPacket.ReadBit(); + Guid[6] = _worldPacket.ReadBit(); + Guid[0] = _worldPacket.ReadBit(); + Guid[7] = _worldPacket.ReadBit(); + Guid[1] = _worldPacket.ReadBit(); + Guid[3] = _worldPacket.ReadBit(); + Guid[2] = _worldPacket.ReadBit(); + Guid[4] = _worldPacket.ReadBit(); + + bool hasFallData = false; + bool hasFallVelocity = false; + bool hasFacing = false; + bool hasTransportData = false; + bool hasTransportTime2 = false; + bool hasVehicleId = false; + bool hasSplineElevation = false; + bool hasPitch = false; + bool hasMoveTime = false; + + // Thanks to Cataclysm's randomized packet structures we now have to read the packet like this instead of using the MovementStructures helper + if (_worldPacket.ReadBit()) + { + Status.emplace(); + + Status->guid[2] = _worldPacket.ReadBit(); + Status->heightChangeFailed = _worldPacket.ReadBit(); + bool hasMovementFlags0 = !_worldPacket.ReadBit(); + bool hasSpline = _worldPacket.ReadBit(); + Status->guid[4] = _worldPacket.ReadBit(); + + if (hasMovementFlags0) + Status->SetMovementFlags(_worldPacket.ReadBits(30)); + + Status->guid[3] = _worldPacket.ReadBit(); + hasPitch = _worldPacket.ReadBit(); + bool hasMovementFlags1 = _worldPacket.ReadBit(); + hasTransportData = _worldPacket.ReadBit(); + Status->guid[7] = _worldPacket.ReadBit(); + + if (hasTransportData) + { + Status->transport.guid[0] = _worldPacket.ReadBit(); + Status->transport.guid[7] = _worldPacket.ReadBit(); + Status->transport.guid[2] = _worldPacket.ReadBit(); + Status->transport.guid[4] = _worldPacket.ReadBit(); + hasVehicleId = _worldPacket.ReadBit(); + Status->transport.guid[5] = _worldPacket.ReadBit(); + Status->transport.guid[3] = _worldPacket.ReadBit(); + Status->transport.guid[6] = _worldPacket.ReadBit(); + hasTransportTime2 = _worldPacket.ReadBit(); + Status->transport.guid[1] = _worldPacket.ReadBit(); + } + + Status->guid[6] = _worldPacket.ReadBit(); + hasFacing = !_worldPacket.ReadBit(); + hasMoveTime = !_worldPacket.ReadBit(); + Status->guid[5] = _worldPacket.ReadBit(); + hasSplineElevation = !_worldPacket.ReadBit(); + Status->guid[1] = _worldPacket.ReadBit(); + hasFallData = _worldPacket.ReadBit(); + Status->guid[0] = _worldPacket.ReadBit(); + + if (hasFallData) + hasFallVelocity = _worldPacket.ReadBit(); + + if (hasMovementFlags1) + Status->SetExtraMovementFlags(_worldPacket.ReadBits(12)); + } + + _worldPacket.ReadByteSeq(Guid[2]); + _worldPacket.ReadByteSeq(Guid[1]); + _worldPacket.ReadByteSeq(Guid[3]); + _worldPacket.ReadByteSeq(Guid[7]); + _worldPacket.ReadByteSeq(Guid[6]); + _worldPacket.ReadByteSeq(Guid[4]); + _worldPacket.ReadByteSeq(Guid[0]); + _worldPacket.ReadByteSeq(Guid[5]); + + if (Status.has_value()) + { + if (hasFallData) + { + if (hasFallVelocity) + { + _worldPacket >> Status->jump.cosAngle; + _worldPacket >> Status->jump.sinAngle; + _worldPacket >> Status->jump.xyspeed; + } + + _worldPacket >> Status->jump.zspeed; + _worldPacket >> Status->jump.fallTime; + } + + if (hasFacing) + Status->pos.SetOrientation(_worldPacket.read()); + + if (hasTransportData) + { + _worldPacket >> Status->transport.pos.m_positionZ; + _worldPacket.ReadByteSeq(Status->transport.guid[3]); + _worldPacket.ReadByteSeq(Status->transport.guid[7]); + _worldPacket >> Status->transport.pos.m_positionX; + Status->transport.pos.SetOrientation(_worldPacket.read()); + + if (hasTransportTime2) + _worldPacket >> Status->transport.time2; + + _worldPacket.ReadByteSeq(Status->transport.guid[2]); + _worldPacket >> Status->transport.time; + _worldPacket.ReadByteSeq(Status->transport.guid[0]); + _worldPacket >> Status->transport.pos.m_positionY; + + if (hasVehicleId) + _worldPacket >> Status->transport.vehicleId; + + _worldPacket.ReadByteSeq(Status->transport.guid[4]); + _worldPacket.ReadByteSeq(Status->transport.guid[6]); + _worldPacket.ReadByteSeq(Status->transport.guid[1]); + _worldPacket >> Status->transport.seat; + _worldPacket.ReadByteSeq(Status->transport.guid[5]); + } + + if (hasSplineElevation) + _worldPacket >> Status->splineElevation; + + _worldPacket.ReadByteSeq(Status->guid[4]); + + if (hasPitch) + _worldPacket >> Status->pitch; + + _worldPacket.ReadByteSeq(Status->guid[7]); + _worldPacket.ReadByteSeq(Status->guid[2]); + + if (hasMoveTime) + _worldPacket >> Status->time; + + _worldPacket >> Status->pos.m_positionX; + _worldPacket.ReadByteSeq(Status->guid[5]); + _worldPacket.ReadByteSeq(Status->guid[3]); + _worldPacket.ReadByteSeq(Status->guid[1]); + _worldPacket.ReadByteSeq(Status->guid[0]); + _worldPacket >> Status->pos.m_positionY; + _worldPacket >> Status->pos.m_positionZ; + _worldPacket.ReadByteSeq(Status->guid[6]); + } +} diff --git a/src/server/game/Server/Packets/SpellPackets.h b/src/server/game/Server/Packets/SpellPackets.h index 8a2ca65d5f..8a51f48d94 100644 --- a/src/server/game/Server/Packets/SpellPackets.h +++ b/src/server/game/Server/Packets/SpellPackets.h @@ -489,6 +489,23 @@ namespace WorldPackets ObjectGuid CastItem; SpellCastRequest Cast; }; + + class UpdateMissileTrajectory final : public ClientPacket + { + public: + UpdateMissileTrajectory(WorldPacket&& packet) : ClientPacket(CMSG_UPDATE_MISSILE_TRAJECTORY, std::move(packet)) { } + + void Read() override; + + uint16 MoveMsgID = 0; + float Speed = 0.0f; + float Pitch = 0.0f; + int32 SpellID = 0; + ObjectGuid Guid; + TaggedPosition FirePos; + TaggedPosition ImpactPos; + Optional Status; + }; } } diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 74d5d49501..923eab61d6 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -200,6 +200,7 @@ namespace WorldPackets class CastSpell; class CancelQueuedSpell; class UseItem; + class UpdateMissileTrajectory; } namespace Who @@ -1207,7 +1208,7 @@ class TC_GAME_API WorldSession void HandleEjectPassenger(WorldPacket& data); void HandleEnterPlayerVehicle(WorldPacket& data); void HandleUpdateProjectilePosition(WorldPacket& recvPacket); - void HandleUpdateMissileTrajectory(WorldPacket& recvPacket); + void HandleUpdateMissileTrajectory(WorldPackets::Spells::UpdateMissileTrajectory& updateMissileTrajectory); void HandleViolenceLevel(WorldPacket& recvPacket); void HandleObjectUpdateFailedOpcode(WorldPacket& recvPacket); void HandleRequestCategoryCooldowns(WorldPacket& recvPacket);