forked from mirror/azerothcore-wotlk
fix(Core/Battlefield): collapse BfCapturePoint::ActivePlayers to single set (#26034)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -857,7 +857,7 @@ bool BfCapturePoint::HandlePlayerEnter(Player* player)
|
||||
player->SendUpdateWorldState(go->GetGOInfo()->capturePoint.worldstate2, uint32(std::ceil((Value + MaxValue) / (2 * MaxValue) * 100.0f)));
|
||||
player->SendUpdateWorldState(go->GetGOInfo()->capturePoint.worldstate3, NeutralValuePct);
|
||||
}
|
||||
return ActivePlayers[player->GetTeamId()].insert(player->GetGUID()).second;
|
||||
return ActivePlayers.insert(player->GetGUID()).second;
|
||||
}
|
||||
|
||||
GuidUnorderedSet::iterator BfCapturePoint::HandlePlayerLeave(Player* player)
|
||||
@@ -865,13 +865,12 @@ GuidUnorderedSet::iterator BfCapturePoint::HandlePlayerLeave(Player* player)
|
||||
if (GameObject* go = GetCapturePointGo(player))
|
||||
player->SendUpdateWorldState(go->GetGOInfo()->capturePoint.worldState1, 0);
|
||||
|
||||
GuidUnorderedSet::iterator current = ActivePlayers[player->GetTeamId()].find(player->GetGUID());
|
||||
GuidUnorderedSet::iterator current = ActivePlayers.find(player->GetGUID());
|
||||
|
||||
if (current == ActivePlayers[player->GetTeamId()].end())
|
||||
if (current == ActivePlayers.end())
|
||||
return current; // return end()
|
||||
|
||||
current = ActivePlayers[player->GetTeamId()].erase(current);
|
||||
return current;
|
||||
return ActivePlayers.erase(current);
|
||||
}
|
||||
|
||||
void BfCapturePoint::SendChangePhase()
|
||||
@@ -880,17 +879,16 @@ void BfCapturePoint::SendChangePhase()
|
||||
if (!capturePoint)
|
||||
return;
|
||||
|
||||
for (uint8 team = 0; team < 2; ++team)
|
||||
for (ObjectGuid const& guid : ActivePlayers[team]) // send to all players present in the area
|
||||
if (Player* player = ObjectAccessor::FindPlayer(guid))
|
||||
{
|
||||
// send this too, sometimes the slider disappears, dunno why :(
|
||||
player->SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldState1, 1);
|
||||
// send these updates to only the ones in this objective
|
||||
player->SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldstate2, (uint32) std::ceil((Value + MaxValue) / (2 * MaxValue) * 100.0f));
|
||||
// send this too, sometimes it resets :S
|
||||
player->SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldstate3, NeutralValuePct);
|
||||
}
|
||||
for (ObjectGuid const& guid : ActivePlayers) // send to all players present in the area
|
||||
if (Player* player = ObjectAccessor::FindPlayer(guid))
|
||||
{
|
||||
// send this too, sometimes the slider disappears, dunno why :(
|
||||
player->SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldState1, 1);
|
||||
// send these updates to only the ones in this objective
|
||||
player->SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldstate2, (uint32) std::ceil((Value + MaxValue) / (2 * MaxValue) * 100.0f));
|
||||
// send this too, sometimes it resets :S
|
||||
player->SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldstate3, NeutralValuePct);
|
||||
}
|
||||
}
|
||||
|
||||
bool BfCapturePoint::SetCapturePointData(GameObject* capturePoint, TeamId team)
|
||||
@@ -962,19 +960,19 @@ bool BfCapturePoint::Update(uint32 diff)
|
||||
|
||||
float radius = capturePoint->GetGOInfo()->capturePoint.radius;
|
||||
|
||||
for (uint8 team = 0; team < 2; ++team)
|
||||
// Single pass over the existing set: drop leavers, count survivors per team.
|
||||
uint32 counts[PVP_TEAMS_COUNT] = { 0, 0 };
|
||||
for (auto itr = ActivePlayers.begin(); itr != ActivePlayers.end();)
|
||||
{
|
||||
for (auto itr = ActivePlayers[team].begin(); itr != ActivePlayers[team].end();)
|
||||
Player* player = ObjectAccessor::FindPlayer(*itr);
|
||||
if (player && capturePoint->IsWithinDistInMap(player, radius) && player->IsOutdoorPvPActive())
|
||||
{
|
||||
if (Player* player = ObjectAccessor::FindPlayer(*itr))
|
||||
if (!capturePoint->IsWithinDistInMap(player, radius) || !player->IsOutdoorPvPActive())
|
||||
{
|
||||
itr = HandlePlayerLeave(player);
|
||||
continue;
|
||||
}
|
||||
|
||||
++counts[player->GetTeamId()];
|
||||
++itr;
|
||||
continue;
|
||||
}
|
||||
|
||||
itr = (player ? HandlePlayerLeave(player) : ActivePlayers.erase(itr));
|
||||
}
|
||||
|
||||
std::list<Player*> players;
|
||||
@@ -984,11 +982,14 @@ bool BfCapturePoint::Update(uint32 diff)
|
||||
|
||||
for (Player* player : players)
|
||||
if (player->IsOutdoorPvPActive())
|
||||
if (ActivePlayers[player->GetTeamId()].insert(player->GetGUID()).second)
|
||||
if (ActivePlayers.insert(player->GetGUID()).second)
|
||||
{
|
||||
HandlePlayerEnter(player);
|
||||
++counts[player->GetTeamId()];
|
||||
}
|
||||
|
||||
// get the difference of numbers
|
||||
float factDiff = ((float) ActivePlayers[0].size() - (float) ActivePlayers[1].size()) * diff / BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL;
|
||||
float factDiff = ((float)counts[TEAM_ALLIANCE] - (float)counts[TEAM_HORDE]) * diff / BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL;
|
||||
if (G3D::fuzzyEq(factDiff, 0.0f))
|
||||
return false;
|
||||
|
||||
@@ -1074,34 +1075,36 @@ bool BfCapturePoint::Update(uint32 diff)
|
||||
|
||||
void BfCapturePoint::SendUpdateWorldState(uint32 field, uint32 value)
|
||||
{
|
||||
for (uint8 team = 0; team < 2; ++team)
|
||||
for (ObjectGuid const& guid : ActivePlayers[team]) // send to all players present in the area
|
||||
if (Player* player = ObjectAccessor::FindPlayer(guid))
|
||||
player->SendUpdateWorldState(field, value);
|
||||
for (ObjectGuid const& guid : ActivePlayers) // send to all players present in the area
|
||||
if (Player* player = ObjectAccessor::FindPlayer(guid))
|
||||
player->SendUpdateWorldState(field, value);
|
||||
}
|
||||
|
||||
void BfCapturePoint::SendObjectiveComplete(uint32 id, ObjectGuid guid)
|
||||
{
|
||||
uint8 team;
|
||||
TeamId winner;
|
||||
switch (State)
|
||||
{
|
||||
case BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE:
|
||||
team = 0;
|
||||
winner = TEAM_ALLIANCE;
|
||||
break;
|
||||
case BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE:
|
||||
team = 1;
|
||||
winner = TEAM_HORDE;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// send to all players present in the area
|
||||
for (ObjectGuid const& playerGuid : ActivePlayers[team])
|
||||
// Credit only players on the controlling team. Team is read from the
|
||||
// player at iteration time, not at insert time, so players whose
|
||||
// GetTeamId() changed mid-stay get credit on their current side.
|
||||
for (ObjectGuid const& playerGuid : ActivePlayers)
|
||||
if (Player* player = ObjectAccessor::FindPlayer(playerGuid))
|
||||
player->KilledMonsterCredit(id, guid);
|
||||
if (player->GetTeamId() == winner)
|
||||
player->KilledMonsterCredit(id, guid);
|
||||
}
|
||||
|
||||
bool BfCapturePoint::IsInsideObjective(Player* player) const
|
||||
{
|
||||
return ActivePlayers[player->GetTeamId()].find(player->GetGUID()) != ActivePlayers[player->GetTeamId()].end();
|
||||
return ActivePlayers.find(player->GetGUID()) != ActivePlayers.end();
|
||||
}
|
||||
|
||||
@@ -119,8 +119,10 @@ public:
|
||||
protected:
|
||||
bool DelCapturePoint();
|
||||
|
||||
// Active players in the area of the objective, 0 - alliance, 1 - horde
|
||||
GuidUnorderedSet ActivePlayers[2];
|
||||
// Active players in the area of the objective. Single set keyed by GUID:
|
||||
// team is computed from Player::GetTeamId() at the point it is needed.
|
||||
// Splitting by team here would desync if GetTeamId() changes mid-stay.
|
||||
GuidUnorderedSet ActivePlayers;
|
||||
|
||||
// Total shift needed to capture the objective
|
||||
float MaxValue;
|
||||
|
||||
Reference in New Issue
Block a user