Skip to content

Commit f8ceac0

Browse files
Nyeriahclaude
andauthored
fix(Core/Battlefield): collapse BfCapturePoint::ActivePlayers to single set (azerothcore#26034)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 919eefe commit f8ceac0

2 files changed

Lines changed: 45 additions & 40 deletions

File tree

src/server/game/Battlefield/Battlefield.cpp

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -857,21 +857,20 @@ bool BfCapturePoint::HandlePlayerEnter(Player* player)
857857
player->SendUpdateWorldState(go->GetGOInfo()->capturePoint.worldstate2, uint32(std::ceil((Value + MaxValue) / (2 * MaxValue) * 100.0f)));
858858
player->SendUpdateWorldState(go->GetGOInfo()->capturePoint.worldstate3, NeutralValuePct);
859859
}
860-
return ActivePlayers[player->GetTeamId()].insert(player->GetGUID()).second;
860+
return ActivePlayers.insert(player->GetGUID()).second;
861861
}
862862

863863
GuidUnorderedSet::iterator BfCapturePoint::HandlePlayerLeave(Player* player)
864864
{
865865
if (GameObject* go = GetCapturePointGo(player))
866866
player->SendUpdateWorldState(go->GetGOInfo()->capturePoint.worldState1, 0);
867867

868-
GuidUnorderedSet::iterator current = ActivePlayers[player->GetTeamId()].find(player->GetGUID());
868+
GuidUnorderedSet::iterator current = ActivePlayers.find(player->GetGUID());
869869

870-
if (current == ActivePlayers[player->GetTeamId()].end())
870+
if (current == ActivePlayers.end())
871871
return current; // return end()
872872

873-
current = ActivePlayers[player->GetTeamId()].erase(current);
874-
return current;
873+
return ActivePlayers.erase(current);
875874
}
876875

877876
void BfCapturePoint::SendChangePhase()
@@ -880,17 +879,16 @@ void BfCapturePoint::SendChangePhase()
880879
if (!capturePoint)
881880
return;
882881

883-
for (uint8 team = 0; team < 2; ++team)
884-
for (ObjectGuid const& guid : ActivePlayers[team]) // send to all players present in the area
885-
if (Player* player = ObjectAccessor::FindPlayer(guid))
886-
{
887-
// send this too, sometimes the slider disappears, dunno why :(
888-
player->SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldState1, 1);
889-
// send these updates to only the ones in this objective
890-
player->SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldstate2, (uint32) std::ceil((Value + MaxValue) / (2 * MaxValue) * 100.0f));
891-
// send this too, sometimes it resets :S
892-
player->SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldstate3, NeutralValuePct);
893-
}
882+
for (ObjectGuid const& guid : ActivePlayers) // send to all players present in the area
883+
if (Player* player = ObjectAccessor::FindPlayer(guid))
884+
{
885+
// send this too, sometimes the slider disappears, dunno why :(
886+
player->SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldState1, 1);
887+
// send these updates to only the ones in this objective
888+
player->SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldstate2, (uint32) std::ceil((Value + MaxValue) / (2 * MaxValue) * 100.0f));
889+
// send this too, sometimes it resets :S
890+
player->SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldstate3, NeutralValuePct);
891+
}
894892
}
895893

896894
bool BfCapturePoint::SetCapturePointData(GameObject* capturePoint, TeamId team)
@@ -962,19 +960,19 @@ bool BfCapturePoint::Update(uint32 diff)
962960

963961
float radius = capturePoint->GetGOInfo()->capturePoint.radius;
964962

965-
for (uint8 team = 0; team < 2; ++team)
963+
// Single pass over the existing set: drop leavers, count survivors per team.
964+
uint32 counts[PVP_TEAMS_COUNT] = { 0, 0 };
965+
for (auto itr = ActivePlayers.begin(); itr != ActivePlayers.end();)
966966
{
967-
for (auto itr = ActivePlayers[team].begin(); itr != ActivePlayers[team].end();)
967+
Player* player = ObjectAccessor::FindPlayer(*itr);
968+
if (player && capturePoint->IsWithinDistInMap(player, radius) && player->IsOutdoorPvPActive())
968969
{
969-
if (Player* player = ObjectAccessor::FindPlayer(*itr))
970-
if (!capturePoint->IsWithinDistInMap(player, radius) || !player->IsOutdoorPvPActive())
971-
{
972-
itr = HandlePlayerLeave(player);
973-
continue;
974-
}
975-
970+
++counts[player->GetTeamId()];
976971
++itr;
972+
continue;
977973
}
974+
975+
itr = (player ? HandlePlayerLeave(player) : ActivePlayers.erase(itr));
978976
}
979977

980978
std::list<Player*> players;
@@ -984,11 +982,14 @@ bool BfCapturePoint::Update(uint32 diff)
984982

985983
for (Player* player : players)
986984
if (player->IsOutdoorPvPActive())
987-
if (ActivePlayers[player->GetTeamId()].insert(player->GetGUID()).second)
985+
if (ActivePlayers.insert(player->GetGUID()).second)
986+
{
988987
HandlePlayerEnter(player);
988+
++counts[player->GetTeamId()];
989+
}
989990

990991
// get the difference of numbers
991-
float factDiff = ((float) ActivePlayers[0].size() - (float) ActivePlayers[1].size()) * diff / BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL;
992+
float factDiff = ((float)counts[TEAM_ALLIANCE] - (float)counts[TEAM_HORDE]) * diff / BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL;
992993
if (G3D::fuzzyEq(factDiff, 0.0f))
993994
return false;
994995

@@ -1074,34 +1075,36 @@ bool BfCapturePoint::Update(uint32 diff)
10741075

10751076
void BfCapturePoint::SendUpdateWorldState(uint32 field, uint32 value)
10761077
{
1077-
for (uint8 team = 0; team < 2; ++team)
1078-
for (ObjectGuid const& guid : ActivePlayers[team]) // send to all players present in the area
1079-
if (Player* player = ObjectAccessor::FindPlayer(guid))
1080-
player->SendUpdateWorldState(field, value);
1078+
for (ObjectGuid const& guid : ActivePlayers) // send to all players present in the area
1079+
if (Player* player = ObjectAccessor::FindPlayer(guid))
1080+
player->SendUpdateWorldState(field, value);
10811081
}
10821082

10831083
void BfCapturePoint::SendObjectiveComplete(uint32 id, ObjectGuid guid)
10841084
{
1085-
uint8 team;
1085+
TeamId winner;
10861086
switch (State)
10871087
{
10881088
case BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE:
1089-
team = 0;
1089+
winner = TEAM_ALLIANCE;
10901090
break;
10911091
case BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE:
1092-
team = 1;
1092+
winner = TEAM_HORDE;
10931093
break;
10941094
default:
10951095
return;
10961096
}
10971097

1098-
// send to all players present in the area
1099-
for (ObjectGuid const& playerGuid : ActivePlayers[team])
1098+
// Credit only players on the controlling team. Team is read from the
1099+
// player at iteration time, not at insert time, so players whose
1100+
// GetTeamId() changed mid-stay get credit on their current side.
1101+
for (ObjectGuid const& playerGuid : ActivePlayers)
11001102
if (Player* player = ObjectAccessor::FindPlayer(playerGuid))
1101-
player->KilledMonsterCredit(id, guid);
1103+
if (player->GetTeamId() == winner)
1104+
player->KilledMonsterCredit(id, guid);
11021105
}
11031106

11041107
bool BfCapturePoint::IsInsideObjective(Player* player) const
11051108
{
1106-
return ActivePlayers[player->GetTeamId()].find(player->GetGUID()) != ActivePlayers[player->GetTeamId()].end();
1109+
return ActivePlayers.find(player->GetGUID()) != ActivePlayers.end();
11071110
}

src/server/game/Battlefield/Battlefield.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,10 @@ class BfCapturePoint
119119
protected:
120120
bool DelCapturePoint();
121121

122-
// Active players in the area of the objective, 0 - alliance, 1 - horde
123-
GuidUnorderedSet ActivePlayers[2];
122+
// Active players in the area of the objective. Single set keyed by GUID:
123+
// team is computed from Player::GetTeamId() at the point it is needed.
124+
// Splitting by team here would desync if GetTeamId() changes mid-stay.
125+
GuidUnorderedSet ActivePlayers;
124126

125127
// Total shift needed to capture the objective
126128
float MaxValue;

0 commit comments

Comments
 (0)