@@ -93,6 +93,8 @@ void Battlefield::HandlePlayerEnterZone(Player* player, uint32 /*zone*/)
9393 // any team-based battlefield containers (such as player lists or queues) are updated.
9494 sScriptMgr ->OnBattlefieldPlayerEnterZone (this , player);
9595
96+ TryRejoinAfterLogout (player); // relog: auto-rejoin, skip invite below
97+
9698 // Xinef: do not invite players on taxi
9799 if (!player->IsInFlight ())
98100 {
@@ -124,12 +126,20 @@ void Battlefield::HandlePlayerEnterZone(Player* player, uint32 /*zone*/)
124126
125127void Battlefield::HandlePlayerLeaveZone (Player* player, uint32 /* zone*/ )
126128{
129+ // Logout still runs full leave-war cleanup, but marks the player for grace-window auto-rejoin.
130+ bool const isLogout = player->GetSession () && player->GetSession ()->PlayerLogout ();
131+
127132 if (IsWarTime ())
128133 {
129134 // If the player is participating to the battle
130135 if (PlayersInWar[player->GetTeamId ()].erase (player->GetGUID ()))
131136 {
132- player->GetSession ()->SendBfLeaveMessage (BattleId);
137+ if (isLogout)
138+ LogoutGracePlayers[player->GetTeamId ()][player->GetGUID ()] =
139+ GameTime::GetGameTime ().count () + LOGOUT_GRACE_SECONDS;
140+ else
141+ player->GetSession ()->SendBfLeaveMessage (BattleId);
142+
133143 if (Group* group = player->GetGroup ()) // Remove the player from the raid group
134144 if (group->isBFGroup ())
135145 group->RemoveMember (player->GetGUID ());
@@ -321,6 +331,7 @@ void Battlefield::StartBattle()
321331 {
322332 PlayersInWar[team].clear ();
323333 Groups[team].clear ();
334+ LogoutGracePlayers[team].clear ();
324335 }
325336
326337 Timer = BattleTime;
@@ -396,6 +407,14 @@ void Battlefield::EndBattle(bool endByTimer)
396407 OnBattleEnd (endByTimer);
397408 sScriptMgr ->OnBattlefieldWarEnd (this , endByTimer);
398409
410+ for (uint8 team = 0 ; team < PVP_TEAMS_COUNT; ++team)
411+ {
412+ for (ObjectGuid const & guid : Groups[team])
413+ if (Group* group = sGroupMgr ->GetGroupByGUID (guid.GetCounter ()))
414+ group->Disband ();
415+ Groups[team].clear ();
416+ }
417+
399418 // Reset battlefield timer
400419 Timer = NoWarBattleTime;
401420 SendInitWorldStatesToAll ();
@@ -588,6 +607,41 @@ bool Battlefield::AddOrSetPlayerToCorrectBfGroup(Player* player)
588607 return true ;
589608}
590609
610+ void Battlefield::TryRejoinAfterLogout (Player* player)
611+ {
612+ ObjectGuid const guid = player->GetGUID ();
613+ time_t const now = GameTime::GetGameTime ().count ();
614+
615+ // Consume the marker and honor its grace window (check both teams; team may have changed).
616+ bool pending = false ;
617+ for (uint8 team = 0 ; team < PVP_TEAMS_COUNT; ++team)
618+ if (auto itr = LogoutGracePlayers[team].find (guid); itr != LogoutGracePlayers[team].end ())
619+ {
620+ pending = itr->second > now;
621+ LogoutGracePlayers[team].erase (itr);
622+ }
623+
624+ // Vacancy gate mirrors HandlePlayerEnterZone (full team -> queue path). Pre-hook:
625+ // we can't abort after JoinWar, which may already have mutated module state.
626+ if (!pending || !IsWarTime () || !HasWarVacancy (player->GetTeamId ()))
627+ return ;
628+
629+ if (Group* current = player->GetGroup ())
630+ if (current->isBGGroup () || current->isBFGroup ())
631+ return ;
632+
633+ // Rejoin via the normal join path: firing JoinWar lets modules rebuild
634+ // per-session (Player*-keyed) state and pick the team before the raid bind.
635+ sScriptMgr ->OnBattlefieldPlayerJoinWar (this , player);
636+
637+ if (AddOrSetPlayerToCorrectBfGroup (player))
638+ {
639+ player->GetSession ()->SendBfEntered (BattleId);
640+ PlayersInWar[player->GetTeamId ()].insert (guid);
641+ OnPlayerJoinWar (player);
642+ }
643+ }
644+
591645BfGraveyard* Battlefield::GetGraveyardById (uint32 id) const
592646{
593647 if (id < GraveyardList.size ())
0 commit comments