aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMachiavelli <machiavelli.trinity@gmail.com>2011-02-26 03:47:23 +0100
committerMachiavelli <machiavelli.trinity@gmail.com>2011-02-26 03:47:23 +0100
commit30738e645ffe03458bf8051e2bf3189ddeed09fa (patch)
tree84d43f575b37a854c88cac1e56cf7580f8f81628 /src
parent98f6c2fe8074ff671d9be893b68a9f20a8ed6260 (diff)
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 04b656a44f4e1019acdf. - 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
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp116
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.h3
-rwxr-xr-xsrc/server/game/Entities/Vehicle/Vehicle.cpp26
-rwxr-xr-xsrc/server/game/Entities/Vehicle/Vehicle.h1
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/MovementHandler.cpp201
-rw-r--r--src/server/game/Server/Protocol/Handlers/VehicleHandler.cpp222
6 files changed, 313 insertions, 256 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 2c697245ca1..9cc92c7e7d4 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -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);
-
- WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
- data.append(GetPackGUID());
- data << m_rootTimes;
- SendMessageToSet(&data,true);
+ AddUnitMovementFlag(MOVEMENTFLAG_ROOT);
- 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?
-
- WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10);
- data.append(GetPackGUID());
- data << m_rootTimes;
- SendMessageToSet(&data,true);
+ 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);
+ }
-// 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
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 25509e2230f..cb35ee7bafd 100755
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -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);
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp
index bb8c443d09a..e22fe9668e4 100755
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -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)
diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h
index 03e283548d4..8ec342e21e5 100755
--- a/src/server/game/Entities/Vehicle/Vehicle.h
+++ b/src/server/game/Entities/Vehicle/Vehicle.h
@@ -145,6 +145,7 @@ class Vehicle
private:
SeatMap::iterator GetSeatIteratorForPassenger(Unit* passenger);
+ void InitMovementInfoForBase();
protected:
Unit *me;
diff --git a/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp b/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp
index 3624773a9b4..671f7541cf7 100755
--- a/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp
@@ -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);
diff --git a/src/server/game/Server/Protocol/Handlers/VehicleHandler.cpp b/src/server/game/Server/Protocol/Handlers/VehicleHandler.cpp
new file mode 100644
index 00000000000..296ae23899c
--- /dev/null
+++ b/src/server/game/Server/Protocol/Handlers/VehicleHandler.cpp
@@ -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);
+ }
+ }
+} \ No newline at end of file