feat(Core/Visibility): Visibility improvements part 1 (#22624)

This commit is contained in:
Takenbacon
2025-08-07 07:17:45 -07:00
committed by GitHub
parent bde4e076ed
commit 1499aa51de
25 changed files with 456 additions and 296 deletions

View File

@@ -412,6 +412,9 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this)
m_isInstantFlightOn = true;
_wasOutdoor = true;
GetObjectVisibilityContainer().InitForPlayer();
sScriptMgr->OnConstructPlayer(this);
}
@@ -5707,20 +5710,7 @@ void Player::SendMessageToSetInRange(WorldPacket const* data, float dist, bool s
SendDirectMessage(data);
Acore::MessageDistDeliverer notifier(this, data, dist);
Cell::VisitWorldObjects(this, notifier, dist);
}
void Player::SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, bool includeMargin, bool ownTeamOnly, bool required3dDist) const
{
if (self)
SendDirectMessage(data);
dist += GetObjectSize();
if (includeMargin)
dist += VISIBILITY_COMPENSATION; // pussywizard: to ensure everyone receives all important packets
Acore::MessageDistDeliverer notifier(this, data, dist, ownTeamOnly, nullptr, required3dDist);
Cell::VisitWorldObjects(this, notifier, dist);
notifier.Visit(GetObjectVisibilityContainer().GetVisiblePlayersMap());
}
void Player::SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const
@@ -5728,8 +5718,8 @@ void Player::SendMessageToSet(WorldPacket const* data, Player const* skipped_rcv
if (skipped_rcvr != this)
SendDirectMessage(data);
Acore::MessageDistDeliverer notifier(this, data, GetVisibilityRange(), false, skipped_rcvr);
Cell::VisitWorldObjects(this, notifier, GetVisibilityRange());
Acore::MessageDistDeliverer notifier(this, data, 0.0f, false, skipped_rcvr);
notifier.Visit(GetObjectVisibilityContainer().GetVisiblePlayersMap());
}
void Player::SendDirectMessage(WorldPacket const* data) const
@@ -7711,23 +7701,26 @@ bool Player::CheckAmmoCompatibility(ItemTemplate const* ammo_proto) const
void Player::SendQuestGiverStatusMultiple()
{
if (GetObjectVisibilityContainer().GetVisibleWorldObjectsMap()->empty())
return;
uint32 count = 0;
WorldPacket data(SMSG_QUESTGIVER_STATUS_MULTIPLE, 4);
data << uint32(count); // placeholder
for (GuidUnorderedSet::const_iterator itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr)
DoForAllVisibleWorldObjects([this, &data, &count](WorldObject* worldObject)
{
uint32 questStatus = DIALOG_STATUS_NONE;
if ((*itr).IsAnyTypeCreature())
if (worldObject->IsCreature())
{
// need also pet quests case support
Creature* questgiver = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, *itr);
Creature* questgiver = worldObject->ToCreature();
if (!questgiver || questgiver->IsHostileTo(this))
continue;
return;
if (!questgiver->HasNpcFlag(UNIT_NPC_FLAG_QUESTGIVER))
continue;
return;
questStatus = GetQuestDialogStatus(questgiver);
@@ -7735,11 +7728,11 @@ void Player::SendQuestGiverStatusMultiple()
data << uint8(questStatus);
++count;
}
else if ((*itr).IsGameObject())
else if (worldObject->IsGameObject())
{
GameObject* questgiver = GetMap()->GetGameObject(*itr);
GameObject* questgiver = worldObject->ToGameObject();
if (!questgiver || questgiver->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER)
continue;
return;
questStatus = GetQuestDialogStatus(questgiver);
@@ -7747,7 +7740,7 @@ void Player::SendQuestGiverStatusMultiple()
data << uint8(questStatus);
++count;
}
}
});
data.put<uint32>(0, count); // write real count
GetSession()->SendPacket(&data);
@@ -9383,7 +9376,12 @@ void Player::Say(std::string_view text, Language language, WorldObject const* /*
WorldPacket data;
ChatHandler::BuildChatPacket(data, CHAT_MSG_SAY, language, this, this, _text);
SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true, false, false, true);
SendDirectMessage(&data);
// Special handling for messages, do not use visibility map for stealthed units
Acore::MessageDistDeliverer notifier(this, &data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), false, nullptr, true);
Cell::VisitWorldObjects(this, notifier, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY));
}
void Player::Say(uint32 textId, WorldObject const* target /*= nullptr*/)
@@ -9404,7 +9402,12 @@ void Player::Yell(std::string_view text, Language language, WorldObject const* /
WorldPacket data;
ChatHandler::BuildChatPacket(data, CHAT_MSG_YELL, language, this, this, _text);
SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), true, false, false, true);
SendDirectMessage(&data);
// Special handling for messages, do not use visibility map for stealthed units
Acore::MessageDistDeliverer notifier(this, &data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), false, nullptr, true);
Cell::VisitWorldObjects(this, notifier, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL));
}
void Player::Yell(uint32 textId, WorldObject const* target /*= nullptr*/)
@@ -9426,7 +9429,11 @@ void Player::TextEmote(std::string_view text, WorldObject const* /*= nullptr*/,
WorldPacket data;
ChatHandler::BuildChatPacket(data, CHAT_MSG_EMOTE, LANG_UNIVERSAL, this, this, _text);
SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), true, false, !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_EMOTE), true);
SendDirectMessage(&data);
// Special handling for messages, do not use visibility map for stealthed units
Acore::MessageDistDeliverer notifier(this, &data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_EMOTE), nullptr, true);
Cell::VisitWorldObjects(this, notifier, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE));
}
void Player::TextEmote(uint32 textId, WorldObject const* target /*= nullptr*/, bool /*isBossEmote = false*/)
@@ -10487,35 +10494,24 @@ void Player::ContinueTaxiFlight()
void Player::SendTaxiNodeStatusMultiple()
{
for (auto itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr)
DoForAllVisibleWorldObjects([this](WorldObject* worldObject)
{
if (!itr->IsCreature())
{
continue;
}
Creature* creature = ObjectAccessor::GetCreature(*this, *itr);
Creature* creature = worldObject->ToCreature();
if (!creature || creature->IsHostileTo(this))
{
continue;
}
return;
if (!creature->HasNpcFlag(UNIT_NPC_FLAG_FLIGHTMASTER))
{
continue;
}
return;
uint32 nearestNode = sObjectMgr->GetNearestTaxiNode(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetMapId(), GetTeamId());
if (!nearestNode)
{
continue;
}
return;
WorldPacket data(SMSG_TAXINODE_STATUS, 9);
data << *itr;
data << creature->GetGUID();
data << uint8(m_taxi.IsTaximaskNodeKnown(nearestNode) ? 1 : 0);
SendDirectMessage(&data);
}
});
}
void Player::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs)
@@ -11393,31 +11389,22 @@ WorldLocation Player::GetStartPosition() const
bool Player::HaveAtClient(WorldObject const* u) const
{
if (u == this)
{
return true;
}
// Motion Transports are always present in player's client
if (GameObject const* gameobject = u->ToGameObject())
{
if (gameobject->IsMotionTransport())
{
return true;
}
}
return m_clientGUIDs.find(u->GetGUID()) != m_clientGUIDs.end();
return HaveAtClient(u->GetGUID());
}
bool Player::HaveAtClient(ObjectGuid guid) const
{
if (guid == GetGUID())
{
return true;
}
return m_clientGUIDs.find(guid) != m_clientGUIDs.end();
return GetObjectVisibilityContainer().GetVisibleWorldObjectsMap()->find(guid) != GetObjectVisibilityContainer().GetVisibleWorldObjectsMap()->end();
}
bool Player::IsNeverVisible() const