Core/Packets: converted SMSG_PARTY_MEMBER_STATE and SMSG_PARTY_MEMBER_FULL_STATE to packet class

* handle GROUP_UPDATE_FLAG_PHASE when changing phases
* define and implement GROUP_UPDATE_FLAG_WMO_GROUP_ID
This commit is contained in:
Ovahlord
2021-01-09 16:30:03 +01:00
parent 4f50bafd03
commit c3831d30e5
15 changed files with 452 additions and 409 deletions

View File

@@ -1155,7 +1155,7 @@ bool Object::PrintIndexError(uint32 index, bool set) const
WorldObject::WorldObject(bool isWorldObject) : WorldLocation(), LastUsedScriptID(0),
m_name(""), m_isActive(false), m_isFarVisible(false), m_isWorldObject(isWorldObject), m_zoneScript(nullptr),
m_transport(nullptr), m_zoneId(0), m_areaId(0), m_staticFloorZ(VMAP_INVALID_HEIGHT), m_outdoors(true), m_liquidStatus(LIQUID_MAP_NO_WATER),
m_currMap(nullptr), m_InstanceId(0), _dbPhase(0), m_notifyflags(0),
m_wmoGroupID(0), m_currMap(nullptr), m_InstanceId(0), _dbPhase(0), m_notifyflags(0),
m_aiAnimKitId(0), m_movementAnimKitId(0), m_meleeAnimKitId(0)
{
m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE | GHOST_VISIBILITY_GHOST);
@@ -1261,6 +1261,7 @@ void WorldObject::ProcessPositionDataChanged(PositionFullTerrainStatus const& da
m_outdoors = data.outdoors;
m_staticFloorZ = data.floorZ;
m_liquidStatus = data.liquidStatus;
m_wmoGroupID = data.areaInfo.is_initialized() ? data.areaInfo->groupId : 0;
}
void WorldObject::AddToWorld()

View File

@@ -324,6 +324,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
void GetZoneAndAreaId(uint32& zoneid, uint32& areaid) const { zoneid = m_zoneId, areaid = m_areaId; }
bool IsOutdoors() const { return m_outdoors; }
ZLiquidStatus GetLiquidStatus() const { return m_liquidStatus; }
uint32 GetWMOGroupId() const { return m_wmoGroupID; }
InstanceScript* GetInstanceScript() const;
@@ -502,6 +503,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
float m_staticFloorZ;
bool m_outdoors;
ZLiquidStatus m_liquidStatus;
uint32 m_wmoGroupID;
//these functions are used mostly for Relocate() and Corpse/Player specific stuff...
//use them ONLY in LoadFromDB()/Create() funcs and nowhere else!

View File

@@ -5875,6 +5875,8 @@ ActionButton const* Player::GetActionButton(uint8 button)
bool Player::UpdatePosition(float x, float y, float z, float orientation, bool teleport)
{
uint32 oldWmoGroupId = GetWMOGroupId();
if (!Unit::UpdatePosition(x, y, z, orientation, teleport))
return false;
@@ -5893,10 +5895,17 @@ bool Player::UpdatePosition(float x, float y, float z, float orientation, bool t
m_needsZoneUpdate = false;
}
// group update
// Add group update flags
if (GetGroup())
{
// Position has changed
SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POSITION);
// Player is no longer on a WMO that belongs to the same area
if (oldWmoGroupId != GetWMOGroupId())
SetGroupUpdateFlag(GROUP_UPDATE_FLAG_WMO_GROUP_ID);
}
CheckAreaExploreAndOutdoor();
// Update mount capabilities

View File

@@ -12435,6 +12435,10 @@ void Unit::OnPhaseChange()
{
if (!IsInWorld())
return;
// Inform player groups that a member's phase has changed so the next PartyMemberState packet will update the phasing accordingly
if (IsPlayer() && ToPlayer()->GetGroup())
ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PHASE);
}
void Unit::UpdateObjectVisibility(bool forced)

View File

@@ -34,6 +34,7 @@
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Opcodes.h"
#include "PartyPackets.h"
#include "PhasingHandler.h"
#include "Player.h"
#include "Random.h"
@@ -1812,15 +1813,15 @@ void Group::UpdatePlayerOutOfRange(Player* player)
if (!player || !player->IsInWorld())
return;
WorldPacket data;
player->GetSession()->BuildPartyMemberStatsChangedPacket(player, &data);
WorldPackets::Party::PartyMemberState packet;
packet.Initialize(player);
Player* member;
for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
{
member = itr->GetSource();
if (member && member != player && (!member->IsInMap(player) || !member->IsWithinDist(player, member->GetSightRange(), false)))
member->SendDirectMessage(&data);
member->SendDirectMessage(packet.Write());
}
}

View File

@@ -105,7 +105,7 @@ enum GroupUpdateFlags
GROUP_UPDATE_FLAG_MAX_POWER = 0x00000020, // int16 (power value)
GROUP_UPDATE_FLAG_LEVEL = 0x00000040, // uint16 (level value)
GROUP_UPDATE_FLAG_ZONE = 0x00000080, // uint16 (zone id)
GROUP_UPDATE_FLAG_UNK100 = 0x00000100, // int16 (unk)
GROUP_UPDATE_FLAG_WMO_GROUP_ID = 0x00000100, // int16 (WMOGroupID)
GROUP_UPDATE_FLAG_POSITION = 0x00000200, // uint16 (x), uint16 (y), uint16 (z)
GROUP_UPDATE_FLAG_AURAS = 0x00000400, // uint8 (unk), uint64 (mask), uint32 (count), for each bit set: uint32 (spell id) + uint16 (AuraFlags) (if has flags Scalable -> 3x int32 (bps))
GROUP_UPDATE_FLAG_PET_GUID = 0x00000800, // uint64 (pet guid)
@@ -135,7 +135,7 @@ enum GroupUpdateFlags
GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER | GROUP_UPDATE_FLAG_PET_AURAS, // all pet flags
GROUP_UPDATE_FULL = GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP |
GROUP_UPDATE_FLAG_POWER_TYPE | GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER |
GROUP_UPDATE_FLAG_LEVEL | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_UNK100 |GROUP_UPDATE_FLAG_POSITION |
GROUP_UPDATE_FLAG_LEVEL | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_WMO_GROUP_ID |GROUP_UPDATE_FLAG_POSITION |
GROUP_UPDATE_FLAG_AURAS | GROUP_UPDATE_FLAG_PHASE | GROUP_UPDATE_FLAG_UNK400000 | GROUP_UPDATE_FLAG_UNK800000 |
GROUP_UPDATE_FLAG_UNK1000000 | GROUP_UPDATE_FLAG_UNK2000000 | GROUP_UPDATE_FLAG_UNK4000000 |
GROUP_UPDATE_FLAG_UNK8000000 | GROUP_UPDATE_FLAG_UNK10000000 | GROUP_UPDATE_FLAG_UNK20000000 | GROUP_UPDATE_FLAG_UNK40000000

View File

@@ -24,6 +24,7 @@
#include "Log.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "PartyPackets.h"
#include "Pet.h"
#include "PhasingHandler.h"
#include "Player.h"
@@ -982,237 +983,6 @@ void WorldSession::HandleRaidReadyCheckFinishedOpcode(WorldPacket& /*recvData*/)
// Is any reaction need?
}
void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket* data)
{
uint32 mask = player->GetGroupUpdateFlag();
if (mask == GROUP_UPDATE_FLAG_NONE)
return;
if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also
mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER);
if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets
mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER);
data->Initialize(SMSG_PARTY_MEMBER_STATS, 80); // average value
*data << player->GetPackGUID();
*data << uint32(mask);
if (mask & GROUP_UPDATE_FLAG_STATUS)
{
uint16 playerStatus = MEMBER_STATUS_ONLINE;
if (player->IsPvP())
playerStatus |= MEMBER_STATUS_PVP;
if (!player->IsAlive())
{
if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
playerStatus |= MEMBER_STATUS_GHOST;
else
playerStatus |= MEMBER_STATUS_DEAD;
}
if (player->IsFFAPvP())
playerStatus |= MEMBER_STATUS_PVP_FFA;
if (player->isAFK())
playerStatus |= MEMBER_STATUS_AFK;
if (player->isDND())
playerStatus |= MEMBER_STATUS_DND;
*data << uint16(playerStatus);
}
if (mask & GROUP_UPDATE_FLAG_CUR_HP)
*data << int32(player->GetHealth());
if (mask & GROUP_UPDATE_FLAG_MAX_HP)
*data << int32(player->GetMaxHealth());
Powers powerType = player->GetPowerType();
if (mask & GROUP_UPDATE_FLAG_POWER_TYPE)
*data << uint8(powerType);
if (mask & GROUP_UPDATE_FLAG_CUR_POWER)
*data << int16(player->GetPower(powerType));
if (mask & GROUP_UPDATE_FLAG_MAX_POWER)
*data << int16(player->GetMaxPower(powerType));
if (mask & GROUP_UPDATE_FLAG_LEVEL)
*data << int16(player->getLevel());
if (mask & GROUP_UPDATE_FLAG_ZONE)
*data << int16(player->GetZoneId());
if (mask & GROUP_UPDATE_FLAG_UNK100)
*data << uint16(0);
if (mask & GROUP_UPDATE_FLAG_POSITION)
{
*data << uint16(player->GetPositionX());
*data << uint16(player->GetPositionY());
*data << uint16(player->GetPositionZ());
}
if (mask & GROUP_UPDATE_FLAG_AURAS)
{
*data << uint8(0);
uint64 auramask = player->GetAuraUpdateMaskForRaid();
*data << uint64(auramask);
*data << uint32(MAX_AURAS); // count
for (uint32 i = 0; i < MAX_AURAS; ++i)
{
if (auramask & (uint64(1) << i))
{
AuraApplication const* aurApp = player->GetVisibleAura(i);
if (!aurApp)
{
*data << uint32(0);
*data << uint16(0);
continue;
}
*data << uint32(aurApp->GetBase()->GetId());
*data << uint16(aurApp->GetFlags());
if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
{
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
*data << int32(eff->GetAmount());
else
*data << int32(0);
}
}
}
}
}
Pet* pet = player->GetPet();
if (mask & GROUP_UPDATE_FLAG_PET_GUID)
{
if (pet)
*data << uint64(pet->GetGUID());
else
*data << uint64(0);
}
if (mask & GROUP_UPDATE_FLAG_PET_NAME)
{
if (pet)
*data << pet->GetName();
else
*data << uint8(0);
}
if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID)
{
if (pet)
*data << int16(pet->GetDisplayId());
else
*data << uint16(0);
}
if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP)
{
if (pet)
*data << int32(pet->GetHealth());
else
*data << int32(0);
}
if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP)
{
if (pet)
*data << int32(pet->GetMaxHealth());
else
*data << int32(0);
}
if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE)
{
if (pet)
*data << uint8(pet->GetPowerType());
else
*data << uint8(0);
}
if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER)
{
if (pet)
*data << int16(pet->GetPower(pet->GetPowerType()));
else
*data << int16(0);
}
if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER)
{
if (pet)
*data << int16(pet->GetMaxPower(pet->GetPowerType()));
else
*data << int16(0);
}
if (mask & GROUP_UPDATE_FLAG_PET_AURAS)
{
if (pet)
{
*data << uint8(0);
uint64 auramask = pet->GetAuraUpdateMaskForRaid();
*data << uint64(auramask);
*data << uint32(MAX_AURAS); // count
for (uint32 i = 0; i < MAX_AURAS; ++i)
{
if (auramask & (uint64(1) << i))
{
AuraApplication const* aurApp = pet->GetVisibleAura(i);
if (!aurApp)
{
*data << uint32(0);
*data << uint16(0);
continue;
}
*data << uint32(aurApp->GetBase()->GetId());
*data << uint16(aurApp->GetFlags());
if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
{
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
*data << int32(eff->GetAmount());
else
*data << int32(0);
}
}
}
}
}
else
{
*data << uint8(0);
*data << uint64(0);
*data << uint32(0);
}
}
if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
{
if (Vehicle* veh = player->GetVehicle())
*data << int32(veh->GetVehicleInfo()->SeatID[player->m_movementInfo.transport.seat]);
else
*data << int32(0);
}
if (mask & GROUP_UPDATE_FLAG_PHASE)
PhasingHandler::FillPartyMemberPhase(data, player->GetPhaseShift());
}
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/
void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData)
{
@@ -1223,168 +993,17 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData)
Player* player = ObjectAccessor::FindConnectedPlayer(Guid);
if (!player)
{
WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2);
data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
data << Guid.WriteAsPacked();
data << uint32(GROUP_UPDATE_FLAG_STATUS);
data << uint16(MEMBER_STATUS_OFFLINE);
SendPacket(&data);
WorldPackets::Party::PartyMemberState packet(true);
packet.MemberGuid = Guid;
packet.ChangeMask = GROUP_UPDATE_FLAG_STATUS;
packet.MemberStats.Status = MEMBER_STATUS_OFFLINE;
SendPacket(packet.Write());
return;
}
Pet* pet = player->GetPet();
Powers powerType = player->GetPowerType();
WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8);
data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
data << player->GetPackGUID();
uint32 updateFlags = GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP
| GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER | GROUP_UPDATE_FLAG_LEVEL
| GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_POSITION | GROUP_UPDATE_FLAG_AURAS
| GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_MODEL_ID | GROUP_UPDATE_FLAG_PET_AURAS;
if (powerType != POWER_MANA)
updateFlags |= GROUP_UPDATE_FLAG_POWER_TYPE;
if (pet)
updateFlags |= GROUP_UPDATE_FLAG_PET_GUID | GROUP_UPDATE_FLAG_PET_CUR_HP | GROUP_UPDATE_FLAG_PET_MAX_HP
| GROUP_UPDATE_FLAG_PET_POWER_TYPE | GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER;
if (player->GetVehicle())
updateFlags |= GROUP_UPDATE_FLAG_VEHICLE_SEAT;
if (!player->GetPhaseShift().GetPhases().empty())
updateFlags |= GROUP_UPDATE_FLAG_PHASE;
uint16 playerStatus = MEMBER_STATUS_ONLINE;
if (player->IsPvP())
playerStatus |= MEMBER_STATUS_PVP;
if (!player->IsAlive())
{
if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
playerStatus |= MEMBER_STATUS_GHOST;
else
playerStatus |= MEMBER_STATUS_DEAD;
}
if (player->IsFFAPvP())
playerStatus |= MEMBER_STATUS_PVP_FFA;
if (player->isAFK())
playerStatus |= MEMBER_STATUS_AFK;
if (player->isDND())
playerStatus |= MEMBER_STATUS_DND;
data << uint32(updateFlags);
data << uint16(playerStatus); // GROUP_UPDATE_FLAG_STATUS
data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP
data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP
if (updateFlags & GROUP_UPDATE_FLAG_POWER_TYPE)
data << uint8(powerType);
data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER
data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER
data << uint16(player->getLevel()); // GROUP_UPDATE_FLAG_LEVEL
data << uint16(player->GetZoneId()); // GROUP_UPDATE_FLAG_ZONE
data << uint16(player->GetPositionX()); // GROUP_UPDATE_FLAG_POSITION
data << uint16(player->GetPositionY()); // GROUP_UPDATE_FLAG_POSITION
data << uint16(player->GetPositionZ()); // GROUP_UPDATE_FLAG_POSITION
// GROUP_UPDATE_FLAG_AURAS
data << uint8(1);
uint64 auramask = 0;
size_t maskPos = data.wpos();
data << uint64(auramask); // placeholder
data << uint32(MAX_AURAS); // count
for (uint8 i = 0; i < MAX_AURAS; ++i)
{
if (AuraApplication const* aurApp = player->GetVisibleAura(i))
{
auramask |= (uint64(1) << i);
data << uint32(aurApp->GetBase()->GetId());
data << uint16(aurApp->GetFlags());
if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
{
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
data << int32(eff->GetAmount());
else
data << int32(0);
}
}
}
}
data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS
if (updateFlags & GROUP_UPDATE_FLAG_PET_GUID)
data << uint64(ASSERT_NOTNULL(pet)->GetGUID());
data << std::string(pet ? pet->GetName() : ""); // GROUP_UPDATE_FLAG_PET_NAME
data << uint16(pet ? pet->GetDisplayId() : 0); // GROUP_UPDATE_FLAG_PET_MODEL_ID
if (updateFlags & GROUP_UPDATE_FLAG_PET_CUR_HP)
data << uint32(pet->GetHealth());
if (updateFlags & GROUP_UPDATE_FLAG_PET_MAX_HP)
data << uint32(pet->GetMaxHealth());
if (updateFlags & GROUP_UPDATE_FLAG_PET_POWER_TYPE)
data << (uint8)pet->GetPowerType();
if (updateFlags & GROUP_UPDATE_FLAG_PET_CUR_POWER)
data << uint16(pet->GetPower(pet->GetPowerType()));
if (updateFlags & GROUP_UPDATE_FLAG_PET_MAX_POWER)
data << uint16(pet->GetMaxPower(pet->GetPowerType()));
// GROUP_UPDATE_FLAG_PET_AURAS
uint64 petAuraMask = 0;
data << uint8(1);
maskPos = data.wpos();
data << uint64(petAuraMask); // placeholder
data << uint32(MAX_AURAS); // count
if (pet)
{
for (uint8 i = 0; i < MAX_AURAS; ++i)
{
if (AuraApplication const* aurApp = pet->GetVisibleAura(i))
{
petAuraMask |= (uint64(1) << i);
data << uint32(aurApp->GetBase()->GetId());
data << uint16(aurApp->GetFlags());
if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
{
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
data << int32(eff->GetAmount());
else
data << int32(0);
}
}
}
}
}
data.put<uint64>(maskPos, petAuraMask); // GROUP_UPDATE_FLAG_PET_AURAS
if (updateFlags & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
data << uint32(player->GetVehicle()->GetVehicleInfo()->SeatID[player->m_movementInfo.transport.seat]);
if (updateFlags & GROUP_UPDATE_FLAG_PHASE)
PhasingHandler::FillPartyMemberPhase(&data, player->GetPhaseShift());
SendPacket(&data);
WorldPackets::Party::PartyMemberState packet(true);
packet.Initialize(player);
SendPacket(packet.Write());
}
void WorldSession::HandleRequestRaidInfoOpcode(WorldPacket& /*recvData*/)

View File

@@ -24,6 +24,7 @@
#include "Map.h"
#include "MiscPackets.h"
#include "ObjectMgr.h"
#include "PartyPackets.h"
#include "PhaseShift.h"
#include "Player.h"
#include "SpellAuraEffects.h"
@@ -416,12 +417,12 @@ void PhasingHandler::SendToPlayer(Player const* player)
SendToPlayer(player, player->GetPhaseShift());
}
void PhasingHandler::FillPartyMemberPhase(WorldPacket* data, PhaseShift const& phaseShift)
void PhasingHandler::FillPartyMemberPhase(WorldPackets::Party::PartyMemberPhaseStates* partyMemberPhases, PhaseShift const& phaseShift)
{
*data << int32(phaseShift.Flags.AsUnderlyingType());
*data << int32(phaseShift.Phases.size());
for (auto itr = phaseShift.Phases.begin(); itr != phaseShift.Phases.end(); ++itr)
*data << int16(itr->Id);
partyMemberPhases->PhaseShiftFlags = phaseShift.Flags.AsUnderlyingType();
partyMemberPhases->List.reserve(phaseShift.Phases.size());
std::transform(phaseShift.Phases.begin(), phaseShift.Phases.end(), std::back_inserter(partyMemberPhases->List),
[](PhaseShift::PhaseRef const& phase) -> uint16 { return phase.Id; });
}
PhaseShift const& PhasingHandler::GetEmptyPhaseShift()

View File

@@ -27,6 +27,13 @@ class PhaseShift;
class Player;
class WorldObject;
class WorldPacket;
namespace WorldPackets
{
namespace Party
{
struct PartyMemberPhaseStates;
}
}
class TC_GAME_API PhasingHandler
{
@@ -48,7 +55,7 @@ public:
static void SendToPlayer(Player const* player, PhaseShift const& phaseShift);
static void SendToPlayer(Player const* player);
static void FillPartyMemberPhase(WorldPacket* data, PhaseShift const& phaseShift);
static void FillPartyMemberPhase(WorldPackets::Party::PartyMemberPhaseStates* partyMemberPhases, PhaseShift const& phaseShift);
static PhaseShift const& GetEmptyPhaseShift();
static void InitDbPhaseShift(PhaseShift& phaseShift, uint8 phaseUseFlags, uint16 phaseId, uint32 phaseGroupId);

View File

@@ -29,6 +29,7 @@
#include "MiscPackets.h"
#include "MovementPackets.h"
#include "NPCPackets.h"
#include "PartyPackets.h"
#include "QuestPackets.h"
#include "QueryPackets.h"
#include "SystemPackets.h"

View File

@@ -0,0 +1,308 @@
/*
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
*
* 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 "PartyPackets.h"
#include "Group.h"
#include "Pet.h"
#include "Player.h"
#include "PhasingHandler.h"
#include "SpellAuras.h"
#include "SpellAuraEffects.h"
#include "Vehicle.h"
void WorldPackets::Party::PartyMemberState::Initialize(Player const* player)
{
MemberGuid = player->GetGUID();
// Update Flags
if (GetOpcode() == SMSG_PARTY_MEMBER_FULL_STATE)
{
ChangeMask = GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP
| GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER | GROUP_UPDATE_FLAG_LEVEL
| GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_WMO_GROUP_ID | GROUP_UPDATE_FLAG_POSITION | GROUP_UPDATE_FLAG_AURAS
| GROUP_UPDATE_FLAG_PET_AURAS | GROUP_UPDATE_FLAG_PHASE | GROUP_UPDATE_FLAG_UNK400000 | GROUP_UPDATE_FLAG_UNK800000
| GROUP_UPDATE_FLAG_UNK1000000 | GROUP_UPDATE_FLAG_UNK2000000 | GROUP_UPDATE_FLAG_UNK4000000 | GROUP_UPDATE_FLAG_UNK8000000
| GROUP_UPDATE_FLAG_UNK10000000 | GROUP_UPDATE_FLAG_UNK20000000 | GROUP_UPDATE_FLAG_UNK40000000;
// Additional update flags depending on the player's state
if (player->GetPowerType() != POWER_MANA)
ChangeMask |= GROUP_UPDATE_FLAG_POWER_TYPE;
if (player->GetPet())
ChangeMask |= GROUP_UPDATE_FLAG_PET_GUID | GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_MODEL_ID
| GROUP_UPDATE_FLAG_PET_CUR_HP | GROUP_UPDATE_FLAG_PET_MAX_HP | GROUP_UPDATE_FLAG_PET_POWER_TYPE | GROUP_UPDATE_FLAG_PET_CUR_POWER
| GROUP_UPDATE_FLAG_PET_MAX_POWER;
if (player->GetVehicle())
ChangeMask |= GROUP_UPDATE_FLAG_VEHICLE_SEAT;
}
else
{
ChangeMask = player->GetGroupUpdateFlag();
// Additional update flags based on the current group update flags
if (ChangeMask & GROUP_UPDATE_FLAG_POWER_TYPE)
ChangeMask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER);
if (ChangeMask & GROUP_UPDATE_FLAG_PET_POWER_TYPE)
ChangeMask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER);
}
// Status
MemberStats.Status = MEMBER_STATUS_ONLINE;
if (player->IsPvP())
MemberStats.Status |= MEMBER_STATUS_PVP;
if (!player->IsAlive())
{
if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
MemberStats.Status |= MEMBER_STATUS_GHOST;
else
MemberStats.Status |= MEMBER_STATUS_DEAD;
}
if (player->IsFFAPvP())
MemberStats.Status |= MEMBER_STATUS_PVP_FFA;
if (player->isAFK())
MemberStats.Status |= MEMBER_STATUS_AFK;
if (player->isDND())
MemberStats.Status |= MEMBER_STATUS_DND;
// Level
MemberStats.Level = player->getLevel();
// Health
MemberStats.CurrentHealth = player->GetHealth();
MemberStats.MaxHealth = player->GetMaxHealth();
// Power
MemberStats.PowerType = player->GetPowerType();
MemberStats.CurrentPower = player->GetPower(player->GetPowerType());
MemberStats.MaxPower = player->GetMaxPower(player->GetPowerType());
// Position
MemberStats.ZoneID = player->GetZoneId();
MemberStats.PositionX = int16(player->GetPositionX());
MemberStats.PositionY = int16(player->GetPositionY());
MemberStats.PositionZ = int16(player->GetPositionZ());
MemberStats.WmoGroupID = uint16(player->GetWMOGroupId());
// Vehicle
if (player->GetVehicle() && player->GetVehicle()->GetVehicleInfo())
MemberStats.VehicleSeat = player->GetVehicle()->GetVehicleInfo()->SeatID[player->m_movementInfo.transport.seat];
// Auras
MemberStats.AuraMask = player->GetAuraUpdateMaskForRaid();
for (uint8 i = 0; i < MAX_AURAS; ++i)
{
if (!(MemberStats.AuraMask & (uint64(1) << i)))
continue;
if (AuraApplication const* aurApp = player->GetVisibleAura(i))
{
WorldPackets::Party::PartyMemberAuraStates aura;
aura.SpellID = aurApp->GetBase()->GetId();
aura.Flags = aurApp->GetFlags();
if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
{
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
if (AuraEffect const* aurEff = aurApp->GetBase()->GetEffect(i))
aura.Points.push_back(aurEff->GetAmount());
else
aura.Points.push_back(0);
}
}
MemberStats.Auras.push_back(aura);
}
}
// Phases
PhasingHandler::FillPartyMemberPhase(&MemberStats.Phases, player->GetPhaseShift());
// Pet
if (player->GetPet())
{
::Pet* pet = player->GetPet();
MemberStats.PetStats = boost::in_place();
MemberStats.PetStats->GUID = pet->GetGUID();
MemberStats.PetStats->Name = pet->GetName();
MemberStats.PetStats->ModelId = pet->GetDisplayId();
MemberStats.PetStats->CurrentHealth = pet->GetHealth();
MemberStats.PetStats->MaxHealth = pet->GetMaxHealth();
MemberStats.PetStats->PowerType = pet->GetPowerType();
MemberStats.PetStats->CurrentPower = player->GetPower(player->GetPowerType());
MemberStats.PetStats->MaxPower = player->GetMaxPower(player->GetPowerType());
// Auras
MemberStats.PetStats->AuraMask = player->GetAuraUpdateMaskForRaid();
for (uint8 i = 0; i < MAX_AURAS; ++i)
{
if (!(MemberStats.PetStats->AuraMask & (uint64(1) << i)))
continue;
if (AuraApplication const* aurApp = pet->GetVisibleAura(i))
{
WorldPackets::Party::PartyMemberAuraStates aura;
aura.SpellID = aurApp->GetBase()->GetId();
aura.Flags = aurApp->GetFlags();
if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
{
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
if (AuraEffect const* aurEff = aurApp->GetBase()->GetEffect(i))
aura.Points.push_back(aurEff->GetAmount());
else
aura.Points.push_back(0);
}
}
MemberStats.PetStats->Auras.push_back(aura);
}
}
}
}
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::PartyMemberPhaseStates const& phases)
{
data << uint32(phases.PhaseShiftFlags);
data << uint32(phases.List.size());
for (uint16 phaseId : phases.List)
data << uint16(phaseId);
return data;
}
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::PartyMemberAuraStates const& aura)
{
data << uint32(aura.SpellID);
data << uint16(aura.Flags);
for (int32 points : aura.Points)
data << int32(points);
return data;
}
WorldPacket const* WorldPackets::Party::PartyMemberState::Write()
{
if (_worldPacket.GetOpcode() == SMSG_PARTY_MEMBER_FULL_STATE)
_worldPacket << uint8(ForEnemy);
_worldPacket << MemberGuid.WriteAsPacked();
_worldPacket << uint32(ChangeMask);
if (ChangeMask & GROUP_UPDATE_FLAG_STATUS)
_worldPacket << uint16(MemberStats.Status);
if (ChangeMask & GROUP_UPDATE_FLAG_CUR_HP)
_worldPacket << int32(MemberStats.CurrentHealth);
if (ChangeMask & GROUP_UPDATE_FLAG_MAX_HP)
_worldPacket << int32(MemberStats.MaxHealth);
if (ChangeMask & GROUP_UPDATE_FLAG_POWER_TYPE)
_worldPacket << uint8(MemberStats.PowerType);
if (ChangeMask & GROUP_UPDATE_FLAG_CUR_POWER)
_worldPacket << uint16(MemberStats.CurrentPower);
if (ChangeMask & GROUP_UPDATE_FLAG_MAX_POWER)
_worldPacket << uint16(MemberStats.MaxPower);
if (ChangeMask & GROUP_UPDATE_FLAG_LEVEL)
_worldPacket << uint16(MemberStats.Level);
if (ChangeMask & GROUP_UPDATE_FLAG_ZONE)
_worldPacket << uint16(MemberStats.ZoneID);
if (ChangeMask & GROUP_UPDATE_FLAG_WMO_GROUP_ID)
_worldPacket << int16(MemberStats.WmoGroupID);
if (ChangeMask & GROUP_UPDATE_FLAG_POSITION)
{
_worldPacket << int16(MemberStats.PositionX);
_worldPacket << int16(MemberStats.PositionY);
_worldPacket << int16(MemberStats.PositionZ);
}
if (ChangeMask & GROUP_UPDATE_FLAG_AURAS)
{
_worldPacket << uint8(_worldPacket.GetOpcode() == SMSG_PARTY_MEMBER_FULL_STATE);
_worldPacket << uint64(MemberStats.AuraMask);
_worldPacket << uint32(MemberStats.Auras.size());
for (WorldPackets::Party::PartyMemberAuraStates const& aura : MemberStats.Auras)
_worldPacket << aura;
}
if (MemberStats.PetStats.is_initialized())
{
if (ChangeMask & GROUP_UPDATE_FLAG_PET_GUID)
_worldPacket << MemberStats.PetStats->GUID;
if (ChangeMask & GROUP_UPDATE_FLAG_PET_NAME)
_worldPacket << MemberStats.PetStats->Name;
if (ChangeMask & GROUP_UPDATE_FLAG_PET_MODEL_ID)
_worldPacket << int16(MemberStats.PetStats->ModelId);
if (ChangeMask & GROUP_UPDATE_FLAG_PET_CUR_HP)
_worldPacket << int32(MemberStats.PetStats->CurrentHealth);
if (ChangeMask & GROUP_UPDATE_FLAG_PET_MAX_HP)
_worldPacket << int32(MemberStats.PetStats->MaxHealth);
if (ChangeMask & GROUP_UPDATE_FLAG_PET_POWER_TYPE)
_worldPacket << uint8(MemberStats.PetStats->PowerType);
if (ChangeMask & GROUP_UPDATE_FLAG_PET_CUR_POWER)
_worldPacket << uint16(MemberStats.PetStats->CurrentPower);
if (ChangeMask & GROUP_UPDATE_FLAG_PET_MAX_POWER)
_worldPacket << uint16(MemberStats.PetStats->MaxPower);
}
// Pet auras may be sent even when no pet is present
if (ChangeMask & GROUP_UPDATE_FLAG_PET_AURAS)
{
_worldPacket << uint8(_worldPacket.GetOpcode() == SMSG_PARTY_MEMBER_FULL_STATE);
_worldPacket << uint64(MemberStats.PetStats.is_initialized() ? MemberStats.PetStats->AuraMask : 0);
_worldPacket << uint32(MemberStats.PetStats.is_initialized() ? MemberStats.PetStats->Auras.size() : 0);
if (MemberStats.PetStats.is_initialized())
for (WorldPackets::Party::PartyMemberAuraStates const& aura : MemberStats.PetStats->Auras)
_worldPacket << aura;
}
if (ChangeMask & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
_worldPacket << int32(MemberStats.VehicleSeat);
if (ChangeMask & GROUP_UPDATE_FLAG_PHASE)
_worldPacket << MemberStats.Phases;
return &_worldPacket;
}

View File

@@ -0,0 +1,92 @@
/*
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
*
* 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/>.
*/
#ifndef PartyPackets_h__
#define PartyPackets_h__
#include "Packet.h"
namespace WorldPackets
{
namespace Party
{
struct PartyMemberPhaseStates
{
uint32 PhaseShiftFlags = 0;
std::vector<uint16> List;
};
struct PartyMemberAuraStates
{
int32 SpellID = 0;
uint16 Flags = 0;
std::vector<int32> Points;
};
struct PartyMemberPetStats
{
ObjectGuid GUID;
std::string Name;
int16 ModelId = 0;
int32 CurrentHealth = 0;
int32 MaxHealth = 0;
uint8 PowerType = 0u;
uint16 CurrentPower = 0;
uint16 MaxPower = 0;
uint64 AuraMask = 0;
std::vector<PartyMemberAuraStates> Auras;
};
struct PartyMemberStats
{
uint16 Level = 0;
uint16 Status = 0;
int32 CurrentHealth = 0;
int32 MaxHealth = 0;
uint8 PowerType = 0u;
uint16 CurrentPower = 0;
uint16 MaxPower = 0;
uint16 ZoneID = 0;
uint16 WmoGroupID = 0;
int16 PositionX = 0;
int16 PositionY = 0;
int16 PositionZ = 0;
int32 VehicleSeat = 0;
uint64 AuraMask = 0;
PartyMemberPhaseStates Phases;
std::vector<PartyMemberAuraStates> Auras;
Optional<PartyMemberPetStats> PetStats;
};
class PartyMemberState final : public ServerPacket
{
public:
PartyMemberState(bool fullUpdate = false) : ServerPacket(fullUpdate ? SMSG_PARTY_MEMBER_FULL_STATE : SMSG_PARTY_MEMBER_STATE, 80) { }
WorldPacket const* Write() override;
void Initialize(Player const* player);
bool ForEnemy = false;
ObjectGuid MemberGuid;
uint32 ChangeMask = 0;
PartyMemberStats MemberStats;
};
}
}
#endif // PartyPackets_h__

View File

@@ -1084,8 +1084,8 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PAGE_TEXT_QUERY_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTYKILLLOG, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_COMMAND_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_MEMBER_STATS, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_MEMBER_STATS_FULL, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_MEMBER_STATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_MEMBER_FULL_STATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PAUSE_MIRROR_TIMER, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PERIODICAURALOG, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PETGODMODE, STATUS_NEVER, CONNECTION_TYPE_REALM);

View File

@@ -1040,8 +1040,8 @@ enum OpcodeServer
SMSG_PAGE_TEXT_QUERY_RESPONSE = 0x2B14,
SMSG_PARTYKILLLOG = 0x4937,
SMSG_PARTY_COMMAND_RESULT = 0x6E07,
SMSG_PARTY_MEMBER_STATS = 0x2104,
SMSG_PARTY_MEMBER_STATS_FULL = 0x0215,
SMSG_PARTY_MEMBER_STATE = 0x2104,
SMSG_PARTY_MEMBER_FULL_STATE = 0x0215,
SMSG_PAUSE_MIRROR_TIMER = 0x4015,
SMSG_PERIODICAURALOG = 0x0416,
SMSG_PETGODMODE = 0x2E36,

View File

@@ -546,8 +546,6 @@ class TC_GAME_API WorldSession
void SendNotInArenaTeamPacket(uint8 type);
void SendPetitionShowList(ObjectGuid guid);
void BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket* data);
void DoLootRelease(ObjectGuid lguid);
// Account mute time