mirror of
https://github.com/azerothcore/azerothcore-wotlk.git
synced 2025-11-10 21:04:26 +08:00
feat(Scripts): Add matchmaking hooks for module-based MMR systems
Add two new script hooks to AllBattlegroundScript system enabling modules to implement custom matchmaking logic: 1. CanAddGroupToMatchingPool - Allows filtering groups before adding to battleground selection pool based on custom criteria (e.g., MMR) 2. GetPlayerMatchmakingRating - Allows modules to provide player ratings for matchmaking algorithms Integration points: - BattlegroundQueue::FillPlayersToBG (6 locations) - Initial Alliance/Horde fills - Team balance adjustments - BattlegroundQueue::CheckNormalMatch (2 locations) - Normal match creation - Team balance These hooks enable modular MMR systems (Glicko-2, Elo, TrueSkill, etc.) without modifying core matchmaking code. Hooks are non-intrusive with no performance impact when unused. Use cases: - Battleground MMR-based matchmaking - Queue time-based MMR relaxation - Skill-based team balancing - Custom rating systems
This commit is contained in:
parent
675135e19b
commit
38882cd5a2
@ -434,15 +434,39 @@ void BattlegroundQueue::FillPlayersToBG(Battleground* bg, BattlegroundBracketId
|
||||
|
||||
//index to queue which group is current
|
||||
uint32 aliIndex = 0;
|
||||
for (; aliIndex < aliCount && m_SelectionPools[TEAM_ALLIANCE].AddGroup((*Ali_itr), aliFree); aliIndex++)
|
||||
for (; aliIndex < aliCount; aliIndex++)
|
||||
{
|
||||
// Allow modules to filter groups based on custom criteria (e.g., MMR)
|
||||
if (!sScriptMgr->CanAddGroupToMatchingPool(this, (*Ali_itr), m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount(), bg, bracket_id))
|
||||
{
|
||||
++Ali_itr;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!m_SelectionPools[TEAM_ALLIANCE].AddGroup((*Ali_itr), aliFree))
|
||||
break;
|
||||
|
||||
++Ali_itr;
|
||||
}
|
||||
|
||||
//the same thing for horde
|
||||
GroupsQueueType::const_iterator Horde_itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE].begin();
|
||||
|
||||
uint32 hordeIndex = 0;
|
||||
for (; hordeIndex < hordeCount && m_SelectionPools[TEAM_HORDE].AddGroup((*Horde_itr), hordeFree); hordeIndex++)
|
||||
for (; hordeIndex < hordeCount; hordeIndex++)
|
||||
{
|
||||
// Allow modules to filter groups based on custom criteria (e.g., MMR)
|
||||
if (!sScriptMgr->CanAddGroupToMatchingPool(this, (*Horde_itr), m_SelectionPools[TEAM_HORDE].GetPlayerCount(), bg, bracket_id))
|
||||
{
|
||||
++Horde_itr;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!m_SelectionPools[TEAM_HORDE].AddGroup((*Horde_itr), hordeFree))
|
||||
break;
|
||||
|
||||
++Horde_itr;
|
||||
}
|
||||
|
||||
//if ofc like BG queue invitation is set in config, then we are happy
|
||||
if (sWorld->getIntConfig(CONFIG_BATTLEGROUND_INVITATION_TYPE) == BG_QUEUE_INVITATION_TYPE_NO_BALANCE)
|
||||
@ -468,8 +492,19 @@ void BattlegroundQueue::FillPlayersToBG(Battleground* bg, BattlegroundBracketId
|
||||
//kick alliance group, add to pool new group if needed
|
||||
if (m_SelectionPools[TEAM_ALLIANCE].KickGroup(diffHorde - diffAli))
|
||||
{
|
||||
for (; aliIndex < aliCount && m_SelectionPools[TEAM_ALLIANCE].AddGroup((*Ali_itr), (aliFree >= diffHorde) ? aliFree - diffHorde : 0); aliIndex++)
|
||||
for (; aliIndex < aliCount; aliIndex++)
|
||||
{
|
||||
if (!sScriptMgr->CanAddGroupToMatchingPool(this, (*Ali_itr), m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount(), bg, bracket_id))
|
||||
{
|
||||
++Ali_itr;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!m_SelectionPools[TEAM_ALLIANCE].AddGroup((*Ali_itr), (aliFree >= diffHorde) ? aliFree - diffHorde : 0))
|
||||
break;
|
||||
|
||||
++Ali_itr;
|
||||
}
|
||||
}
|
||||
|
||||
//if ali selection is already empty, then kick horde group, but if there are less horde than ali in bg - break;
|
||||
@ -486,8 +521,19 @@ void BattlegroundQueue::FillPlayersToBG(Battleground* bg, BattlegroundBracketId
|
||||
//kick horde group, add to pool new group if needed
|
||||
if (m_SelectionPools[TEAM_HORDE].KickGroup(diffAli - diffHorde))
|
||||
{
|
||||
for (; hordeIndex < hordeCount && m_SelectionPools[TEAM_HORDE].AddGroup((*Horde_itr), (hordeFree >= diffAli) ? hordeFree - diffAli : 0); hordeIndex++)
|
||||
for (; hordeIndex < hordeCount; hordeIndex++)
|
||||
{
|
||||
if (!sScriptMgr->CanAddGroupToMatchingPool(this, (*Horde_itr), m_SelectionPools[TEAM_HORDE].GetPlayerCount(), bg, bracket_id))
|
||||
{
|
||||
++Horde_itr;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!m_SelectionPools[TEAM_HORDE].AddGroup((*Horde_itr), (hordeFree >= diffAli) ? hordeFree - diffAli : 0))
|
||||
break;
|
||||
|
||||
++Horde_itr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_SelectionPools[TEAM_HORDE].GetPlayerCount())
|
||||
@ -596,9 +642,13 @@ bool BattlegroundQueue::CheckNormalMatch(Battleground* bgTemplate, BattlegroundB
|
||||
{
|
||||
if (!(*(itr_team[i]))->IsInvitedToBGInstanceGUID)
|
||||
{
|
||||
m_SelectionPools[i].AddGroup(*(itr_team[i]), maxPlayers);
|
||||
if (m_SelectionPools[i].GetPlayerCount() >= minPlayers)
|
||||
break;
|
||||
// Allow modules to filter groups based on custom criteria (e.g., MMR)
|
||||
if (sScriptMgr->CanAddGroupToMatchingPool(this, *(itr_team[i]), m_SelectionPools[i].GetPlayerCount(), bgTemplate, bracket_id))
|
||||
{
|
||||
m_SelectionPools[i].AddGroup(*(itr_team[i]), maxPlayers);
|
||||
if (m_SelectionPools[i].GetPlayerCount() >= minPlayers)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -616,8 +666,14 @@ bool BattlegroundQueue::CheckNormalMatch(Battleground* bgTemplate, BattlegroundB
|
||||
for (; itr_team[j] != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + j].end(); ++(itr_team[j]))
|
||||
{
|
||||
if (!(*(itr_team[j]))->IsInvitedToBGInstanceGUID)
|
||||
{
|
||||
// Allow modules to filter groups based on custom criteria (e.g., MMR)
|
||||
if (!sScriptMgr->CanAddGroupToMatchingPool(this, *(itr_team[j]), m_SelectionPools[j].GetPlayerCount(), bgTemplate, bracket_id))
|
||||
continue;
|
||||
|
||||
if (!m_SelectionPools[j].AddGroup(*(itr_team[j]), m_SelectionPools[(j + 1) % PVP_TEAMS_COUNT].GetPlayerCount()))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// do not allow to start bg with more than 2 players more on 1 faction
|
||||
|
||||
@ -104,6 +104,16 @@ void ScriptMgr::OnBattlegroundCreate(Battleground* bg)
|
||||
CALL_ENABLED_HOOKS(AllBattlegroundScript, ALLBATTLEGROUNDHOOK_ON_BATTLEGROUND_CREATE, script->OnBattlegroundCreate(bg));
|
||||
}
|
||||
|
||||
bool ScriptMgr::CanAddGroupToMatchingPool(BattlegroundQueue* queue, GroupQueueInfo* group, uint32 poolPlayerCount, Battleground* bg, BattlegroundBracketId bracketId)
|
||||
{
|
||||
CALL_ENABLED_BOOLEAN_HOOKS(AllBattlegroundScript, ALLBATTLEGROUNDHOOK_CAN_ADD_GROUP_TO_MATCHING_POOL, !script->CanAddGroupToMatchingPool(queue, group, poolPlayerCount, bg, bracketId));
|
||||
}
|
||||
|
||||
bool ScriptMgr::GetPlayerMatchmakingRating(ObjectGuid playerGuid, BattlegroundTypeId bgTypeId, float& outRating)
|
||||
{
|
||||
CALL_ENABLED_BOOLEAN_HOOKS_WITH_DEFAULT_FALSE(AllBattlegroundScript, ALLBATTLEGROUNDHOOK_GET_PLAYER_MATCHMAKING_RATING, script->GetPlayerMatchmakingRating(playerGuid, bgTypeId, outRating));
|
||||
}
|
||||
|
||||
AllBattlegroundScript::AllBattlegroundScript(char const* name, std::vector<uint16> enabledHooks) :
|
||||
ScriptObject(name, ALLBATTLEGROUNDHOOK_END)
|
||||
{
|
||||
|
||||
@ -40,6 +40,8 @@ enum AllBattlegroundHook
|
||||
ALLBATTLEGROUNDHOOK_ON_BATTLEGROUND_END,
|
||||
ALLBATTLEGROUNDHOOK_ON_BATTLEGROUND_DESTROY,
|
||||
ALLBATTLEGROUNDHOOK_ON_BATTLEGROUND_CREATE,
|
||||
ALLBATTLEGROUNDHOOK_CAN_ADD_GROUP_TO_MATCHING_POOL,
|
||||
ALLBATTLEGROUNDHOOK_GET_PLAYER_MATCHMAKING_RATING,
|
||||
ALLBATTLEGROUNDHOOK_END
|
||||
};
|
||||
|
||||
@ -47,6 +49,9 @@ enum BattlegroundBracketId : uint8;
|
||||
enum BattlegroundTypeId : uint8;
|
||||
enum TeamId : uint8;
|
||||
|
||||
class BattlegroundQueue;
|
||||
struct GroupQueueInfo;
|
||||
|
||||
class AllBattlegroundScript : public ScriptObject
|
||||
{
|
||||
protected:
|
||||
@ -132,6 +137,34 @@ public:
|
||||
* @param bg Contains information about the Battleground
|
||||
*/
|
||||
virtual void OnBattlegroundCreate(Battleground* /*bg*/) { }
|
||||
|
||||
/**
|
||||
* @brief This hook runs before adding a group to the battleground matching pool
|
||||
*
|
||||
* Allows modules to filter groups based on custom criteria (e.g., MMR matching).
|
||||
* Called during FillPlayersToBG before each group is added to the SelectionPool.
|
||||
*
|
||||
* @param queue The battleground queue
|
||||
* @param group The group being considered for addition
|
||||
* @param poolPlayerCount Current number of players already in the selection pool
|
||||
* @param bg The battleground instance
|
||||
* @param bracketId The bracket ID
|
||||
* @return True to allow adding this group, false to skip it
|
||||
*/
|
||||
[[nodiscard]] virtual bool CanAddGroupToMatchingPool(BattlegroundQueue* /*queue*/, GroupQueueInfo* /*group*/, uint32 /*poolPlayerCount*/, Battleground* /*bg*/, BattlegroundBracketId /*bracketId*/) { return true; }
|
||||
|
||||
/**
|
||||
* @brief This hook allows modules to provide matchmaking rating for a player
|
||||
*
|
||||
* Modules implementing MMR systems can use this hook to provide player ratings
|
||||
* for use in matchmaking algorithms.
|
||||
*
|
||||
* @param playerGuid The player's GUID
|
||||
* @param bgTypeId The battleground type
|
||||
* @param outRating Reference to store the rating value
|
||||
* @return True if rating was provided, false otherwise
|
||||
*/
|
||||
[[nodiscard]] virtual bool GetPlayerMatchmakingRating(ObjectGuid /*playerGuid*/, BattlegroundTypeId /*bgTypeId*/, float& /*outRating*/) { return false; }
|
||||
};
|
||||
|
||||
// Compatibility for old scripts
|
||||
|
||||
@ -601,6 +601,8 @@ public: /* BGScript */
|
||||
void OnBattlegroundEnd(Battleground* bg, TeamId winnerTeamId);
|
||||
void OnBattlegroundDestroy(Battleground* bg);
|
||||
void OnBattlegroundCreate(Battleground* bg);
|
||||
bool CanAddGroupToMatchingPool(BattlegroundQueue* queue, GroupQueueInfo* group, uint32 poolPlayerCount, Battleground* bg, BattlegroundBracketId bracketId);
|
||||
bool GetPlayerMatchmakingRating(ObjectGuid playerGuid, BattlegroundTypeId bgTypeId, float& outRating);
|
||||
|
||||
public: /* Arena Team Script */
|
||||
void OnGetSlotByType(const uint32 type, uint8& slot);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user