mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-22 13:16:23 +00:00
fix(Core/Entities): extend combo point system to all Units (#9816)
- Closes #1140
This commit is contained in:
@@ -169,8 +169,6 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this)
|
||||
if (AccountMgr::IsPlayerAccount(GetSession()->GetSecurity()))
|
||||
SetAcceptWhispers(true);
|
||||
|
||||
m_comboPoints = 0;
|
||||
|
||||
m_usedTalentCount = 0;
|
||||
m_questRewardTalentCount = 0;
|
||||
m_extraBonusTalentCount = 0;
|
||||
@@ -391,7 +389,6 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this)
|
||||
|
||||
// Ours
|
||||
m_NeedToSaveGlyphs = false;
|
||||
m_comboPointGain = 0;
|
||||
m_MountBlockId = 0;
|
||||
m_realDodge = 0.0f;
|
||||
m_realParry = 0.0f;
|
||||
@@ -6202,12 +6199,11 @@ void Player::DuelComplete(DuelCompleteType type)
|
||||
if (duel->State == DUEL_STATE_COMPLETED)
|
||||
return;
|
||||
|
||||
Player* opponent = duel->Opponent;
|
||||
duel->State = DUEL_STATE_COMPLETED;
|
||||
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());
|
||||
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);
|
||||
@@ -6219,8 +6215,8 @@ void Player::DuelComplete(DuelCompleteType type)
|
||||
|
||||
if (type != DUEL_INTERRUPTED)
|
||||
{
|
||||
data.Initialize(SMSG_DUEL_WINNER, (1+20)); // we guess size
|
||||
data << uint8(type == DUEL_WON ? 0 : 1); // 0 = just won; 1 = fled
|
||||
data.Initialize(SMSG_DUEL_WINNER, (1 + 20)); // we guess size
|
||||
data << uint8(type == DUEL_WON ? 0 : 1); // 0 = just won; 1 = fled
|
||||
data << opponent->GetName();
|
||||
data << GetName();
|
||||
SendMessageToSet(&data, true);
|
||||
@@ -6230,45 +6226,45 @@ void Player::DuelComplete(DuelCompleteType 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 (GetTeamId() == opponent->GetTeamId())
|
||||
case DUEL_FLED:
|
||||
// if initiator and opponent are on the same team
|
||||
// or initiator and opponent are not PvP enabled, forcibly stop attacking
|
||||
if (GetTeamId() == opponent->GetTeamId())
|
||||
{
|
||||
AttackStop();
|
||||
opponent->AttackStop();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IsPvP())
|
||||
{
|
||||
AttackStop();
|
||||
}
|
||||
if (!opponent->IsPvP())
|
||||
{
|
||||
opponent->AttackStop();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IsPvP())
|
||||
{
|
||||
AttackStop();
|
||||
}
|
||||
if (!opponent->IsPvP())
|
||||
{
|
||||
opponent->AttackStop();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DUEL_WON:
|
||||
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL, 1);
|
||||
opponent->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL, 1);
|
||||
}
|
||||
break;
|
||||
case DUEL_WON:
|
||||
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL, 1);
|
||||
opponent->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL, 1);
|
||||
|
||||
// Credit for quest Death's Challenge
|
||||
if (getClass() == CLASS_DEATH_KNIGHT && opponent->GetQuestStatus(12733) == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
opponent->CastSpell(opponent, 52994, true);
|
||||
}
|
||||
// Credit for quest Death's Challenge
|
||||
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))
|
||||
{
|
||||
opponent->RewardHonor(nullptr, 1, amount);
|
||||
}
|
||||
// Honor points after duel (the winner) - ImpConfig
|
||||
if (uint32 amount = sWorld->getIntConfig(CONFIG_HONOR_AFTER_DUEL))
|
||||
{
|
||||
opponent->RewardHonor(nullptr, 1, amount);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Victory emote spell
|
||||
@@ -6277,7 +6273,7 @@ void Player::DuelComplete(DuelCompleteType type)
|
||||
opponent->CastSpell(opponent, 52852, true);
|
||||
}
|
||||
|
||||
//Remove Duel Flag object
|
||||
// Remove Duel Flag object
|
||||
GameObject* obj = GetMap()->GetGameObject(GetGuidValue(PLAYER_DUEL_ARBITER));
|
||||
if (obj)
|
||||
{
|
||||
@@ -6285,7 +6281,7 @@ void Player::DuelComplete(DuelCompleteType type)
|
||||
}
|
||||
|
||||
/* remove auras */
|
||||
AuraApplicationMap &itsAuras = opponent->GetAppliedAuras();
|
||||
AuraApplicationMap& itsAuras = opponent->GetAppliedAuras();
|
||||
for (AuraApplicationMap::iterator i = itsAuras.begin(); i != itsAuras.end();)
|
||||
{
|
||||
Aura const* aura = i->second->GetBase();
|
||||
@@ -6299,7 +6295,7 @@ void Player::DuelComplete(DuelCompleteType type)
|
||||
}
|
||||
}
|
||||
|
||||
AuraApplicationMap &myAuras = GetAppliedAuras();
|
||||
AuraApplicationMap& myAuras = GetAppliedAuras();
|
||||
for (AuraApplicationMap::iterator i = myAuras.begin(); i != myAuras.end();)
|
||||
{
|
||||
Aura const* aura = i->second->GetBase();
|
||||
@@ -6310,16 +6306,20 @@ void Player::DuelComplete(DuelCompleteType type)
|
||||
}
|
||||
|
||||
// cleanup combo points
|
||||
if (GetComboTarget() == duel->Opponent->GetGUID())
|
||||
if (GetComboTarget() == duel->Opponent)
|
||||
{
|
||||
ClearComboPoints();
|
||||
else if (GetComboTarget() == duel->Opponent->GetPetGUID())
|
||||
}
|
||||
else if (GetComboTargetGUID() == duel->Opponent->GetPetGUID())
|
||||
{
|
||||
ClearComboPoints();
|
||||
}
|
||||
|
||||
if (duel->Opponent->GetComboTarget() == GetGUID())
|
||||
if (duel->Opponent->GetComboTarget() == this)
|
||||
{
|
||||
duel->Opponent->ClearComboPoints();
|
||||
}
|
||||
else if (duel->Opponent->GetComboTarget() == GetPetGUID())
|
||||
else if (duel->Opponent->GetComboTargetGUID() == GetPetGUID())
|
||||
{
|
||||
duel->Opponent->ClearComboPoints();
|
||||
}
|
||||
@@ -10822,75 +10822,6 @@ void Player::SetSelection(ObjectGuid guid)
|
||||
ArenaSpectator::SendCommand_GUID(FindMap(), GetGUID(), "TRG", guid);
|
||||
}
|
||||
|
||||
void Player::SendComboPoints()
|
||||
{
|
||||
Unit* combotarget = ObjectAccessor::GetUnit(*this, m_comboTarget);
|
||||
if (combotarget)
|
||||
{
|
||||
WorldPacket data;
|
||||
if (m_mover != this)
|
||||
{
|
||||
data.Initialize(SMSG_PET_UPDATE_COMBO_POINTS, m_mover->GetPackGUID().size() + combotarget->GetPackGUID().size() + 1);
|
||||
data << m_mover->GetPackGUID();
|
||||
}
|
||||
else
|
||||
data.Initialize(SMSG_UPDATE_COMBO_POINTS, combotarget->GetPackGUID().size() + 1);
|
||||
data << combotarget->GetPackGUID();
|
||||
data << uint8(m_comboPoints);
|
||||
GetSession()->SendPacket(&data);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::AddComboPoints(Unit* target, int8 count)
|
||||
{
|
||||
if (!count)
|
||||
return;
|
||||
|
||||
int8* comboPoints = &m_comboPoints;
|
||||
|
||||
// without combo points lost (duration checked in aura)
|
||||
RemoveAurasByType(SPELL_AURA_RETAIN_COMBO_POINTS);
|
||||
|
||||
if (target->GetGUID() == m_comboTarget)
|
||||
*comboPoints += count;
|
||||
else
|
||||
{
|
||||
if (m_comboTarget)
|
||||
if (Unit* target2 = ObjectAccessor::GetUnit(*this, m_comboTarget))
|
||||
target2->RemoveComboPointHolder(GetGUID());
|
||||
|
||||
m_comboTarget = target->GetGUID();
|
||||
*comboPoints = count;
|
||||
|
||||
target->AddComboPointHolder(GetGUID());
|
||||
}
|
||||
|
||||
if (*comboPoints > 5)
|
||||
*comboPoints = 5;
|
||||
else if (*comboPoints < 0)
|
||||
*comboPoints = 0;
|
||||
|
||||
SendComboPoints();
|
||||
}
|
||||
|
||||
void Player::ClearComboPoints()
|
||||
{
|
||||
if (!m_comboTarget)
|
||||
return;
|
||||
|
||||
// without combopoints lost (duration checked in aura)
|
||||
RemoveAurasByType(SPELL_AURA_RETAIN_COMBO_POINTS);
|
||||
|
||||
m_comboPoints = 0;
|
||||
|
||||
SendComboPoints();
|
||||
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*this, m_comboTarget))
|
||||
target->RemoveComboPointHolder(GetGUID());
|
||||
|
||||
m_comboTarget.Clear();
|
||||
}
|
||||
|
||||
void Player::SetGroup(Group* group, int8 subgroup)
|
||||
{
|
||||
if (group == nullptr)
|
||||
|
||||
@@ -1582,13 +1582,6 @@ public:
|
||||
void SetTarget(ObjectGuid /*guid*/ = ObjectGuid::Empty) override { } /// Used for serverside target changes, does not apply to players
|
||||
void SetSelection(ObjectGuid guid);
|
||||
|
||||
[[nodiscard]] uint8 GetComboPoints() const { return m_comboPoints; }
|
||||
[[nodiscard]] ObjectGuid GetComboTarget() const { return m_comboTarget; }
|
||||
|
||||
void AddComboPoints(Unit* target, int8 count);
|
||||
void ClearComboPoints();
|
||||
void SendComboPoints();
|
||||
|
||||
void SendMailResult(uint32 mailId, MailResponseType mailAction, MailResponseResult mailError, uint32 equipError = 0, ObjectGuid::LowType item_guid = 0, uint32 item_count = 0);
|
||||
void SendNewMail();
|
||||
void UpdateNextMailTimeAndUnreads();
|
||||
@@ -2562,9 +2555,6 @@ public:
|
||||
void PrepareCharmAISpells();
|
||||
uint32 m_charmUpdateTimer;
|
||||
|
||||
int8 GetComboPointGain() { return m_comboPointGain; }
|
||||
void SetComboPointGain(int8 combo) { m_comboPointGain = combo; }
|
||||
|
||||
bool NeedToSaveGlyphs() { return m_NeedToSaveGlyphs; }
|
||||
void SetNeedToSaveGlyphs(bool val) { m_NeedToSaveGlyphs = val; }
|
||||
|
||||
@@ -2610,8 +2600,6 @@ public:
|
||||
// Gamemaster whisper whitelist
|
||||
WhisperListContainer WhisperList;
|
||||
|
||||
// Combo Points
|
||||
int8 m_comboPointGain;
|
||||
// Performance Varibales
|
||||
bool m_NeedToSaveGlyphs;
|
||||
// Mount block bug
|
||||
@@ -2753,9 +2741,6 @@ public:
|
||||
|
||||
uint32 m_ExtraFlags;
|
||||
|
||||
ObjectGuid m_comboTarget;
|
||||
int8 m_comboPoints;
|
||||
|
||||
QuestStatusMap m_QuestStatus;
|
||||
QuestStatusSaveMap m_QuestStatusSave;
|
||||
|
||||
|
||||
@@ -208,7 +208,8 @@ Unit::Unit(bool isWorldObject) : WorldObject(isWorldObject),
|
||||
m_vehicleKit(nullptr),
|
||||
m_unitTypeMask(UNIT_MASK_NONE),
|
||||
m_HostileRefMgr(this),
|
||||
m_comboTarget(nullptr)
|
||||
m_comboTarget(nullptr),
|
||||
m_comboPoints(0)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(default:4355)
|
||||
@@ -9086,9 +9087,11 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
|
||||
Unit* cptarget = nullptr;
|
||||
if (trigger_spell_id == 51699)
|
||||
{
|
||||
cptarget = ObjectAccessor::GetUnit(*target, pTarget->GetComboTarget());
|
||||
cptarget = pTarget->GetComboTarget();
|
||||
if (!cptarget)
|
||||
{
|
||||
cptarget = pTarget->GetSelectedUnit();
|
||||
}
|
||||
}
|
||||
else
|
||||
cptarget = target;
|
||||
@@ -14069,7 +14072,7 @@ int32 Unit::CalculateSpellDamage(Unit const* target, SpellInfo const* spellProto
|
||||
|
||||
int32 Unit::CalcSpellDuration(SpellInfo const* spellProto)
|
||||
{
|
||||
uint8 comboPoints = m_movedByPlayer ? m_movedByPlayer->ToPlayer()->GetComboPoints() : 0;
|
||||
uint8 comboPoints = GetComboPoints();
|
||||
|
||||
int32 minduration = spellProto->GetDuration();
|
||||
int32 maxduration = spellProto->GetMaxDuration();
|
||||
@@ -14938,6 +14941,7 @@ void Unit::CleanupBeforeRemoveFromMap(bool finalCleanup)
|
||||
|
||||
m_Events.KillAllEvents(false); // non-delatable (currently casted spells) will not deleted now but it will deleted at call in Map::RemoveAllObjectsInRemoveList
|
||||
CombatStop();
|
||||
ClearComboPoints();
|
||||
ClearComboPointHolders();
|
||||
DeleteThreatList();
|
||||
getHostileRefMgr().deleteReferences();
|
||||
@@ -15556,7 +15560,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
|
||||
{
|
||||
if (GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_WARRIOR)
|
||||
{
|
||||
ToPlayer()->AddComboPoints(target, 1);
|
||||
AddComboPoints(target, 1);
|
||||
StartReactiveTimer(REACTIVE_OVERPOWER);
|
||||
}
|
||||
}
|
||||
@@ -16208,17 +16212,96 @@ void Unit::RestoreDisplayId()
|
||||
SetDisplayId(GetNativeDisplayId());
|
||||
}
|
||||
|
||||
void Unit::AddComboPoints(Unit* target, int8 count)
|
||||
{
|
||||
if (!count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// remove Premed-like effects
|
||||
// (NB: this Aura removes the already-added CP when it expires from duration - now that we've added CP, this shouldn't happen anymore)
|
||||
RemoveAurasByType(SPELL_AURA_RETAIN_COMBO_POINTS);
|
||||
|
||||
if (target && target != m_comboTarget)
|
||||
{
|
||||
if (m_comboTarget)
|
||||
{
|
||||
m_comboTarget->RemoveComboPointHolder(this);
|
||||
}
|
||||
|
||||
m_comboTarget = target;
|
||||
m_comboPoints = count;
|
||||
target->AddComboPointHolder(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_comboPoints = std::max<int8>(std::min<int8>(m_comboPoints + count, 5), 0);
|
||||
}
|
||||
|
||||
SendComboPoints();
|
||||
}
|
||||
|
||||
void Unit::ClearComboPoints()
|
||||
{
|
||||
if (!m_comboTarget)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// remove Premed-like effects
|
||||
// (NB: this Aura retains the CP while it's active - now that CP have reset, it shouldn't be there anymore)
|
||||
RemoveAurasByType(SPELL_AURA_RETAIN_COMBO_POINTS);
|
||||
|
||||
m_comboPoints = 0;
|
||||
SendComboPoints();
|
||||
m_comboTarget->RemoveComboPointHolder(this);
|
||||
m_comboTarget = nullptr;
|
||||
}
|
||||
|
||||
void Unit::SendComboPoints()
|
||||
{
|
||||
if (m_cleanupDone)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PackedGuid const packGUID = m_comboTarget ? m_comboTarget->GetPackGUID() : PackedGuid();
|
||||
if (Player* playerMe = ToPlayer())
|
||||
{
|
||||
WorldPacket data(SMSG_UPDATE_COMBO_POINTS, packGUID.size() + 1);
|
||||
data << packGUID;
|
||||
data << uint8(m_comboPoints);
|
||||
playerMe->SendDirectMessage(&data);
|
||||
}
|
||||
|
||||
ObjectGuid ownerGuid = GetCharmerOrOwnerGUID();
|
||||
Player* owner = nullptr;
|
||||
if (ownerGuid.IsPlayer())
|
||||
{
|
||||
owner = ObjectAccessor::GetPlayer(*this, ownerGuid);
|
||||
}
|
||||
|
||||
if (m_movedByPlayer || owner)
|
||||
{
|
||||
WorldPacket data(SMSG_PET_UPDATE_COMBO_POINTS, GetPackGUID().size() + packGUID.size() + 1);
|
||||
data << GetPackGUID();
|
||||
data << packGUID;
|
||||
data << uint8(m_comboPoints);
|
||||
|
||||
if (m_movedByPlayer)
|
||||
m_movedByPlayer->ToPlayer()->SendDirectMessage(&data);
|
||||
|
||||
if (owner && owner != m_movedByPlayer)
|
||||
owner->SendDirectMessage(&data);
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::ClearComboPointHolders()
|
||||
{
|
||||
while (!m_ComboPointHolders.empty())
|
||||
{
|
||||
ObjectGuid guid = *m_ComboPointHolders.begin();
|
||||
|
||||
Player* player = ObjectAccessor::GetPlayer(*this, guid);
|
||||
if (player && player->GetComboTarget() == GetGUID()) // recheck for safe
|
||||
player->ClearComboPoints(); // remove also guid from m_ComboPointHolders;
|
||||
else
|
||||
m_ComboPointHolders.erase(guid); // or remove manually
|
||||
(*m_ComboPointHolders.begin())->ClearComboPoints(); // this also removes it from m_comboPointHolders
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16232,7 +16315,7 @@ void Unit::ClearAllReactives()
|
||||
if (getClass() == CLASS_HUNTER && HasAuraState(AURA_STATE_HUNTER_PARRY))
|
||||
ModifyAuraState(AURA_STATE_HUNTER_PARRY, false);
|
||||
if (getClass() == CLASS_WARRIOR && GetTypeId() == TYPEID_PLAYER)
|
||||
ToPlayer()->ClearComboPoints();
|
||||
ClearComboPoints();
|
||||
}
|
||||
|
||||
void Unit::UpdateReactives(uint32 p_time)
|
||||
@@ -16260,7 +16343,7 @@ void Unit::UpdateReactives(uint32 p_time)
|
||||
break;
|
||||
case REACTIVE_OVERPOWER:
|
||||
if (getClass() == CLASS_WARRIOR && GetTypeId() == TYPEID_PLAYER)
|
||||
ToPlayer()->ClearComboPoints();
|
||||
ClearComboPoints();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -2369,8 +2369,19 @@ public:
|
||||
void DisableRotate(bool apply);
|
||||
void DisableSpline();
|
||||
|
||||
void AddComboPointHolder(ObjectGuid lowguid) { m_ComboPointHolders.insert(lowguid); }
|
||||
void RemoveComboPointHolder(ObjectGuid lowguid) { m_ComboPointHolders.erase(lowguid); }
|
||||
///-----------Combo point system-------------------
|
||||
// This unit having CP on other units
|
||||
[[nodiscard]] uint8 GetComboPoints(Unit const* who = nullptr) const { return (who && m_comboTarget != who) ? 0 : m_comboPoints; }
|
||||
[[nodiscard]] uint8 GetComboPoints(ObjectGuid const& guid) const { return (m_comboTarget && m_comboTarget->GetGUID() == guid) ? m_comboPoints : 0; }
|
||||
[[nodiscard]] Unit* GetComboTarget() const { return m_comboTarget; }
|
||||
[[nodiscard]] ObjectGuid const GetComboTargetGUID() const { return m_comboTarget ? m_comboTarget->GetGUID() : ObjectGuid::Empty; }
|
||||
void AddComboPoints(Unit* target, int8 count);
|
||||
void AddComboPoints(int8 count) { AddComboPoints(nullptr, count); }
|
||||
void ClearComboPoints();
|
||||
void SendComboPoints();
|
||||
// Other units having CP on this unit
|
||||
void AddComboPointHolder(Unit* unit) { m_ComboPointHolders.insert(unit); }
|
||||
void RemoveComboPointHolder(Unit* unit) { m_ComboPointHolders.erase(unit); }
|
||||
void ClearComboPointHolders();
|
||||
|
||||
///----------Pet responses methods-----------------
|
||||
@@ -2647,9 +2658,10 @@ private:
|
||||
HostileRefMgr m_HostileRefMgr;
|
||||
|
||||
FollowerRefMgr m_FollowingRefMgr;
|
||||
Unit* m_comboTarget;
|
||||
|
||||
ComboPointHolderSet m_ComboPointHolders;
|
||||
Unit* m_comboTarget;
|
||||
int8 m_comboPoints;
|
||||
std::unordered_set<Unit*> m_ComboPointHolders;
|
||||
|
||||
RedirectThreatInfo _redirectThreatInfo;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user