Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CountAsLoss + fix CheckStartSolo3v3Arena #19

Merged
merged 6 commits into from
Sep 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions conf/arena_3v3_solo_queue.conf.dist
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ Solo.3v3.FilterTalents = 0
Arena.CheckEquipAndTalents = 0
Arena.3v3.BlockForbiddenTalents = 0
Solo.3v3.CastDeserterOnAfk = 1
Solo.3v3.CastDeserterOnLeave = 0
Solo.3v3.StopGameIncomplete = 0
Solo.3v3.CastDeserterOnLeave = 1
Solo.3v3.StopGameIncomplete = 1
Solo.3v3.RatingPenalty.LeaveDuringMatch = 24
Solo.3v3.RatingPenalty.LeaveBeforeMatchStart = 50


Solo.3v3.MinLevel = 80
Solo.3v3.Cost = 45
Solo.3v3.ArenaPointsMulti = 0.8
Expand Down
107 changes: 73 additions & 34 deletions src/solo3v3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,64 @@ uint32 Solo3v3::GetAverageMMR(ArenaTeam* team)
return matchMakerRating;
}

void Solo3v3::CountAsLoss(Player* player, bool isInProgress)
{
ArenaTeam* plrArenaTeam = sArenaTeamMgr->GetArenaTeamById(player->GetArenaTeamId(ARENA_SLOT_SOLO_3v3));

if (!plrArenaTeam)
return;

int32 ratingLoss = 0;

// leave while arena is in progress
if (isInProgress)
{
ratingLoss = sConfigMgr->GetOption<int32>("Solo.3v3.RatingPenalty.LeaveDuringMatch", 24);
}
// leave while arena is in preparation || don't accept queue || logout while invited
else
{
ratingLoss = sConfigMgr->GetOption<int32>("Solo.3v3.RatingPenalty.LeaveBeforeMatchStart", 50);
}

ArenaTeamStats atStats = plrArenaTeam->GetStats();

if (int32(atStats.Rating) - ratingLoss < 0)
atStats.Rating = 0;
else
atStats.Rating -= ratingLoss;

atStats.SeasonGames += 1;
atStats.WeekGames += 1;
atStats.Rank = 1;

// Update team's rank, start with rank 1 and increase until no team with more rating was found
ArenaTeamMgr::ArenaTeamContainer::const_iterator i = sArenaTeamMgr->GetArenaTeamMapBegin();
for (; i != sArenaTeamMgr->GetArenaTeamMapEnd(); ++i) {
if (i->second->GetType() == ARENA_TEAM_SOLO_3v3 && i->second->GetStats().Rating > atStats.Rating)
++atStats.Rank;
}

for (ArenaTeam::MemberList::iterator itr = plrArenaTeam->GetMembers().begin(); itr != plrArenaTeam->GetMembers().end(); ++itr) {
if (itr->Guid == player->GetGUID()) {
itr->WeekGames = atStats.WeekGames;
itr->SeasonGames = atStats.SeasonGames;
itr->PersonalRating = atStats.Rating;

if (int32(itr->MatchMakerRating) - ratingLoss < 0)
itr->MatchMakerRating = 0;
else
itr->MatchMakerRating -= ratingLoss;

break;
}
}

plrArenaTeam->SetArenaTeamStats(atStats);
plrArenaTeam->NotifyStatsChanged();
plrArenaTeam->SaveToDB(true);
}

void Solo3v3::CleanUp3v3SoloQ(Battleground* bg)
{
// Cleanup temp arena teams for solo 3v3
Expand All @@ -65,50 +123,31 @@ void Solo3v3::CleanUp3v3SoloQ(Battleground* bg)

void Solo3v3::CheckStartSolo3v3Arena(Battleground* bg)
{
// Fix crash with Arena Replay module
bool someoneNotInArena = false;
uint32 PlayersInArena = 0;

for (const auto& playerPair : bg->GetPlayers())
{
Player* player = playerPair.second;
if (player->IsSpectator())
return;
}

if (bg->GetArenaType() != ARENA_TYPE_3v3_SOLO)
return;

if (bg->GetStatus() != STATUS_IN_PROGRESS)
return; // if CheckArenaWinConditions ends the game

bool someoneNotInArena = false;
if (!player)
continue;

ArenaTeam* team[2];
team[0] = sArenaTeamMgr->GetArenaTeamById(bg->GetArenaTeamIdForTeam(TEAM_ALLIANCE));
team[1] = sArenaTeamMgr->GetArenaTeamById(bg->GetArenaTeamIdForTeam(TEAM_HORDE));
// Fix crash with Arena Replay module
if (player->IsSpectator())
return;

ASSERT(team[0] && team[1]);
PlayersInArena++;
}

for (int i = 0; i < 2; i++)
uint32 AmountPlayersSolo3v3 = 6;
if (PlayersInArena < AmountPlayersSolo3v3)
{
for (auto const& itr : team[i]->GetMembers())
{
Player* plr = ObjectAccessor::FindPlayer(itr.Guid);
if (!plr)
{
someoneNotInArena = true;
continue;
}

if (plr->GetInstanceId() != bg->GetInstanceID())
{
if (sConfigMgr->GetOption<bool>("Solo.3v3.CastDeserterOnAfk", true))
plr->CastSpell(plr, 26013, true); // Deserter

someoneNotInArena = true;
}
}
someoneNotInArena = true;
}

if (someoneNotInArena && sConfigMgr->GetOption<bool>("Solo.3v3.StopGameIncomplete", false))
// if one player didn't enter arena and StopGameIncomplete is true, then end arena
if (someoneNotInArena && sConfigMgr->GetOption<bool>("Solo.3v3.StopGameIncomplete", true))
{
bg->SetRated(false);
bg->EndBattleground(TEAM_NEUTRAL);
Expand Down
1 change: 1 addition & 0 deletions src/solo3v3.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class Solo3v3
void CleanUp3v3SoloQ(Battleground* bg);
bool CheckSolo3v3Arena(BattlegroundQueue* queue, BattlegroundBracketId bracket_id, bool isRated);
void CreateTempArenaTeamForQueue(BattlegroundQueue* queue, ArenaTeam* arenaTeams[]);
void CountAsLoss(Player* player, bool isInProgress);

// Return false, if player have invested more than 35 talentpoints in a forbidden talenttree.
bool Arena3v3CheckTalents(Player* player);
Expand Down
121 changes: 105 additions & 16 deletions src/solo3v3_sc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ bool NpcSolo3v3::OnGossipSelect(Player* player, Creature* creature, uint32 /*sen
}
else
{
ChatHandler(player->GetSession()).PSendSysMessage("You need level %u+ to create an arena team.", sConfigMgr->GetOption<uint32>("Solo.3v3.MinLevel", 80));
ChatHandler(player->GetSession()).PSendSysMessage("You need level {}+ to create an arena team.", sConfigMgr->GetOption<uint32>("Solo.3v3.MinLevel", 80));
}

CloseGossipMenuFor(player);
Expand Down Expand Up @@ -180,6 +180,19 @@ bool NpcSolo3v3::OnGossipSelect(Player* player, Creature* creature, uint32 /*sen

ChatHandler(player->GetSession()).PSendSysMessage("{}", s.str().c_str());
CloseGossipMenuFor(player);

ArenaTeam::MemberList::iterator itr;
for (itr = at->GetMembers().begin(); itr != at->GetMembers().end(); ++itr)
{
if (itr->Guid == player->GetGUID())
{
std::stringstream s;
s << "\nSolo MMR: " << itr->MatchMakerRating;

ChatHandler(player->GetSession()).PSendSysMessage("{}", s.str().c_str());
break;
}
}
}

return true;
Expand Down Expand Up @@ -514,14 +527,6 @@ bool Solo3v3BG::OnQueueUpdateValidity(BattlegroundQueue* /* queue */, uint32 /*d
return true;
}

void Solo3v3BG::OnBattlegroundUpdate(Battleground* bg, uint32 /*diff*/)
{
if (bg->GetStatus() != STATUS_IN_PROGRESS || !bg->isArena())
return;

sSolo->CheckStartSolo3v3Arena(bg);
}

void Solo3v3BG::OnBattlegroundDestroy(Battleground* bg)
{
sSolo->CleanUp3v3SoloQ(bg);
Expand All @@ -531,7 +536,8 @@ void Solo3v3BG::OnBattlegroundEndReward(Battleground* bg, Player* player, TeamId
{
if (bg->isRated() && bg->GetArenaType() == ARENA_TYPE_3v3_SOLO)
{
ArenaTeam* plrArenaTeam = sArenaTeamMgr->GetArenaTeamByCaptain(player->GetGUID(), ARENA_TYPE_3v3_SOLO);
// this way we always get the correct solo team (sometimes when using GetArenaTeamByCaptain inside solo arena it can return a teamID >= 4293918720)
ArenaTeam* plrArenaTeam = sArenaTeamMgr->GetArenaTeamById(player->GetArenaTeamId(ARENA_SLOT_SOLO_3v3));

if (!plrArenaTeam)
return;
Expand Down Expand Up @@ -567,13 +573,10 @@ void Solo3v3BG::OnBattlegroundEndReward(Battleground* bg, Player* player, TeamId
atStats.Rank = 1;
ArenaTeamMgr::ArenaTeamContainer::const_iterator i = sArenaTeamMgr->GetArenaTeamMapBegin();
for (; i != sArenaTeamMgr->GetArenaTeamMapEnd(); ++i) {
if (i->second->GetType() == ARENA_TYPE_3v3_SOLO && i->second->GetStats().Rating > atStats.Rating)
if (i->second->GetType() == ARENA_TEAM_SOLO_3v3 && i->second->GetStats().Rating > atStats.Rating)
++atStats.Rank;
}

plrArenaTeam->SetArenaTeamStats(atStats);
plrArenaTeam->NotifyStatsChanged();

for (ArenaTeam::MemberList::iterator itr = plrArenaTeam->GetMembers().begin(); itr != plrArenaTeam->GetMembers().end(); ++itr)
{
if (itr->Guid == player->GetGUID())
Expand Down Expand Up @@ -602,6 +605,8 @@ void Solo3v3BG::OnBattlegroundEndReward(Battleground* bg, Player* player, TeamId

}

plrArenaTeam->SetArenaTeamStats(atStats);
plrArenaTeam->NotifyStatsChanged();
plrArenaTeam->SaveToDB(true);
}
}
Expand Down Expand Up @@ -648,9 +653,94 @@ void Team3v3arena::OnQueueIdToArenaType(const BattlegroundQueueTypeId _bgQueueTy
}
}

void Arena_SC::OnArenaStart(Battleground* bg)
{
if (bg->GetArenaType() != ARENA_TYPE_3v3_SOLO)
return;

sSolo->CheckStartSolo3v3Arena(bg);
}

void PlayerScript3v3Arena::OnBattlegroundDesertion(Player* player, const BattlegroundDesertionType type)
{
Battleground* bg = ((BattlegroundMap*)player->FindMap())->GetBG();

switch (type)
{
case ARENA_DESERTION_TYPE_LEAVE_BG:

if (bg->GetArenaType() == ARENA_TYPE_3v3_SOLO)
{
if (bg->GetStatus() == STATUS_WAIT_JOIN)
{
if (sConfigMgr->GetOption<bool>("Solo.3v3.CastDeserterOnAfk", true) || sConfigMgr->GetOption<bool>("Solo.3v3.CastDeserterOnLeave", true))
player->CastSpell(player, 26013, true);

// end arena if a player leaves while in preparation
if (sConfigMgr->GetOption<bool>("Solo.3v3.StopGameIncomplete", true))
{
bg->SetRated(false);
bg->EndBattleground(TEAM_NEUTRAL);
}

sSolo->CountAsLoss(player, false);
}

if (bg->GetStatus() == STATUS_IN_PROGRESS)
sSolo->CountAsLoss(player, true);
}
break;

case ARENA_DESERTION_TYPE_NO_ENTER_BUTTON: // called if player doesn't click 'enter arena' for solo 3v3

if (player->IsInvitedForBattlegroundQueueType((BattlegroundQueueTypeId)BATTLEGROUND_QUEUE_3v3_SOLO))
{
if (sConfigMgr->GetOption<bool>("Solo.3v3.CastDeserterOnAfk", true))
player->CastSpell(player, 26013, true);

sSolo->CountAsLoss(player, false);
}
break;

case ARENA_DESERTION_TYPE_INVITE_LOGOUT: // called if player logout when solo 3v3 queue pops (it removes the queue)

if (player->IsInvitedForBattlegroundQueueType((BattlegroundQueueTypeId)BATTLEGROUND_QUEUE_3v3_SOLO))
{
if (sConfigMgr->GetOption<bool>("Solo.3v3.CastDeserterOnAfk", true) || sConfigMgr->GetOption<bool>("Solo.3v3.CastDeserterOnLeave", true))
player->CastSpell(player, 26013, true);

sSolo->CountAsLoss(player, false);
}
break;

/*
case ARENA_DESERTION_TYPE_LEAVE_QUEUE: // called if player uses macro to leave queue when it pops. /run AcceptBattlefieldPort(1, 0);

// I believe these are being called AFTER the player removes the queue, so we can't know his queue
if (player->IsInvitedForBattlegroundQueueType((BattlegroundQueueTypeId)BATTLEGROUND_QUEUE_3v3_SOLO))
{
LOG_ERROR("solo3v3", "IsInvitedForBattlegroundQueueType BATTLEGROUND_QUEUE_3v3_SOLO");
sSolo->CountAsLoss(player, false);

}
else if (player->InBattlegroundQueueForBattlegroundQueueType((BattlegroundQueueTypeId)BATTLEGROUND_QUEUE_3v3_SOLO))
{
LOG_ERROR("solo3v3", "InBattlegroundQueueForBattlegroundQueueType BATTLEGROUND_QUEUE_3v3_SOLO");
}
else
{
LOG_ERROR("solo3v3", "ARENA_DESERTION_TYPE_LEAVE_QUEUE - else");
}
*/

default:
break;
}
}

void PlayerScript3v3Arena::OnLogin(Player* pPlayer)
{
if (sConfigMgr->GetOption<bool>("Solo.3v3.Enable", false)) {
if (sConfigMgr->GetOption<bool>("Solo.3v3.ShowMessageOnLogin", false)) {
ChatHandler(pPlayer->GetSession()).SendSysMessage("This server is running the |cff4CFF00Arena solo Q 3v3 |rmodule.");
}
}
Expand Down Expand Up @@ -704,7 +794,6 @@ bool PlayerScript3v3Arena::NotSetArenaTeamInfoField(Player* player, uint8 slot,
return true;
}


bool PlayerScript3v3Arena::CanBattleFieldPort(Player* player, uint8 arenaType, BattlegroundTypeId BGTypeID, uint8 /*action*/)
{
if (!player)
Expand Down
4 changes: 3 additions & 1 deletion src/solo3v3_sc.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ class Solo3v3BG : public AllBattlegroundScript
uint32 oldTeamRatingHorde;

void OnQueueUpdate(BattlegroundQueue* queue, uint32 /*diff*/, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id, uint8 arenaType, bool isRated, uint32 /*arenaRatedTeamId*/) override;
void OnBattlegroundUpdate(Battleground* bg, uint32 /*diff*/) override;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why did you delete this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have the hook OnArenaStart now, so we can use it to call CheckStartSolo3v3.

But we could use OnBGUpdate and check if there's a player that didn't accept the queue and then end the solo earlier, while not in progress, instead of waiting the arena to start

bool OnQueueUpdateValidity(BattlegroundQueue* /* queue */, uint32 /*diff*/, BattlegroundTypeId /* bgTypeId */, BattlegroundBracketId /* bracket_id */, uint8 arenaType, bool /* isRated */, uint32 /*arenaRatedTeamId*/) override;
void OnBattlegroundDestroy(Battleground* bg) override;
void OnBattlegroundEndReward(Battleground* bg, Player* player, TeamId /* winnerTeamId */) override;
Expand Down Expand Up @@ -103,6 +102,7 @@ class PlayerScript3v3Arena : public PlayerScript
void OnGetArenaTeamId(Player* player, uint8 slot, uint32& result) override;
bool NotSetArenaTeamInfoField(Player* player, uint8 slot, ArenaTeamInfoType type, uint32 value) override;
bool CanBattleFieldPort(Player* player, uint8 arenaType, BattlegroundTypeId BGTypeID, uint8 action) override;
void OnBattlegroundDesertion(Player* player, const BattlegroundDesertionType type) override;
};

class Arena_SC : public ArenaScript
Expand Down Expand Up @@ -140,6 +140,8 @@ class Arena_SC : public ArenaScript

return true;
}

void OnArenaStart(Battleground* bg) override;
};

class Solo3v3Spell : public SpellSC
Expand Down