feat(Core/Arena): swap OnGetStartPersonalRating for OnAddMember, add OnArenaWeekReset (#27512)

This commit is contained in:
Stefano Borzì
2026-09-07 17:00:34 +02:00
committed by GitHub
parent b53c5576a9
commit c665359412
9 changed files with 53 additions and 17 deletions
@@ -278,7 +278,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
// Arena teams
PrepareStatement(CHAR_INS_ARENA_TEAM, "INSERT INTO arena_team (arenaTeamId, name, captainGuid, type, rating, backgroundColor, emblemStyle, emblemColor, borderStyle, borderColor) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_ARENA_TEAM_MEMBER, "INSERT INTO arena_team_member (arenaTeamId, guid, personalRating) VALUES (?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_ARENA_TEAM_MEMBER, "INSERT INTO arena_team_member (arenaTeamId, guid, weekGames, weekWins, seasonGames, seasonWins, personalRating) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_ARENA_TEAM, "DELETE FROM arena_team WHERE arenaTeamId = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_ARENA_TEAM_MEMBERS, "DELETE FROM arena_team_member WHERE arenaTeamId = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_ARENA_TEAM_CAPTAIN, "UPDATE arena_team SET captainGuid = ? WHERE arenaTeamId = ?", CONNECTION_ASYNC);
+7 -3
View File
@@ -137,8 +137,6 @@ bool ArenaTeam::AddMember(ObjectGuid playerGuid)
else if (GetRating() >= 1000)
personalRating = 1000;
sScriptMgr->OnGetStartPersonalRating(this, playerGuid, personalRating);
// xinef: sync query
// Try to get player's match maker rating from db and fall back to config setting if not found
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MATCH_MAKER_RATING);
@@ -177,6 +175,8 @@ bool ArenaTeam::AddMember(ObjectGuid playerGuid)
newMember.MatchMakerRating = matchMakerRating;
newMember.MaxMMR = maxMMR;
sScriptMgr->OnAddMember(this, newMember);
Members.push_back(newMember);
sCharacterCache->UpdateCharacterArenaTeamId(playerGuid, GetSlot(), GetId());
@@ -184,7 +184,11 @@ bool ArenaTeam::AddMember(ObjectGuid playerGuid)
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_TEAM_MEMBER);
stmt->SetData(0, TeamId);
stmt->SetData(1, playerGuid.GetCounter());
stmt->SetData(2, personalRating);
stmt->SetData(2, newMember.WeekGames);
stmt->SetData(3, newMember.WeekWins);
stmt->SetData(4, newMember.SeasonGames);
stmt->SetData(5, newMember.SeasonWins);
stmt->SetData(6, newMember.PersonalRating);
CharacterDatabase.Execute(stmt);
// Inform player if online
@@ -268,6 +268,8 @@ void ArenaTeamMgr::DistributeArenaPoints()
}
}
sScriptMgr->OnArenaWeekReset();
ChatHandler(nullptr).SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_END);
ChatHandler(nullptr).SendWorldText(LANG_DIST_ARENA_POINTS_END);
@@ -54,9 +54,9 @@ bool ScriptMgr::CanSaveArenaStatsForMember(ArenaTeam* team, ObjectGuid playerGui
CALL_ENABLED_BOOLEAN_HOOKS(ArenaScript, ARENAHOOK_CAN_SAVE_ARENA_STATS_FOR_MEMBER, !script->CanSaveArenaStatsForMember(team, playerGuid));
}
void ScriptMgr::OnGetStartPersonalRating(ArenaTeam* team, ObjectGuid playerGuid, uint32& personalRating)
void ScriptMgr::OnAddMember(ArenaTeam* team, ArenaTeamMember& member)
{
CALL_ENABLED_HOOKS(ArenaScript, ARENAHOOK_ON_GET_START_PERSONAL_RATING, script->OnGetStartPersonalRating(team, playerGuid, personalRating));
CALL_ENABLED_HOOKS(ArenaScript, ARENAHOOK_ON_ADD_MEMBER, script->OnAddMember(team, member));
}
ArenaScript::ArenaScript(char const* name, std::vector<uint16> enabledHooks)
@@ -22,6 +22,8 @@
#include "ScriptObject.h"
#include <vector>
struct ArenaTeamMember;
enum ArenaHook
{
ARENAHOOK_CAN_ADD_MEMBER,
@@ -31,7 +33,7 @@ enum ArenaHook
ARENAHOOK_ON_ARENA_START,
ARENAHOOK_ON_BEFORE_TEAM_MEMBER_UPDATE,
ARENAHOOK_CAN_SAVE_ARENA_STATS_FOR_MEMBER,
ARENAHOOK_ON_GET_START_PERSONAL_RATING,
ARENAHOOK_ON_ADD_MEMBER,
ARENAHOOK_END
};
@@ -59,9 +61,13 @@ public:
[[nodiscard]] virtual bool CanSaveArenaStatsForMember(ArenaTeam* /*team*/, ObjectGuid /*playerGuid*/) { return true; }
// Called with the personal rating the core computed for a player joining the team, before it is
// stored on the member and written to arena_team_member.
virtual void OnGetStartPersonalRating(ArenaTeam* /*team*/, ObjectGuid /*playerGuid*/, uint32& /*personalRating*/) { }
// Called with the fully built member right before it is added to the team and written to
// arena_team_member. The personal rating and the week/season counters left on the struct are
// what the team holds and what is stored. MatchMakerRating and MaxMMR are held in memory but
// not written here, only by the next ArenaTeam::SaveToDB; Guid, Name and Class are identity,
// and changing them desyncs the member from its row and the character cache.
// Cannot veto the join, CanAddMember does that.
virtual void OnAddMember(ArenaTeam* /*team*/, ArenaTeamMember& /*member*/) { }
};
#endif
@@ -74,6 +74,11 @@ void ScriptMgr::OnBeforeUpdateArenaPoints(ArenaTeam* at, std::map<ObjectGuid, ui
CALL_ENABLED_HOOKS(GlobalScript, GLOBALHOOK_ON_BEFORE_UPDATE_ARENA_POINTS, script->OnBeforeUpdateArenaPoints(at, ap));
}
void ScriptMgr::OnArenaWeekReset()
{
CALL_ENABLED_HOOKS(GlobalScript, GLOBALHOOK_ON_ARENA_WEEK_RESET, script->OnArenaWeekReset());
}
void ScriptMgr::OnAfterUpdateEncounterState(Map* map, EncounterCreditType type, uint32 creditEntry, Unit* source, Difficulty difficulty_fixed, DungeonEncounterList const* encounters, uint32 dungeonCompleted, bool updated)
{
CALL_ENABLED_HOOKS(GlobalScript, GLOBALHOOK_ON_AFTER_UPDATE_ENCOUNTER_STATE, script->OnAfterUpdateEncounterState(map, type, creditEntry, source, difficulty_fixed, encounters, dungeonCompleted, updated));
@@ -37,6 +37,7 @@ enum GlobalHook
GLOBALHOOK_ON_INITIALIZE_LOCKED_DUNGEONS,
GLOBALHOOK_ON_AFTER_INITIALIZE_LOCKED_DUNGEONS,
GLOBALHOOK_ON_BEFORE_UPDATE_ARENA_POINTS,
GLOBALHOOK_ON_ARENA_WEEK_RESET,
GLOBALHOOK_ON_AFTER_UPDATE_ENCOUNTER_STATE,
GLOBALHOOK_ON_BEFORE_WORLDOBJECT_SET_PHASEMASK,
GLOBALHOOK_ON_IS_AFFECTED_BY_SPELL_MOD_CHECK,
@@ -73,6 +74,10 @@ public:
// On Before arena points distribution
virtual void OnBeforeUpdateArenaPoints(ArenaTeam* /*at*/, std::map<ObjectGuid, uint32>& /*ap*/) { }
// Called when the weekly arena point distribution has just reset the week statistics of every
// arena team on the realm.
virtual void OnArenaWeekReset() { }
// Called when a dungeon encounter is updated.
virtual void OnAfterUpdateEncounterState(Map* /*map*/, EncounterCreditType /*type*/, uint32 /*creditEntry*/, Unit* /*source*/, Difficulty /*difficulty_fixed*/, std::list<DungeonEncounter const*> const* /*encounters*/, uint32 /*dungeonCompleted*/, bool /*updated*/) { }
+2 -1
View File
@@ -522,6 +522,7 @@ public: /* GlobalScript */
void OnGlobalItemDelFromDB(CharacterDatabaseTransaction trans, ObjectGuid::LowType itemGuid);
void OnGlobalMirrorImageDisplayItem(Item const* item, uint32& display);
void OnBeforeUpdateArenaPoints(ArenaTeam* at, std::map<ObjectGuid, uint32>& ap);
void OnArenaWeekReset();
void OnAfterRefCount(Player const* player, Loot& loot, bool canRate, uint16 lootMode, LootStoreItem* LootStoreItem, uint32& maxcount, LootStore const& store);
void OnAfterCalculateLootGroupAmount(Player const* player, Loot& loot, uint16 lootMode, uint32& groupAmount, LootStore const& store);
void OnBeforeDropAddItem(Player const* player, Loot& loot, bool canRate, uint16 lootMode, LootStoreItem* LootStoreItem, LootStore const& store);
@@ -675,7 +676,7 @@ public: /* ArenaScript */
void OnArenaStart(Battleground* const bg);
bool OnBeforeArenaTeamMemberUpdate(ArenaTeam* team, Player* player, bool won, uint32 opponentMatchmakerRating, int32 matchmakerChange);
bool CanSaveArenaStatsForMember(ArenaTeam* team, ObjectGuid playerGuid);
void OnGetStartPersonalRating(ArenaTeam* team, ObjectGuid playerGuid, uint32& personalRating);
void OnAddMember(ArenaTeam* team, ArenaTeamMember& member);
public: /* MiscScript */
@@ -92,14 +92,27 @@ TEST_F(ArenaHookDefaultsTest, CanSaveArenaStatsForMemberDefaultsTrue)
EXPECT_TRUE(sScriptMgr->CanSaveArenaStatsForMember(&team, ObjectGuid::Empty));
}
// OnGetStartPersonalRating must leave the rating untouched by default so a new
// arena team member keeps the value ArenaTeam::AddMember computed for them.
TEST_F(ArenaHookDefaultsTest, OnGetStartPersonalRatingKeepsCoreValue)
// OnAddMember must leave the member untouched by default so a new arena team
// member keeps the rating and counters ArenaTeam::AddMember built for them,
// which are also what is written to arena_team_member.
TEST_F(ArenaHookDefaultsTest, OnAddMemberLeavesMemberUntouched)
{
ArenaTeam team;
uint32 personalRating = 1000;
sScriptMgr->OnGetStartPersonalRating(&team, ObjectGuid::Empty, personalRating);
EXPECT_EQ(personalRating, 1000u);
ArenaTeamMember member{};
member.PersonalRating = 1000;
member.WeekGames = 6;
member.WeekWins = 3;
member.SeasonGames = 40;
member.SeasonWins = 22;
sScriptMgr->OnAddMember(&team, member);
EXPECT_EQ(member.PersonalRating, 1000u);
EXPECT_EQ(member.WeekGames, 6u);
EXPECT_EQ(member.WeekWins, 3u);
EXPECT_EQ(member.SeasonGames, 40u);
EXPECT_EQ(member.SeasonWins, 22u);
}
// OnBeforeArenaCheckWinConditions must return true by default so