aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorModoX <moardox@gmail.com>2024-02-24 15:05:21 +0100
committerGitHub <noreply@github.com>2024-02-24 15:05:21 +0100
commitdd15d763cc0529afc9b7f077817645d875608626 (patch)
tree2a20e5e9b23609f856195ad26789dbabe263c581
parent7751d278b1e594ea5abb8d292a42be361886ba5e (diff)
Core/Creatures: Implemented UNIT_NPC_FLAG_GOSSIP as viewer dependent and update npcflags on quest changes (#29646)
-rw-r--r--src/server/game/Entities/Object/Updates/ViewerDependentValues.h12
-rw-r--r--src/server/game/Entities/Player/Player.cpp78
-rw-r--r--src/server/game/Entities/Player/Player.h4
-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
6 files changed, 96 insertions, 4 deletions
diff --git a/src/server/game/Entities/Object/Updates/ViewerDependentValues.h b/src/server/game/Entities/Object/Updates/ViewerDependentValues.h
index 852ba9b86e3..b6c3c61bb6a 100644
--- a/src/server/game/Entities/Object/Updates/ViewerDependentValues.h
+++ b/src/server/game/Entities/Object/Updates/ViewerDependentValues.h
@@ -326,9 +326,17 @@ public:
static value_type GetValue(UF::UnitData const* unitData, uint32 i, Unit const* unit, Player const* receiver)
{
value_type npcFlag = unitData->NpcFlags[i];
- if (i == 0 && unit->IsCreature() && !receiver->CanSeeSpellClickOn(unit->ToCreature()))
- npcFlag &= ~UNIT_NPC_FLAG_SPELLCLICK;
+ if (i == 0)
+ {
+ if (Creature const* creature = unit->ToCreature())
+ {
+ if (!receiver->CanSeeGossipOn(creature))
+ npcFlag &= ~(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER);
+ if (!receiver->CanSeeSpellClickOn(creature))
+ npcFlag &= ~UNIT_NPC_FLAG_SPELLCLICK;
+ }
+ }
return npcFlag;
}
};
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 51e79741296..f0a1d0ab99f 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -2033,6 +2033,37 @@ 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)
@@ -14362,7 +14393,7 @@ uint32 Player::GetGossipTextId(uint32 menuId, WorldObject* source)
return textId;
}
-uint32 Player::GetGossipMenuForSource(WorldObject* source)
+uint32 Player::GetGossipMenuForSource(WorldObject const* source) const
{
switch (source->GetTypeId())
{
@@ -14995,6 +15026,8 @@ 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)
@@ -15382,6 +15415,8 @@ void Player::RewardQuest(Quest const* quest, LootItemType rewardType, uint32 rew
if (quest->HasFlag(QUEST_FLAGS_UPDATE_PHASESHIFT))
updateVisibility = PhasingHandler::OnConditionChange(this, false);
+ UpdateNearbyCreatureNpcFlags();
+
//lets remove flag for delayed teleports
SetCanDelayTeleport(false);
@@ -15413,6 +15448,8 @@ void Player::RewardQuest(Quest const* quest, LootItemType rewardType, uint32 rew
if (updateVisibility)
UpdateObjectVisibility();
+
+ UpdateNearbyCreatureNpcFlags();
}
void Player::SetRewardedQuest(uint32 quest_id)
@@ -16067,6 +16104,8 @@ void Player::SetQuestStatus(uint32 questId, QuestStatus status, bool update /*=
sScriptMgr->OnQuestStatusChange(this, quest, oldStatus, status);
}
+ UpdateNearbyCreatureNpcFlags();
+
if (update)
SendQuestUpdate(questId);
}
@@ -16331,6 +16370,8 @@ void Player::SkipQuests(std::vector<uint32> const& questIds)
if (updateVisibility)
UpdateObjectVisibility();
+
+ UpdateNearbyCreatureNpcFlags();
}
void Player::DespawnPersonalSummonsForQuest(uint32 questId)
@@ -16863,6 +16904,8 @@ void Player::UpdateQuestObjectiveProgress(QuestObjectiveType objectiveType, int3
if (updatePhaseShift)
PhasingHandler::OnConditionChange(this);
+ UpdateNearbyCreatureNpcFlags();
+
if (updateZoneAuras)
{
UpdateZoneDependentAuras(GetZoneId());
@@ -27086,6 +27129,39 @@ bool Player::IsPetNeedBeTemporaryUnsummoned() const
return !IsInWorld() || !IsAlive() || HasUnitMovementFlag(MOVEMENTFLAG_FLYING) || HasExtraUnitMovementFlag2(MOVEMENTFLAG3_ADV_FLYING);
}
+bool Player::CanSeeGossipOn(Creature const* creature) const
+{
+ if (creature->HasNpcFlag(UNIT_NPC_FLAG_GOSSIP))
+ {
+ if (GetGossipMenuForSource(creature))
+ return true;
+ }
+
+ // for cases with questgiver/ender without gossip menus
+ if (creature->HasNpcFlag(UNIT_NPC_FLAG_QUESTGIVER))
+ {
+ QuestRelationResult objectQIR = sObjectMgr->GetCreatureQuestInvolvedRelations(creature->GetEntry());
+ for (uint32 quest_id : objectQIR)
+ {
+ QuestStatus status = GetQuestStatus(quest_id);
+ if (status == QUEST_STATUS_COMPLETE || status == QUEST_STATUS_INCOMPLETE)
+ return true;
+ }
+
+ QuestRelationResult objectQR = sObjectMgr->GetCreatureQuestRelations(creature->GetEntry());
+ for (uint32 quest_id : objectQR)
+ {
+ Quest const* quest = sObjectMgr->GetQuestTemplate(quest_id);
+ if (!quest)
+ continue;
+
+ if (CanTakeQuest(quest, false))
+ return true;
+ }
+ }
+ return false;
+}
+
bool Player::CanSeeSpellClickOn(Creature const* c) const
{
if (!c->HasNpcFlag(UNIT_NPC_FLAG_SPELLCLICK))
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 446a0725333..da3e165ffe3 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1150,6 +1150,7 @@ 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();
@@ -1531,7 +1532,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
uint32 GetGossipTextId(uint32 menuId, WorldObject* source);
uint32 GetGossipTextId(WorldObject* source);
- uint32 GetGossipMenuForSource(WorldObject* source);
+ uint32 GetGossipMenuForSource(WorldObject const* source) const;
/*********************************************************/
/*** QUEST SYSTEM ***/
@@ -2663,6 +2664,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
void SetKnownTitles(uint32 index, uint64 mask) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::KnownTitles, index), mask); }
//bool isActiveObject() const { return true; }
+ bool CanSeeGossipOn(Creature const* creature) const;
bool CanSeeSpellClickOn(Creature const* creature) const;
uint32 GetChampioningFaction() const { return m_ChampioningFaction; }
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index e98b85608aa..4e86ba962d1 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -490,6 +490,8 @@ 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 06c3ccaf4ad..ecbba144f33 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -4030,6 +4030,8 @@ 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 3dd04ef8eea..bf8d4ebcddf 100644
--- a/src/server/scripts/Commands/cs_quest.cpp
+++ b/src/server/scripts/Commands/cs_quest.cpp
@@ -142,6 +142,8 @@ public:
sScriptMgr->OnQuestStatusChange(player, quest->GetQuestId());
sScriptMgr->OnQuestStatusChange(player, quest, oldStatus, QUEST_STATUS_NONE);
+ player->UpdateNearbyCreatureNpcFlags();
+
handler->SendSysMessage(LANG_COMMAND_QUEST_REMOVED);
return true;
}