aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Player/Player.cpp147
-rw-r--r--src/server/game/Entities/Player/Player.h5
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp4
-rw-r--r--src/server/game/Groups/Group.cpp10
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp2
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp2
-rw-r--r--src/server/game/Spells/SpellEffects.cpp2
-rw-r--r--src/server/scripts/Commands/cs_quest.cpp2
8 files changed, 77 insertions, 97 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 7498890db63..56ddc31a2b7 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -2034,37 +2034,6 @@ GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid const& guid, Gameo
return go;
}
-void Player::UpdateNearbyCreatureNpcFlags()
-{
- std::vector<Creature*> creatures;
- GetCreatureListWithOptionsInGrid(creatures, GetVisibilityRange(), { .IgnorePhases = false });
-
- UpdateData udata(GetMapId());
- UF::ObjectData::Base objMask;
- UF::UnitData::Base unitMask;
- for (uint32 i = 0; i < m_unitData->NpcFlags.size(); ++i)
- unitMask.MarkChanged(&UF::UnitData::NpcFlags, i);
-
- for (Creature* creature : creatures)
- {
- if (!HaveAtClient(creature))
- continue;
-
- // skip creatures which dont have any npcflags set
- if (!creature->GetNpcFlags() && !creature->GetNpcFlags2())
- continue;
-
- creature->BuildValuesUpdateForPlayerWithMask(&udata, objMask.GetChangesMask(), unitMask.GetChangesMask(), this);
- }
-
- if (!udata.HasData())
- return;
-
- WorldPacket packet;
- udata.BuildPacket(&packet);
- SendDirectMessage(&packet);
-}
-
bool Player::IsInAreaTriggerRadius(AreaTriggerEntry const* trigger) const
{
if (!trigger)
@@ -15027,8 +14996,6 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
sScriptMgr->OnQuestStatusChange(this, quest_id);
sScriptMgr->OnQuestStatusChange(this, quest, oldStatus, questStatusData.Status);
-
- UpdateNearbyCreatureNpcFlags();
}
void Player::CompleteQuest(uint32 quest_id)
@@ -15408,16 +15375,12 @@ void Player::RewardQuest(Quest const* quest, LootItemType rewardType, uint32 rew
UpdatePvPState();
}
- SendQuestGiverStatusMultiple();
-
- SendQuestUpdate(quest_id);
+ SendQuestUpdate(quest_id, true, true);
bool updateVisibility = false;
if (quest->HasFlag(QUEST_FLAGS_UPDATE_PHASESHIFT))
updateVisibility = PhasingHandler::OnConditionChange(this, false);
- UpdateNearbyCreatureNpcFlags();
-
//lets remove flag for delayed teleports
SetCanDelayTeleport(false);
@@ -15449,8 +15412,6 @@ void Player::RewardQuest(Quest const* quest, LootItemType rewardType, uint32 rew
if (updateVisibility)
UpdateObjectVisibility();
-
- UpdateNearbyCreatureNpcFlags();
}
void Player::SetRewardedQuest(uint32 quest_id)
@@ -16105,8 +16066,6 @@ void Player::SetQuestStatus(uint32 questId, QuestStatus status, bool update /*=
sScriptMgr->OnQuestStatusChange(this, quest, oldStatus, status);
}
- UpdateNearbyCreatureNpcFlags();
-
if (update)
SendQuestUpdate(questId);
}
@@ -16160,7 +16119,7 @@ void Player::RemoveRewardedQuest(uint32 questId, bool update /*= true*/)
SendQuestUpdate(questId);
}
-void Player::SendQuestUpdate(uint32 questId)
+void Player::SendQuestUpdate(uint32 questId, bool updateInteractions /*= true*/, bool updateGameObjectQuestGiverStatus /*= false*/)
{
SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(questId);
@@ -16208,7 +16167,8 @@ void Player::SendQuestUpdate(uint32 questId)
RemoveAurasDueToSpell(spellId);
}
- UpdateVisibleGameobjectsOrSpellClicks();
+ if (updateInteractions)
+ UpdateVisibleObjectInteractions(true, false, updateGameObjectQuestGiverStatus, true);
}
QuestGiverStatus Player::GetQuestDialogStatus(Object const* questgiver) const
@@ -16355,7 +16315,7 @@ void Player::SkipQuests(std::vector<uint32> const& questIds)
}
SetRewardedQuest(questId);
- SendQuestUpdate(questId);
+ SendQuestUpdate(questId, false);
if (!updateVisibility && quest->HasFlag(QUEST_FLAGS_UPDATE_PHASESHIFT))
updateVisibility = PhasingHandler::OnConditionChange(this, false);
@@ -16364,15 +16324,13 @@ void Player::SkipQuests(std::vector<uint32> const& questIds)
sScriptMgr->OnQuestStatusChange(this, quest, oldStatus, QUEST_STATUS_REWARDED);
}
- SendQuestGiverStatusMultiple();
+ UpdateVisibleObjectInteractions(true, false, true, true);
// make full db save
SaveToDB(false);
if (updateVisibility)
UpdateObjectVisibility();
-
- UpdateNearbyCreatureNpcFlags();
}
void Player::DespawnPersonalSummonsForQuest(uint32 questId)
@@ -16677,7 +16635,7 @@ void Player::ItemRemovedQuestCheck(uint32 entry, uint32 /*count*/)
IncompleteQuest(questId);
}
}
- UpdateVisibleGameobjectsOrSpellClicks();
+ UpdateVisibleObjectInteractions(true, false, false, true);
}
void Player::KilledMonster(CreatureTemplate const* cInfo, ObjectGuid guid)
@@ -16900,13 +16858,11 @@ void Player::UpdateQuestObjectiveProgress(QuestObjectiveType objectiveType, int3
}
if (anyObjectiveChangedCompletionState)
- UpdateVisibleGameobjectsOrSpellClicks();
+ UpdateVisibleObjectInteractions(true, false, false, true);
if (updatePhaseShift)
PhasingHandler::OnConditionChange(this);
- UpdateNearbyCreatureNpcFlags();
-
if (updateZoneAuras)
{
UpdateZoneDependentAuras(GetZoneId());
@@ -25155,33 +25111,37 @@ bool Player::HasQuestForGO(int32 GOId) const
return false;
}
-void Player::UpdateVisibleGameobjectsOrSpellClicks()
+void Player::UpdateVisibleObjectInteractions(bool allUnits, bool onlySpellClicks, bool gameObjectQuestGiverStatus, bool questObjectiveGameObjects)
{
- if (m_clientGUIDs.empty())
- return;
-
+ WorldPackets::Quest::QuestGiverStatusMultiple giverStatusMultiple;
UpdateData udata(GetMapId());
- WorldPacket packet;
- for (auto itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr)
+ for (ObjectGuid visibleObjectGuid : m_clientGUIDs)
{
- if (itr->IsGameObject())
+ if (visibleObjectGuid.IsGameObject() && (gameObjectQuestGiverStatus || questObjectiveGameObjects))
{
- if (GameObject* obj = ObjectAccessor::GetGameObject(*this, *itr))
+ GameObject* gameObject = ObjectAccessor::GetGameObject(*this, visibleObjectGuid);
+ if (!gameObject)
+ continue;
+
+ if (gameObjectQuestGiverStatus && gameObject->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER)
+ giverStatusMultiple.QuestGiver.emplace_back(visibleObjectGuid, GetQuestDialogStatus(gameObject));
+
+ if (questObjectiveGameObjects)
{
UF::ObjectData::Base objMask;
UF::GameObjectData::Base goMask;
- if (m_questObjectiveStatus.find({ QUEST_OBJECTIVE_GAMEOBJECT, int32(obj->GetEntry()) }) != m_questObjectiveStatus.end())
+ if (m_questObjectiveStatus.contains({ QUEST_OBJECTIVE_GAMEOBJECT, int32(gameObject->GetEntry()) }))
objMask.MarkChanged(&UF::ObjectData::DynamicFlags);
- switch (obj->GetGoType())
+ switch (gameObject->GetGoType())
{
case GAMEOBJECT_TYPE_QUESTGIVER:
case GAMEOBJECT_TYPE_CHEST:
case GAMEOBJECT_TYPE_GOOBER:
case GAMEOBJECT_TYPE_GENERIC:
case GAMEOBJECT_TYPE_GATHERING_NODE:
- if (sObjectMgr->IsGameObjectForQuests(obj->GetEntry()))
+ if (sObjectMgr->IsGameObjectForQuests(gameObject->GetEntry()))
objMask.MarkChanged(&UF::ObjectData::DynamicFlags);
break;
default:
@@ -25189,35 +25149,62 @@ void Player::UpdateVisibleGameobjectsOrSpellClicks()
}
if (objMask.GetChangesMask().IsAnySet() || goMask.GetChangesMask().IsAnySet())
- obj->BuildValuesUpdateForPlayerWithMask(&udata, objMask.GetChangesMask(), goMask.GetChangesMask(), this);
+ gameObject->BuildValuesUpdateForPlayerWithMask(&udata, objMask.GetChangesMask(), goMask.GetChangesMask(), this);
}
}
- else if (itr->IsCreatureOrVehicle())
+ else if (visibleObjectGuid.IsCreatureOrVehicle() && (allUnits || onlySpellClicks))
{
- Creature* obj = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, *itr);
- if (!obj)
+ Creature* creature = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, visibleObjectGuid);
+ if (!creature)
continue;
- // check if this unit requires quest specific flags
- if (!obj->HasNpcFlag(UNIT_NPC_FLAG_SPELLCLICK))
- continue;
+ if (allUnits)
+ {
+ UF::ObjectData::Base objMask;
+ UF::UnitData::Base unitMask;
+ for (uint32 i = 0; i < creature->m_unitData->NpcFlags.size(); ++i)
+ if (creature->m_unitData->NpcFlags[i])
+ unitMask.MarkChanged(&UF::UnitData::NpcFlags, i);
+
+ if (objMask.GetChangesMask().IsAnySet() || unitMask.GetChangesMask().IsAnySet())
+ creature->BuildValuesUpdateForPlayerWithMask(&udata, objMask.GetChangesMask(), unitMask.GetChangesMask(), this);
- auto clickBounds = sObjectMgr->GetSpellClickInfoMapBounds(obj->GetEntry());
- for (auto const& clickPair : clickBounds)
+ if (creature->IsQuestGiver())
+ giverStatusMultiple.QuestGiver.emplace_back(visibleObjectGuid, GetQuestDialogStatus(creature));
+ }
+ else if (onlySpellClicks)
{
- if (sConditionMgr->HasConditionsForSpellClickEvent(obj->GetEntry(), clickPair.second.spellId))
+ // check if this unit requires quest specific flags
+ if (!creature->HasNpcFlag(UNIT_NPC_FLAG_SPELLCLICK))
+ continue;
+
+ auto clickBounds = sObjectMgr->GetSpellClickInfoMapBounds(creature->GetEntry());
+ for (auto const& clickPair : clickBounds)
{
- UF::ObjectData::Base objMask;
- UF::UnitData::Base unitMask;
- unitMask.MarkChanged(&UF::UnitData::NpcFlags, 0); // NpcFlags[0] has UNIT_NPC_FLAG_SPELLCLICK
- obj->BuildValuesUpdateForPlayerWithMask(&udata, objMask.GetChangesMask(), unitMask.GetChangesMask(), this);
- break;
+ if (sConditionMgr->HasConditionsForSpellClickEvent(creature->GetEntry(), clickPair.second.spellId))
+ {
+ UF::ObjectData::Base objMask;
+ UF::UnitData::Base unitMask;
+ unitMask.MarkChanged(&UF::UnitData::NpcFlags, 0); // NpcFlags[0] has UNIT_NPC_FLAG_SPELLCLICK
+ creature->BuildValuesUpdateForPlayerWithMask(&udata, objMask.GetChangesMask(), unitMask.GetChangesMask(), this);
+ break;
+ }
}
}
}
}
- udata.BuildPacket(&packet);
- SendDirectMessage(&packet);
+
+ // If as a result of npcflag updates we stop seeing UNIT_NPC_FLAG_QUESTGIVER then
+ // we must also send SMSG_QUEST_GIVER_STATUS_MULTIPLE because client will not request it automatically
+ if (!giverStatusMultiple.QuestGiver.empty())
+ SendDirectMessage(giverStatusMultiple.Write());
+
+ if (udata.HasData())
+ {
+ WorldPacket packet;
+ udata.BuildPacket(&packet);
+ SendDirectMessage(&packet);
+ }
}
bool Player::HasSummonPending() const
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 80eed2d2ccd..e5a39a319fc 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1150,7 +1150,6 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
Creature* GetNPCIfCanInteractWith(ObjectGuid const& guid, NPCFlags npcFlags, NPCFlags2 npcFlags2) const;
GameObject* GetGameObjectIfCanInteractWith(ObjectGuid const& guid) const;
GameObject* GetGameObjectIfCanInteractWith(ObjectGuid const& guid, GameobjectTypes type) const;
- void UpdateNearbyCreatureNpcFlags();
void ToggleAFK();
void ToggleDND();
@@ -1595,7 +1594,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
void SetQuestStatus(uint32 questId, QuestStatus status, bool update = true);
void RemoveActiveQuest(uint32 questId, bool update = true);
void RemoveRewardedQuest(uint32 questId, bool update = true);
- void SendQuestUpdate(uint32 questId);
+ void SendQuestUpdate(uint32 questId, bool updateInteractions = true, bool updateGameObjectQuestGiverStatus = false);
QuestGiverStatus GetQuestDialogStatus(Object const* questGiver) const;
void SkipQuests(std::vector<uint32> const& questIds); // removes quest from log, flags rewarded, but does not give any rewards to player
void DespawnPersonalSummonsForQuest(uint32 questId);
@@ -1646,7 +1645,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
bool HasQuestForItem(uint32 itemId) const;
QuestObjective const* GetQuestObjectiveForItem(uint32 itemId, bool onlyIncomplete) const;
bool HasQuestForGO(int32 goId) const;
- void UpdateVisibleGameobjectsOrSpellClicks();
+ void UpdateVisibleObjectInteractions(bool allUnits, bool onlySpellClicks, bool gameObjectQuestGiverStatus, bool questObjectiveGameObjects);
bool CanShareQuest(uint32 questId) const;
int32 GetQuestObjectiveData(QuestObjective const& objective) const;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 7648dd96fe3..45252511720 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -3443,7 +3443,7 @@ void Unit::_ApplyAura(AuraApplication* aurApp, uint32 effMask)
if (Player* player = ToPlayer())
{
if (sConditionMgr->IsSpellUsedInSpellClickConditions(aurApp->GetBase()->GetId()))
- player->UpdateVisibleGameobjectsOrSpellClicks();
+ player->UpdateVisibleObjectInteractions(false, true, false, false);
player->FailCriteria(CriteriaFailEvent::GainAura, aurApp->GetBase()->GetId());
player->StartCriteria(CriteriaStartEvent::GainAura, aurApp->GetBase()->GetId());
@@ -3538,7 +3538,7 @@ void Unit::_UnapplyAura(AuraApplicationMap::iterator& i, AuraRemoveMode removeMo
if (Player* player = ToPlayer())
{
if (sConditionMgr->IsSpellUsedInSpellClickConditions(aurApp->GetBase()->GetId()))
- player->UpdateVisibleGameobjectsOrSpellClicks();
+ player->UpdateVisibleObjectInteractions(false, true, false, false);
player->FailCriteria(CriteriaFailEvent::LoseAura, aurApp->GetBase()->GetId());
}
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index c98dcee1152..ea6c783571e 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -319,7 +319,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->UpdateVisibleGameobjectsOrSpellClicks();
+ player->UpdateVisibleObjectInteractions(false, true, false, true);
}
void Group::ConvertToGroup()
@@ -350,7 +350,7 @@ void Group::ConvertToGroup()
// 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->UpdateVisibleGameobjectsOrSpellClicks();
+ player->UpdateVisibleObjectInteractions(false, true, false, true);
}
bool Group::AddInvite(Player* player)
@@ -523,7 +523,7 @@ bool Group::AddMember(Player* player)
// quest related GO state dependent from raid membership
if (isRaidGroup())
- player->UpdateVisibleGameobjectsOrSpellClicks();
+ player->UpdateVisibleObjectInteractions(false, true, false, true);
player->FailCriteria(CriteriaFailEvent::ModifyPartyStatus, 0);
@@ -613,7 +613,7 @@ bool Group::RemoveMember(ObjectGuid guid, RemoveMethod method /*= GROUP_REMOVEME
player->SetGroup(nullptr);
// quest related GO state dependent from raid membership
- player->UpdateVisibleGameobjectsOrSpellClicks();
+ player->UpdateVisibleObjectInteractions(false, true, false, true);
}
player->SetPartyType(m_groupCategory, GROUP_TYPE_NONE);
@@ -758,7 +758,7 @@ void Group::Disband(bool hideDestroy /* = false */)
// quest related GO state dependent from raid membership
if (isRaidGroup())
- player->UpdateVisibleGameobjectsOrSpellClicks();
+ player->UpdateVisibleObjectInteractions(false, true, false, true);
if (!hideDestroy)
player->SendDirectMessage(WorldPackets::Party::GroupDestroyed().Write());
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 2416a635d1d..e7baa92f361 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -550,7 +550,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPackets::AreaTrigger::AreaTrigge
}
if (anyObjectiveChangedCompletionState)
- player->UpdateVisibleGameobjectsOrSpellClicks();
+ player->UpdateVisibleObjectInteractions(true, false, false, true);
}
}
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index 4e86ba962d1..e98b85608aa 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -490,8 +490,6 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPackets::Quest::QuestLogRemove
if (quest)
sScriptMgr->OnQuestStatusChange(_player, quest, oldStatus, QUEST_STATUS_NONE);
-
- _player->UpdateNearbyCreatureNpcFlags();
}
_player->UpdateCriteria(CriteriaType::AbandonAnyQuest, 1);
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 9425c36e836..72d0271d656 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -4018,8 +4018,6 @@ void Spell::EffectQuestClear()
sScriptMgr->OnQuestStatusChange(player, quest_id);
sScriptMgr->OnQuestStatusChange(player, quest, oldStatus, QUEST_STATUS_NONE);
-
- player->UpdateNearbyCreatureNpcFlags();
}
void Spell::EffectSendTaxi()
diff --git a/src/server/scripts/Commands/cs_quest.cpp b/src/server/scripts/Commands/cs_quest.cpp
index bf8d4ebcddf..3dd04ef8eea 100644
--- a/src/server/scripts/Commands/cs_quest.cpp
+++ b/src/server/scripts/Commands/cs_quest.cpp
@@ -142,8 +142,6 @@ public:
sScriptMgr->OnQuestStatusChange(player, quest->GetQuestId());
sScriptMgr->OnQuestStatusChange(player, quest, oldStatus, QUEST_STATUS_NONE);
- player->UpdateNearbyCreatureNpcFlags();
-
handler->SendSysMessage(LANG_COMMAND_QUEST_REMOVED);
return true;
}