diff --git a/src/CFBG.cpp b/src/CFBG.cpp index b2d9b97..c1a9383 100644 --- a/src/CFBG.cpp +++ b/src/CFBG.cpp @@ -537,8 +537,12 @@ void CFBG::ClearFakePlayer(Player* player) return; player->setRace(_fakePlayerStore[player].RealRace); - player->SetDisplayId(_fakePlayerStore[player].RealMorph); + // Restore via the aura-resolution path, not the entry-time snapshot: a + // player who dropped a shapeshift/transform mid-BG must get the real model + // back, one still in the form keeps the form model. RestoreDisplayId's + // no-aura fallback is the native display, so set that first. player->SetNativeDisplayId(_fakePlayerStore[player].RealNativeMorph); + player->RestoreDisplayId(); SetFactionForRace(player, _fakePlayerStore[player].RealRace, _fakePlayerStore[player].RealTeamID); // Clear forced faction reactions. Rank doesn't matter here, not used when they are removed. @@ -622,24 +626,7 @@ TeamId CFBG::ResolveWGWarTeam(Player* player, uint32 nativeAllianceInvited, uint return (_wgMajorityTeam == TEAM_ALLIANCE) ? TEAM_HORDE : TEAM_ALLIANCE; } -void CFBG::DoForgetPlayersInList(Player* player) -{ - // m_FakePlayers is filled from a vector within the battleground - // they were in previously so all players that have been in that BG will be invalidated. - for (auto const& itr : _fakeNamePlayersStore) - { - WorldPacket data(SMSG_INVALIDATE_PLAYER, 8); - data << itr.second; - player->GetSession()->SendPacket(&data); - - if (Player* _player = ObjectAccessor::FindPlayer(itr.second)) - player->GetSession()->SendNameQueryOpcode(_player->GetGUID()); - } - - _fakeNamePlayersStore.erase(player); -} - -void CFBG::FitPlayerInTeam(Player* player, bool action, Battleground* bg) +void CFBG::FitPlayerInTeam(Player* player, Battleground* bg) { if (!_IsEnableSystem) return; @@ -647,13 +634,10 @@ void CFBG::FitPlayerInTeam(Player* player, bool action, Battleground* bg) if (!bg) bg = player->GetBattleground(); - if ((!bg || bg->isArena()) && action) + if (!bg || bg->isArena()) return; - if (action) - SetForgetBGPlayers(player, true); - else - SetForgetInListPlayers(player, true); + SetForgetBGPlayers(player, true); } void CFBG::SetForgetBGPlayers(Player* player, bool value) @@ -666,14 +650,10 @@ bool CFBG::ShouldForgetBGPlayers(Player* player) return _forgetBGPlayersStore[player]; } -void CFBG::SetForgetInListPlayers(Player* player, bool value) -{ - _forgetInListPlayersStore[player] = value; -} - -bool CFBG::ShouldForgetInListPlayers(Player* player) +bool CFBG::HasPendingForget(Player* player) const { - return _forgetInListPlayersStore.find(player) != _forgetInListPlayersStore.end() && _forgetInListPlayersStore[player]; + auto const itr = _forgetBGPlayersStore.find(player); + return itr != _forgetBGPlayersStore.end() && itr->second; } void CFBG::DoForgetPlayersInBG(Player* player, Battleground* bg) @@ -698,25 +678,6 @@ void CFBG::DoForgetPlayersInBG(Player* player, Battleground* bg) } } -bool CFBG::SendRealNameQuery(Player* player) -{ - if (IsPlayingNative(player)) - return false; - - WorldPacket data(SMSG_NAME_QUERY_RESPONSE, (8 + 1 + 1 + 1 + 1 + 1 + 10)); - data << player->GetGUID().WriteAsPacked(); // player guid - data << uint8(0); // added in 3.1; if > 1, then end of packet - data << player->GetName(); // played name - data << uint8(0); // realm name for cross realm BG usage - data << uint8(player->getRace(true)); - data << uint8(player->getGender()); - data << uint8(player->getClass()); - data << uint8(0); // is not declined - player->GetSession()->SendPacket(&data); - - return true; -} - bool CFBG::IsPlayingNative(Player* player) { return player->GetTeamId(true) == player->GetBGData().bgTeamId; @@ -947,18 +908,10 @@ bool CFBG::isClassJoining(uint8 _class, Player* player, uint32 minLevel) void CFBG::UpdateForget(Player* player) { Battleground* bg = player->GetBattleground(); - if (bg) - { - if (ShouldForgetBGPlayers(player) && bg) - { - DoForgetPlayersInBG(player, bg); - SetForgetBGPlayers(player, false); - } - } - else if (ShouldForgetInListPlayers(player)) + if (bg && ShouldForgetBGPlayers(player)) { - DoForgetPlayersInList(player); - SetForgetInListPlayers(player, false); + DoForgetPlayersInBG(player, bg); + SetForgetBGPlayers(player, false); } } diff --git a/src/CFBG.h b/src/CFBG.h index 0cfb317..2b7e6e3 100644 --- a/src/CFBG.h +++ b/src/CFBG.h @@ -143,7 +143,6 @@ class CFBG TeamId ResolveBalancedTeam(TeamBalanceContext const& ctx); - bool SendRealNameQuery(Player* player); bool IsPlayerFake(Player* player); FakePlayer const* GetFakePlayer(Player* player) const; @@ -158,7 +157,6 @@ class CFBG // of a war, reset in ClearWGWarAssignments. TeamId ResolveWGWarTeam(Player* player, uint32 nativeAllianceInvited, uint32 nativeHordeInvited); - bool ShouldForgetInListPlayers(Player* player); bool IsPlayingNative(Player* player); void ValidatePlayerForBG(Battleground* bg, Player* player); @@ -170,12 +168,14 @@ class CFBG void SetFactionForRace(Player* player, uint8 Race, TeamId teamId); void ClearFakePlayer(Player* player); void ReapplyFakePlayer(Player* player); - void DoForgetPlayersInList(Player* player); - void FitPlayerInTeam(Player* player, bool action, Battleground* bg); + void FitPlayerInTeam(Player* player, Battleground* bg); void DoForgetPlayersInBG(Player* player, Battleground* bg); void SetForgetBGPlayers(Player* player, bool value); bool ShouldForgetBGPlayers(Player* player); - void SetForgetInListPlayers(Player* player, bool value); + // Const, non-inserting flag probe for the per-tick update hook + // (ShouldForgetBGPlayers' operator[] would default-insert an entry for + // every online player every tick). + bool HasPendingForget(Player* player) const; void UpdateForget(Player* player); void SendMessageQueue(BattlegroundQueue* bgQueue, Battleground* bg, PvPDifficultyEntry const* bracketEntry, Player* leader); @@ -219,9 +219,7 @@ class CFBG TeamId _wgMajorityTeam = TEAM_ALLIANCE; uint32 _wgMajorityFairShare = 0; uint32 _wgMajorityNativeKept = 0; - std::unordered_map _fakeNamePlayersStore; std::unordered_map _forgetBGPlayersStore; - std::unordered_map _forgetInListPlayersStore; std::array _raceData{}; std::array _raceInfo{}; diff --git a/src/CFBG_SC.cpp b/src/CFBG_SC.cpp index 3447810..1fb0ff5 100644 --- a/src/CFBG_SC.cpp +++ b/src/CFBG_SC.cpp @@ -6,6 +6,7 @@ #include "CFBG.h" #include "Battlefield.h" #include "BattlefieldMgr.h" +#include "Chat.h" #include "Group.h" #include "ObjectAccessor.h" #include "Player.h" @@ -35,7 +36,7 @@ class CFBG_BG : public BGScript void OnBattlegroundAddPlayer(Battleground* bg, Player* player) override { - sCFBG->FitPlayerInTeam(player, true, bg); + sCFBG->FitPlayerInTeam(player, bg); if (sCFBG->IsEnableResetCooldowns()) player->RemoveArenaSpellCooldowns(true); @@ -55,8 +56,6 @@ class CFBG_BG : public BGScript if (!sCFBG->IsEnableSystem() || bg->isArena()) return; - sCFBG->FitPlayerInTeam(player, false, bg); - if (sCFBG->IsPlayerFake(player)) sCFBG->ClearFakePlayer(player); } @@ -118,7 +117,7 @@ class CFBG_Player : public PlayerScript return; if (player->GetTeamId(true) != player->GetBgTeamId()) - sCFBG->FitPlayerInTeam(player, player->GetBattleground() && !player->GetBattleground()->isArena(), player->GetBattleground()); + sCFBG->FitPlayerInTeam(player, player->GetBattleground()); } void OnPlayerLogout(Player* player) override @@ -175,7 +174,12 @@ class CFBG_Player : public PlayerScript return true; if (group->isRaidGroup() || group->GetMembersCount() > sCFBG->GetMaxPlayersCountInGroup()) + { + // The client shows only a generic "Join as a group failed."; + // name the actual limit so the leader knows what to change. + ChatHandler(player->GetSession()).PSendSysMessage("Battleground groups are limited to {} players.", sCFBG->GetMaxPlayersCountInGroup()); err = ERR_BATTLEGROUND_JOIN_FAILED; + } return false; } @@ -183,15 +187,12 @@ class CFBG_Player : public PlayerScript return true; } - void OnPlayerBeforeUpdate(Player* player, uint32 diff) override + void OnPlayerBeforeUpdate(Player* player, uint32 /*diff*/) override { - if (timeCheck <= diff) - { + // The flag is set once per BG add (or login into a BG) and cleared + // after service, so serving it on the next tick self-rate-limits. + if (sCFBG->HasPendingForget(player)) sCFBG->UpdateForget(player); - timeCheck = 10000; - } - else - timeCheck -= diff; } void OnPlayerBeforeSendChatMessage(Player* player, uint32& type, uint32& lang, std::string& /*msg*/) override @@ -212,6 +213,11 @@ class CFBG_Player : public PlayerScript if (type == CHAT_MSG_ADDON || type == CHAT_MSG_SYSTEM) return; + // keep proximity chat in the native language so enemies get + // the normal cross-faction scramble instead of readable text + if (type == CHAT_MSG_SAY || type == CHAT_MSG_YELL) + return; + // to gm lang lang = LANG_UNIVERSAL; } @@ -246,22 +252,25 @@ class CFBG_Player : public PlayerScript bool OnPlayerReputationChange(Player* player, uint32 factionID, int32& standing, bool /*incremental*/) override { - uint32 repGain = player->GetReputation(factionID); + if (!sCFBG->IsEnableSystem()) + return true; + TeamId teamId = player->GetTeamId(true); if ((factionID == FACTION_FROSTWOLF_CLAN && teamId == TEAM_ALLIANCE) || (factionID == FACTION_STORMPIKE_GUARD && teamId == TEAM_HORDE)) { - uint32 diff = standing - repGain; + // Signed arithmetic: a reputation LOSS must arrive as a negative + // delta; an unsigned difference would wrap and slam the mirror + // faction to the reputation floor. + int32 current = player->GetReputationMgr().GetReputation(sFactionStore.LookupEntry(factionID)); + int32 diff = standing - current; player->GetReputationMgr().ModifyReputation(sFactionStore.LookupEntry(teamId == TEAM_ALLIANCE ? FACTION_STORMPIKE_GUARD : FACTION_FROSTWOLF_CLAN), diff); return false; } return true; } - -private: - uint32 timeCheck = 10000; }; // WG constants duplicated here to avoid pulling in BattlefieldWG.h diff --git a/src/cs_cfbg.cpp b/src/cs_cfbg.cpp index 83c1e0d..20e12fb 100644 --- a/src/cs_cfbg.cpp +++ b/src/cs_cfbg.cpp @@ -129,7 +129,6 @@ class cfbg_commandscript : public CommandScript bool const isFake = sCFBG->IsPlayerFake(target); bool const native = sCFBG->IsPlayingNative(target); bool const forgetBG = sCFBG->ShouldForgetBGPlayers(target); - bool const forgetList = sCFBG->ShouldForgetInListPlayers(target); bool const inBG = target->InBattleground(); uint8 const preferredRace = target->GetPlayerSetting("mod-cfbg", SETTING_CFBG_RACE).value; FakePlayer const* fake = sCFBG->GetFakePlayer(target); @@ -161,7 +160,6 @@ class cfbg_commandscript : public CommandScript uint32(target->getClass()), uint32(target->getGender())); handler->PSendSysMessage(" Preferred race {}", uint32(preferredRace)); handler->PSendSysMessage(" Forget BG players {}", YesNo(forgetBG)); - handler->PSendSysMessage(" Forget in list {}", YesNo(forgetList)); // === Fake record === if (fake)