From ab761c986589a7c07ab6a897b0fe4a2672f30d86 Mon Sep 17 00:00:00 2001 From: IntelligentQuantum Date: Sun, 28 Nov 2021 23:12:53 +0330 Subject: [PATCH] fix(Core/Player): prevent crash exploit spam duel starting (#9226) --- src/server/game/Entities/Player/Player.cpp | 132 +++++++++++------- src/server/game/Entities/Player/Player.h | 24 ++-- .../game/Entities/Player/PlayerMisc.cpp | 18 ++- src/server/game/Entities/Unit/Unit.cpp | 24 ++-- src/server/game/Handlers/DuelHandler.cpp | 36 ++--- src/server/game/Spells/Spell.cpp | 2 +- src/server/game/Spells/SpellEffects.cpp | 18 +-- .../scripts/World/achievement_scripts.cpp | 2 +- 8 files changed, 144 insertions(+), 112 deletions(-) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 36d7faeb1..3deeb2018 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -211,8 +211,6 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this) m_auraRaidUpdateMask = 0; m_bPassOnGroupLoot = false; - duel = nullptr; - m_GuildIdInvited = 0; m_ArenaTeamIdInvited = 0; @@ -6154,18 +6152,20 @@ uint32 Player::GetZoneIdFromDB(ObjectGuid guid) void Player::CheckDuelDistance(time_t currTime) { if (!duel) + { return; + } ObjectGuid duelFlagGUID = GetGuidValue(PLAYER_DUEL_ARBITER); GameObject* obj = GetMap()->GetGameObject(duelFlagGUID); if (!obj) return; - if (duel->outOfBound == 0) + if (!duel->OutOfBoundsTime) { if (!IsWithinDistInMap(obj, 50)) { - duel->outOfBound = currTime; + duel->OutOfBoundsTime = currTime + 10; WorldPacket data(SMSG_DUEL_OUTOFBOUNDS, 0); GetSession()->SendPacket(&data); @@ -6175,12 +6175,12 @@ void Player::CheckDuelDistance(time_t currTime) { if (IsWithinDistInMap(obj, 40)) { - duel->outOfBound = 0; + duel->OutOfBoundsTime = 0; WorldPacket data(SMSG_DUEL_INBOUNDS, 0); GetSession()->SendPacket(&data); } - else if (currTime >= (duel->outOfBound + 10)) + else if (currTime >= duel->OutOfBoundsTime) DuelComplete(DUEL_FLED); } } @@ -6193,57 +6193,76 @@ bool Player::IsOutdoorPvPActive() void Player::DuelComplete(DuelCompleteType type) { // duel not requested - if (!duel || !duel->opponent || !duel->initiator) + if (!duel) return; - LOG_DEBUG("entities.unit", "Duel Complete %s %s", GetName().c_str(), duel->opponent->GetName().c_str()); + // Check if DuelComplete() has been called already up in the stack and in that case don't do anything else here + if (duel->State == DUEL_STATE_COMPLETED) + return; + + Player* opponent = duel->Opponent; + duel->State = DUEL_STATE_COMPLETED; + opponent->duel->State = DUEL_STATE_COMPLETED; + + LOG_DEBUG("entities.unit", "Player::DuelComplete: Player '%s' (%s), Opponent: '%s' (%s)", + GetName().c_str(), GetGUID().ToString().c_str(), opponent->GetName().c_str(), opponent->GetGUID().ToString().c_str()); WorldPacket data(SMSG_DUEL_COMPLETE, (1)); - data << (uint8)((type != DUEL_INTERRUPTED) ? 1 : 0); - GetSession()->SendPacket(&data); - - duel->opponent->GetSession()->SendPacket(&data); + data << uint8((type != DUEL_INTERRUPTED) ? 1 : 0); + SendDirectMessage(&data); + if (opponent->GetSession()) + { + opponent->SendDirectMessage(&data); + } if (type != DUEL_INTERRUPTED) { - data.Initialize(SMSG_DUEL_WINNER, (1 + 20)); // we guess size + data.Initialize(SMSG_DUEL_WINNER, (1+20)); // we guess size data << uint8(type == DUEL_WON ? 0 : 1); // 0 = just won; 1 = fled - data << duel->opponent->GetName(); + data << opponent->GetName(); data << GetName(); SendMessageToSet(&data, true); } - sScriptMgr->OnPlayerDuelEnd(duel->opponent, this, type); + sScriptMgr->OnPlayerDuelEnd(opponent, this, type); switch (type) { case DUEL_FLED: // if initiator and opponent are on the same team // or initiator and opponent are not PvP enabled, forcibly stop attacking - if (duel->initiator->GetTeamId() == duel->opponent->GetTeamId()) + if (GetTeamId() == opponent->GetTeamId()) { - duel->initiator->AttackStop(); - duel->opponent->AttackStop(); + AttackStop(); + opponent->AttackStop(); } else { - if (!duel->initiator->IsPvP()) - duel->initiator->AttackStop(); - if (!duel->opponent->IsPvP()) - duel->opponent->AttackStop(); + if (!IsPvP()) + { + AttackStop(); + } + if (!opponent->IsPvP()) + { + opponent->AttackStop(); + } } break; case DUEL_WON: UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL, 1); - duel->opponent->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL, 1); + opponent->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL, 1); // Credit for quest Death's Challenge - if (getClass() == CLASS_DEATH_KNIGHT && duel->opponent->GetQuestStatus(12733) == QUEST_STATUS_INCOMPLETE) - duel->opponent->CastSpell(duel->opponent, 52994, true); + if (getClass() == CLASS_DEATH_KNIGHT && opponent->GetQuestStatus(12733) == QUEST_STATUS_INCOMPLETE) + { + opponent->CastSpell(opponent, 52994, true); + } // Honor points after duel (the winner) - ImpConfig if (uint32 amount = sWorld->getIntConfig(CONFIG_HONOR_AFTER_DUEL)) - duel->opponent->RewardHonor(nullptr, 1, amount); + { + opponent->RewardHonor(nullptr, 1, amount); + } break; default: @@ -6251,56 +6270,66 @@ void Player::DuelComplete(DuelCompleteType type) } // Victory emote spell - if (type != DUEL_INTERRUPTED && duel->opponent) - duel->opponent->CastSpell(duel->opponent, 52852, true); + if (type != DUEL_INTERRUPTED) + { + opponent->CastSpell(opponent, 52852, true); + } //Remove Duel Flag object GameObject* obj = GetMap()->GetGameObject(GetGuidValue(PLAYER_DUEL_ARBITER)); if (obj) - duel->initiator->RemoveGameObject(obj, true); + { + duel->Initiator->RemoveGameObject(obj, true); + } /* remove auras */ - AuraApplicationMap& itsAuras = duel->opponent->GetAppliedAuras(); + AuraApplicationMap &itsAuras = opponent->GetAppliedAuras(); for (AuraApplicationMap::iterator i = itsAuras.begin(); i != itsAuras.end();) { Aura const* aura = i->second->GetBase(); - if (!i->second->IsPositive() && aura->GetCasterGUID() == GetGUID() && aura->GetApplyTime() >= duel->startTime) - duel->opponent->RemoveAura(i); + if (!i->second->IsPositive() && aura->GetCasterGUID() == GetGUID() && aura->GetApplyTime() >= duel->StartTime) + { + opponent->RemoveAura(i); + } else + { ++i; + } } - AuraApplicationMap& myAuras = GetAppliedAuras(); + AuraApplicationMap &myAuras = GetAppliedAuras(); for (AuraApplicationMap::iterator i = myAuras.begin(); i != myAuras.end();) { Aura const* aura = i->second->GetBase(); - if (!i->second->IsPositive() && aura->GetCasterGUID() == duel->opponent->GetGUID() && aura->GetApplyTime() >= duel->startTime) + if (!i->second->IsPositive() && aura->GetCasterGUID() == opponent->GetGUID() && aura->GetApplyTime() >= duel->StartTime) RemoveAura(i); else ++i; } // cleanup combo points - if (GetComboTarget() == duel->opponent->GetGUID()) + if (GetComboTarget() == duel->Opponent->GetGUID()) ClearComboPoints(); - else if (GetComboTarget() == duel->opponent->GetPetGUID()) + else if (GetComboTarget() == duel->Opponent->GetPetGUID()) ClearComboPoints(); - if (duel->opponent->GetComboTarget() == GetGUID()) - duel->opponent->ClearComboPoints(); - else if (duel->opponent->GetComboTarget() == GetPetGUID()) - duel->opponent->ClearComboPoints(); + if (duel->Opponent->GetComboTarget() == GetGUID()) + { + duel->Opponent->ClearComboPoints(); + } + else if (duel->Opponent->GetComboTarget() == GetPetGUID()) + { + duel->Opponent->ClearComboPoints(); + } //cleanups SetGuidValue(PLAYER_DUEL_ARBITER, ObjectGuid::Empty); SetUInt32Value(PLAYER_DUEL_TEAM, 0); - duel->opponent->SetGuidValue(PLAYER_DUEL_ARBITER, ObjectGuid::Empty); - duel->opponent->SetUInt32Value(PLAYER_DUEL_TEAM, 0); + opponent->SetGuidValue(PLAYER_DUEL_ARBITER, ObjectGuid::Empty); + opponent->SetUInt32Value(PLAYER_DUEL_TEAM, 0); - delete duel->opponent->duel; - duel->opponent->duel = nullptr; - delete duel; - duel = nullptr; + opponent->duel.reset(nullptr); + duel.reset(nullptr); } //---------------------------------------------------------// @@ -10668,9 +10697,18 @@ bool Player::IsAlwaysDetectableFor(WorldObject const* seer) const if (Unit::IsAlwaysDetectableFor(seer)) return true; + if (duel && duel->State != DUEL_STATE_CHALLENGED && duel->Opponent == seer) + { + return false; + } + if (const Player* seerPlayer = seer->ToPlayer()) + { if (IsGroupVisibleFor(seerPlayer)) - return !(seerPlayer->duel && seerPlayer->duel->startTime != 0 && seerPlayer->duel->opponent == this); + { + return true; + } + } return false; } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index cb44a1284..60254d8a6 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -357,16 +357,24 @@ struct PvPInfo time_t FFAPvPEndTimer{0}; ///> Time when player unflags himself for FFA PvP (flag removed after 30 sec) }; +enum DuelState +{ + DUEL_STATE_CHALLENGED, + DUEL_STATE_COUNTDOWN, + DUEL_STATE_IN_PROGRESS, + DUEL_STATE_COMPLETED +}; + struct DuelInfo { - DuelInfo() {} + DuelInfo(Player* opponent, Player* initiator, bool isMounted) : Opponent(opponent), Initiator(initiator), IsMounted(isMounted) {} - Player* initiator{nullptr}; - Player* opponent{nullptr}; - time_t startTimer{0}; - time_t startTime{0}; - time_t outOfBound{0}; - bool isMounted{false}; + Player* const Opponent; + Player* const Initiator; + bool const IsMounted; + DuelState State = DUEL_STATE_CHALLENGED; + time_t StartTime = 0; + time_t OutOfBoundsTime = 0; }; struct Areas @@ -1814,7 +1822,7 @@ public: } /** todo: -maybe move UpdateDuelFlag+DuelComplete to independent DuelHandler.. **/ - DuelInfo* duel; + std::unique_ptr duel; void UpdateDuelFlag(time_t currTime); void CheckDuelDistance(time_t currTime); void DuelComplete(DuelCompleteType type); diff --git a/src/server/game/Entities/Player/PlayerMisc.cpp b/src/server/game/Entities/Player/PlayerMisc.cpp index 2b153b2c7..85c3ede30 100644 --- a/src/server/game/Entities/Player/PlayerMisc.cpp +++ b/src/server/game/Entities/Player/PlayerMisc.cpp @@ -403,18 +403,16 @@ void Player::UpdateFFAPvPFlag(time_t currTime) void Player::UpdateDuelFlag(time_t currTime) { - if (!duel || duel->startTimer == 0 || currTime < duel->startTimer + 3) - return; + if (duel && duel->State == DUEL_STATE_COUNTDOWN && duel->StartTime <= currTime) + { + sScriptMgr->OnPlayerDuelStart(this, duel->Opponent); - sScriptMgr->OnPlayerDuelStart(this, duel->opponent); + SetUInt32Value(PLAYER_DUEL_TEAM, 1); + duel->Opponent->SetUInt32Value(PLAYER_DUEL_TEAM, 2); - SetUInt32Value(PLAYER_DUEL_TEAM, 1); - duel->opponent->SetUInt32Value(PLAYER_DUEL_TEAM, 2); - - duel->startTimer = 0; - duel->startTime = currTime; - duel->opponent->duel->startTimer = 0; - duel->opponent->duel->startTime = currTime; + duel->State = DUEL_STATE_IN_PROGRESS; + duel->Opponent->duel->State = DUEL_STATE_IN_PROGRESS; + } } /*********************************************************/ diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 66cd45196..70434d0aa 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -921,7 +921,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage return 0; // prevent kill only if killed in duel and killed by opponent or opponent controlled creature - if (victim->ToPlayer()->duel->opponent == attacker || victim->ToPlayer()->duel->opponent->GetGUID() == attacker->GetOwnerGUID()) + if (victim->ToPlayer()->duel->Opponent == attacker || victim->ToPlayer()->duel->Opponent->GetGUID() == attacker->GetOwnerGUID()) damage = health - 1; duel_hasEnded = true; @@ -930,14 +930,14 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage { Player* victimRider = victim->GetCharmer()->ToPlayer(); - if (victimRider && victimRider->duel && victimRider->duel->isMounted) + if (victimRider && victimRider->duel && victimRider->duel->IsMounted) { // xinef: situation not possible earlier, just return silently. if (!attacker) return 0; // prevent kill only if killed in duel and killed by opponent or opponent controlled creature - if (victimRider->duel->opponent == attacker || victimRider->duel->opponent->GetGUID() == attacker->GetCharmerGUID()) + if (victimRider->duel->Opponent == attacker || victimRider->duel->Opponent->GetGUID() == attacker->GetCharmerGUID()) damage = health - 1; duel_wasMounted = true; @@ -1065,7 +1065,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage else he->SetHealth(1); - he->duel->opponent->CombatStopWithPets(true); + he->duel->Opponent->CombatStopWithPets(true); he->CombatStopWithPets(true); he->CastSpell(he, 7267, true); // beg @@ -9545,7 +9545,7 @@ ReputationRank Unit::GetReactionTo(Unit const* target) const return REP_FRIENDLY; // duel - always hostile to opponent - if (selfPlayerOwner->duel && selfPlayerOwner->duel->opponent == targetPlayerOwner && selfPlayerOwner->duel->startTime != 0) + if (selfPlayerOwner->duel && selfPlayerOwner->duel->Opponent == targetPlayerOwner && selfPlayerOwner->duel->StartTime != 0) return REP_HOSTILE; // same group - checks dependant only on our faction - skip FFA_PVP for example @@ -12817,7 +12817,7 @@ void Unit::SetInCombatWith(Unit* enemy, uint32 duration) if (eOwner->GetTypeId() == TYPEID_PLAYER && eOwner->ToPlayer()->duel) { Unit const* myOwner = GetCharmerOrOwnerOrSelf(); - if (((Player const*)eOwner)->duel->opponent == myOwner) + if (((Player const*)eOwner)->duel->Opponent == myOwner) { SetInCombatState(true, enemy, duration); return; @@ -12890,7 +12890,7 @@ void Unit::CombatStart(Unit* victim, bool initialAggro) SetContestedPvP(who->ToPlayer()); Player* me = GetCharmerOrOwnerPlayerOrPlayerItself(); - if (me && who->IsPvP() && (who->GetTypeId() != TYPEID_PLAYER || !me->duel || me->duel->opponent != who)) + if (me && who->IsPvP() && (who->GetTypeId() != TYPEID_PLAYER || !me->duel || me->duel->Opponent != who)) { me->UpdatePvP(true); me->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); @@ -12917,7 +12917,7 @@ void Unit::CombatStartOnCast(Unit* target, bool initialAggro, uint32 duration) SetContestedPvP(who->ToPlayer()); Player* me = GetCharmerOrOwnerPlayerOrPlayerItself(); - if (me && who->IsPvP() && (who->GetTypeId() != TYPEID_PLAYER || !me->duel || me->duel->opponent != who)) + if (me && who->IsPvP() && (who->GetTypeId() != TYPEID_PLAYER || !me->duel || me->duel->Opponent != who)) { me->UpdatePvP(true); me->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); @@ -13155,7 +13155,7 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo // check duel - before sanctuary checks if (playerAffectingAttacker && playerAffectingTarget) - if (playerAffectingAttacker->duel && playerAffectingAttacker->duel->opponent == playerAffectingTarget && playerAffectingAttacker->duel->startTime != 0) + if (playerAffectingAttacker->duel && playerAffectingAttacker->duel->Opponent == playerAffectingTarget && playerAffectingAttacker->duel->StartTime != 0) return true; // PvP case - can't attack when attacker or target are in sanctuary @@ -16466,7 +16466,7 @@ void Unit::SetContestedPvP(Player* attackedPlayer, bool lookForNearContestedGuar { Player* player = GetCharmerOrOwnerPlayerOrPlayerItself(); - if (!player || ((attackedPlayer && (attackedPlayer == player || (player->duel && player->duel->opponent == attackedPlayer))) || player->InBattleground())) + if (!player || ((attackedPlayer && (attackedPlayer == player || (player->duel && player->duel->Opponent == attackedPlayer))) || player->InBattleground())) return; // check if there any guards that should care about the contested flag on player @@ -17098,7 +17098,7 @@ void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackTyp // last damage from non duel opponent or opponent controlled creature if (plrVictim->duel) { - plrVictim->duel->opponent->CombatStopWithPets(true); + plrVictim->duel->Opponent->CombatStopWithPets(true); plrVictim->CombatStopWithPets(true); plrVictim->DuelComplete(DUEL_INTERRUPTED); } @@ -18856,7 +18856,7 @@ void Unit::_ExitVehicle(Position const* exitPosition) Player* player = ToPlayer(); // If player is on mouted duel and exits the mount should immediatly lose the duel - if (player && player->duel && player->duel->isMounted) + if (player && player->duel && player->duel->IsMounted) player->DuelComplete(DUEL_FLED); // This should be done before dismiss, because there may be some aura removal diff --git a/src/server/game/Handlers/DuelHandler.cpp b/src/server/game/Handlers/DuelHandler.cpp index 14f9afd74..3d55e79e7 100644 --- a/src/server/game/Handlers/DuelHandler.cpp +++ b/src/server/game/Handlers/DuelHandler.cpp @@ -24,48 +24,48 @@ void WorldSession::HandleDuelAcceptedOpcode(WorldPacket& recvPacket) { - ObjectGuid guid; - Player* player; - Player* plTarget; - - recvPacket >> guid; - - if (!GetPlayer()->duel) // ignore accept from duel-sender + Player* player = GetPlayer(); + if (!player->duel || player == player->duel->Initiator || player->duel->State != DUEL_STATE_CHALLENGED) return; - player = GetPlayer(); - plTarget = player->duel->opponent; + ObjectGuid guid; + recvPacket >> guid; - if (player == player->duel->initiator || !plTarget || player == plTarget || player->duel->startTime != 0 || plTarget->duel->startTime != 0) + Player* target = player->duel->Opponent; + if (target->GetGuidValue(PLAYER_DUEL_ARBITER) != guid) return; LOG_DEBUG("network.opcode", "Player 1 is: %s (%s)", player->GetGUID().ToString().c_str(), player->GetName().c_str()); - LOG_DEBUG("network.opcode", "Player 2 is: %s (%s)", plTarget->GetGUID().ToString().c_str(), plTarget->GetName().c_str()); + LOG_DEBUG("network.opcode", "Player 2 is: %s (%s)", target->GetGUID().ToString().c_str(), target->GetName().c_str()); time_t now = time(nullptr); - player->duel->startTimer = now; - plTarget->duel->startTimer = now; + player->duel->StartTime = now + 3; + target->duel->StartTime = now + 3; + + player->duel->State = DUEL_STATE_COUNTDOWN; + target->duel->State = DUEL_STATE_COUNTDOWN; player->SendDuelCountdown(3000); - plTarget->SendDuelCountdown(3000); + target->SendDuelCountdown(3000); } void WorldSession::HandleDuelCancelledOpcode(WorldPacket& recvPacket) { LOG_DEBUG("network", "WORLD: Received CMSG_DUEL_CANCELLED"); + Player* player = GetPlayer(); + ObjectGuid guid; recvPacket >> guid; // no duel requested - if (!GetPlayer()->duel) + if (!player->duel || player->duel->State == DUEL_STATE_COMPLETED) return; // player surrendered in a duel using /forfeit - if (GetPlayer()->duel->startTime != 0) + if (GetPlayer()->duel->State == DUEL_STATE_IN_PROGRESS) { GetPlayer()->CombatStopWithPets(true); - if (GetPlayer()->duel->opponent) - GetPlayer()->duel->opponent->CombatStopWithPets(true); + GetPlayer()->duel->Opponent->CombatStopWithPets(true); GetPlayer()->CastSpell(GetPlayer(), 7267, true); // beg GetPlayer()->DuelComplete(DUEL_WON); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 11ec56a92..7afdd46aa 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5631,7 +5631,7 @@ SpellCastResult Spell::CheckCast(bool strict) { // Xinef: fix for duels Player* player = m_caster->ToPlayer(); - if (!player || !player->duel || target != player->duel->opponent) + if (!player || !player->duel || target != player->duel->Opponent) return SPELL_FAILED_NOTHING_TO_DISPEL; } } diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 7ff4e4045..8b1e01021 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -4408,21 +4408,9 @@ void Spell::EffectDuel(SpellEffIndex effIndex) target->GetSession()->SendPacket(&data); // create duel-info - DuelInfo* duel = new DuelInfo; - duel->initiator = caster; - duel->opponent = target; - duel->startTime = 0; - duel->startTimer = 0; - duel->isMounted = (GetSpellInfo()->Id == 62875); // Mounted Duel - caster->duel = duel; - - DuelInfo* duel2 = new DuelInfo; - duel2->initiator = caster; - duel2->opponent = caster; - duel2->startTime = 0; - duel2->startTimer = 0; - duel2->isMounted = (GetSpellInfo()->Id == 62875); // Mounted Duel - target->duel = duel2; + bool isMounted = (GetSpellInfo()->Id == 62875); + caster->duel = std::make_unique(target, caster, isMounted); + target->duel = std::make_unique(caster, caster, isMounted); caster->SetGuidValue(PLAYER_DUEL_ARBITER, pGameObj->GetGUID()); target->SetGuidValue(PLAYER_DUEL_ARBITER, pGameObj->GetGUID()); diff --git a/src/server/scripts/World/achievement_scripts.cpp b/src/server/scripts/World/achievement_scripts.cpp index df6d38e78..ff5cf3cdf 100644 --- a/src/server/scripts/World/achievement_scripts.cpp +++ b/src/server/scripts/World/achievement_scripts.cpp @@ -221,7 +221,7 @@ public: areaid == AREA_RING_OF_HORDE_VALIANTS || areaid == AREA_RING_OF_CHAMPIONS; - return checkArea && player->duel && player->duel->isMounted; + return checkArea && player->duel && player->duel->IsMounted; } };