From 0325d8b523214a6905b4d2be629792902dadf24c Mon Sep 17 00:00:00 2001 From: hondacrx Date: Mon, 4 Mar 2024 12:18:45 -0500 Subject: [PATCH] Core/Quests: Merged UpdateNearbyCreatureNpcFlags, UpdateVisibleGameobjectsOrSpellClicks and SendQuestGiverStatusMultiple on quest actions * Fixes quest markers above NPC heads not disappearing when player stops seeing questgiver npc flag Port From (https://github.com/TrinityCore/TrinityCore/commit/97d7ccd180f96a414f205396261907e1e87d491a) --- Source/Game/Chat/Commands/QuestCommands.cs | 2 - Source/Game/Entities/Player/Player.Quest.cs | 123 +++++++++++--------- Source/Game/Entities/Player/Player.cs | 29 ----- Source/Game/Entities/Unit/Unit.Spells.cs | 4 +- Source/Game/Groups/Group.cs | 10 +- Source/Game/Handlers/MiscHandler.cs | 2 +- Source/Game/Handlers/QuestHandler.cs | 2 - Source/Game/Spells/SpellEffects.cs | 2 - 8 files changed, 78 insertions(+), 96 deletions(-) diff --git a/Source/Game/Chat/Commands/QuestCommands.cs b/Source/Game/Chat/Commands/QuestCommands.cs index 887adf5e9..24dd586fc 100644 --- a/Source/Game/Chat/Commands/QuestCommands.cs +++ b/Source/Game/Chat/Commands/QuestCommands.cs @@ -112,8 +112,6 @@ namespace Game.Chat Global.ScriptMgr.OnQuestStatusChange(player, quest.Id); Global.ScriptMgr.OnQuestStatusChange(player, quest, oldStatus, QuestStatus.None); - player.UpdateNearbyCreatureNpcFlags(); - handler.SendSysMessage(CypherStrings.CommandQuestRemoved); return true; } diff --git a/Source/Game/Entities/Player/Player.Quest.cs b/Source/Game/Entities/Player/Player.Quest.cs index 0aefc1f4b..78b582a91 100644 --- a/Source/Game/Entities/Player/Player.Quest.cs +++ b/Source/Game/Entities/Player/Player.Quest.cs @@ -841,8 +841,6 @@ namespace Game.Entities Global.ScriptMgr.OnQuestStatusChange(this, questId); Global.ScriptMgr.OnQuestStatusChange(this, quest, oldStatus, questStatusData.Status); - - UpdateNearbyCreatureNpcFlags(); } public void CompleteQuest(uint quest_id) @@ -1222,16 +1220,12 @@ namespace Game.Entities UpdatePvPState(); } - SendQuestGiverStatusMultiple(); - - SendQuestUpdate(questId); + SendQuestUpdate(questId, true, true); bool updateVisibility = false; if (quest.HasFlag(QuestFlags.UpdatePhaseshift)) updateVisibility = PhasingHandler.OnConditionChange(this, false); - UpdateNearbyCreatureNpcFlags(); - //lets remove flag for delayed teleports SetCanDelayTeleport(false); @@ -1262,8 +1256,6 @@ namespace Game.Entities if (updateVisibility) UpdateObjectVisibility(); - - UpdateNearbyCreatureNpcFlags(); } public void SetRewardedQuest(uint questId) @@ -1916,8 +1908,6 @@ namespace Game.Entities Global.ScriptMgr.OnQuestStatusChange(this, quest, oldStatus, status); } - UpdateNearbyCreatureNpcFlags(); - if (update) SendQuestUpdate(questId); } @@ -1968,7 +1958,7 @@ namespace Game.Entities SendQuestUpdate(questId); } - void SendQuestUpdate(uint questId) + void SendQuestUpdate(uint questId, bool updateInteractions = true, bool updateGameObjectQuestGiverStatus = false) { var saBounds = Global.SpellMgr.GetSpellAreaForQuestMapBounds(questId); if (!saBounds.Empty()) @@ -2015,7 +2005,8 @@ namespace Game.Entities RemoveAurasDueToSpell(spellId); } - UpdateVisibleGameobjectsOrSpellClicks(); + if (updateInteractions) + UpdateVisibleObjectInteractions(true, false, updateGameObjectQuestGiverStatus, true); } public QuestGiverStatus GetQuestDialogStatus(WorldObject questgiver) @@ -2176,7 +2167,7 @@ namespace Game.Entities } SetRewardedQuest(questId); - SendQuestUpdate(questId); + SendQuestUpdate(questId, false); if (!updateVisibility && quest.HasFlag(QuestFlags.UpdatePhaseshift)) updateVisibility = PhasingHandler.OnConditionChange(this, false); @@ -2185,15 +2176,13 @@ namespace Game.Entities Global.ScriptMgr.OnQuestStatusChange(this, quest, oldStatus, QuestStatus.Rewarded); } - SendQuestGiverStatusMultiple(); + UpdateVisibleObjectInteractions(true, false, true, true); // make full db save SaveToDB(false); if (updateVisibility) UpdateObjectVisibility(); - - UpdateNearbyCreatureNpcFlags(); } public void DespawnPersonalSummonsForQuest(uint questId) @@ -2488,7 +2477,7 @@ namespace Game.Entities } } - UpdateVisibleGameobjectsOrSpellClicks(); + UpdateVisibleObjectInteractions(true, false, false, true); } public void KilledMonster(CreatureTemplate cInfo, ObjectGuid guid) @@ -2710,13 +2699,11 @@ namespace Game.Entities } if (anyObjectiveChangedCompletionState) - UpdateVisibleGameobjectsOrSpellClicks(); + UpdateVisibleObjectInteractions(true, false, false, true); if (updatePhaseShift) PhasingHandler.OnConditionChange(this); - UpdateNearbyCreatureNpcFlags(); - if (updateZoneAuras) { UpdateZoneDependentAuras(GetZoneId()); @@ -3294,70 +3281,100 @@ namespace Game.Entities return false; } - public void UpdateVisibleGameobjectsOrSpellClicks() + public void UpdateVisibleObjectInteractions(bool allUnits, bool onlySpellClicks, bool gameObjectQuestGiverStatus, bool questObjectiveGameObjects) { - if (m_clientGUIDs.Empty()) - return; - + QuestGiverStatusMultiple giverStatusMultiple = new(); UpdateData udata = new(GetMapId()); - UpdateObject packet; - foreach (var guid in m_clientGUIDs) + foreach (var visibleObjectGuid in m_clientGUIDs) { - if (guid.IsGameObject()) + if (visibleObjectGuid.IsGameObject() && (gameObjectQuestGiverStatus || questObjectiveGameObjects)) { - GameObject obj = ObjectAccessor.GetGameObject(this, guid); - if (obj != null) + GameObject gameObject = ObjectAccessor.GetGameObject(this, visibleObjectGuid); + if (gameObject == null) + continue; + + if (gameObjectQuestGiverStatus && gameObject.GetGoType() == GameObjectTypes.QuestGiver) + giverStatusMultiple.QuestGiver.Add(new QuestGiverInfo(visibleObjectGuid, GetQuestDialogStatus(gameObject))); + + if (questObjectiveGameObjects) { ObjectFieldData objMask = new(); GameObjectFieldData goMask = new(); - if (m_questObjectiveStatus.ContainsKey((QuestObjectiveType.GameObject, (int)obj.GetEntry()))) - objMask.MarkChanged(obj.m_objectData.DynamicFlags); + if (m_questObjectiveStatus.ContainsKey((QuestObjectiveType.GameObject, (int)gameObject.GetEntry()))) + objMask.MarkChanged(gameObject.m_objectData.DynamicFlags); - switch (obj.GetGoType()) + switch (gameObject.GetGoType()) { case GameObjectTypes.QuestGiver: case GameObjectTypes.Chest: case GameObjectTypes.Goober: case GameObjectTypes.Generic: case GameObjectTypes.GatheringNode: - if (Global.ObjectMgr.IsGameObjectForQuests(obj.GetEntry())) - objMask.MarkChanged(obj.m_objectData.DynamicFlags); + if (Global.ObjectMgr.IsGameObjectForQuests(gameObject.GetEntry())) + objMask.MarkChanged(gameObject.m_objectData.DynamicFlags); break; default: break; } if (objMask.GetUpdateMask().IsAnySet() || goMask.GetUpdateMask().IsAnySet()) - obj.BuildValuesUpdateForPlayerWithMask(udata, objMask.GetUpdateMask(), goMask.GetUpdateMask(), this); + gameObject.BuildValuesUpdateForPlayerWithMask(udata, objMask.GetUpdateMask(), goMask.GetUpdateMask(), this); } + } - else if (guid.IsCreatureOrVehicle()) + else if (visibleObjectGuid.IsCreatureOrVehicle() && (allUnits || onlySpellClicks)) { - Creature obj = ObjectAccessor.GetCreatureOrPetOrVehicle(this, guid); - if (obj == null) + Creature creature = ObjectAccessor.GetCreatureOrPetOrVehicle(this, visibleObjectGuid); + if (creature == null) continue; - // check if this unit requires quest specific flags - if (!obj.HasNpcFlag(NPCFlags.SpellClick)) - continue; - - var clickBounds = Global.ObjectMgr.GetSpellClickInfoMapBounds(obj.GetEntry()); - foreach (var spellClickInfo in clickBounds) + if (allUnits) { - if (Global.ConditionMgr.HasConditionsForSpellClickEvent(obj.GetEntry(), spellClickInfo.spellId)) + ObjectFieldData objMask = new(); + UnitData unitMask = new(); + for (int i = 0; i < creature.m_unitData.NpcFlags.GetSize(); ++i) + if (creature.m_unitData.NpcFlags[i] != 0) + unitMask.MarkChanged(creature.m_unitData.NpcFlags, i); + + if (objMask.GetUpdateMask().IsAnySet() || unitMask.GetUpdateMask().IsAnySet()) + creature.BuildValuesUpdateForPlayerWithMask(udata, objMask.GetUpdateMask(), unitMask.GetUpdateMask(), this); + + if (creature.IsQuestGiver()) + giverStatusMultiple.QuestGiver.Add(new QuestGiverInfo(visibleObjectGuid, GetQuestDialogStatus(creature))); + } + else if (onlySpellClicks) + { + // check if this unit requires quest specific flags + if (!creature.HasNpcFlag(NPCFlags.SpellClick)) + continue; + + var clickBounds = Global.ObjectMgr.GetSpellClickInfoMapBounds(creature.GetEntry()); + foreach (var spellClickInfo in clickBounds) { - ObjectFieldData objMask = new(); - UnitData unitMask = new(); - unitMask.MarkChanged(m_unitData.NpcFlags, 0); // NpcFlags[0] has UNIT_NPC_FLAG_SPELLCLICK - obj.BuildValuesUpdateForPlayerWithMask(udata, objMask.GetUpdateMask(), unitMask.GetUpdateMask(), this); - break; + if (Global.ConditionMgr.HasConditionsForSpellClickEvent(creature.GetEntry(), spellClickInfo.spellId)) + { + ObjectFieldData objMask = new(); + UnitData unitMask = new(); + unitMask.MarkChanged(m_unitData.NpcFlags, 0); // NpcFlags[0] has UNIT_NPC_FLAG_SPELLCLICK + creature.BuildValuesUpdateForPlayerWithMask(udata, objMask.GetUpdateMask(), unitMask.GetUpdateMask(), this); + break; + } } } } } - udata.BuildPacket(out packet); - SendPacket(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()) + SendPacket(giverStatusMultiple); + + if (udata.HasData()) + { + udata.BuildPacket(out var packet); + SendPacket(packet); + } } void SetDailyQuestStatus(uint quest_id) diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index a647a3ca9..984ac190a 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -5520,35 +5520,6 @@ namespace Game.Entities return go; } - public void UpdateNearbyCreatureNpcFlags() - { - List creatures = GetCreatureListWithOptionsInGrid(GetVisibilityRange(), new() { IgnorePhases = false }); - - UpdateData udata = new(GetMapId()); - ObjectFieldData objMask = new(); - UnitData unitMask = new(); - for (int i = 0; i < m_unitData.NpcFlags.GetSize(); ++i) - unitMask.MarkChanged(m_unitData.NpcFlags, i); - - foreach (Creature creature in creatures) - { - if (!HaveAtClient(creature)) - continue; - - // skip creatures which dont have any npcflags set - if (creature.GetNpcFlags() == 0 && creature.GetNpcFlags2() == 0) - continue; - - creature.BuildValuesUpdateForPlayerWithMask(udata, objMask.GetUpdateMask(), unitMask.GetUpdateMask(), this); - } - - if (!udata.HasData()) - return; - - udata.BuildPacket(out UpdateObject packet); - SendPacket(packet); - } - public void SendInitialPacketsBeforeAddToMap() { if (!m_teleport_options.HasAnyFlag(TeleportToOptions.Seamless)) diff --git a/Source/Game/Entities/Unit/Unit.Spells.cs b/Source/Game/Entities/Unit/Unit.Spells.cs index e4b4b8671..9d5ca192c 100644 --- a/Source/Game/Entities/Unit/Unit.Spells.cs +++ b/Source/Game/Entities/Unit/Unit.Spells.cs @@ -3800,7 +3800,7 @@ namespace Game.Entities if (player != null) { if (Global.ConditionMgr.IsSpellUsedInSpellClickConditions(aurApp.GetBase().GetId())) - player.UpdateVisibleGameobjectsOrSpellClicks(); + player.UpdateVisibleObjectInteractions(false, true, false, false); player.FailCriteria(CriteriaFailEvent.LoseAura, aurApp.GetBase().GetId()); } @@ -4020,7 +4020,7 @@ namespace Game.Entities if (player != null) { if (Global.ConditionMgr.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()); diff --git a/Source/Game/Groups/Group.cs b/Source/Game/Groups/Group.cs index 48202581d..a7d3c8539 100644 --- a/Source/Game/Groups/Group.cs +++ b/Source/Game/Groups/Group.cs @@ -269,7 +269,7 @@ namespace Game.Groups { Player player = Global.ObjAccessor.FindPlayer(member.guid); if (player != null) - player.UpdateVisibleGameobjectsOrSpellClicks(); + player.UpdateVisibleObjectInteractions(false, true, false, true); } } @@ -299,7 +299,7 @@ namespace Game.Groups { Player player = Global.ObjAccessor.FindPlayer(member.guid); if (player != null) - player.UpdateVisibleGameobjectsOrSpellClicks(); + player.UpdateVisibleObjectInteractions(false, true, false, true); } } @@ -474,7 +474,7 @@ namespace Game.Groups // quest related GO state dependent from raid membership if (IsRaidGroup()) - player.UpdateVisibleGameobjectsOrSpellClicks(); + player.UpdateVisibleObjectInteractions(false, true, false, true); player.FailCriteria(CriteriaFailEvent.ModifyPartyStatus, 0); @@ -566,7 +566,7 @@ namespace Game.Groups player.SetGroup(null); // quest related GO state dependent from raid membership - player.UpdateVisibleGameobjectsOrSpellClicks(); + player.UpdateVisibleObjectInteractions(false, true, false, true); } @@ -713,7 +713,7 @@ namespace Game.Groups // quest related GO state dependent from raid membership if (IsRaidGroup()) - player.UpdateVisibleGameobjectsOrSpellClicks(); + player.UpdateVisibleObjectInteractions(false, true, false, true); if (!hideDestroy) player.SendPacket(new GroupDestroyed()); diff --git a/Source/Game/Handlers/MiscHandler.cs b/Source/Game/Handlers/MiscHandler.cs index a7eab1aeb..3ab4e0a42 100644 --- a/Source/Game/Handlers/MiscHandler.cs +++ b/Source/Game/Handlers/MiscHandler.cs @@ -229,7 +229,7 @@ namespace Game } if (anyObjectiveChangedCompletionState) - player.UpdateVisibleGameobjectsOrSpellClicks(); + player.UpdateVisibleObjectInteractions(true, false, false, true); } } diff --git a/Source/Game/Handlers/QuestHandler.cs b/Source/Game/Handlers/QuestHandler.cs index d40e0aed4..0de78b89e 100644 --- a/Source/Game/Handlers/QuestHandler.cs +++ b/Source/Game/Handlers/QuestHandler.cs @@ -445,8 +445,6 @@ namespace Game if (quest != null) Global.ScriptMgr.OnQuestStatusChange(_player, quest, oldStatus, QuestStatus.None); - - _player.UpdateNearbyCreatureNpcFlags(); } GetPlayer().UpdateCriteria(CriteriaType.AbandonAnyQuest, 1); diff --git a/Source/Game/Spells/SpellEffects.cs b/Source/Game/Spells/SpellEffects.cs index af439babe..2eb70b219 100644 --- a/Source/Game/Spells/SpellEffects.cs +++ b/Source/Game/Spells/SpellEffects.cs @@ -3752,8 +3752,6 @@ namespace Game.Spells Global.ScriptMgr.OnQuestStatusChange(player, quest_id); Global.ScriptMgr.OnQuestStatusChange(player, quest, oldStatus, QuestStatus.None); - - player.UpdateNearbyCreatureNpcFlags(); } [SpellEffectHandler(SpellEffectName.SendTaxi)]