From d337fb99ed81dc3522bdea17e762febd989a6956 Mon Sep 17 00:00:00 2001 From: Chaouki Dhib Date: Tue, 15 Jun 2021 23:09:48 +0200 Subject: Core/Movement: Implement proper player speed change (#26561) --- src/server/game/Movement/MovementPacketSender.cpp | 106 ++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 src/server/game/Movement/MovementPacketSender.cpp (limited to 'src/server/game/Movement/MovementPacketSender.cpp') diff --git a/src/server/game/Movement/MovementPacketSender.cpp b/src/server/game/Movement/MovementPacketSender.cpp new file mode 100644 index 00000000000..df0ff5e7bbf --- /dev/null +++ b/src/server/game/Movement/MovementPacketSender.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2008-2017 TrinityCore + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "GameClient.h" +#include "MovementPacketSender.h" +#include "Player.h" +#include "WorldPacket.h" +#include "WorldSession.h" + +// SMSG_SPLINE_SET_* messages are for units controlled by the server. +// SMSG_FORCE_*_SPEED_CHANGE messages are for units controlled by a player and require the client to respond with an ACK message. +// MSG_MOVE_SET_*_SPEED is used to broadcast changes to observers of units controlled by a player +Opcodes const MovementPacketSender::moveTypeToOpcode[MAX_MOVE_TYPE][3] = +{ + { SMSG_SPLINE_SET_WALK_SPEED, SMSG_FORCE_WALK_SPEED_CHANGE, MSG_MOVE_SET_WALK_SPEED }, + { SMSG_SPLINE_SET_RUN_SPEED, SMSG_FORCE_RUN_SPEED_CHANGE, MSG_MOVE_SET_RUN_SPEED }, + { SMSG_SPLINE_SET_RUN_BACK_SPEED, SMSG_FORCE_RUN_BACK_SPEED_CHANGE, MSG_MOVE_SET_RUN_BACK_SPEED }, + { SMSG_SPLINE_SET_SWIM_SPEED, SMSG_FORCE_SWIM_SPEED_CHANGE, MSG_MOVE_SET_SWIM_SPEED }, + { SMSG_SPLINE_SET_SWIM_BACK_SPEED, SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, MSG_MOVE_SET_SWIM_BACK_SPEED }, + { SMSG_SPLINE_SET_TURN_RATE, SMSG_FORCE_TURN_RATE_CHANGE, MSG_MOVE_SET_TURN_RATE }, + { SMSG_SPLINE_SET_FLIGHT_SPEED, SMSG_FORCE_FLIGHT_SPEED_CHANGE, MSG_MOVE_SET_FLIGHT_SPEED }, + { SMSG_SPLINE_SET_FLIGHT_BACK_SPEED, SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, MSG_MOVE_SET_FLIGHT_BACK_SPEED }, + { SMSG_SPLINE_SET_PITCH_RATE, SMSG_FORCE_PITCH_RATE_CHANGE, MSG_MOVE_SET_PITCH_RATE }, +}; + +MovementChangeType MovementPacketSender::GetChangeTypeByMoveType(UnitMoveType moveType) +{ + switch (moveType) + { + case MOVE_WALK: return MovementChangeType::SPEED_CHANGE_WALK; + case MOVE_RUN: return MovementChangeType::SPEED_CHANGE_RUN; + case MOVE_RUN_BACK: return MovementChangeType::SPEED_CHANGE_RUN_BACK; + case MOVE_SWIM: return MovementChangeType::SPEED_CHANGE_SWIM; + case MOVE_SWIM_BACK: return MovementChangeType::SPEED_CHANGE_SWIM_BACK; + case MOVE_TURN_RATE: return MovementChangeType::RATE_CHANGE_TURN; + case MOVE_FLIGHT: return MovementChangeType::SPEED_CHANGE_FLIGHT_SPEED; + case MOVE_FLIGHT_BACK: return MovementChangeType::SPEED_CHANGE_FLIGHT_BACK_SPEED; + case MOVE_PITCH_RATE: return MovementChangeType::RATE_CHANGE_PITCH; + default: + ASSERT(false, "MovementPacketSender::SendSpeedChangeToMover Unsupported UnitMoveType"); + } +} + +void MovementPacketSender::SendSpeedChangeToMover(Unit* unit, UnitMoveType mtype, float newSpeedFlat) +{ + GameClient* controller = unit->GetGameClientMovingMe(); + + ASSERT(controller); + + uint32 mCounter = unit->GetMovementCounterAndInc(); + PlayerMovementPendingChange pendingChange; + pendingChange.movementCounter = mCounter; + pendingChange.newValue = newSpeedFlat; + pendingChange.movementChangeType = MovementPacketSender::GetChangeTypeByMoveType(mtype); + unit->PushPendingMovementChange(pendingChange); + + WorldPacket data; + data.Initialize(moveTypeToOpcode[mtype][1], mtype != MOVE_RUN ? 8 + 4 + 4 : 8 + 4 + 1 + 4); + data << unit->GetPackGUID(); + data << mCounter; + if (mtype == MOVE_RUN) + data << uint8(1); // unknown byte added in 2.1.0 + data << newSpeedFlat; + controller->SendDirectMessage(&data); +} + +void MovementPacketSender::SendSpeedChangeToObservers(Unit* unit, UnitMoveType mtype, float newSpeedFlat) +{ + GameClient* controller = unit->GetGameClientMovingMe(); + + ASSERT(controller); + + WorldPacket data; + data.Initialize(moveTypeToOpcode[mtype][2], 8 + 30 + 4); + WorldSession::WriteMovementInfo(&data, &unit->m_movementInfo); + data << newSpeedFlat; + unit->SendMessageToSet(&data, controller->GetBasePlayer()); +} + +void MovementPacketSender::SendSpeedChangeToAll(Unit* unit, UnitMoveType mtype, float newSpeedFlat) +{ + GameClient* controller = unit->GetGameClientMovingMe(); + + ASSERT(!controller); + + WorldPacket data; + data.Initialize(moveTypeToOpcode[mtype][0], 8 + 4); + data << unit->GetPackGUID(); + data << newSpeedFlat; + unit->SendMessageToSet(&data, true); +} + -- cgit v1.2.3