fix(Core/Entities): extend combo point system to all Units (#9816)

- Closes #1140
This commit is contained in:
UltraNix
2022-01-07 11:18:03 +01:00
committed by GitHub
parent 2e6213d526
commit 2c6a692000
9 changed files with 217 additions and 182 deletions

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;