Implement vehicles created by player mounts.

Original idea by Elmaster, packet research by Wrong, ty.

--HG--
branch : trunk
This commit is contained in:
thenecromancer
2010-01-13 11:16:38 +01:00
parent db24e2927c
commit ea4e25f3aa
11 changed files with 153 additions and 20 deletions
+9
View File
@@ -31,6 +31,7 @@
#include "SocialMgr.h"
#include "Util.h"
#include "SpellAuras.h"
#include "Vehicle.h"
class Aura;
@@ -775,6 +776,14 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke
*data << (uint16) 0;
}
if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
{
if(player->GetVehicle()){
Vehicle* vv=player->GetVehicle();
*data << (uint32) vv->GetVehicleInfo()->m_seatID[player->m_movementInfo.t_seat];
}
}
if (mask & GROUP_UPDATE_FLAG_PET_AURAS)
{
if(pet)
+14
View File
@@ -358,6 +358,20 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
plMover->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
plMover->UpdateFallInformationIfNeed(movementInfo, opcode);
// If on vehicle, update carried players
if (Vehicle *vehicle=plMover->GetVehicleKit())
{
if (plMover->IsVehicle())
{
for (int i=0; i < 8; ++i)
{
if (Unit *passenger = vehicle->GetPassenger(i))
if (passenger != NULL && passenger->GetTypeId() == TYPEID_PLAYER)
((Player*)passenger)->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
}
}
}
if (movementInfo.z < -500.0f)
{
if (plMover->InBattleGround()
+3 -3
View File
@@ -1219,9 +1219,9 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x4A4*/ { "CMSG_QUERY_VEHICLE_STATUS", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4A5*/ { "UMSG_UNKNOWN_1189", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4A6*/ { "SMSG_UNKNOWN_1190", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4A7*/ { "SMSG_UNKNOWN_1191", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4A8*/ { "CMSG_UNKNOWN_1192", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4A9*/ { "CMSG_EJECT_PASSENGER", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4A7*/ { "SMSG_PLAYER_VEHICLE_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4A8*/ { "CMSG_PLAYER_VEHICLE_ENTER", STATUS_LOGGEDIN, &WorldSession::HandleEnterPlayerVehicle },
/*0x4A9*/ { "CMSG_EJECT_PASSENGER", STATUS_LOGGEDIN, &WorldSession::HandleEjectPasenger },
/*0x4AA*/ { "SMSG_PET_GUIDS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4AB*/ { "SMSG_CLIENTCACHE_VERSION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4AC*/ { "UMSG_UNKNOWN_1196", STATUS_NEVER, &WorldSession::Handle_NULL },
+2 -2
View File
@@ -1227,8 +1227,8 @@ enum Opcodes
CMSG_QUERY_VEHICLE_STATUS = 0x4A4, // not found
UMSG_UNKNOWN_1189 = 0x4A5, // not found, old SMSG_PET_GUIDS
SMSG_UNKNOWN_1190 = 0x4A6, // smsg unk, "You can't do that yet"
SMSG_UNKNOWN_1191 = 0x4A7, // smsg guid+uint32 (vehicle)
CMSG_UNKNOWN_1192 = 0x4A8, // cmsg uint64
SMSG_PLAYER_VEHICLE_DATA = 0x4A7, // smsg guid+uint32 (vehicle)
CMSG_PLAYER_VEHICLE_ENTER = 0x4A8, // cmsg uint64
CMSG_EJECT_PASSENGER = 0x4A9, // cmsg uint64
SMSG_PET_GUIDS = 0x4AA, // shifted+5
SMSG_CLIENTCACHE_VERSION = 0x4AB, // shifted+5
+1
View File
@@ -3981,6 +3981,7 @@ void Player::InitVisibleBits()
updateVisualBits.SetBit(PLAYER_BYTES_3);
updateVisualBits.SetBit(PLAYER_DUEL_TEAM);
updateVisualBits.SetBit(PLAYER_GUILD_TIMESTAMP);
updateVisualBits.SetBit(UNIT_NPC_FLAGS);
// PLAYER_QUEST_LOG_x also visible bit on official (but only on party/raid)...
for (uint16 i = PLAYER_QUEST_LOG_1_1; i < PLAYER_QUEST_LOG_25_2; i += 4)
+1 -1
View File
@@ -3471,7 +3471,7 @@ void AuraEffect::HandleAuraMounted(AuraApplication const * aurApp, uint8 mode, b
if(GetSpellProto()->Effect[i] == SPELL_EFFECT_SUMMON
&& GetSpellProto()->EffectMiscValue[i] == GetMiscValue())
display_id = 0;
target->Mount(display_id);
target->Mount(display_id,ci->VehicleId);
}
else
{
+48 -1
View File
@@ -11099,7 +11099,7 @@ float Unit::GetPPMProcChance(uint32 WeaponSpeed, float PPM, const SpellEntry * s
return uint32((WeaponSpeed * PPM) / 600.0f); // result is chance in percents (probability = Speed_in_sec * (PPM / 60))
}
void Unit::Mount(uint32 mount)
void Unit::Mount(uint32 mount, uint32 VehicleId)
{
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNT);
@@ -11121,6 +11121,27 @@ void Unit::Mount(uint32 mount)
else
((Player*)this)->UnsummonPetTemporaryIfAny();
}
if(VehicleId !=0)
{
if(VehicleEntry const *ve = sVehicleStore.LookupEntry(VehicleId))
{
if (CreateVehicleKit(VehicleId))
{
GetVehicleKit()->Reset();
// Send others that we now have a vehicle
WorldPacket data( SMSG_PLAYER_VEHICLE_DATA, GetPackGUID().size()+4);
data.appendPackGUID(GetGUID());
data << uint32(VehicleId);
SendMessageToSet( &data,true );
data.Initialize(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
((Player*)this)->GetSession()->SendPacket( &data );
}
}
}
}
}
@@ -11148,6 +11169,16 @@ void Unit::Unmount()
else
((Player*)this)->ResummonPetTemporaryUnSummonedIfAny();
}
if(GetTypeId()==TYPEID_PLAYER && GetVehicleKit())
{
// Send other players that we are no longer a vehicle
WorldPacket data( SMSG_PLAYER_VEHICLE_DATA, 8+4 );
data.appendPackGUID(GetGUID());
data << uint32(0);
((Player*)this)->SendMessageToSet(&data, true);
// Remove vehicle class from player
RemoveVehicleKit();
}
}
void Unit::SetInCombatWith(Unit* enemy)
@@ -14956,6 +14987,22 @@ bool Unit::CreateVehicleKit(uint32 id)
return true;
}
void Unit::RemoveVehicleKit()
{
if (!m_vehicleKit)
return;
m_vehicleKit->Uninstall();
delete m_vehicleKit;
m_vehicleKit = NULL;
m_updateFlag &= ~UPDATEFLAG_VEHICLE;
m_unitTypeMask &= ~UNIT_MASK_VEHICLE;
RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE);
}
Unit *Unit::GetVehicleBase() const
{
return m_vehicle ? m_vehicle->GetBase() : NULL;
+3 -1
View File
@@ -631,6 +631,7 @@ enum NPCFlags
UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, // 100%
UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // cause client to send 997 opcode
UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // cause client to send 1015 opcode (spell click), dynamic, set at loading and don't must be set in DB
UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x02000000, // players with mounts that have vehicle data should have it set
UNIT_NPC_FLAG_GUARD = 0x10000000, // custom flag for guards
UNIT_NPC_FLAG_OUTDOORPVP = 0x20000000, // custom flag for outdoor pvp creatures
};
@@ -1272,7 +1273,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
bool IsMounted() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); }
uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); }
void Mount(uint32 mount);
void Mount(uint32 mount, uint32 vehicleId=0);
void Unmount();
uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; }
@@ -1913,6 +1914,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
bool IsAIEnabled, NeedChangeAI;
MovementInfo m_movementInfo;
bool CreateVehicleKit(uint32 id);
void RemoveVehicleKit();
Vehicle *GetVehicleKit()const { return m_vehicleKit; }
Vehicle *GetVehicle() const { return m_vehicle; }
bool IsOnVehicle(const Unit *unit) const { return m_vehicle && m_vehicle == unit->GetVehicleKit(); }
+36 -12
View File
@@ -151,9 +151,18 @@ void Vehicle::Die()
void Vehicle::Reset()
{
sLog.outDebug("Vehicle::Reset");
InstallAllAccessories();
if(m_usableSeatNum)
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
{
if (me->GetTypeId() == TYPEID_PLAYER)
{
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE);
}
else
{
InstallAllAccessories();
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
}
}
}
void Vehicle::RemoveAllPassengers()
@@ -275,7 +284,12 @@ bool Vehicle::AddPassenger(Unit *unit, int8 seatId)
assert(m_usableSeatNum);
--m_usableSeatNum;
if(!m_usableSeatNum)
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
{
if (me->GetTypeId() == TYPEID_PLAYER)
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE);
else
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
}
}
if(seat->second.seatInfo->m_flags && !(seat->second.seatInfo->m_flags & 0x400))
@@ -292,21 +306,24 @@ bool Vehicle::AddPassenger(Unit *unit, int8 seatId)
unit->m_movementInfo.t_time = 0; // 1 for player
unit->m_movementInfo.t_seat = seat->first;
if(unit->GetTypeId() == TYPEID_PLAYER && seat->first == 0 && seat->second.seatInfo->m_flags & 0x800) // not right
if(me->GetTypeId() == TYPEID_UNIT
&& unit->GetTypeId() == TYPEID_PLAYER
&& seat->first == 0 && seat->second.seatInfo->m_flags & 0x800) // not right
if (!me->SetCharmedBy(unit, CHARM_TYPE_VEHICLE))
assert(false);
if(me->GetTypeId() == TYPEID_UNIT)
if(me->IsInWorld())
{
if(me->IsInWorld())
unit->SendMonsterMoveTransport(me);
if(me->GetTypeId() == TYPEID_UNIT)
{
unit->SendMonsterMoveTransport(me);
if(((Creature*)me)->IsAIEnabled)
((Creature*)me)->AI()->PassengerBoarded(unit, seat->first, true);
// move self = move all passengers
me->GetMap()->CreatureRelocation((Creature*)me, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
}
if(((Creature*)me)->IsAIEnabled)
((Creature*)me)->AI()->PassengerBoarded(unit, seat->first, true);
}
//if(unit->GetTypeId() == TYPEID_PLAYER)
@@ -334,7 +351,12 @@ void Vehicle::RemovePassenger(Unit *unit)
if(seat->second.seatInfo->IsUsable())
{
if(!m_usableSeatNum)
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
{
if (me->GetTypeId() == TYPEID_PLAYER)
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE);
else
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
}
++m_usableSeatNum;
}
@@ -342,7 +364,9 @@ void Vehicle::RemovePassenger(Unit *unit)
//SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
if(unit->GetTypeId() == TYPEID_PLAYER && seat->first == 0 && seat->second.seatInfo->m_flags & 0x800)
if(me->GetTypeId() == TYPEID_UNIT
&& unit->GetTypeId() == TYPEID_PLAYER
&& seat->first == 0 && seat->second.seatInfo->m_flags & 0x800)
me->RemoveCharmedBy(unit);
if(me->GetTypeId() == TYPEID_UNIT && ((Creature*)me)->IsAIEnabled)
+34
View File
@@ -30,6 +30,7 @@
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Player.h"
#include "Vehicle.h"
#include "ObjectMgr.h"
#include "Group.h"
#include "Guild.h"
@@ -937,6 +938,39 @@ void WorldSession::SendAddonsInfo()
SendPacket(&data);
}
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::HandleEjectPasenger(WorldPacket &data)
{
if(data.GetOpcode()==CMSG_EJECT_PASSENGER)
{
if(Vehicle* Vv= _player->GetVehicleKit())
{
uint64 guid;
data >> guid;
if(Player* Pl=ObjectAccessor::FindPlayer(guid))
Pl->ExitVehicle();
}
}
}
void WorldSession::SetPlayer( Player *plr )
{
_player = plr;
+2
View File
@@ -748,6 +748,8 @@ class TRINITY_DLL_SPEC WorldSession
bool HandleOnItemOpen(Item *pItem);
bool HandleOnGoClick(GameObject *pGameObject);
void HandleOnCreatureKill(Creature *pCreature);
void HandleEjectPasenger(WorldPacket &data);
void HandleEnterPlayerVehicle(WorldPacket &data);
private:
// private trade methods
void moveItems(Item* myItems[], Item* hisItems[]);