Skip to content

Commit b15d765

Browse files
Merge AzerothCore 3.3.5 to ElunaAzerothcore [skip ci]
2 parents 202580d + c029eab commit b15d765

12 files changed

Lines changed: 123 additions & 7 deletions

File tree

src/server/apps/worldserver/worldserver.conf.dist

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3690,6 +3690,18 @@ Wintergrasp.SkipBattleSessionCount = 3500
36903690

36913691
Wintergrasp.KickVoAPlayers = 1
36923692

3693+
#
3694+
# Wintergrasp.EssenceBothFactions
3695+
# Description: Grant the "Essence of Wintergrasp" buff to both factions
3696+
# during peacetime, regardless of who controls the keep.
3697+
# The wartime suppression still applies; this only affects
3698+
# who receives the buff once the battle is over.
3699+
# Default: 0 - (Disabled, only the defending faction gets the buff)
3700+
# 1 - (Enabled, attackers and defenders both get the buff,
3701+
# so both factions can access Vault of Archavon)
3702+
3703+
Wintergrasp.EssenceBothFactions = 0
3704+
36933705
#
36943706
###################################################################################################
36953707

src/server/game/Battlefield/Battlefield.cpp

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

125127
void 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+
591645
BfGraveyard* Battlefield::GetGraveyardById(uint32 id) const
592646
{
593647
if (id < GraveyardList.size())

src/server/game/Battlefield/Battlefield.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,11 @@ class Battlefield : public ZoneScript
278278
/// Force player to join a battlefield group
279279
bool AddOrSetPlayerToCorrectBfGroup(Player* player);
280280

281+
/// Auto-rejoin a player who relogged within the grace window after a mid-war
282+
/// logout, via the normal join hooks. No-op without a pending logout marker.
283+
/// Called from HandlePlayerEnterZone (which fires on the post-login zone set).
284+
void TryRejoinAfterLogout(Player* player);
285+
281286
// Graveyard methods
282287
// Find which graveyard the player must be teleported to to be resurrected by spiritguide
283288
GraveyardStruct const* GetClosestGraveyard(Player* player);
@@ -381,6 +386,10 @@ class Battlefield : public ZoneScript
381386
GuidUnorderedSet PlayersInWar[PVP_TEAMS_COUNT]; // Players in WG combat
382387
PlayerTimerMap InvitedPlayers[PVP_TEAMS_COUNT];
383388
PlayerTimerMap PlayersWillBeKick[PVP_TEAMS_COUNT];
389+
// Mid-war logouts: GUID -> timestamp until which a relog auto-rejoins the war.
390+
PlayerTimerMap LogoutGracePlayers[PVP_TEAMS_COUNT];
391+
392+
static constexpr uint32 LOGOUT_GRACE_SECONDS = 120; // relog auto-rejoin window
384393

385394
// Variables that must exist for each battlefield
386395
uint32 TypeId; // See enum BattlefieldTypes

src/server/game/Battlefield/Zones/BattlefieldWG.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,12 +479,17 @@ void BattlefieldWG::OnBattleEnd(bool endByTimer)
479479
}
480480
}
481481

482+
bool const grantEssenceToAttackers = sWorld->getBoolConfig(CONFIG_WINTERGRASP_ESSENCE_BOTH_FACTIONS);
483+
482484
for (ObjectGuid const& guid : PlayersInWar[GetAttackerTeam()])
483485
if (Player* player = ObjectAccessor::FindPlayer(guid))
484486
{
485487
player->CastSpell(player, SPELL_DEFEAT_REWARD, true);
486488
RemoveAurasFromPlayer(player);
487489

490+
if (grantEssenceToAttackers)
491+
player->CastSpell(player, SPELL_ESSENCE_OF_WINTERGRASP, true);
492+
488493
for (uint8 i = 0; i < damagedTowersAtt; ++i)
489494
player->CastSpell(player, spellDamagedAtt, true);
490495
for (uint8 i = 0; i < brokenTowersAtt; ++i)

src/server/game/Entities/Player/Player.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13119,6 +13119,11 @@ PartyResult Player::CanUninviteFromGroup(ObjectGuid targetPlayerGUID) const
1311913119

1312013120
if (InBattleground())
1312113121
return ERR_INVITE_RESTRICTED;
13122+
13123+
// BF raids are owned by the Battlefield system; leaders/assistants must not
13124+
// be able to kick members (would drop their team assignment mid-battle).
13125+
if (grp->isBFGroup())
13126+
return ERR_NOT_LEADER;
1312213127
}
1312313128

1312413129
return ERR_PARTY_RESULT_OK;

src/server/game/Entities/Unit/Unit.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,9 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, uint32 effectMask, Unit
954954
for (auto const& [immunitySchoolMask, immunityAuraId] : schoolList)
955955
{
956956
SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(immunityAuraId);
957+
if (immunityAuraId == spellInfo->Id)
958+
continue;
959+
957960
if ((immunitySchoolMask & schoolMask) != schoolMask)
958961
continue;
959962

@@ -10087,6 +10090,9 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell)
1008710090
SpellImmuneContainer const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
1008810091
for (auto itr = schoolList.begin(); itr != schoolList.end(); ++itr)
1008910092
{
10093+
if (itr->second == spellInfo->Id)
10094+
continue;
10095+
1009010096
SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->second);
1009110097
if (!(itr->first & spellSchoolMask))
1009210098
continue;

src/server/game/Handlers/GroupHandler.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,16 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
129129
return;
130130
}
131131

132+
// Battlefield raids (e.g. Wintergrasp) have their composition managed by the BF
133+
// system based on queue and team balance. Letting raid members recruit outsiders
134+
// bypasses Battlefield::AddOrSetPlayerToCorrectBfGroup, which on WG entry then
135+
// refuses to add the invitee because they are already in a BF group.
136+
if (Group* invitingGroup = invitingPlayer->GetGroup(); invitingGroup && invitingGroup->isBFGroup())
137+
{
138+
SendPartyResult(PARTY_OP_INVITE, membername, ERR_NOT_LEADER);
139+
return;
140+
}
141+
132142
Group* group = invitingPlayer->GetGroup();
133143
if (group && group->isBGGroup())
134144
group = invitingPlayer->GetOriginalGroup();

src/server/game/Spells/SpellInfoCorrections.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,7 +1527,7 @@ void SpellMgr::LoadSpellInfoCorrections()
15271527
spellInfo->Speed = 8.0f;
15281528
});
15291529

1530-
// Spell Absorption
1530+
// Shadowmoon Reaver - Spell Absorption
15311531
ApplySpellFix({ 41034 }, [](SpellInfo* spellInfo)
15321532
{
15331533
spellInfo->Effects[EFFECT_2].Effect = SPELL_EFFECT_APPLY_AURA;
@@ -1536,12 +1536,13 @@ void SpellMgr::LoadSpellInfoCorrections()
15361536
spellInfo->Effects[EFFECT_2].MiscValue = SPELL_SCHOOL_MASK_MAGIC;
15371537
});
15381538

1539-
// Shared Bonds
1539+
// Priestess of Delight and Priestess of Torment - Shared Bonds
15401540
ApplySpellFix({ 41363 }, [](SpellInfo* spellInfo)
15411541
{
15421542
spellInfo->AttributesEx &= ~SPELL_ATTR1_IS_CHANNELED;
15431543
});
15441544

1545+
// Illidari Council - Veras Darkshadow
15451546
ApplySpellFix({
15461547
41485, // Deadly Poison
15471548
41487 // Envenom
@@ -1570,13 +1571,13 @@ void SpellMgr::LoadSpellInfoCorrections()
15701571
spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(13); // 0-50000yd
15711572
});
15721573

1573-
// Watery Grave Explosion
1574+
// Morogrim Tidewalker - Watery Grave Explosion
15741575
ApplySpellFix({ 37852 }, [](SpellInfo* spellInfo)
15751576
{
15761577
spellInfo->AttributesEx5 |= SPELL_ATTR5_ALLOW_WHILE_STUNNED;
15771578
});
15781579

1579-
// Amplify Damage
1580+
// Prince Malchezaar - Amplify Damage
15801581
ApplySpellFix({ 39095 }, [](SpellInfo* spellInfo)
15811582
{
15821583
spellInfo->MaxAffectedTargets = 1;
@@ -1589,6 +1590,7 @@ void SpellMgr::LoadSpellInfoCorrections()
15891590
spellInfo->AttributesCu |= SPELL_ATTR0_CU_SINGLE_AURA_STACK;
15901591
});
15911592

1593+
// Archimonde
15921594
ApplySpellFix({
15931595
31984, // Finger of Death
15941596
35354 // Hand of Death
@@ -1598,12 +1600,18 @@ void SpellMgr::LoadSpellInfoCorrections()
15981600
spellInfo->Attributes = SPELL_ATTR0_IS_ABILITY;
15991601
});
16001602

1601-
// Finger of Death
1603+
// Archimonde - Finger of Death
16021604
ApplySpellFix({ 32111 }, [](SpellInfo* spellInfo)
16031605
{
16041606
spellInfo->CastTimeEntry = sSpellCastTimesStore.LookupEntry(0); // We only need the animation, no damage
16051607
});
16061608

1609+
// Archimonde - Doomfire
1610+
ApplySpellFix({ 31944, 31969 }, [](SpellInfo* spellInfo)
1611+
{
1612+
spellInfo->AttributesEx4 |= SPELL_ATTR4_NO_CAST_LOG;
1613+
});
1614+
16071615
// Flame Breath, catapult spell
16081616
ApplySpellFix({ 50989 }, [](SpellInfo* spellInfo)
16091617
{

src/server/game/Spells/SpellMgr.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1101,7 +1101,9 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32
11011101
return false;
11021102

11031103
Battlefield* Bf = sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG);
1104-
if (!Bf || player->GetTeamId() != Bf->GetDefenderTeam() || Bf->IsWarTime())
1104+
if (!Bf || Bf->IsWarTime())
1105+
return false;
1106+
if (!sWorld->getBoolConfig(CONFIG_WINTERGRASP_ESSENCE_BOTH_FACTIONS) && player->GetTeamId() != Bf->GetDefenderTeam())
11051107
return false;
11061108
break;
11071109
}

src/server/game/World/WorldConfig.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@ void WorldConfig::BuildConfigCache()
596596

597597
SetConfigValue<uint32>(CONFIG_WINTERGRASP_SKIP_BATTLE_SESSION_COUNT, "Wintergrasp.SkipBattleSessionCount", 3500);
598598
SetConfigValue<bool>(CONFIG_WINTERGRASP_KICK_VOA_PLAYERS, "Wintergrasp.KickVoAPlayers", true, ConfigValueCache::Reloadable::No);
599+
SetConfigValue<bool>(CONFIG_WINTERGRASP_ESSENCE_BOTH_FACTIONS, "Wintergrasp.EssenceBothFactions", false);
599600

600601
SetConfigValue<uint32>(CONFIG_BIRTHDAY_TIME, "BirthdayTime", 1222964635);
601602
SetConfigValue<bool>(CONFIG_MINIGOB_MANABONK, "Minigob.Manabonk.Enable", true);

0 commit comments

Comments
 (0)