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)
This commit is contained in:
hondacrx
2024-03-04 12:18:45 -05:00
parent 974ca273ae
commit 0325d8b523
8 changed files with 78 additions and 96 deletions
@@ -112,8 +112,6 @@ namespace Game.Chat
Global.ScriptMgr.OnQuestStatusChange(player, quest.Id); Global.ScriptMgr.OnQuestStatusChange(player, quest.Id);
Global.ScriptMgr.OnQuestStatusChange(player, quest, oldStatus, QuestStatus.None); Global.ScriptMgr.OnQuestStatusChange(player, quest, oldStatus, QuestStatus.None);
player.UpdateNearbyCreatureNpcFlags();
handler.SendSysMessage(CypherStrings.CommandQuestRemoved); handler.SendSysMessage(CypherStrings.CommandQuestRemoved);
return true; return true;
} }
+70 -53
View File
@@ -841,8 +841,6 @@ namespace Game.Entities
Global.ScriptMgr.OnQuestStatusChange(this, questId); Global.ScriptMgr.OnQuestStatusChange(this, questId);
Global.ScriptMgr.OnQuestStatusChange(this, quest, oldStatus, questStatusData.Status); Global.ScriptMgr.OnQuestStatusChange(this, quest, oldStatus, questStatusData.Status);
UpdateNearbyCreatureNpcFlags();
} }
public void CompleteQuest(uint quest_id) public void CompleteQuest(uint quest_id)
@@ -1222,16 +1220,12 @@ namespace Game.Entities
UpdatePvPState(); UpdatePvPState();
} }
SendQuestGiverStatusMultiple(); SendQuestUpdate(questId, true, true);
SendQuestUpdate(questId);
bool updateVisibility = false; bool updateVisibility = false;
if (quest.HasFlag(QuestFlags.UpdatePhaseshift)) if (quest.HasFlag(QuestFlags.UpdatePhaseshift))
updateVisibility = PhasingHandler.OnConditionChange(this, false); updateVisibility = PhasingHandler.OnConditionChange(this, false);
UpdateNearbyCreatureNpcFlags();
//lets remove flag for delayed teleports //lets remove flag for delayed teleports
SetCanDelayTeleport(false); SetCanDelayTeleport(false);
@@ -1262,8 +1256,6 @@ namespace Game.Entities
if (updateVisibility) if (updateVisibility)
UpdateObjectVisibility(); UpdateObjectVisibility();
UpdateNearbyCreatureNpcFlags();
} }
public void SetRewardedQuest(uint questId) public void SetRewardedQuest(uint questId)
@@ -1916,8 +1908,6 @@ namespace Game.Entities
Global.ScriptMgr.OnQuestStatusChange(this, quest, oldStatus, status); Global.ScriptMgr.OnQuestStatusChange(this, quest, oldStatus, status);
} }
UpdateNearbyCreatureNpcFlags();
if (update) if (update)
SendQuestUpdate(questId); SendQuestUpdate(questId);
} }
@@ -1968,7 +1958,7 @@ namespace Game.Entities
SendQuestUpdate(questId); SendQuestUpdate(questId);
} }
void SendQuestUpdate(uint questId) void SendQuestUpdate(uint questId, bool updateInteractions = true, bool updateGameObjectQuestGiverStatus = false)
{ {
var saBounds = Global.SpellMgr.GetSpellAreaForQuestMapBounds(questId); var saBounds = Global.SpellMgr.GetSpellAreaForQuestMapBounds(questId);
if (!saBounds.Empty()) if (!saBounds.Empty())
@@ -2015,7 +2005,8 @@ namespace Game.Entities
RemoveAurasDueToSpell(spellId); RemoveAurasDueToSpell(spellId);
} }
UpdateVisibleGameobjectsOrSpellClicks(); if (updateInteractions)
UpdateVisibleObjectInteractions(true, false, updateGameObjectQuestGiverStatus, true);
} }
public QuestGiverStatus GetQuestDialogStatus(WorldObject questgiver) public QuestGiverStatus GetQuestDialogStatus(WorldObject questgiver)
@@ -2176,7 +2167,7 @@ namespace Game.Entities
} }
SetRewardedQuest(questId); SetRewardedQuest(questId);
SendQuestUpdate(questId); SendQuestUpdate(questId, false);
if (!updateVisibility && quest.HasFlag(QuestFlags.UpdatePhaseshift)) if (!updateVisibility && quest.HasFlag(QuestFlags.UpdatePhaseshift))
updateVisibility = PhasingHandler.OnConditionChange(this, false); updateVisibility = PhasingHandler.OnConditionChange(this, false);
@@ -2185,15 +2176,13 @@ namespace Game.Entities
Global.ScriptMgr.OnQuestStatusChange(this, quest, oldStatus, QuestStatus.Rewarded); Global.ScriptMgr.OnQuestStatusChange(this, quest, oldStatus, QuestStatus.Rewarded);
} }
SendQuestGiverStatusMultiple(); UpdateVisibleObjectInteractions(true, false, true, true);
// make full db save // make full db save
SaveToDB(false); SaveToDB(false);
if (updateVisibility) if (updateVisibility)
UpdateObjectVisibility(); UpdateObjectVisibility();
UpdateNearbyCreatureNpcFlags();
} }
public void DespawnPersonalSummonsForQuest(uint questId) 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) public void KilledMonster(CreatureTemplate cInfo, ObjectGuid guid)
@@ -2710,13 +2699,11 @@ namespace Game.Entities
} }
if (anyObjectiveChangedCompletionState) if (anyObjectiveChangedCompletionState)
UpdateVisibleGameobjectsOrSpellClicks(); UpdateVisibleObjectInteractions(true, false, false, true);
if (updatePhaseShift) if (updatePhaseShift)
PhasingHandler.OnConditionChange(this); PhasingHandler.OnConditionChange(this);
UpdateNearbyCreatureNpcFlags();
if (updateZoneAuras) if (updateZoneAuras)
{ {
UpdateZoneDependentAuras(GetZoneId()); UpdateZoneDependentAuras(GetZoneId());
@@ -3294,70 +3281,100 @@ namespace Game.Entities
return false; return false;
} }
public void UpdateVisibleGameobjectsOrSpellClicks() public void UpdateVisibleObjectInteractions(bool allUnits, bool onlySpellClicks, bool gameObjectQuestGiverStatus, bool questObjectiveGameObjects)
{ {
if (m_clientGUIDs.Empty()) QuestGiverStatusMultiple giverStatusMultiple = new();
return;
UpdateData udata = new(GetMapId()); UpdateData udata = new(GetMapId());
UpdateObject packet; foreach (var visibleObjectGuid in m_clientGUIDs)
foreach (var guid in m_clientGUIDs)
{ {
if (guid.IsGameObject()) if (visibleObjectGuid.IsGameObject() && (gameObjectQuestGiverStatus || questObjectiveGameObjects))
{ {
GameObject obj = ObjectAccessor.GetGameObject(this, guid); GameObject gameObject = ObjectAccessor.GetGameObject(this, visibleObjectGuid);
if (obj != null) if (gameObject == null)
continue;
if (gameObjectQuestGiverStatus && gameObject.GetGoType() == GameObjectTypes.QuestGiver)
giverStatusMultiple.QuestGiver.Add(new QuestGiverInfo(visibleObjectGuid, GetQuestDialogStatus(gameObject)));
if (questObjectiveGameObjects)
{ {
ObjectFieldData objMask = new(); ObjectFieldData objMask = new();
GameObjectFieldData goMask = new(); GameObjectFieldData goMask = new();
if (m_questObjectiveStatus.ContainsKey((QuestObjectiveType.GameObject, (int)obj.GetEntry()))) if (m_questObjectiveStatus.ContainsKey((QuestObjectiveType.GameObject, (int)gameObject.GetEntry())))
objMask.MarkChanged(obj.m_objectData.DynamicFlags); objMask.MarkChanged(gameObject.m_objectData.DynamicFlags);
switch (obj.GetGoType()) switch (gameObject.GetGoType())
{ {
case GameObjectTypes.QuestGiver: case GameObjectTypes.QuestGiver:
case GameObjectTypes.Chest: case GameObjectTypes.Chest:
case GameObjectTypes.Goober: case GameObjectTypes.Goober:
case GameObjectTypes.Generic: case GameObjectTypes.Generic:
case GameObjectTypes.GatheringNode: case GameObjectTypes.GatheringNode:
if (Global.ObjectMgr.IsGameObjectForQuests(obj.GetEntry())) if (Global.ObjectMgr.IsGameObjectForQuests(gameObject.GetEntry()))
objMask.MarkChanged(obj.m_objectData.DynamicFlags); objMask.MarkChanged(gameObject.m_objectData.DynamicFlags);
break; break;
default: default:
break; break;
} }
if (objMask.GetUpdateMask().IsAnySet() || goMask.GetUpdateMask().IsAnySet()) 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); Creature creature = ObjectAccessor.GetCreatureOrPetOrVehicle(this, visibleObjectGuid);
if (obj == null) if (creature == null)
continue; continue;
// check if this unit requires quest specific flags if (allUnits)
if (!obj.HasNpcFlag(NPCFlags.SpellClick))
continue;
var clickBounds = Global.ObjectMgr.GetSpellClickInfoMapBounds(obj.GetEntry());
foreach (var spellClickInfo in clickBounds)
{ {
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(); if (Global.ConditionMgr.HasConditionsForSpellClickEvent(creature.GetEntry(), spellClickInfo.spellId))
UnitData unitMask = new(); {
unitMask.MarkChanged(m_unitData.NpcFlags, 0); // NpcFlags[0] has UNIT_NPC_FLAG_SPELLCLICK ObjectFieldData objMask = new();
obj.BuildValuesUpdateForPlayerWithMask(udata, objMask.GetUpdateMask(), unitMask.GetUpdateMask(), this); UnitData unitMask = new();
break; 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) void SetDailyQuestStatus(uint quest_id)
-29
View File
@@ -5520,35 +5520,6 @@ namespace Game.Entities
return go; return go;
} }
public void UpdateNearbyCreatureNpcFlags()
{
List<Creature> 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() public void SendInitialPacketsBeforeAddToMap()
{ {
if (!m_teleport_options.HasAnyFlag(TeleportToOptions.Seamless)) if (!m_teleport_options.HasAnyFlag(TeleportToOptions.Seamless))
+2 -2
View File
@@ -3800,7 +3800,7 @@ namespace Game.Entities
if (player != null) if (player != null)
{ {
if (Global.ConditionMgr.IsSpellUsedInSpellClickConditions(aurApp.GetBase().GetId())) if (Global.ConditionMgr.IsSpellUsedInSpellClickConditions(aurApp.GetBase().GetId()))
player.UpdateVisibleGameobjectsOrSpellClicks(); player.UpdateVisibleObjectInteractions(false, true, false, false);
player.FailCriteria(CriteriaFailEvent.LoseAura, aurApp.GetBase().GetId()); player.FailCriteria(CriteriaFailEvent.LoseAura, aurApp.GetBase().GetId());
} }
@@ -4020,7 +4020,7 @@ namespace Game.Entities
if (player != null) if (player != null)
{ {
if (Global.ConditionMgr.IsSpellUsedInSpellClickConditions(aurApp.GetBase().GetId())) if (Global.ConditionMgr.IsSpellUsedInSpellClickConditions(aurApp.GetBase().GetId()))
player.UpdateVisibleGameobjectsOrSpellClicks(); player.UpdateVisibleObjectInteractions(false, true, false, false);
player.FailCriteria(CriteriaFailEvent.GainAura, aurApp.GetBase().GetId()); player.FailCriteria(CriteriaFailEvent.GainAura, aurApp.GetBase().GetId());
player.StartCriteria(CriteriaStartEvent.GainAura, aurApp.GetBase().GetId()); player.StartCriteria(CriteriaStartEvent.GainAura, aurApp.GetBase().GetId());
+5 -5
View File
@@ -269,7 +269,7 @@ namespace Game.Groups
{ {
Player player = Global.ObjAccessor.FindPlayer(member.guid); Player player = Global.ObjAccessor.FindPlayer(member.guid);
if (player != null) 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); Player player = Global.ObjAccessor.FindPlayer(member.guid);
if (player != null) 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 // quest related GO state dependent from raid membership
if (IsRaidGroup()) if (IsRaidGroup())
player.UpdateVisibleGameobjectsOrSpellClicks(); player.UpdateVisibleObjectInteractions(false, true, false, true);
player.FailCriteria(CriteriaFailEvent.ModifyPartyStatus, 0); player.FailCriteria(CriteriaFailEvent.ModifyPartyStatus, 0);
@@ -566,7 +566,7 @@ namespace Game.Groups
player.SetGroup(null); player.SetGroup(null);
// quest related GO state dependent from raid membership // 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 // quest related GO state dependent from raid membership
if (IsRaidGroup()) if (IsRaidGroup())
player.UpdateVisibleGameobjectsOrSpellClicks(); player.UpdateVisibleObjectInteractions(false, true, false, true);
if (!hideDestroy) if (!hideDestroy)
player.SendPacket(new GroupDestroyed()); player.SendPacket(new GroupDestroyed());
+1 -1
View File
@@ -229,7 +229,7 @@ namespace Game
} }
if (anyObjectiveChangedCompletionState) if (anyObjectiveChangedCompletionState)
player.UpdateVisibleGameobjectsOrSpellClicks(); player.UpdateVisibleObjectInteractions(true, false, false, true);
} }
} }
-2
View File
@@ -445,8 +445,6 @@ namespace Game
if (quest != null) if (quest != null)
Global.ScriptMgr.OnQuestStatusChange(_player, quest, oldStatus, QuestStatus.None); Global.ScriptMgr.OnQuestStatusChange(_player, quest, oldStatus, QuestStatus.None);
_player.UpdateNearbyCreatureNpcFlags();
} }
GetPlayer().UpdateCriteria(CriteriaType.AbandonAnyQuest, 1); GetPlayer().UpdateCriteria(CriteriaType.AbandonAnyQuest, 1);
-2
View File
@@ -3752,8 +3752,6 @@ namespace Game.Spells
Global.ScriptMgr.OnQuestStatusChange(player, quest_id); Global.ScriptMgr.OnQuestStatusChange(player, quest_id);
Global.ScriptMgr.OnQuestStatusChange(player, quest, oldStatus, QuestStatus.None); Global.ScriptMgr.OnQuestStatusChange(player, quest, oldStatus, QuestStatus.None);
player.UpdateNearbyCreatureNpcFlags();
} }
[SpellEffectHandler(SpellEffectName.SendTaxi)] [SpellEffectHandler(SpellEffectName.SendTaxi)]