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
@@ -32,7 +32,6 @@ void VisibleNotifier::Visit(GameObjectMapType& m)
if (i_largeOnly != go->IsVisibilityOverridden())
continue;
vis_guids.erase(go->GetGUID());
i_player.UpdateVisibilityOf(go, i_data, i_visibleNow);
}
}
@@ -42,56 +41,66 @@ void VisibleNotifier::SendToSelf()
// at this moment i_clientGUIDs have guids that not iterate at grid level checks
// but exist one case when this possible and object not out of range: transports
if (Transport* transport = i_player.GetTransport())
{
for (Transport::PassengerSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr)
{
if (i_largeOnly != (*itr)->IsVisibilityOverridden())
continue;
if (vis_guids.find((*itr)->GetGUID()) != vis_guids.end())
switch ((*itr)->GetTypeId())
{
vis_guids.erase((*itr)->GetGUID());
case TYPEID_GAMEOBJECT:
i_player.UpdateVisibilityOf((*itr)->ToGameObject(), i_data, i_visibleNow);
break;
case TYPEID_PLAYER:
i_player.UpdateVisibilityOf((*itr)->ToPlayer(), i_data, i_visibleNow);
(*itr)->ToPlayer()->UpdateVisibilityOf(&i_player);
break;
case TYPEID_UNIT:
i_player.UpdateVisibilityOf((*itr)->ToCreature(), i_data, i_visibleNow);
break;
default:
break;
}
}
}
switch ((*itr)->GetTypeId())
VisibleWorldObjectsMap* visibleWorldObjects = i_player.GetObjectVisibilityContainer().GetVisibleWorldObjectsMap();
for (VisibleWorldObjectsMap::iterator itr = visibleWorldObjects->begin(); itr != visibleWorldObjects->end();)
{
WorldObject* obj = itr->second;
if (i_largeOnly != obj->IsVisibilityOverridden())
{
++itr;
continue;
}
// pussywizard: static transports are removed only in RemovePlayerFromMap and here if can no longer detect (eg. phase changed)
if (itr->first.IsTransport())
{
if (GameObject* staticTrans = obj->ToGameObject())
{
if (i_player.CanSeeOrDetect(staticTrans, false, true))
{
case TYPEID_GAMEOBJECT:
i_player.UpdateVisibilityOf((*itr)->ToGameObject(), i_data, i_visibleNow);
break;
case TYPEID_PLAYER:
i_player.UpdateVisibilityOf((*itr)->ToPlayer(), i_data, i_visibleNow);
(*itr)->ToPlayer()->UpdateVisibilityOf(&i_player);
break;
case TYPEID_UNIT:
i_player.UpdateVisibilityOf((*itr)->ToCreature(), i_data, i_visibleNow);
break;
default:
break;
++itr;
continue;
}
}
}
for (GuidUnorderedSet::const_iterator it = vis_guids.begin(); it != vis_guids.end(); ++it)
{
if (WorldObject* obj = ObjectAccessor::GetWorldObject(i_player, *it))
if (i_player.m_seer->IsWithinDist(obj, i_player.GetSightRange(obj), true))
{
if (i_largeOnly != obj->IsVisibilityOverridden())
continue;
++itr;
continue;
}
// pussywizard: static transports are removed only in RemovePlayerFromMap and here if can no longer detect (eg. phase changed)
if ((*it).IsTransport())
if (GameObject* staticTrans = i_player.GetMap()->GetGameObject(*it))
if (i_player.CanSeeOrDetect(staticTrans, false, true))
continue;
i_data.AddOutOfRangeGUID(obj->GetGUID());
i_player.m_clientGUIDs.erase(*it);
i_data.AddOutOfRangeGUID(*it);
if (Player* objPlayer = obj->ToPlayer())
objPlayer->UpdateVisibilityOf(&i_player);
if ((*it).IsPlayer())
{
Player* player = ObjectAccessor::FindPlayer(*it);
if (player && player->IsInMap(&i_player))
player->UpdateVisibilityOf(&i_player);
}
// Clean up references
itr = i_player.GetObjectVisibilityContainer().UnlinkVisibilityFromPlayer(obj, itr);
}
if (!i_data.HasData())
@@ -170,7 +179,6 @@ void PlayerRelocationNotifier::Visit(PlayerMapType& m)
for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
Player* player = iter->GetSource();
vis_guids.erase(player->GetGUID());
i_player.UpdateVisibilityOf(player, i_data, i_visibleNow);
player->UpdateVisibilityOf(&i_player); // this notifier with different Visit(PlayerMapType&) than VisibleNotifier is needed to update visibility of self for other players when we move (eg. stealth detection changes)
}
@@ -208,6 +216,23 @@ void AIRelocationNotifier::Visit(CreatureMapType& m)
}
}
// Uses visibility map
void MessageDistDeliverer::Visit(VisiblePlayersMap const& m)
{
for (auto const& kvPair : m)
{
Player const* target = kvPair.second;
if (i_distSq != 0.0f && target->m_seer->GetExactDist2dSq(i_source) > i_distSq)
continue;
// @todo: Might not need this check anymore
if (skipped_receiver == target)
continue;
target->SendDirectMessage(i_message);
}
}
void MessageDistDeliverer::Visit(PlayerMapType& m)
{
for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
@@ -43,14 +43,13 @@ namespace Acore
struct VisibleNotifier
{
Player& i_player;
GuidUnorderedSet vis_guids;
std::vector<Unit*>& i_visibleNow;
bool i_gobjOnly;
bool i_largeOnly;
UpdateData i_data;
VisibleNotifier(Player& player, bool gobjOnly, bool largeOnly) :
i_player(player), vis_guids(player.m_clientGUIDs), i_visibleNow(player.m_newVisible), i_gobjOnly(gobjOnly), i_largeOnly(largeOnly)
i_player(player), i_visibleNow(player.m_newVisible), i_gobjOnly(gobjOnly), i_largeOnly(largeOnly)
{
i_visibleNow.clear();
}
@@ -111,6 +110,7 @@ namespace Acore
, skipped_receiver(skipped), required3dDist(req3dDist)
{
}
void Visit(VisiblePlayersMap const& m);
void Visit(PlayerMapType& m);
void Visit(CreatureMapType& m);
void Visit(DynamicObjectMapType& m);
@@ -37,7 +37,6 @@ inline void Acore::VisibleNotifier::Visit(GridRefMgr<T>& m)
if (i_largeOnly != iter->GetSource()->IsVisibilityOverridden())
continue;
vis_guids.erase(iter->GetSource()->GetGUID());
i_player.UpdateVisibilityOf(iter->GetSource(), i_data, i_visibleNow);
}
}