mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-18 19:35:42 +00:00
fix(Core/Player): prevent crash exploit spam duel starting (#9226)
This commit is contained in:
committed by
GitHub
parent
25ca425357
commit
ab761c9865
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user