@@ -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;
@@ -588,6 +599,41 @@ bool Battlefield::AddOrSetPlayerToCorrectBfGroup(Player* player)
588599 return true ;
589600}
590601
602+ void Battlefield::TryRejoinAfterLogout (Player* player)
603+ {
604+ ObjectGuid const guid = player->GetGUID ();
605+ time_t const now = GameTime::GetGameTime ().count ();
606+
607+ // Consume the marker and honor its grace window (check both teams; team may have changed).
608+ bool pending = false ;
609+ for (uint8 team = 0 ; team < PVP_TEAMS_COUNT ; ++team)
610+ if (auto itr = LogoutGracePlayers[team].find (guid); itr != LogoutGracePlayers[team].end ())
611+ {
612+ pending = itr->second > now;
613+ LogoutGracePlayers[team].erase (itr);
614+ }
615+
616+ // Vacancy gate mirrors HandlePlayerEnterZone (full team -> queue path). Pre-hook:
617+ // we can't abort after JoinWar, which may already have mutated module state.
618+ if (!pending || !IsWarTime () || !HasWarVacancy (player->GetTeamId ()))
619+ return ;
620+
621+ if (Group* current = player->GetGroup ())
622+ if (current->isBGGroup () || current->isBFGroup ())
623+ return ;
624+
625+ // Rejoin via the normal join path: firing JoinWar lets modules rebuild
626+ // per-session (Player*-keyed) state and pick the team before the raid bind.
627+ sScriptMgr ->OnBattlefieldPlayerJoinWar (this , player);
628+
629+ if (AddOrSetPlayerToCorrectBfGroup (player))
630+ {
631+ player->GetSession ()->SendBfEntered (BattleId);
632+ PlayersInWar[player->GetTeamId ()].insert (guid);
633+ OnPlayerJoinWar (player);
634+ }
635+ }
636+
591637BfGraveyard* Battlefield::GetGraveyardById (uint32 id) const
592638{
593639 if (id < GraveyardList.size ())
0 commit comments