mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-16 04:59:41 -04:00
Core/Vehicles&Movement:
- Send correct SMSG_MONSTER_MOVE with newly discovered SPLINEFLAG_EXIT_VEHICLE on vehicle exit. Fixes the "stuck on exit" bug as a result of removing the previous hack in 04b656a44f.
- Use SMSG_SPLINE_MOVE_ROOT and SMSG_SPLINE_MOVE_UNROOT as root packets for creatures.
- Reimplement toggling of MOVEMENTFLAG_ROOT on root event (including enter vehicle)
- Speedup in fetching movementflags for vehicles depending on vehicleflags on object updates.
- Code cleanup and refactoring
This commit is contained in:
@@ -435,6 +435,27 @@ void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 M
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
void Unit::SendMonsterMoveExitVehicle(Position const* newPos)
|
||||
{
|
||||
WorldPacket data(SMSG_MONSTER_MOVE, 1+12+4+1+4+4+4+12+GetPackGUID().size());
|
||||
data.append(GetPackGUID());
|
||||
|
||||
data << uint8(GetTypeId() == TYPEID_PLAYER ? 1 : 0); // new in 3.1, bool
|
||||
data << GetPositionX() << GetPositionY() << GetPositionZ();
|
||||
data << getMSTime();
|
||||
|
||||
data << uint8(SPLINETYPE_FACING_ANGLE);
|
||||
data << float(GetOrientation()); // guess
|
||||
data << uint32(SPLINEFLAG_EXIT_VEHICLE);
|
||||
data << uint32(0); // Time in between points
|
||||
data << uint32(1); // 1 single waypoint
|
||||
data << newPos->GetPositionX();
|
||||
data << newPos->GetPositionY();
|
||||
data << newPos->GetPositionZ();
|
||||
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
void Unit::SendMonsterMoveTransport(Unit *vehicleOwner)
|
||||
{
|
||||
// TODO: Turn into BuildMonsterMoveTransport packet and allow certain variables (for npc movement aboard vehicles)
|
||||
@@ -442,7 +463,7 @@ void Unit::SendMonsterMoveTransport(Unit *vehicleOwner)
|
||||
data.append(GetPackGUID());
|
||||
data.append(vehicleOwner->GetPackGUID());
|
||||
data << int8(GetTransSeat());
|
||||
data << uint8(0); // unk boolean
|
||||
data << uint8(GetTypeId() == TYPEID_PLAYER ? 1 : 0); // boolean
|
||||
data << GetPositionX() - vehicleOwner->GetPositionX();
|
||||
data << GetPositionY() - vehicleOwner->GetPositionY();
|
||||
data << GetPositionZ() - vehicleOwner->GetPositionZ();
|
||||
@@ -451,7 +472,7 @@ void Unit::SendMonsterMoveTransport(Unit *vehicleOwner)
|
||||
data << GetTransOffsetO(); // facing angle?
|
||||
data << uint32(SPLINEFLAG_TRANSPORT);
|
||||
data << uint32(GetTransTime()); // move time
|
||||
data << uint32(0); // amount of waypoints
|
||||
data << uint32(1); // amount of waypoints
|
||||
data << uint32(0); // waypoint X
|
||||
data << uint32(0); // waypoint Y
|
||||
data << uint32(0); // waypoint Z
|
||||
@@ -15301,28 +15322,42 @@ void Unit::SetRooted(bool apply)
|
||||
if (m_rootTimes > 0) //blizzard internal check?
|
||||
m_rootTimes++;
|
||||
|
||||
// AddUnitMovementFlag(MOVEMENTFLAG_ROOT);
|
||||
AddUnitMovementFlag(MOVEMENTFLAG_ROOT);
|
||||
|
||||
WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
|
||||
data.append(GetPackGUID());
|
||||
data << m_rootTimes;
|
||||
SendMessageToSet(&data,true);
|
||||
|
||||
if (GetTypeId() != TYPEID_PLAYER)
|
||||
if (Player* thisPlr = this->ToPlayer())
|
||||
{
|
||||
WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
|
||||
data.append(GetPackGUID());
|
||||
data << m_rootTimes;
|
||||
SendMessageToSet(&data,true);
|
||||
}
|
||||
else
|
||||
{
|
||||
WorldPacket data(SMSG_SPLINE_MOVE_ROOT, 8);
|
||||
data.append(GetPackGUID());
|
||||
SendMessageToSet(&data,true);
|
||||
ToCreature()->StopMoving();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!HasUnitState(UNIT_STAT_STUNNED)) // prevent allow move if have also stun effect
|
||||
{
|
||||
m_rootTimes++; //blizzard internal check?
|
||||
if (Player* thisPlr = this->ToPlayer())
|
||||
{
|
||||
WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10);
|
||||
data.append(GetPackGUID());
|
||||
data << ++m_rootTimes;
|
||||
SendMessageToSet(&data,true);
|
||||
}
|
||||
else
|
||||
{
|
||||
WorldPacket data(SMSG_SPLINE_MOVE_UNROOT, 8);
|
||||
data.append(GetPackGUID());
|
||||
SendMessageToSet(&data,true);
|
||||
}
|
||||
|
||||
WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10);
|
||||
data.append(GetPackGUID());
|
||||
data << m_rootTimes;
|
||||
SendMessageToSet(&data,true);
|
||||
|
||||
// RemoveUnitMovementFlag(MOVEMENTFLAG_ROOT);
|
||||
RemoveUnitMovementFlag(MOVEMENTFLAG_ROOT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16465,6 +16500,12 @@ void Unit::EnterVehicle(Vehicle *vehicle, int8 seatId, AuraApplication const * a
|
||||
if (aurApp && aurApp->GetRemoveMode())
|
||||
return;
|
||||
|
||||
if (Player* thisPlr = this->ToPlayer())
|
||||
{
|
||||
WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
|
||||
thisPlr->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
ASSERT(!m_vehicle);
|
||||
m_vehicle = vehicle;
|
||||
if (!m_vehicle->AddPassenger(this, seatId))
|
||||
@@ -16472,19 +16513,6 @@ void Unit::EnterVehicle(Vehicle *vehicle, int8 seatId, AuraApplication const * a
|
||||
m_vehicle = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Player* thisPlr = this->ToPlayer())
|
||||
{
|
||||
WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
|
||||
thisPlr->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
SendClearTarget();
|
||||
|
||||
SetControlled(true, UNIT_STAT_ROOT);
|
||||
//movementInfo is set in AddPassenger
|
||||
//packets are sent in AddPassenger
|
||||
|
||||
}
|
||||
|
||||
void Unit::ChangeSeat(int8 seatId, bool next)
|
||||
@@ -16531,23 +16559,31 @@ void Unit::ExitVehicle(Position const* exitPosition)
|
||||
Vehicle *vehicle = m_vehicle;
|
||||
m_vehicle = NULL;
|
||||
|
||||
SetControlled(false, UNIT_STAT_ROOT); // SMSG_MOVE_FORCE_UNROOT
|
||||
SetControlled(false, UNIT_STAT_ROOT); // SMSG_MOVE_FORCE_UNROOT, ~MOVEMENTFLAG_ROOT
|
||||
|
||||
if (exitPosition) // Exit position specified
|
||||
Relocate(exitPosition);
|
||||
Position pos;
|
||||
if (!exitPosition) // Exit position not specified
|
||||
vehicle->GetBase()->GetPosition(&pos);
|
||||
else
|
||||
Relocate(vehicle->GetBase()); // Relocate to vehicle base
|
||||
pos = *exitPosition;
|
||||
|
||||
AddUnitState(UNIT_STAT_MOVE);
|
||||
|
||||
//Send leave vehicle, not correct
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
//this->ToPlayer()->SetClientControl(this, 1);
|
||||
this->ToPlayer()->SetFallInformation(0, GetPositionZ());
|
||||
else if (HasUnitMovementFlag(MOVEMENTFLAG_ROOT))
|
||||
{
|
||||
WorldPacket data(SMSG_SPLINE_MOVE_UNROOT, 8);
|
||||
data.append(GetPackGUID());
|
||||
SendMessageToSet(&data, false);
|
||||
}
|
||||
|
||||
WorldPacket data;
|
||||
BuildHeartBeatMsg(&data);
|
||||
SendMessageToSet(&data, false);
|
||||
SendMonsterMoveExitVehicle(&pos);
|
||||
Relocate(&pos);
|
||||
|
||||
WorldPacket data2;
|
||||
BuildHeartBeatMsg(&data2);
|
||||
SendMessageToSet(&data2, false);
|
||||
|
||||
if (vehicle->GetBase()->HasUnitTypeMask(UNIT_MASK_MINION))
|
||||
if (((Minion*)vehicle->GetBase())->GetOwner() == this)
|
||||
@@ -16561,8 +16597,6 @@ void Unit::BuildMovementPacket(ByteBuffer *data) const
|
||||
case TYPEID_UNIT:
|
||||
if (canFly())
|
||||
const_cast<Unit*>(this)->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
|
||||
if (IsVehicle())
|
||||
const_cast<Unit*>(this)->AddExtraUnitMovementFlag(GetVehicleKit()->GetExtraMovementFlagsForBase());
|
||||
break;
|
||||
case TYPEID_PLAYER:
|
||||
// remove unknown, unused etc flags for now
|
||||
|
||||
@@ -721,7 +721,7 @@ enum SplineFlags
|
||||
SPLINEFLAG_UNKNOWN22 = 0x00200000,
|
||||
SPLINEFLAG_UNKNOWN23 = 0x00400000,
|
||||
SPLINEFLAG_TRANSPORT = 0x00800000,
|
||||
SPLINEFLAG_UNKNOWN25 = 0x01000000,
|
||||
SPLINEFLAG_EXIT_VEHICLE = 0x01000000,
|
||||
SPLINEFLAG_UNKNOWN26 = 0x02000000,
|
||||
SPLINEFLAG_UNKNOWN27 = 0x04000000,
|
||||
SPLINEFLAG_UNKNOWN28 = 0x08000000,
|
||||
@@ -1521,6 +1521,7 @@ class Unit : public WorldObject
|
||||
void SendMonsterStop(bool on_death = false);
|
||||
void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 Time, Player* player = NULL);
|
||||
void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 MoveFlags, uint32 time, float speedZ, Player *player = NULL);
|
||||
void SendMonsterMoveExitVehicle(Position const* newPos);
|
||||
//void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL);
|
||||
void SendMonsterMoveTransport(Unit *vehicleOwner);
|
||||
void SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime = 0, Player* player = NULL);
|
||||
|
||||
@@ -61,6 +61,8 @@ Vehicle::Vehicle(Unit *unit, VehicleEntry const *vehInfo) : me(unit), m_vehicleI
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
InitMovementInfoForBase();
|
||||
}
|
||||
|
||||
Vehicle::~Vehicle()
|
||||
@@ -373,8 +375,10 @@ bool Vehicle::AddPassenger(Unit *unit, int8 seatId)
|
||||
|
||||
if (me->IsInWorld())
|
||||
{
|
||||
// In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures)
|
||||
unit->SendMonsterMoveTransport(me);
|
||||
unit->SendClearTarget(); // SMSG_BREAK_TARGET
|
||||
unit->SetControlled(true, UNIT_STAT_ROOT); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures)
|
||||
// also adds MOVEMENTFLAG_ROOT
|
||||
unit->SendMonsterMoveTransport(me); // SMSG_MONSTER_MOVE_TRANSPORT
|
||||
|
||||
if (me->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
@@ -476,29 +480,25 @@ void Vehicle::Dismiss()
|
||||
{
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Dismiss %u", me->GetEntry());
|
||||
Uninstall();
|
||||
me->SendObjectDeSpawnAnim(me->GetGUID());
|
||||
me->DestroyForNearbyPlayers();
|
||||
me->CombatStop();
|
||||
me->AddObjectToRemoveList();
|
||||
}
|
||||
|
||||
uint16 Vehicle::GetExtraMovementFlagsForBase() const
|
||||
void Vehicle::InitMovementInfoForBase()
|
||||
{
|
||||
uint16 movementMask = MOVEMENTFLAG2_NONE;
|
||||
uint32 vehicleFlags = GetVehicleInfo()->m_flags;
|
||||
|
||||
if (vehicleFlags & VEHICLE_FLAG_NO_STRAFE)
|
||||
movementMask |= MOVEMENTFLAG2_NO_STRAFE;
|
||||
me->AddExtraUnitMovementFlag(MOVEMENTFLAG2_NO_STRAFE);
|
||||
if (vehicleFlags & VEHICLE_FLAG_NO_JUMPING)
|
||||
movementMask |= MOVEMENTFLAG2_NO_JUMPING;
|
||||
me->AddExtraUnitMovementFlag(MOVEMENTFLAG2_NO_JUMPING);
|
||||
if (vehicleFlags & VEHICLE_FLAG_FULLSPEEDTURNING)
|
||||
movementMask |= MOVEMENTFLAG2_FULL_SPEED_TURNING;
|
||||
me->AddExtraUnitMovementFlag(MOVEMENTFLAG2_FULL_SPEED_TURNING);
|
||||
if (vehicleFlags & VEHICLE_FLAG_ALLOW_PITCHING)
|
||||
movementMask |= MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING;
|
||||
me->AddExtraUnitMovementFlag( MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING);
|
||||
if (vehicleFlags & VEHICLE_FLAG_FULLSPEEDPITCHING)
|
||||
movementMask |= MOVEMENTFLAG2_FULL_SPEED_PITCHING;
|
||||
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::GetExtraMovementFlagsForBase() returned %u", movementMask);
|
||||
return movementMask;
|
||||
me->AddExtraUnitMovementFlag(MOVEMENTFLAG2_FULL_SPEED_PITCHING);
|
||||
}
|
||||
|
||||
VehicleSeatEntry const* Vehicle::GetSeatForPassenger(Unit* passenger)
|
||||
|
||||
@@ -145,6 +145,7 @@ class Vehicle
|
||||
|
||||
private:
|
||||
SeatMap::iterator GetSeatIteratorForPassenger(Unit* passenger);
|
||||
void InitMovementInfoForBase();
|
||||
|
||||
protected:
|
||||
Unit *me;
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "Log.h"
|
||||
#include "Corpse.h"
|
||||
#include "Player.h"
|
||||
#include "Vehicle.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "MapManager.h"
|
||||
#include "Transport.h"
|
||||
@@ -513,206 +512,6 @@ void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data)
|
||||
_player->m_movementInfo = mi;
|
||||
}
|
||||
|
||||
void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
|
||||
{
|
||||
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_DISMISS_CONTROLLED_VEHICLE");
|
||||
recv_data.hexlike();
|
||||
|
||||
uint64 vehicleGUID = _player->GetCharmGUID();
|
||||
|
||||
if (!vehicleGUID) // something wrong here...
|
||||
{
|
||||
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
|
||||
return;
|
||||
}
|
||||
|
||||
uint64 guid;
|
||||
|
||||
recv_data.readPackGUID(guid);
|
||||
|
||||
MovementInfo mi;
|
||||
mi.guid = guid;
|
||||
ReadMovementInfo(recv_data, &mi);
|
||||
|
||||
_player->m_movementInfo = mi;
|
||||
|
||||
_player->ExitVehicle();
|
||||
}
|
||||
|
||||
void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data)
|
||||
{
|
||||
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE");
|
||||
recv_data.hexlike();
|
||||
|
||||
Unit* vehicle_base = GetPlayer()->GetVehicleBase();
|
||||
if (!vehicle_base)
|
||||
return;
|
||||
|
||||
VehicleSeatEntry const* seat = GetPlayer()->GetVehicle()->GetSeatForPassenger(GetPlayer());
|
||||
if (!seat->CanSwitchFromSeat())
|
||||
{
|
||||
sLog->outError("HandleChangeSeatsOnControlledVehicle, Opcode: %u, Player %u tried to switch seats but current seatflags %u don't permit that.",
|
||||
recv_data.GetOpcode(), GetPlayer()->GetGUIDLow(), seat->m_flags);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (recv_data.GetOpcode())
|
||||
{
|
||||
case CMSG_REQUEST_VEHICLE_PREV_SEAT:
|
||||
GetPlayer()->ChangeSeat(-1, false);
|
||||
break;
|
||||
case CMSG_REQUEST_VEHICLE_NEXT_SEAT:
|
||||
GetPlayer()->ChangeSeat(-1, true);
|
||||
break;
|
||||
case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE:
|
||||
{
|
||||
uint64 guid; // current vehicle guid
|
||||
recv_data.readPackGUID(guid);
|
||||
|
||||
ReadMovementInfo(recv_data, &vehicle_base->m_movementInfo);
|
||||
|
||||
uint64 accessory; // accessory guid
|
||||
recv_data.readPackGUID(accessory);
|
||||
|
||||
int8 seatId;
|
||||
recv_data >> seatId;
|
||||
|
||||
if (vehicle_base->GetGUID() != guid)
|
||||
return;
|
||||
|
||||
if (!accessory)
|
||||
GetPlayer()->ChangeSeat(-1, seatId > 0); // prev/next
|
||||
else if (Unit *vehUnit = Unit::GetUnit(*GetPlayer(), accessory))
|
||||
{
|
||||
if (Vehicle *vehicle = vehUnit->GetVehicleKit())
|
||||
if (vehicle->HasEmptySeat(seatId))
|
||||
GetPlayer()->EnterVehicle(vehicle, seatId);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CMSG_REQUEST_VEHICLE_SWITCH_SEAT:
|
||||
{
|
||||
uint64 guid; // current vehicle guid
|
||||
recv_data.readPackGUID(guid);
|
||||
|
||||
int8 seatId;
|
||||
recv_data >> seatId;
|
||||
|
||||
if (vehicle_base->GetGUID() == guid)
|
||||
GetPlayer()->ChangeSeat(seatId);
|
||||
else if (Unit *vehUnit = Unit::GetUnit(*GetPlayer(), guid))
|
||||
if (Vehicle *vehicle = vehUnit->GetVehicleKit())
|
||||
if (vehicle->HasEmptySeat(seatId))
|
||||
GetPlayer()->EnterVehicle(vehicle, seatId);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleEnterPlayerVehicle(WorldPacket &data)
|
||||
{
|
||||
// Read guid
|
||||
uint64 guid;
|
||||
data >> guid;
|
||||
|
||||
if (Player* pl=ObjectAccessor::FindPlayer(guid))
|
||||
{
|
||||
if (!pl->GetVehicleKit())
|
||||
return;
|
||||
if (!pl->IsInRaidWith(_player))
|
||||
return;
|
||||
if (!pl->IsWithinDistInMap(_player,INTERACTION_DISTANCE))
|
||||
return;
|
||||
_player->EnterVehicle(pl);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleEjectPassenger(WorldPacket &data)
|
||||
{
|
||||
Vehicle* vehicle = _player->GetVehicleKit();
|
||||
if (!vehicle)
|
||||
{
|
||||
sLog->outError("HandleEjectPassenger: Player %u is not in a vehicle!", GetPlayer()->GetGUIDLow());
|
||||
return;
|
||||
}
|
||||
|
||||
uint64 guid;
|
||||
data >> guid;
|
||||
|
||||
if (IS_PLAYER_GUID(guid))
|
||||
{
|
||||
Player *plr = ObjectAccessor::FindPlayer(guid);
|
||||
if (!plr)
|
||||
{
|
||||
sLog->outError("Player %u tried to eject player %u from vehicle, but the latter was not found in world!", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!plr->IsOnVehicle(vehicle->GetBase()))
|
||||
{
|
||||
sLog->outError("Player %u tried to eject player %u, but they are not in the same vehicle", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid));
|
||||
return;
|
||||
}
|
||||
|
||||
VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(plr);
|
||||
ASSERT(seat);
|
||||
if (seat->IsEjectable())
|
||||
plr->ExitVehicle();
|
||||
else
|
||||
sLog->outError("Player %u attempted to eject player %u from non-ejectable seat.", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid));
|
||||
}
|
||||
|
||||
else if (IS_CREATURE_GUID(guid))
|
||||
{
|
||||
Unit *unit = ObjectAccessor::GetUnit(*_player, guid);
|
||||
if (!unit) // creatures can be ejected too from player mounts
|
||||
{
|
||||
sLog->outError("Player %u tried to eject creature guid %u from vehicle, but the latter was not found in world!", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!unit->IsOnVehicle(vehicle->GetBase()))
|
||||
{
|
||||
sLog->outError("Player %u tried to eject unit %u, but they are not in the same vehicle", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid));
|
||||
return;
|
||||
}
|
||||
|
||||
VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(unit);
|
||||
ASSERT(seat);
|
||||
if (seat->IsEjectable())
|
||||
{
|
||||
ASSERT(GetPlayer() == vehicle->GetBase());
|
||||
unit->ExitVehicle();
|
||||
unit->ToCreature()->DespawnOrUnsummon(1000);
|
||||
ASSERT(!unit->IsOnVehicle(vehicle->GetBase()));
|
||||
}
|
||||
else
|
||||
sLog->outError("Player %u attempted to eject creature GUID %u from non-ejectable seat.", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid));
|
||||
}
|
||||
else
|
||||
sLog->outError("HandleEjectPassenger: Player %u tried to eject invalid GUID "UI64FMTD, GetPlayer()->GetGUIDLow(), guid);
|
||||
}
|
||||
|
||||
void WorldSession::HandleRequestVehicleExit(WorldPacket &recv_data)
|
||||
{
|
||||
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_REQUEST_VEHICLE_EXIT");
|
||||
recv_data.hexlike();
|
||||
|
||||
if (Vehicle* vehicle = GetPlayer()->GetVehicle())
|
||||
{
|
||||
if (VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(GetPlayer()))
|
||||
{
|
||||
if (seat->CanEnterOrExit())
|
||||
GetPlayer()->ExitVehicle();
|
||||
else
|
||||
sLog->outError("Player %u tried to exit vehicle, but seatflags %u (ID: %u) don't permit that.",
|
||||
GetPlayer()->GetGUIDLow(), seat->m_ID, seat->m_flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recv_data*/)
|
||||
{
|
||||
WorldPacket data(SMSG_MOUNTSPECIAL_ANIM, 8);
|
||||
|
||||
222
src/server/game/Server/Protocol/Handlers/VehicleHandler.cpp
Normal file
222
src/server/game/Server/Protocol/Handlers/VehicleHandler.cpp
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
#include "Opcodes.h"
|
||||
#include "Vehicle.h"
|
||||
#include "Player.h"
|
||||
#include "Log.h"
|
||||
|
||||
void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
|
||||
{
|
||||
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_DISMISS_CONTROLLED_VEHICLE");
|
||||
recv_data.hexlike();
|
||||
|
||||
uint64 vehicleGUID = _player->GetCharmGUID();
|
||||
|
||||
if (!vehicleGUID) // something wrong here...
|
||||
{
|
||||
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
|
||||
return;
|
||||
}
|
||||
|
||||
uint64 guid;
|
||||
|
||||
recv_data.readPackGUID(guid);
|
||||
|
||||
MovementInfo mi;
|
||||
mi.guid = guid;
|
||||
ReadMovementInfo(recv_data, &mi);
|
||||
|
||||
_player->m_movementInfo = mi;
|
||||
|
||||
_player->ExitVehicle();
|
||||
}
|
||||
|
||||
void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data)
|
||||
{
|
||||
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE");
|
||||
recv_data.hexlike();
|
||||
|
||||
Unit* vehicle_base = GetPlayer()->GetVehicleBase();
|
||||
if (!vehicle_base)
|
||||
return;
|
||||
|
||||
VehicleSeatEntry const* seat = GetPlayer()->GetVehicle()->GetSeatForPassenger(GetPlayer());
|
||||
if (!seat->CanSwitchFromSeat())
|
||||
{
|
||||
sLog->outError("HandleChangeSeatsOnControlledVehicle, Opcode: %u, Player %u tried to switch seats but current seatflags %u don't permit that.",
|
||||
recv_data.GetOpcode(), GetPlayer()->GetGUIDLow(), seat->m_flags);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (recv_data.GetOpcode())
|
||||
{
|
||||
case CMSG_REQUEST_VEHICLE_PREV_SEAT:
|
||||
GetPlayer()->ChangeSeat(-1, false);
|
||||
break;
|
||||
case CMSG_REQUEST_VEHICLE_NEXT_SEAT:
|
||||
GetPlayer()->ChangeSeat(-1, true);
|
||||
break;
|
||||
case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE:
|
||||
{
|
||||
uint64 guid; // current vehicle guid
|
||||
recv_data.readPackGUID(guid);
|
||||
|
||||
ReadMovementInfo(recv_data, &vehicle_base->m_movementInfo);
|
||||
|
||||
uint64 accessory; // accessory guid
|
||||
recv_data.readPackGUID(accessory);
|
||||
|
||||
int8 seatId;
|
||||
recv_data >> seatId;
|
||||
|
||||
if (vehicle_base->GetGUID() != guid)
|
||||
return;
|
||||
|
||||
if (!accessory)
|
||||
GetPlayer()->ChangeSeat(-1, seatId > 0); // prev/next
|
||||
else if (Unit *vehUnit = Unit::GetUnit(*GetPlayer(), accessory))
|
||||
{
|
||||
if (Vehicle *vehicle = vehUnit->GetVehicleKit())
|
||||
if (vehicle->HasEmptySeat(seatId))
|
||||
GetPlayer()->EnterVehicle(vehicle, seatId);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CMSG_REQUEST_VEHICLE_SWITCH_SEAT:
|
||||
{
|
||||
uint64 guid; // current vehicle guid
|
||||
recv_data.readPackGUID(guid);
|
||||
|
||||
int8 seatId;
|
||||
recv_data >> seatId;
|
||||
|
||||
if (vehicle_base->GetGUID() == guid)
|
||||
GetPlayer()->ChangeSeat(seatId);
|
||||
else if (Unit *vehUnit = Unit::GetUnit(*GetPlayer(), guid))
|
||||
if (Vehicle *vehicle = vehUnit->GetVehicleKit())
|
||||
if (vehicle->HasEmptySeat(seatId))
|
||||
GetPlayer()->EnterVehicle(vehicle, seatId);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleEnterPlayerVehicle(WorldPacket &data)
|
||||
{
|
||||
// Read guid
|
||||
uint64 guid;
|
||||
data >> guid;
|
||||
|
||||
if (Player* pl=ObjectAccessor::FindPlayer(guid))
|
||||
{
|
||||
if (!pl->GetVehicleKit())
|
||||
return;
|
||||
if (!pl->IsInRaidWith(_player))
|
||||
return;
|
||||
if (!pl->IsWithinDistInMap(_player,INTERACTION_DISTANCE))
|
||||
return;
|
||||
_player->EnterVehicle(pl);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleEjectPassenger(WorldPacket &data)
|
||||
{
|
||||
Vehicle* vehicle = _player->GetVehicleKit();
|
||||
if (!vehicle)
|
||||
{
|
||||
sLog->outError("HandleEjectPassenger: Player %u is not in a vehicle!", GetPlayer()->GetGUIDLow());
|
||||
return;
|
||||
}
|
||||
|
||||
uint64 guid;
|
||||
data >> guid;
|
||||
|
||||
if (IS_PLAYER_GUID(guid))
|
||||
{
|
||||
Player *plr = ObjectAccessor::FindPlayer(guid);
|
||||
if (!plr)
|
||||
{
|
||||
sLog->outError("Player %u tried to eject player %u from vehicle, but the latter was not found in world!", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!plr->IsOnVehicle(vehicle->GetBase()))
|
||||
{
|
||||
sLog->outError("Player %u tried to eject player %u, but they are not in the same vehicle", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid));
|
||||
return;
|
||||
}
|
||||
|
||||
VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(plr);
|
||||
ASSERT(seat);
|
||||
if (seat->IsEjectable())
|
||||
plr->ExitVehicle();
|
||||
else
|
||||
sLog->outError("Player %u attempted to eject player %u from non-ejectable seat.", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid));
|
||||
}
|
||||
|
||||
else if (IS_CREATURE_GUID(guid))
|
||||
{
|
||||
Unit *unit = ObjectAccessor::GetUnit(*_player, guid);
|
||||
if (!unit) // creatures can be ejected too from player mounts
|
||||
{
|
||||
sLog->outError("Player %u tried to eject creature guid %u from vehicle, but the latter was not found in world!", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!unit->IsOnVehicle(vehicle->GetBase()))
|
||||
{
|
||||
sLog->outError("Player %u tried to eject unit %u, but they are not in the same vehicle", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid));
|
||||
return;
|
||||
}
|
||||
|
||||
VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(unit);
|
||||
ASSERT(seat);
|
||||
if (seat->IsEjectable())
|
||||
{
|
||||
ASSERT(GetPlayer() == vehicle->GetBase());
|
||||
unit->ExitVehicle();
|
||||
unit->AddObjectToRemoveList();
|
||||
}
|
||||
else
|
||||
sLog->outError("Player %u attempted to eject creature GUID %u from non-ejectable seat.", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid));
|
||||
}
|
||||
else
|
||||
sLog->outError("HandleEjectPassenger: Player %u tried to eject invalid GUID "UI64FMTD, GetPlayer()->GetGUIDLow(), guid);
|
||||
}
|
||||
|
||||
void WorldSession::HandleRequestVehicleExit(WorldPacket &recv_data)
|
||||
{
|
||||
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_REQUEST_VEHICLE_EXIT");
|
||||
recv_data.hexlike();
|
||||
|
||||
if (Vehicle* vehicle = GetPlayer()->GetVehicle())
|
||||
{
|
||||
if (VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(GetPlayer()))
|
||||
{
|
||||
if (seat->CanEnterOrExit())
|
||||
GetPlayer()->ExitVehicle();
|
||||
else
|
||||
sLog->outError("Player %u tried to exit vehicle, but seatflags %u (ID: %u) don't permit that.",
|
||||
GetPlayer()->GetGUIDLow(), seat->m_ID, seat->m_flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user