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_auraRaidUpdateMask = 0;
|
||||||
m_bPassOnGroupLoot = false;
|
m_bPassOnGroupLoot = false;
|
||||||
|
|
||||||
duel = nullptr;
|
|
||||||
|
|
||||||
m_GuildIdInvited = 0;
|
m_GuildIdInvited = 0;
|
||||||
m_ArenaTeamIdInvited = 0;
|
m_ArenaTeamIdInvited = 0;
|
||||||
|
|
||||||
@@ -6154,18 +6152,20 @@ uint32 Player::GetZoneIdFromDB(ObjectGuid guid)
|
|||||||
void Player::CheckDuelDistance(time_t currTime)
|
void Player::CheckDuelDistance(time_t currTime)
|
||||||
{
|
{
|
||||||
if (!duel)
|
if (!duel)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ObjectGuid duelFlagGUID = GetGuidValue(PLAYER_DUEL_ARBITER);
|
ObjectGuid duelFlagGUID = GetGuidValue(PLAYER_DUEL_ARBITER);
|
||||||
GameObject* obj = GetMap()->GetGameObject(duelFlagGUID);
|
GameObject* obj = GetMap()->GetGameObject(duelFlagGUID);
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (duel->outOfBound == 0)
|
if (!duel->OutOfBoundsTime)
|
||||||
{
|
{
|
||||||
if (!IsWithinDistInMap(obj, 50))
|
if (!IsWithinDistInMap(obj, 50))
|
||||||
{
|
{
|
||||||
duel->outOfBound = currTime;
|
duel->OutOfBoundsTime = currTime + 10;
|
||||||
|
|
||||||
WorldPacket data(SMSG_DUEL_OUTOFBOUNDS, 0);
|
WorldPacket data(SMSG_DUEL_OUTOFBOUNDS, 0);
|
||||||
GetSession()->SendPacket(&data);
|
GetSession()->SendPacket(&data);
|
||||||
@@ -6175,12 +6175,12 @@ void Player::CheckDuelDistance(time_t currTime)
|
|||||||
{
|
{
|
||||||
if (IsWithinDistInMap(obj, 40))
|
if (IsWithinDistInMap(obj, 40))
|
||||||
{
|
{
|
||||||
duel->outOfBound = 0;
|
duel->OutOfBoundsTime = 0;
|
||||||
|
|
||||||
WorldPacket data(SMSG_DUEL_INBOUNDS, 0);
|
WorldPacket data(SMSG_DUEL_INBOUNDS, 0);
|
||||||
GetSession()->SendPacket(&data);
|
GetSession()->SendPacket(&data);
|
||||||
}
|
}
|
||||||
else if (currTime >= (duel->outOfBound + 10))
|
else if (currTime >= duel->OutOfBoundsTime)
|
||||||
DuelComplete(DUEL_FLED);
|
DuelComplete(DUEL_FLED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6193,57 +6193,76 @@ bool Player::IsOutdoorPvPActive()
|
|||||||
void Player::DuelComplete(DuelCompleteType type)
|
void Player::DuelComplete(DuelCompleteType type)
|
||||||
{
|
{
|
||||||
// duel not requested
|
// duel not requested
|
||||||
if (!duel || !duel->opponent || !duel->initiator)
|
if (!duel)
|
||||||
return;
|
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));
|
WorldPacket data(SMSG_DUEL_COMPLETE, (1));
|
||||||
data << (uint8)((type != DUEL_INTERRUPTED) ? 1 : 0);
|
data << uint8((type != DUEL_INTERRUPTED) ? 1 : 0);
|
||||||
GetSession()->SendPacket(&data);
|
SendDirectMessage(&data);
|
||||||
|
if (opponent->GetSession())
|
||||||
duel->opponent->GetSession()->SendPacket(&data);
|
{
|
||||||
|
opponent->SendDirectMessage(&data);
|
||||||
|
}
|
||||||
|
|
||||||
if (type != DUEL_INTERRUPTED)
|
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 << uint8(type == DUEL_WON ? 0 : 1); // 0 = just won; 1 = fled
|
||||||
data << duel->opponent->GetName();
|
data << opponent->GetName();
|
||||||
data << GetName();
|
data << GetName();
|
||||||
SendMessageToSet(&data, true);
|
SendMessageToSet(&data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
sScriptMgr->OnPlayerDuelEnd(duel->opponent, this, type);
|
sScriptMgr->OnPlayerDuelEnd(opponent, this, type);
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case DUEL_FLED:
|
case DUEL_FLED:
|
||||||
// if initiator and opponent are on the same team
|
// if initiator and opponent are on the same team
|
||||||
// or initiator and opponent are not PvP enabled, forcibly stop attacking
|
// 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();
|
AttackStop();
|
||||||
duel->opponent->AttackStop();
|
opponent->AttackStop();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!duel->initiator->IsPvP())
|
if (!IsPvP())
|
||||||
duel->initiator->AttackStop();
|
{
|
||||||
if (!duel->opponent->IsPvP())
|
AttackStop();
|
||||||
duel->opponent->AttackStop();
|
}
|
||||||
|
if (!opponent->IsPvP())
|
||||||
|
{
|
||||||
|
opponent->AttackStop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DUEL_WON:
|
case DUEL_WON:
|
||||||
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL, 1);
|
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
|
// Credit for quest Death's Challenge
|
||||||
if (getClass() == CLASS_DEATH_KNIGHT && duel->opponent->GetQuestStatus(12733) == QUEST_STATUS_INCOMPLETE)
|
if (getClass() == CLASS_DEATH_KNIGHT && opponent->GetQuestStatus(12733) == QUEST_STATUS_INCOMPLETE)
|
||||||
duel->opponent->CastSpell(duel->opponent, 52994, true);
|
{
|
||||||
|
opponent->CastSpell(opponent, 52994, true);
|
||||||
|
}
|
||||||
|
|
||||||
// Honor points after duel (the winner) - ImpConfig
|
// Honor points after duel (the winner) - ImpConfig
|
||||||
if (uint32 amount = sWorld->getIntConfig(CONFIG_HONOR_AFTER_DUEL))
|
if (uint32 amount = sWorld->getIntConfig(CONFIG_HONOR_AFTER_DUEL))
|
||||||
duel->opponent->RewardHonor(nullptr, 1, amount);
|
{
|
||||||
|
opponent->RewardHonor(nullptr, 1, amount);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -6251,56 +6270,66 @@ void Player::DuelComplete(DuelCompleteType type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Victory emote spell
|
// Victory emote spell
|
||||||
if (type != DUEL_INTERRUPTED && duel->opponent)
|
if (type != DUEL_INTERRUPTED)
|
||||||
duel->opponent->CastSpell(duel->opponent, 52852, true);
|
{
|
||||||
|
opponent->CastSpell(opponent, 52852, true);
|
||||||
|
}
|
||||||
|
|
||||||
//Remove Duel Flag object
|
//Remove Duel Flag object
|
||||||
GameObject* obj = GetMap()->GetGameObject(GetGuidValue(PLAYER_DUEL_ARBITER));
|
GameObject* obj = GetMap()->GetGameObject(GetGuidValue(PLAYER_DUEL_ARBITER));
|
||||||
if (obj)
|
if (obj)
|
||||||
duel->initiator->RemoveGameObject(obj, true);
|
{
|
||||||
|
duel->Initiator->RemoveGameObject(obj, true);
|
||||||
|
}
|
||||||
|
|
||||||
/* remove auras */
|
/* remove auras */
|
||||||
AuraApplicationMap& itsAuras = duel->opponent->GetAppliedAuras();
|
AuraApplicationMap &itsAuras = opponent->GetAppliedAuras();
|
||||||
for (AuraApplicationMap::iterator i = itsAuras.begin(); i != itsAuras.end();)
|
for (AuraApplicationMap::iterator i = itsAuras.begin(); i != itsAuras.end();)
|
||||||
{
|
{
|
||||||
Aura const* aura = i->second->GetBase();
|
Aura const* aura = i->second->GetBase();
|
||||||
if (!i->second->IsPositive() && aura->GetCasterGUID() == GetGUID() && aura->GetApplyTime() >= duel->startTime)
|
if (!i->second->IsPositive() && aura->GetCasterGUID() == GetGUID() && aura->GetApplyTime() >= duel->StartTime)
|
||||||
duel->opponent->RemoveAura(i);
|
{
|
||||||
|
opponent->RemoveAura(i);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
++i;
|
++i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AuraApplicationMap& myAuras = GetAppliedAuras();
|
AuraApplicationMap &myAuras = GetAppliedAuras();
|
||||||
for (AuraApplicationMap::iterator i = myAuras.begin(); i != myAuras.end();)
|
for (AuraApplicationMap::iterator i = myAuras.begin(); i != myAuras.end();)
|
||||||
{
|
{
|
||||||
Aura const* aura = i->second->GetBase();
|
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);
|
RemoveAura(i);
|
||||||
else
|
else
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// cleanup combo points
|
// cleanup combo points
|
||||||
if (GetComboTarget() == duel->opponent->GetGUID())
|
if (GetComboTarget() == duel->Opponent->GetGUID())
|
||||||
ClearComboPoints();
|
ClearComboPoints();
|
||||||
else if (GetComboTarget() == duel->opponent->GetPetGUID())
|
else if (GetComboTarget() == duel->Opponent->GetPetGUID())
|
||||||
ClearComboPoints();
|
ClearComboPoints();
|
||||||
|
|
||||||
if (duel->opponent->GetComboTarget() == GetGUID())
|
if (duel->Opponent->GetComboTarget() == GetGUID())
|
||||||
duel->opponent->ClearComboPoints();
|
{
|
||||||
else if (duel->opponent->GetComboTarget() == GetPetGUID())
|
duel->Opponent->ClearComboPoints();
|
||||||
duel->opponent->ClearComboPoints();
|
}
|
||||||
|
else if (duel->Opponent->GetComboTarget() == GetPetGUID())
|
||||||
|
{
|
||||||
|
duel->Opponent->ClearComboPoints();
|
||||||
|
}
|
||||||
|
|
||||||
//cleanups
|
//cleanups
|
||||||
SetGuidValue(PLAYER_DUEL_ARBITER, ObjectGuid::Empty);
|
SetGuidValue(PLAYER_DUEL_ARBITER, ObjectGuid::Empty);
|
||||||
SetUInt32Value(PLAYER_DUEL_TEAM, 0);
|
SetUInt32Value(PLAYER_DUEL_TEAM, 0);
|
||||||
duel->opponent->SetGuidValue(PLAYER_DUEL_ARBITER, ObjectGuid::Empty);
|
opponent->SetGuidValue(PLAYER_DUEL_ARBITER, ObjectGuid::Empty);
|
||||||
duel->opponent->SetUInt32Value(PLAYER_DUEL_TEAM, 0);
|
opponent->SetUInt32Value(PLAYER_DUEL_TEAM, 0);
|
||||||
|
|
||||||
delete duel->opponent->duel;
|
opponent->duel.reset(nullptr);
|
||||||
duel->opponent->duel = nullptr;
|
duel.reset(nullptr);
|
||||||
delete duel;
|
|
||||||
duel = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------//
|
//---------------------------------------------------------//
|
||||||
@@ -10668,9 +10697,18 @@ bool Player::IsAlwaysDetectableFor(WorldObject const* seer) const
|
|||||||
if (Unit::IsAlwaysDetectableFor(seer))
|
if (Unit::IsAlwaysDetectableFor(seer))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (duel && duel->State != DUEL_STATE_CHALLENGED && duel->Opponent == seer)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (const Player* seerPlayer = seer->ToPlayer())
|
if (const Player* seerPlayer = seer->ToPlayer())
|
||||||
|
{
|
||||||
if (IsGroupVisibleFor(seerPlayer))
|
if (IsGroupVisibleFor(seerPlayer))
|
||||||
return !(seerPlayer->duel && seerPlayer->duel->startTime != 0 && seerPlayer->duel->opponent == this);
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -357,16 +357,24 @@ struct PvPInfo
|
|||||||
time_t FFAPvPEndTimer{0}; ///> Time when player unflags himself for FFA PvP (flag removed after 30 sec)
|
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
|
struct DuelInfo
|
||||||
{
|
{
|
||||||
DuelInfo() {}
|
DuelInfo(Player* opponent, Player* initiator, bool isMounted) : Opponent(opponent), Initiator(initiator), IsMounted(isMounted) {}
|
||||||
|
|
||||||
Player* initiator{nullptr};
|
Player* const Opponent;
|
||||||
Player* opponent{nullptr};
|
Player* const Initiator;
|
||||||
time_t startTimer{0};
|
bool const IsMounted;
|
||||||
time_t startTime{0};
|
DuelState State = DUEL_STATE_CHALLENGED;
|
||||||
time_t outOfBound{0};
|
time_t StartTime = 0;
|
||||||
bool isMounted{false};
|
time_t OutOfBoundsTime = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Areas
|
struct Areas
|
||||||
@@ -1814,7 +1822,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** todo: -maybe move UpdateDuelFlag+DuelComplete to independent DuelHandler.. **/
|
/** todo: -maybe move UpdateDuelFlag+DuelComplete to independent DuelHandler.. **/
|
||||||
DuelInfo* duel;
|
std::unique_ptr<DuelInfo> duel;
|
||||||
void UpdateDuelFlag(time_t currTime);
|
void UpdateDuelFlag(time_t currTime);
|
||||||
void CheckDuelDistance(time_t currTime);
|
void CheckDuelDistance(time_t currTime);
|
||||||
void DuelComplete(DuelCompleteType type);
|
void DuelComplete(DuelCompleteType type);
|
||||||
|
|||||||
@@ -403,18 +403,16 @@ void Player::UpdateFFAPvPFlag(time_t currTime)
|
|||||||
|
|
||||||
void Player::UpdateDuelFlag(time_t currTime)
|
void Player::UpdateDuelFlag(time_t currTime)
|
||||||
{
|
{
|
||||||
if (!duel || duel->startTimer == 0 || currTime < duel->startTimer + 3)
|
if (duel && duel->State == DUEL_STATE_COUNTDOWN && duel->StartTime <= currTime)
|
||||||
return;
|
{
|
||||||
|
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->State = DUEL_STATE_IN_PROGRESS;
|
||||||
duel->opponent->SetUInt32Value(PLAYER_DUEL_TEAM, 2);
|
duel->Opponent->duel->State = DUEL_STATE_IN_PROGRESS;
|
||||||
|
}
|
||||||
duel->startTimer = 0;
|
|
||||||
duel->startTime = currTime;
|
|
||||||
duel->opponent->duel->startTimer = 0;
|
|
||||||
duel->opponent->duel->startTime = currTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************/
|
/*********************************************************/
|
||||||
|
|||||||
@@ -921,7 +921,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// prevent kill only if killed in duel and killed by opponent or opponent controlled creature
|
// 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;
|
damage = health - 1;
|
||||||
|
|
||||||
duel_hasEnded = true;
|
duel_hasEnded = true;
|
||||||
@@ -930,14 +930,14 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
|
|||||||
{
|
{
|
||||||
Player* victimRider = victim->GetCharmer()->ToPlayer();
|
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.
|
// xinef: situation not possible earlier, just return silently.
|
||||||
if (!attacker)
|
if (!attacker)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// prevent kill only if killed in duel and killed by opponent or opponent controlled creature
|
// 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;
|
damage = health - 1;
|
||||||
|
|
||||||
duel_wasMounted = true;
|
duel_wasMounted = true;
|
||||||
@@ -1065,7 +1065,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
|
|||||||
else
|
else
|
||||||
he->SetHealth(1);
|
he->SetHealth(1);
|
||||||
|
|
||||||
he->duel->opponent->CombatStopWithPets(true);
|
he->duel->Opponent->CombatStopWithPets(true);
|
||||||
he->CombatStopWithPets(true);
|
he->CombatStopWithPets(true);
|
||||||
|
|
||||||
he->CastSpell(he, 7267, true); // beg
|
he->CastSpell(he, 7267, true); // beg
|
||||||
@@ -9545,7 +9545,7 @@ ReputationRank Unit::GetReactionTo(Unit const* target) const
|
|||||||
return REP_FRIENDLY;
|
return REP_FRIENDLY;
|
||||||
|
|
||||||
// duel - always hostile to opponent
|
// 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;
|
return REP_HOSTILE;
|
||||||
|
|
||||||
// same group - checks dependant only on our faction - skip FFA_PVP for example
|
// 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)
|
if (eOwner->GetTypeId() == TYPEID_PLAYER && eOwner->ToPlayer()->duel)
|
||||||
{
|
{
|
||||||
Unit const* myOwner = GetCharmerOrOwnerOrSelf();
|
Unit const* myOwner = GetCharmerOrOwnerOrSelf();
|
||||||
if (((Player const*)eOwner)->duel->opponent == myOwner)
|
if (((Player const*)eOwner)->duel->Opponent == myOwner)
|
||||||
{
|
{
|
||||||
SetInCombatState(true, enemy, duration);
|
SetInCombatState(true, enemy, duration);
|
||||||
return;
|
return;
|
||||||
@@ -12890,7 +12890,7 @@ void Unit::CombatStart(Unit* victim, bool initialAggro)
|
|||||||
SetContestedPvP(who->ToPlayer());
|
SetContestedPvP(who->ToPlayer());
|
||||||
|
|
||||||
Player* me = GetCharmerOrOwnerPlayerOrPlayerItself();
|
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->UpdatePvP(true);
|
||||||
me->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
|
me->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
|
||||||
@@ -12917,7 +12917,7 @@ void Unit::CombatStartOnCast(Unit* target, bool initialAggro, uint32 duration)
|
|||||||
SetContestedPvP(who->ToPlayer());
|
SetContestedPvP(who->ToPlayer());
|
||||||
|
|
||||||
Player* me = GetCharmerOrOwnerPlayerOrPlayerItself();
|
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->UpdatePvP(true);
|
||||||
me->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
|
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
|
// check duel - before sanctuary checks
|
||||||
if (playerAffectingAttacker && playerAffectingTarget)
|
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;
|
return true;
|
||||||
|
|
||||||
// PvP case - can't attack when attacker or target are in sanctuary
|
// 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();
|
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;
|
return;
|
||||||
|
|
||||||
// check if there any guards that should care about the contested flag on player
|
// 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
|
// last damage from non duel opponent or opponent controlled creature
|
||||||
if (plrVictim->duel)
|
if (plrVictim->duel)
|
||||||
{
|
{
|
||||||
plrVictim->duel->opponent->CombatStopWithPets(true);
|
plrVictim->duel->Opponent->CombatStopWithPets(true);
|
||||||
plrVictim->CombatStopWithPets(true);
|
plrVictim->CombatStopWithPets(true);
|
||||||
plrVictim->DuelComplete(DUEL_INTERRUPTED);
|
plrVictim->DuelComplete(DUEL_INTERRUPTED);
|
||||||
}
|
}
|
||||||
@@ -18856,7 +18856,7 @@ void Unit::_ExitVehicle(Position const* exitPosition)
|
|||||||
Player* player = ToPlayer();
|
Player* player = ToPlayer();
|
||||||
|
|
||||||
// If player is on mouted duel and exits the mount should immediatly lose the duel
|
// 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);
|
player->DuelComplete(DUEL_FLED);
|
||||||
|
|
||||||
// This should be done before dismiss, because there may be some aura removal
|
// This should be done before dismiss, because there may be some aura removal
|
||||||
|
|||||||
@@ -24,48 +24,48 @@
|
|||||||
|
|
||||||
void WorldSession::HandleDuelAcceptedOpcode(WorldPacket& recvPacket)
|
void WorldSession::HandleDuelAcceptedOpcode(WorldPacket& recvPacket)
|
||||||
{
|
{
|
||||||
ObjectGuid guid;
|
Player* player = GetPlayer();
|
||||||
Player* player;
|
if (!player->duel || player == player->duel->Initiator || player->duel->State != DUEL_STATE_CHALLENGED)
|
||||||
Player* plTarget;
|
|
||||||
|
|
||||||
recvPacket >> guid;
|
|
||||||
|
|
||||||
if (!GetPlayer()->duel) // ignore accept from duel-sender
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
player = GetPlayer();
|
ObjectGuid guid;
|
||||||
plTarget = player->duel->opponent;
|
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;
|
return;
|
||||||
|
|
||||||
LOG_DEBUG("network.opcode", "Player 1 is: %s (%s)", player->GetGUID().ToString().c_str(), player->GetName().c_str());
|
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);
|
time_t now = time(nullptr);
|
||||||
player->duel->startTimer = now;
|
player->duel->StartTime = now + 3;
|
||||||
plTarget->duel->startTimer = now;
|
target->duel->StartTime = now + 3;
|
||||||
|
|
||||||
|
player->duel->State = DUEL_STATE_COUNTDOWN;
|
||||||
|
target->duel->State = DUEL_STATE_COUNTDOWN;
|
||||||
|
|
||||||
player->SendDuelCountdown(3000);
|
player->SendDuelCountdown(3000);
|
||||||
plTarget->SendDuelCountdown(3000);
|
target->SendDuelCountdown(3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::HandleDuelCancelledOpcode(WorldPacket& recvPacket)
|
void WorldSession::HandleDuelCancelledOpcode(WorldPacket& recvPacket)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("network", "WORLD: Received CMSG_DUEL_CANCELLED");
|
LOG_DEBUG("network", "WORLD: Received CMSG_DUEL_CANCELLED");
|
||||||
|
Player* player = GetPlayer();
|
||||||
|
|
||||||
ObjectGuid guid;
|
ObjectGuid guid;
|
||||||
recvPacket >> guid;
|
recvPacket >> guid;
|
||||||
|
|
||||||
// no duel requested
|
// no duel requested
|
||||||
if (!GetPlayer()->duel)
|
if (!player->duel || player->duel->State == DUEL_STATE_COMPLETED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// player surrendered in a duel using /forfeit
|
// player surrendered in a duel using /forfeit
|
||||||
if (GetPlayer()->duel->startTime != 0)
|
if (GetPlayer()->duel->State == DUEL_STATE_IN_PROGRESS)
|
||||||
{
|
{
|
||||||
GetPlayer()->CombatStopWithPets(true);
|
GetPlayer()->CombatStopWithPets(true);
|
||||||
if (GetPlayer()->duel->opponent)
|
GetPlayer()->duel->Opponent->CombatStopWithPets(true);
|
||||||
GetPlayer()->duel->opponent->CombatStopWithPets(true);
|
|
||||||
|
|
||||||
GetPlayer()->CastSpell(GetPlayer(), 7267, true); // beg
|
GetPlayer()->CastSpell(GetPlayer(), 7267, true); // beg
|
||||||
GetPlayer()->DuelComplete(DUEL_WON);
|
GetPlayer()->DuelComplete(DUEL_WON);
|
||||||
|
|||||||
@@ -5631,7 +5631,7 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||||||
{
|
{
|
||||||
// Xinef: fix for duels
|
// Xinef: fix for duels
|
||||||
Player* player = m_caster->ToPlayer();
|
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;
|
return SPELL_FAILED_NOTHING_TO_DISPEL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4408,21 +4408,9 @@ void Spell::EffectDuel(SpellEffIndex effIndex)
|
|||||||
target->GetSession()->SendPacket(&data);
|
target->GetSession()->SendPacket(&data);
|
||||||
|
|
||||||
// create duel-info
|
// create duel-info
|
||||||
DuelInfo* duel = new DuelInfo;
|
bool isMounted = (GetSpellInfo()->Id == 62875);
|
||||||
duel->initiator = caster;
|
caster->duel = std::make_unique<DuelInfo>(target, caster, isMounted);
|
||||||
duel->opponent = target;
|
target->duel = std::make_unique<DuelInfo>(caster, caster, isMounted);
|
||||||
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;
|
|
||||||
|
|
||||||
caster->SetGuidValue(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
|
caster->SetGuidValue(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
|
||||||
target->SetGuidValue(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
|
target->SetGuidValue(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ public:
|
|||||||
areaid == AREA_RING_OF_HORDE_VALIANTS ||
|
areaid == AREA_RING_OF_HORDE_VALIANTS ||
|
||||||
areaid == AREA_RING_OF_CHAMPIONS;
|
areaid == AREA_RING_OF_CHAMPIONS;
|
||||||
|
|
||||||
return checkArea && player->duel && player->duel->isMounted;
|
return checkArea && player->duel && player->duel->IsMounted;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user