From 877fb1a76f5124ddb3dcc112245b522f8270f127 Mon Sep 17 00:00:00 2001 From: Hondacrx Date: Tue, 19 Aug 2025 17:18:59 -0400 Subject: [PATCH] Core/SpawnTracking: Allow linking a spawn to more than one quest objective Port From (https://github.com/TrinityCore/TrinityCore/commit/138b1b1a21ff871b54f1f2bd815de30a93b803eb) --- Source/Game/Entities/Creature/Creature.cs | 8 +- Source/Game/Entities/GameObject/GameObject.cs | 8 +- .../Entities/Object/Update/UpdateFields.cs | 73 +++++++++++-- Source/Game/Entities/Player/Player.Quest.cs | 100 +++++++++++------- Source/Game/Globals/ObjectManager.cs | 40 +++++-- Source/Game/Handlers/QuestHandler.cs | 4 +- Source/Game/Maps/SpawnData.cs | 2 +- 7 files changed, 173 insertions(+), 62 deletions(-) diff --git a/Source/Game/Entities/Creature/Creature.cs b/Source/Game/Entities/Creature/Creature.cs index 90768af79..a476b75a0 100644 --- a/Source/Game/Entities/Creature/Creature.cs +++ b/Source/Game/Entities/Creature/Creature.cs @@ -338,7 +338,9 @@ namespace Game.Entities ReplaceAllDynamicFlags(UnitDynFlags.None); - SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.StateWorldEffectsQuestObjectiveID), data != null ? data.spawnTrackingQuestObjectiveId : 0); + // Set StateWorldEffectsQuestObjectiveID if there is only one linked objective for this creature + if (data != null && data.spawnTrackingQuestObjectives.Count == 1) + SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.StateWorldEffectsQuestObjectiveID), data.spawnTrackingQuestObjectives.First()); SetCanDualWield(cInfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.UseOffhandAttack)); @@ -3033,9 +3035,9 @@ namespace Game.Entities CreatureData data = GetCreatureData(); if (data != null) { - if (data.spawnTrackingQuestObjectiveId != 0 && data.spawnTrackingData != null) + if (data.spawnTrackingData != null && !data.spawnTrackingQuestObjectives.Empty()) { - SpawnTrackingState state = player.GetSpawnTrackingStateByObjective(data.spawnTrackingData.SpawnTrackingId, data.spawnTrackingQuestObjectiveId); + SpawnTrackingState state = player.GetSpawnTrackingStateByObjectives(data.spawnTrackingData.SpawnTrackingId, data.spawnTrackingQuestObjectives); return data.spawnTrackingStates[(int)state]; } } diff --git a/Source/Game/Entities/GameObject/GameObject.cs b/Source/Game/Entities/GameObject/GameObject.cs index 745b61cd6..dee89bd33 100644 --- a/Source/Game/Entities/GameObject/GameObject.cs +++ b/Source/Game/Entities/GameObject/GameObject.cs @@ -1126,7 +1126,9 @@ namespace Game.Entities PhasingHandler.InitDbPhaseShift(GetPhaseShift(), data.PhaseUseFlags, data.PhaseId, data.PhaseGroup); PhasingHandler.InitDbVisibleMapId(GetPhaseShift(), data.terrainSwapMap); - SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.StateWorldEffectsQuestObjectiveID), data != null ? data.spawnTrackingQuestObjectiveId : 0); + // Set StateWorldEffectsQuestObjectiveID if there is only one linked objective for this gameobject + if (data != null && data.spawnTrackingQuestObjectives.Count == 1) + SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.StateWorldEffectsQuestObjectiveID), data.spawnTrackingQuestObjectives.First()); if (data.spawntimesecs >= 0) { @@ -2741,9 +2743,9 @@ namespace Game.Entities GameObjectData data = GetGameObjectData(); if (data != null) { - if (data.spawnTrackingQuestObjectiveId != 0 && data.spawnTrackingData != null) + if (data.spawnTrackingData != null && !data.spawnTrackingQuestObjectives.Empty()) { - SpawnTrackingState state = player.GetSpawnTrackingStateByObjective(data.spawnTrackingData.SpawnTrackingId, data.spawnTrackingQuestObjectiveId); + SpawnTrackingState state = player.GetSpawnTrackingStateByObjectives(data.spawnTrackingData.SpawnTrackingId, data.spawnTrackingQuestObjectives); return data.spawnTrackingStates[(int)state]; } } diff --git a/Source/Game/Entities/Object/Update/UpdateFields.cs b/Source/Game/Entities/Object/Update/UpdateFields.cs index 0775d5af1..a277c5dd4 100644 --- a/Source/Game/Entities/Object/Update/UpdateFields.cs +++ b/Source/Game/Entities/Object/Update/UpdateFields.cs @@ -9,6 +9,7 @@ using Game.Networking.Packets; using Game.Spells; using System; using System.Collections.Generic; +using System.Linq; using System.Numerics; namespace Game.Entities @@ -166,8 +167,8 @@ namespace Game.Entities dynFlags |= (uint)GameObjectDynamicLowFlags.NoInterract; var data = Global.ObjectMgr.GetSpawnMetadata(SpawnObjectType.GameObject, gameObject.GetSpawnId()); - if (data != null && data.spawnTrackingQuestObjectiveId != 0 && data.spawnTrackingData != null) - if (receiver.GetSpawnTrackingStateByObjective(data.spawnTrackingData.SpawnTrackingId, data.spawnTrackingQuestObjectiveId) != SpawnTrackingState.Active) + if (data.spawnTrackingData != null && !data.spawnTrackingQuestObjectives.Empty()) + if (receiver.GetSpawnTrackingStateByObjectives(data.spawnTrackingData.SpawnTrackingId, data.spawnTrackingQuestObjectives) != SpawnTrackingState.Active) dynFlags &= ~(uint)GameObjectDynamicLowFlags.Activate; } @@ -1295,7 +1296,7 @@ namespace Game.Entities var stateWorldEffectIDs = GetViewerDependentStateWorldEffectIDs(this, owner, receiver); data.WriteInt32(stateWorldEffectIDs.Count); - data.WriteUInt32(StateWorldEffectsQuestObjectiveID); + data.WriteUInt32(GetViewerDependentStateWorldEffectsQuestObjectiveID(this, owner, receiver)); data.WriteInt32(SpellOverrideNameID); for (int i = 0; i < stateWorldEffectIDs.Count; ++i) data.WriteUInt32(stateWorldEffectIDs[i]); @@ -1623,7 +1624,7 @@ namespace Game.Entities } if (changesMask[12]) { - data.WriteUInt32(StateWorldEffectsQuestObjectiveID); + data.WriteUInt32(GetViewerDependentStateWorldEffectsQuestObjectiveID(this, owner, receiver)); } if (changesMask[13]) { @@ -2574,6 +2575,36 @@ namespace Game.Entities return stateAnimKitId; } + + uint GetViewerDependentStateWorldEffectsQuestObjectiveID(UnitData unitData, Unit unit, Player receiver) + { + uint stateWorldEffectsQuestObjectiveId = unitData.StateWorldEffectsQuestObjectiveID; + + if (stateWorldEffectsQuestObjectiveId == 0 && unit.IsCreature()) + { + CreatureData data = unit.ToCreature().GetCreatureData(); + if (data != null) + { + if (data.spawnTrackingQuestObjectives.Any()) + { + // If there is no valid objective for player, fill UF with first objective (if any) + stateWorldEffectsQuestObjectiveId = data.spawnTrackingQuestObjectives.First(); + int i = 0; + while (++i <= data.spawnTrackingQuestObjectives.Count) + { + var id = data.spawnTrackingQuestObjectives[i]; + if (receiver.GetSpawnTrackingStateByObjective(data.spawnTrackingData.SpawnTrackingId, id) != SpawnTrackingState.Active) + continue; + + stateWorldEffectsQuestObjectiveId = id; + break; + } + } + } + } + + return stateWorldEffectsQuestObjectiveId; + } } public class ChrCustomizationChoice : IComparable @@ -7640,7 +7671,7 @@ namespace Game.Entities data.WriteUInt32(GetViewerDependentSpawnTrackingStateAnimKitID(this, owner, receiver)); var stateWorldEffectIDs = GetViewerDependentStateWorldEffectIDs(this, owner, receiver); data.WriteInt32(stateWorldEffectIDs.Count); - data.WriteUInt32(StateWorldEffectsQuestObjectiveID); + data.WriteUInt32(GetViewerDependentStateWorldEffectsQuestObjectiveID(this, owner, receiver)); for (int i = 0; i < stateWorldEffectIDs.Count; ++i) { data.WriteUInt32(stateWorldEffectIDs[i]); @@ -7762,7 +7793,7 @@ namespace Game.Entities } if (changesMask[9]) { - data.WriteUInt32(StateWorldEffectsQuestObjectiveID); + data.WriteUInt32(GetViewerDependentStateWorldEffectsQuestObjectiveID(this, owner, receiver)); } if (changesMask[10]) { @@ -7918,6 +7949,36 @@ namespace Game.Entities return stateAnimKitId; } + uint GetViewerDependentStateWorldEffectsQuestObjectiveID(GameObjectFieldData gameObjectData, GameObject gameObject, Player receiver) + { + uint stateWorldEffectsQuestObjectiveId = gameObjectData.StateWorldEffectsQuestObjectiveID; + + if (stateWorldEffectsQuestObjectiveId == 0) + { + GameObjectData data = gameObject.GetGameObjectData(); + if (data != null) + { + if (data.spawnTrackingQuestObjectives.Any()) + { + // If there is no valid objective for player, fill UF with first objective (if any) + stateWorldEffectsQuestObjectiveId = data.spawnTrackingQuestObjectives.First(); + int i = 0; + while (++i <= data.spawnTrackingQuestObjectives.Count) + { + var id = data.spawnTrackingQuestObjectives[i]; + if (receiver.GetSpawnTrackingStateByObjective(data.spawnTrackingData.SpawnTrackingId, id) != SpawnTrackingState.Active) + continue; + + stateWorldEffectsQuestObjectiveId = id; + break; + } + } + + } + } + + return stateWorldEffectsQuestObjectiveId; + } } public class DynamicObjectData : HasChangesMask diff --git a/Source/Game/Entities/Player/Player.Quest.cs b/Source/Game/Entities/Player/Player.Quest.cs index 1b4771014..c06694e45 100644 --- a/Source/Game/Entities/Player/Player.Quest.cs +++ b/Source/Game/Entities/Player/Player.Quest.cs @@ -2742,38 +2742,41 @@ namespace Game.Entities } } - if (data != null && data.spawnTrackingQuestObjectiveId != 0 && data.spawnTrackingData != null) + if (data != null && data.spawnTrackingData != null && !data.spawnTrackingQuestObjectives.Empty()) { - if (objective.Id == data.spawnTrackingQuestObjectiveId) + foreach (uint spawnTrackingQuestObjectiveId in data.spawnTrackingQuestObjectives) { - // Store spawn tracking to return correct state in Player::GetSpawnTrackingStateByObjective - QuestStatusData questStatus = objectiveStatusData.QuestStatusPair.Status; - questStatus.SpawnTrackingList.Add((objective.StorageIndex, data.spawnTrackingData.SpawnTrackingId)); - - // Send QuestPOIUpdateResponse for every spawn linked to same SpawnTrackingId - foreach (var spawnMetaData in Global.ObjectMgr.GetSpawnMetadataForSpawnTracking(data.spawnTrackingData.SpawnTrackingId)) + if (objective.Id == spawnTrackingQuestObjectiveId) { - SpawnData spawnData = spawnMetaData.ToSpawnData(); - if (spawnData == null) - continue; + // Store spawn tracking to return correct state in Player::GetSpawnTrackingStateByObjective + QuestStatusData questStatus = objectiveStatusData.QuestStatusPair.Status; + questStatus.SpawnTrackingList.Add((objective.StorageIndex, data.spawnTrackingData.SpawnTrackingId)); - QuestPOIUpdateResponse response = new(); + // Send QuestPOIUpdateResponse for every spawn linked to same SpawnTrackingId + foreach (var spawnMetaData in Global.ObjectMgr.GetSpawnMetadataForSpawnTracking(data.spawnTrackingData.SpawnTrackingId)) + { + SpawnData spawnData = spawnMetaData.ToSpawnData(); + if (spawnData == null) + continue; + QuestPOIUpdateResponse response = new(); - SpawnTrackingResponseInfo responseInfo = new(); - responseInfo.SpawnTrackingID = data.spawnTrackingData.SpawnTrackingId; - responseInfo.ObjectID = (int)spawnData.Id; - responseInfo.PhaseID = (int)spawnData.PhaseId; - responseInfo.PhaseGroupID = (int)spawnData.PhaseGroup; - responseInfo.PhaseUseFlags = (int)spawnData.PhaseUseFlags; + SpawnTrackingResponseInfo responseInfo = new(); + responseInfo.SpawnTrackingID = spawnMetaData.spawnTrackingData.SpawnTrackingId; + responseInfo.ObjectID = (int)spawnData.Id; + responseInfo.PhaseID = (int)spawnData.PhaseId; + responseInfo.PhaseGroupID = (int)spawnData.PhaseGroup; + responseInfo.PhaseUseFlags = (int)spawnData.PhaseUseFlags; - SpawnTrackingState state = GetSpawnTrackingStateByObjective(data.spawnTrackingData.SpawnTrackingId, objective.Id); - responseInfo.Visible = data.spawnTrackingStates[(int)state].Visible; + SpawnTrackingState state = GetSpawnTrackingStateByObjectives(spawnMetaData.spawnTrackingData.SpawnTrackingId, spawnMetaData.spawnTrackingQuestObjectives); + responseInfo.Visible = spawnMetaData.spawnTrackingStates[(int)state].Visible; - response.SpawnTrackingResponses.Add(responseInfo); - SendPacket(response); + response.SpawnTrackingResponses.Add(responseInfo); + + SendPacket(response); + } + + anyObjectiveChangedSpawnTrackingState = true; } - - anyObjectiveChangedSpawnTrackingState = true; } } @@ -3435,17 +3438,39 @@ namespace Game.Entities } } - public QuestObjective GetActiveQuestObjectiveForForSpawnTracking(uint spawnTrackingId) + public QuestObjective GetActiveQuestObjectiveForSpawnTracking(uint spawnTrackingId) { var questObjectiveList = Global.ObjectMgr.GetSpawnTrackingQuestObjectiveList(spawnTrackingId); if (questObjectiveList != null) foreach (QuestObjective questObjective in questObjectiveList) - if (FindQuestSlot(questObjective.QuestID) < SharedConst.MaxQuestLogSize) + if (IsQuestObjectiveCompletable(questObjective.QuestID, questObjective.Id)) return questObjective; return null; } + public SpawnTrackingState GetSpawnTrackingStateByObjectives(uint spawnTrackingId, List questObjectives) + { + if (spawnTrackingId != 0 && !questObjectives.Empty()) + { + bool hasAnyQuestObjectiveCompletable = false; + foreach (uint questObjectiveId in questObjectives) + { + SpawnTrackingState state = GetSpawnTrackingStateByObjective(spawnTrackingId, questObjectiveId); + if (state == SpawnTrackingState.Complete) + return SpawnTrackingState.Complete; + + if (state == SpawnTrackingState.Active) + hasAnyQuestObjectiveCompletable = true; + } + + if (hasAnyQuestObjectiveCompletable) + return SpawnTrackingState.Active; + } + + return SpawnTrackingState.None; + } + public SpawnTrackingState GetSpawnTrackingStateByObjective(uint spawnTrackingId, uint questObjectiveId) { if (spawnTrackingId != 0 && questObjectiveId != 0 && Global.ObjectMgr.IsQuestObjectiveForSpawnTracking(spawnTrackingId, questObjectiveId)) @@ -3455,7 +3480,8 @@ namespace Game.Entities { if (IsQuestRewarded(questObjective.QuestID) || IsQuestObjectiveComplete(questObjective.QuestID, questObjective.Id)) return SpawnTrackingState.Complete; - else if (GetQuestStatus(questObjective.QuestID) != QuestStatus.None && IsQuestObjectiveCompletable(questObjective.QuestID, questObjective.Id)) + + if (GetQuestStatus(questObjective.QuestID) != QuestStatus.None && IsQuestObjectiveCompletable(questObjective.QuestID, questObjective.Id)) { var itr = m_QuestStatus.LookupByKey(questObjective.QuestID); if (itr != null && itr.Slot < SharedConst.MaxQuestLogSize) @@ -3512,16 +3538,17 @@ namespace Game.Entities GameObjectFieldData goMask = new(); SpawnMetadata data = Global.ObjectMgr.GetSpawnMetadata(SpawnObjectType.GameObject, gameObject.GetSpawnId()); - if (data != null && data.spawnTrackingQuestObjectiveId != 0 && data.spawnTrackingData != null) + if (data != null && data.spawnTrackingData != null && !data.spawnTrackingQuestObjectives.Empty()) { - objMask.MarkChanged(m_objectData.DynamicFlags); - goMask.MarkChanged(gameObject.m_gameObjectData.StateWorldEffectIDs); - goMask.MarkChanged(gameObject.m_gameObjectData.StateSpellVisualID); - goMask.MarkChanged(gameObject.m_gameObjectData.SpawnTrackingStateAnimID); - goMask.MarkChanged(gameObject.m_gameObjectData.SpawnTrackingStateAnimKitID); + objMask.MarkChanged(objMask.DynamicFlags); + goMask.MarkChanged(goMask.StateWorldEffectIDs); + goMask.MarkChanged(goMask.StateSpellVisualID); + goMask.MarkChanged(goMask.SpawnTrackingStateAnimID); + goMask.MarkChanged(goMask.SpawnTrackingStateAnimKitID); + goMask.MarkChanged(goMask.StateWorldEffectsQuestObjectiveID); } else if (m_questObjectiveStatus.ContainsKey((QuestObjectiveType.GameObject, (int)gameObject.GetEntry())) || gameObject.GetGoInfo().GetConditionID1() != 0) - objMask.MarkChanged(gameObject.m_objectData.DynamicFlags); + objMask.MarkChanged(objMask.DynamicFlags); else { switch (gameObject.GetGoType()) @@ -3533,7 +3560,7 @@ namespace Game.Entities case GameObjectTypes.Goober: case GameObjectTypes.GatheringNode: if (Global.ObjectMgr.IsGameObjectForQuests(gameObject.GetEntry())) - objMask.MarkChanged(gameObject.m_objectData.DynamicFlags); + objMask.MarkChanged(objMask.DynamicFlags); break; default: break; @@ -3562,13 +3589,14 @@ namespace Game.Entities unitMask.MarkChanged(m_unitData.NpcFlags2); SpawnMetadata data = Global.ObjectMgr.GetSpawnMetadata(SpawnObjectType.Creature, creature.GetSpawnId()); - if (data != null && data.spawnTrackingQuestObjectiveId != 0 && data.spawnTrackingData != null) + if (data != null && data.spawnTrackingData != null && !data.spawnTrackingQuestObjectives.Empty()) { objMask.MarkChanged(objMask.DynamicFlags); unitMask.MarkChanged(unitMask.StateWorldEffectIDs); unitMask.MarkChanged(unitMask.StateSpellVisualID); unitMask.MarkChanged(unitMask.StateAnimID); unitMask.MarkChanged(unitMask.StateAnimKitID); + unitMask.MarkChanged(unitMask.StateWorldEffectsQuestObjectiveID); } if (objMask.GetUpdateMask().IsAnySet() || unitMask.GetUpdateMask().IsAnySet()) diff --git a/Source/Game/Globals/ObjectManager.cs b/Source/Game/Globals/ObjectManager.cs index aa8ef905e..7d4c73594 100644 --- a/Source/Game/Globals/ObjectManager.cs +++ b/Source/Game/Globals/ObjectManager.cs @@ -9264,8 +9264,8 @@ namespace Game // need for reload case _spawnTrackingMapStorage.Clear(); - // 0 1 2 3 - SQLResult result = DB.World.Query("SELECT SpawnTrackingId, SpawnType, SpawnId, QuestObjectiveId FROM spawn_tracking"); + // 0 1 2 3 + SQLResult result = DB.World.Query("SELECT SpawnTrackingId, SpawnType, SpawnId, QuestObjectiveIds FROM spawn_tracking"); if (result.IsEmpty()) { @@ -9280,7 +9280,6 @@ namespace Game uint spawnTrackingId = result.Read(0); SpawnObjectType spawnType = (SpawnObjectType)result.Read(1); ulong spawnId = result.Read(2); - uint objectiveId = result.Read(3); if (!SpawnData.TypeIsValid(spawnType)) { @@ -9312,12 +9311,6 @@ namespace Game continue; } - if (!IsQuestObjectiveForSpawnTracking(spawnTrackingId, objectiveId)) - { - Log.outError(LogFilter.Sql, $"Table `spawn_tracking` has spawn tracking {spawnTrackingId} assigned to spawn ({spawnType},{spawnId}), but spawn tracking is not linked to quest objective {objectiveId}. Skipped."); - continue; - } - if (spawnTrackingTemplateData.MapId != data.MapId) { Log.outError(LogFilter.Sql, $"Table `spawn_tracking` has spawn tracking {spawnTrackingId} (map {spawnTrackingTemplateData.MapId}) assigned to spawn ({spawnType},{spawnId}), but spawn has map {data.MapId} - spawn NOT added to spawn tracking!"); @@ -9332,8 +9325,33 @@ namespace Game continue; } + List objectiveList = new(); + string objectivesStr = result.Read(3); + if (!objectivesStr.IsEmpty()) + { + foreach (var objectiveStr in objectivesStr.Split(',', StringSplitOptions.RemoveEmptyEntries)) + { + if (!uint.TryParse(objectiveStr, out uint objectiveId)) + continue; + + if (!IsQuestObjectiveForSpawnTracking(spawnTrackingId, objectiveId)) + { + Log.outError(LogFilter.Sql, $"Table `spawn_tracking` has spawn tracking {spawnTrackingId} assigned to spawn ({spawnType},{spawnId}), but spawn tracking is not linked to quest objective {objectiveId}. Skipped."); + continue; + } + + objectiveList.Add(objectiveId); + } + + if (objectiveList.Empty()) + { + Log.outError(LogFilter.Sql, $"Table `spawn_tracking` has spawn tracking {spawnTrackingId} assigned to spawn ({spawnType},{spawnId}), but spawn tracking is not linked to any quest objective - spawn NOT added to spawn tracking!"); + continue; + } + } + data.spawnTrackingData = spawnTrackingTemplateData; - data.spawnTrackingQuestObjectiveId = objectiveId; + data.spawnTrackingQuestObjectives = objectiveList; _spawnTrackingMapStorage.Add(spawnTrackingId, data); ++count; @@ -9435,7 +9453,7 @@ namespace Game if (!CliDB.WorldEffectStorage.HasRecord(worldEffectId)) { - Log.outError(LogFilter.Sql, $"Table `spawn_tracking_state` references invalid StateAnimKitId {worldEffectId} for spawn ({spawnType},{spawnId}). Skipped."); + Log.outError(LogFilter.Sql, $"Table `spawn_tracking_state` references invalid WorldEffectId {worldEffectId} for spawn ({spawnType},{spawnId}). Skipped."); continue; } diff --git a/Source/Game/Handlers/QuestHandler.cs b/Source/Game/Handlers/QuestHandler.cs index ff2246e88..e492bca69 100644 --- a/Source/Game/Handlers/QuestHandler.cs +++ b/Source/Game/Handlers/QuestHandler.cs @@ -854,7 +854,7 @@ namespace Game responseInfo.ObjectID = requestInfo.ObjectID; var spawnTrackingTemplateData = Global.ObjectMgr.GetSpawnTrackingData(requestInfo.SpawnTrackingID); - QuestObjective activeQuestObjective = _player.GetActiveQuestObjectiveForForSpawnTracking(requestInfo.SpawnTrackingID); + QuestObjective activeQuestObjective = _player.GetActiveQuestObjectiveForSpawnTracking(requestInfo.SpawnTrackingID); // Send phase info if map is the same or spawn tracking related quests are taken or completed if (spawnTrackingTemplateData != null && (_player.GetMapId() == spawnTrackingTemplateData.MapId || activeQuestObjective != null)) @@ -881,7 +881,7 @@ namespace Game if (activeQuestObjective != null) { - SpawnTrackingState state = _player.GetSpawnTrackingStateByObjective(requestInfo.SpawnTrackingID, activeQuestObjective.Id); + SpawnTrackingState state = _player.GetSpawnTrackingStateByObjectives(requestInfo.SpawnTrackingID, data.spawnTrackingQuestObjectives); responseInfo.Visible = data.spawnTrackingStates[(int)state].Visible; break; } diff --git a/Source/Game/Maps/SpawnData.cs b/Source/Game/Maps/SpawnData.cs index a6fe151e1..5b2bca096 100644 --- a/Source/Game/Maps/SpawnData.cs +++ b/Source/Game/Maps/SpawnData.cs @@ -60,7 +60,7 @@ namespace Game.Maps public bool dbData = true; public SpawnGroupTemplateData spawnGroupData; public SpawnTrackingTemplateData spawnTrackingData; - public uint spawnTrackingQuestObjectiveId; + public List spawnTrackingQuestObjectives = new(); public SpawnTrackingStateData[] spawnTrackingStates = new SpawnTrackingStateData[(int)SpawnTrackingState.Max]; public static bool TypeInMask(SpawnObjectType type, SpawnObjectTypeMask mask) { return ((1 << (int)type) & (int)mask) != 0; }