Core/Conditions: allow spellclick conditions to properly work for aura apply/remove (#23527)

# Conflicts:
#	src/server/game/Entities/Player/Player.cpp
This commit is contained in:
Wyrserth
2019-07-05 14:11:15 +02:00
committed by Ovahlord
parent 75ae86d062
commit 3cd1fa44ef
6 changed files with 34 additions and 25 deletions

View File

@@ -1015,6 +1015,11 @@ bool ConditionMgr::IsObjectMeetingVendorItemConditions(uint32 creatureId, uint32
return true;
}
bool ConditionMgr::IsSpellUsedInSpellClickConditions(uint32 spellId) const
{
return SpellsUsedInSpellClickConditions.find(spellId) != SpellsUsedInSpellClickConditions.end();
}
ConditionMgr* ConditionMgr::instance()
{
static ConditionMgr instance;
@@ -1218,6 +1223,8 @@ void ConditionMgr::LoadConditions(bool isReload)
case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT:
{
SpellClickEventConditionStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);
if (cond->ConditionType == CONDITION_AURA)
SpellsUsedInSpellClickConditions.insert(cond->ConditionValue1);
valid = true;
++count;
continue; // do not add to m_AllocatedMemory to avoid double deleting
@@ -1270,6 +1277,8 @@ void ConditionMgr::LoadConditions(bool isReload)
//handle not grouped conditions
//add new Condition to storage based on Type/Entry
if (cond->SourceType == CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT && cond->ConditionType == CONDITION_AURA)
SpellsUsedInSpellClickConditions.insert(cond->ConditionValue1);
ConditionStore[cond->SourceType][cond->SourceEntry].push_back(cond);
++count;
}
@@ -2412,6 +2421,7 @@ void ConditionMgr::Clean()
delete *i;
SpellClickEventConditionStore.clear();
SpellsUsedInSpellClickConditions.clear();
for (ConditionEntriesByCreatureIdMap::iterator itr = NpcVendorConditionContainerStore.begin(); itr != NpcVendorConditionContainerStore.end(); ++itr)
for (ConditionsByEntryMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it)

View File

@@ -23,6 +23,7 @@
#include "Hash.h"
#include <array>
#include <unordered_map>
#include <unordered_set>
#include <vector>
class Creature;
@@ -261,6 +262,8 @@ class TC_GAME_API ConditionMgr
bool IsObjectMeetingSmartEventConditions(int32 entryOrGuid, uint32 eventId, uint32 sourceType, Unit* unit, WorldObject* baseObject) const;
bool IsObjectMeetingVendorItemConditions(uint32 creatureId, uint32 itemId, Player* player, Creature* vendor) const;
bool IsSpellUsedInSpellClickConditions(uint32 spellId) const;
struct ConditionTypeInfo
{
char const* Name;
@@ -291,6 +294,8 @@ class TC_GAME_API ConditionMgr
ConditionEntriesByCreatureIdMap SpellClickEventConditionStore;
ConditionEntriesByCreatureIdMap NpcVendorConditionContainerStore;
SmartEventConditionContainer SmartEventConditionStore;
std::unordered_set<uint32> SpellsUsedInSpellClickConditions;
};
#define sConditionMgr ConditionMgr::instance()

View File

@@ -16231,7 +16231,7 @@ void Player::SendQuestUpdate(uint32 questId)
}
}
UpdateForQuestWorldObjects();
UpdateVisibleGameobjectsOrSpellClicks();
PhasingHandler::OnConditionChange(this);
}
@@ -16525,17 +16525,13 @@ void Player::ItemAddedQuestCheck(uint32 entry, uint32 count)
{
q_status.ItemCount[j] = std::min<uint16>(q_status.ItemCount[j] + count, reqitemcount);
m_QuestStatusSave[questid] = QUEST_DEFAULT_SAVE_TYPE;
//SendQuestUpdateAddItem(qInfo, j, additemcount);
// FIXME: verify if there's any packet sent updating item
}
if (CanCompleteQuest(questid))
CompleteQuest(questid);
return;
}
}
}
UpdateForQuestWorldObjects();
UpdateVisibleGameobjectsOrSpellClicks();
}
void Player::ItemRemovedQuestCheck(uint32 entry, uint32 count)
@@ -16578,7 +16574,7 @@ void Player::ItemRemovedQuestCheck(uint32 entry, uint32 count)
}
}
}
UpdateForQuestWorldObjects();
UpdateVisibleGameobjectsOrSpellClicks();
}
void Player::KilledMonster(CreatureTemplate const* cInfo, ObjectGuid guid)
@@ -24680,7 +24676,7 @@ bool Player::HasQuestForGO(int32 GOId) const
return false;
}
void Player::UpdateForQuestWorldObjects()
void Player::UpdateVisibleGameobjectsOrSpellClicks()
{
if (m_clientGUIDs.empty())
return;
@@ -24707,20 +24703,10 @@ void Player::UpdateForQuestWorldObjects()
SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(obj->GetEntry());
for (SpellClickInfoContainer::const_iterator _itr = clickPair.first; _itr != clickPair.second; ++_itr)
{
//! This code doesn't look right, but it was logically converted to condition system to do the exact
//! same thing it did before. It definitely needs to be overlooked for intended functionality.
if (ConditionContainer const* conds = sConditionMgr->GetConditionsForSpellClickEvent(obj->GetEntry(), _itr->second.spellId))
{
bool buildUpdateBlock = false;
for (ConditionContainer::const_iterator jtr = conds->begin(); jtr != conds->end() && !buildUpdateBlock; ++jtr)
if ((*jtr)->ConditionType == CONDITION_QUESTREWARDED || (*jtr)->ConditionType == CONDITION_QUESTTAKEN || (*jtr)->ConditionType == CONDITION_QUEST_COMPLETE)
buildUpdateBlock = true;
if (buildUpdateBlock)
{
obj->BuildValuesUpdateBlockForPlayer(&udata, this);
break;
}
obj->BuildValuesUpdateBlockForPlayer(&udata, this);
break;
}
}
}

View File

@@ -1437,7 +1437,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void ReputationChanged2(FactionEntry const* factionEntry);
bool HasQuestForItem(uint32 itemId, uint32 excludeQuestId = 0, bool turnIn = false) const;
bool HasQuestForGO(int32 goId) const;
void UpdateForQuestWorldObjects();
void UpdateVisibleGameobjectsOrSpellClicks();
bool CanShareQuest(uint32 questId) const;
void SendQuestComplete(Quest const* quest) const;

View File

@@ -3517,6 +3517,10 @@ void Unit::_ApplyAura(AuraApplication * aurApp, uint8 effMask)
if (effMask & 1 << i && (!aurApp->GetRemoveMode()))
aurApp->_HandleEffect(i, true);
}
if (Player* player = ToPlayer())
if (sConditionMgr->IsSpellUsedInSpellClickConditions(aurApp->GetBase()->GetId()))
player->UpdateVisibleGameobjectsOrSpellClicks();
}
// removes aura application from lists and unapplies effects
@@ -3593,6 +3597,10 @@ void Unit::_UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMo
aura->HandleAuraSpecificMods(aurApp, caster, false, false);
if (Player* player = ToPlayer())
if (sConditionMgr->IsSpellUsedInSpellClickConditions(aurApp->GetBase()->GetId()))
player->UpdateVisibleGameobjectsOrSpellClicks();
// only way correctly remove all auras from list
//if (removedAuras != m_removedAurasCount) new aura may be added
i = m_appliedAuras.begin();

View File

@@ -291,7 +291,7 @@ void Group::ConvertToRaid()
// update quest related GO states (quest activity dependent from raid membership)
for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
if (Player* player = ObjectAccessor::FindPlayer(citr->guid))
player->UpdateForQuestWorldObjects();
player->UpdateVisibleGameobjectsOrSpellClicks();
}
void Group::ConvertToGroup()
@@ -489,7 +489,7 @@ bool Group::AddMember(Player* player)
// quest related GO state dependent from raid membership
if (isRaidGroup())
player->UpdateForQuestWorldObjects();
player->UpdateVisibleGameobjectsOrSpellClicks();
{
// Broadcast new player group member fields to rest of the group
@@ -585,7 +585,7 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R
player->SetGroup(nullptr);
// quest related GO state dependent from raid membership
player->UpdateForQuestWorldObjects();
player->UpdateVisibleGameobjectsOrSpellClicks();
}
WorldPacket data;
@@ -821,7 +821,7 @@ void Group::Disband(bool hideDestroy /* = false */)
// quest related GO state dependent from raid membership
if (isRaidGroup())
player->UpdateForQuestWorldObjects();
player->UpdateVisibleGameobjectsOrSpellClicks();
if (!player->GetSession())
continue;