44 */
55
66#include " CFBG.h"
7+ #include " Battlefield.h"
8+ #include " BattlefieldMgr.h"
79#include " Group.h"
810#include " Player.h"
911#include " ReputationMgr.h"
@@ -118,6 +120,21 @@ class CFBG_Player : public PlayerScript
118120 sCFBG ->FitPlayerInTeam (player, player->GetBattleground () && !player->GetBattleground ()->isArena (), player->GetBattleground ());
119121 }
120122
123+ void OnPlayerLogout (Player* player) override
124+ {
125+ if (!sCFBG ->IsEnableSystem () || !sCFBG ->IsPlayerFake (player))
126+ return ;
127+
128+ // Only clear the WG fake state when the battlefield is not actively at
129+ // war. During a running war the player may safely relog and rejoin
130+ // their assigned faction, so we leave the fake state intact for that
131+ // case. BG fakes are always cleaned up by OnBattlegroundRemovePlayerAtLeave
132+ // and do not need to be handled here.
133+ Battlefield* bf = sBattlefieldMgr ->GetBattlefieldToZoneId (player->GetZoneId ());
134+ if (bf && bf->GetTypeId () == BATTLEFIELD_WG && !bf->IsWarTime ())
135+ sCFBG ->ClearFakePlayer (player);
136+ }
137+
121138 bool OnPlayerCanJoinInBattlegroundQueue (Player* player, ObjectGuid /* BattlemasterGuid*/ , BattlegroundTypeId /* BGTypeID*/ , uint8 joinAsGroup, GroupJoinBattlegroundResult& err) override
122139 {
123140 if (!sCFBG ->IsEnableSystem ())
@@ -191,6 +208,73 @@ class CFBG_Player : public PlayerScript
191208 uint32 timeCheck = 10000 ;
192209};
193210
211+ class CFBG_Battlefield : public BattlefieldScript
212+ {
213+ public:
214+ CFBG_Battlefield () : BattlefieldScript(" CFBG_Battlefield" , {
215+ BATTLEFIELDHOOK_ON_PLAYER_JOIN_WAR ,
216+ BATTLEFIELDHOOK_ON_PLAYER_LEAVE_ZONE
217+ }) {}
218+
219+ void OnBattlefieldPlayerJoinWar (Battlefield* bf, Player* player) override
220+ {
221+ if (!sCFBG ->IsEnableSystem () || !sCFBG ->IsEnableWGSystem ())
222+ return ;
223+
224+ if (bf->GetTypeId () != BATTLEFIELD_WG )
225+ return ;
226+
227+ if (sCFBG ->IsPlayerFake (player))
228+ return ;
229+
230+ // This hook fires at the very start of OnBattlefieldPlayerJoinWar, BEFORE the
231+ // player is inserted into any m_players[] bucket. That means:
232+ // 1. GetPlayersInZoneCount reflects the current balanced distribution.
233+ // 2. SetFakeRaceAndMorphForBF changes player->GetTeamId() before the
234+ // bucket insert, so the player lands in the correct (assigned) bucket.
235+ // 3. All subsequent Battlefield operations (queue, war invite, group
236+ // assignment, leave cleanup) see the assigned team via GetTeamId().
237+ uint32 allianceCount = bf->GetPlayersInWarCount (TEAM_ALLIANCE );
238+ uint32 hordeCount = bf->GetPlayersInWarCount (TEAM_HORDE );
239+
240+ TeamId realTeam = player->GetTeamId (true );
241+ TeamId assignedTeam = realTeam;
242+
243+ LOG_ERROR (" sql.sql" , " Player {} entered WG with real team {}, alliance count {}, horde count {}" , player->GetName (), realTeam, allianceCount, hordeCount);
244+
245+ // Assign player to the team with fewer zone members to balance teams.
246+ if (realTeam == TEAM_ALLIANCE && allianceCount > hordeCount)
247+ assignedTeam = TEAM_HORDE ;
248+ else if (realTeam == TEAM_HORDE && hordeCount > allianceCount)
249+ assignedTeam = TEAM_ALLIANCE ;
250+
251+ if (assignedTeam == realTeam)
252+ return ;
253+
254+ // Apply visual + faction transformation so the player looks and acts as
255+ // the assigned faction in-game (PvP targeting, phase shifts, etc.).
256+ // This also calls player->setTeamId(assignedTeam) so all subsequent
257+ // player->GetTeamId() calls return the assigned team.
258+ sCFBG ->SetFakeRaceAndMorphForBF (player, assignedTeam);
259+ }
260+
261+ void OnBattlefieldPlayerLeaveZone (Battlefield* bf, Player* player) override
262+ {
263+ if (!sCFBG ->IsEnableSystem () || !sCFBG ->IsEnableWGSystem ())
264+ return ;
265+
266+ if (bf->GetTypeId () != BATTLEFIELD_WG )
267+ return ;
268+
269+ // HandlePlayerLeaveZone has already cleaned up all Battlefield data
270+ // structures using the assigned team (player->GetTeamId() still returns
271+ // assignedTeam at that point). Now that cleanup is complete it is safe
272+ // to restore the player's real race/faction.
273+ if (sCFBG ->IsPlayerFake (player))
274+ sCFBG ->ClearFakePlayer (player);
275+ }
276+ };
277+
194278class CFBG_World : public WorldScript
195279{
196280public:
@@ -208,5 +292,6 @@ void AddSC_CFBG()
208292{
209293 new CFBG_BG ();
210294 new CFBG_Player ();
295+ new CFBG_Battlefield ();
211296 new CFBG_World ();
212297}
0 commit comments