Core/Misc: Implemented spawn tracking
Port From (https://github.com/TrinityCore/TrinityCore/commit/c9099c87567ead635811ef71b990ae7f19103509)
This commit is contained in:
@@ -338,7 +338,7 @@ namespace Game.Entities
|
||||
|
||||
ReplaceAllDynamicFlags(UnitDynFlags.None);
|
||||
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.StateAnimID), Global.DB2Mgr.GetEmptyAnimStateID());
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.StateWorldEffectsQuestObjectiveID), data != null ? data.spawnTrackingQuestObjectiveId : 0);
|
||||
|
||||
SetCanDualWield(cInfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.UseOffhandAttack));
|
||||
|
||||
@@ -3025,6 +3025,24 @@ namespace Game.Entities
|
||||
|
||||
public string GetStringId(StringIdType type) { return m_stringIds[(int)type]; }
|
||||
|
||||
public override SpawnTrackingStateData GetSpawnTrackingStateDataForPlayer(Player player)
|
||||
{
|
||||
if (player == null)
|
||||
return null;
|
||||
|
||||
SpawnMetadata data = Global.ObjectMgr.GetSpawnMetadata(SpawnObjectType.Creature, GetSpawnId());
|
||||
if (data != null)
|
||||
{
|
||||
if (data.spawnTrackingQuestObjectiveId != 0 && data.spawnTrackingData != null)
|
||||
{
|
||||
SpawnTrackingState state = player.GetSpawnTrackingStateByObjective(data.spawnTrackingData.SpawnTrackingId, data.spawnTrackingQuestObjectiveId);
|
||||
return data.spawnTrackingStates[(int)state];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public VendorItemData GetVendorItems()
|
||||
{
|
||||
return Global.ObjectMgr.GetNpcVendorItemList(GetEntry());
|
||||
|
||||
@@ -283,8 +283,6 @@ namespace Game.Entities
|
||||
SetGoState(goState);
|
||||
SetGoArtKit(artKit);
|
||||
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.SpawnTrackingStateAnimID), Global.DB2Mgr.GetEmptyAnimStateID());
|
||||
|
||||
switch (goInfo.type)
|
||||
{
|
||||
case GameObjectTypes.FishingHole:
|
||||
@@ -1128,6 +1126,8 @@ 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);
|
||||
|
||||
if (data.spawntimesecs >= 0)
|
||||
{
|
||||
m_spawnedByDefault = true;
|
||||
@@ -2730,6 +2730,24 @@ namespace Game.Entities
|
||||
|
||||
public string GetStringId(StringIdType type) { return m_stringIds[(int)type]; }
|
||||
|
||||
public override SpawnTrackingStateData GetSpawnTrackingStateDataForPlayer(Player player)
|
||||
{
|
||||
if (player == null)
|
||||
return null;
|
||||
|
||||
SpawnMetadata data = Global.ObjectMgr.GetSpawnMetadata(SpawnObjectType.GameObject, GetSpawnId());
|
||||
if (data != null)
|
||||
{
|
||||
if (data.spawnTrackingQuestObjectiveId != 0 && data.spawnTrackingData != null)
|
||||
{
|
||||
SpawnTrackingState state = player.GetSpawnTrackingStateByObjective(data.spawnTrackingData.SpawnTrackingId, data.spawnTrackingQuestObjectiveId);
|
||||
return data.spawnTrackingStates[(int)state];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string GetName(Locale locale = Locale.enUS)
|
||||
{
|
||||
if (locale != Locale.enUS)
|
||||
|
||||
@@ -160,6 +160,11 @@ namespace Game.Entities
|
||||
|
||||
if (!gameObject.MeetsInteractCondition(receiver))
|
||||
dynFlags |= 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)
|
||||
dynFlags &= ~GameObjectDynamicLowFlags.Activate;
|
||||
}
|
||||
|
||||
unitDynFlags = (uint)dynFlags;
|
||||
@@ -1278,14 +1283,15 @@ namespace Game.Entities
|
||||
data.WriteUInt32(GetViewerDependentNpcFlags(this, owner, receiver));
|
||||
data.WriteUInt32(GetViewerDependentNpcFlags2(this, owner, receiver));
|
||||
|
||||
data.WriteUInt32(StateSpellVisualID);
|
||||
data.WriteUInt32(StateAnimID);
|
||||
data.WriteUInt32(StateAnimKitID);
|
||||
data.WriteInt32(StateWorldEffectIDs.GetValue().Count);
|
||||
data.WriteUInt32(GetViewerDependentStateSpellVisualID(this, owner, receiver));
|
||||
data.WriteUInt32(GetViewerDependentStateAnimID(this, owner, receiver));
|
||||
data.WriteUInt32(GetViewerDependentStateAnimKitID(this, owner, receiver));
|
||||
var stateWorldEffects = GetViewerDependentStateWorldEffectIDs(this, owner, receiver);
|
||||
data.WriteInt32(stateWorldEffects.Count);
|
||||
data.WriteUInt32(StateWorldEffectsQuestObjectiveID);
|
||||
data.WriteInt32(SpellOverrideNameID);
|
||||
for (int i = 0; i < StateWorldEffectIDs.GetValue().Count; ++i)
|
||||
data.WriteUInt32(StateWorldEffectIDs.GetValue()[i]);
|
||||
for (int i = 0; i < stateWorldEffects.Count; ++i)
|
||||
data.WriteUInt32(stateWorldEffects[i]);
|
||||
|
||||
data.WritePackedGuid(Charm);
|
||||
data.WritePackedGuid(Summon);
|
||||
@@ -1514,11 +1520,11 @@ namespace Game.Entities
|
||||
}
|
||||
if (changesMask[2])
|
||||
{
|
||||
var list = StateWorldEffectIDs.GetValue();
|
||||
data.WriteBits(list.Count, 32);
|
||||
for (int i = 0; i < list.Count; ++i)
|
||||
var stateWorldEffects = GetViewerDependentStateWorldEffectIDs(this, owner, receiver);
|
||||
data.WriteBits(stateWorldEffects.Count, 32);
|
||||
for (int i = 0; i < stateWorldEffects.Count; ++i)
|
||||
{
|
||||
data.WriteUInt32(list[i]);
|
||||
data.WriteUInt32(stateWorldEffects[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1594,15 +1600,15 @@ namespace Game.Entities
|
||||
}
|
||||
if (changesMask[9])
|
||||
{
|
||||
data.WriteUInt32(StateSpellVisualID);
|
||||
data.WriteUInt32(GetViewerDependentStateSpellVisualID(this, owner, receiver));
|
||||
}
|
||||
if (changesMask[10])
|
||||
{
|
||||
data.WriteUInt32(StateAnimID);
|
||||
data.WriteUInt32(GetViewerDependentStateAnimID(this, owner, receiver));
|
||||
}
|
||||
if (changesMask[11])
|
||||
{
|
||||
data.WriteUInt32(StateAnimKitID);
|
||||
data.WriteUInt32(GetViewerDependentStateAnimKitID(this, owner, receiver));
|
||||
}
|
||||
if (changesMask[12])
|
||||
{
|
||||
@@ -2477,6 +2483,63 @@ namespace Game.Entities
|
||||
}
|
||||
return interactSpellId;
|
||||
}
|
||||
List<uint> GetViewerDependentStateWorldEffectIDs(UnitData unitData, Unit unit, Player receiver)
|
||||
{
|
||||
List<uint> stateWorldEffects = unitData.StateWorldEffectIDs;
|
||||
|
||||
if (unit.IsCreature())
|
||||
{
|
||||
var spawnTrackingStateData = unit.GetSpawnTrackingStateDataForPlayer(receiver);
|
||||
if (spawnTrackingStateData != null)
|
||||
stateWorldEffects = spawnTrackingStateData.StateWorldEffects;
|
||||
}
|
||||
|
||||
return stateWorldEffects;
|
||||
}
|
||||
|
||||
|
||||
uint GetViewerDependentStateSpellVisualID(UnitData unitData, Unit unit, Player receiver)
|
||||
{
|
||||
uint stateSpellVisual = unitData.StateSpellVisualID;
|
||||
|
||||
if (unit.IsCreature())
|
||||
{
|
||||
var spawnTrackingStateData = unit.GetSpawnTrackingStateDataForPlayer(receiver);
|
||||
if (spawnTrackingStateData != null)
|
||||
stateSpellVisual = spawnTrackingStateData.StateSpellVisualId.GetValueOrDefault(0);
|
||||
}
|
||||
|
||||
return stateSpellVisual;
|
||||
}
|
||||
|
||||
|
||||
uint GetViewerDependentStateAnimID(UnitData unitData, Unit unit, Player receiver)
|
||||
{
|
||||
uint stateAnimId = Global.DB2Mgr.GetEmptyAnimStateID();
|
||||
|
||||
if (unit.IsCreature())
|
||||
{
|
||||
var spawnTrackingStateData = unit.GetSpawnTrackingStateDataForPlayer(receiver);
|
||||
if (spawnTrackingStateData != null)
|
||||
stateAnimId = spawnTrackingStateData.StateAnimId.GetValueOrDefault((ushort)stateAnimId);
|
||||
}
|
||||
|
||||
return stateAnimId;
|
||||
}
|
||||
|
||||
uint GetViewerDependentStateAnimKitID(UnitData unitData, Unit unit, Player receiver)
|
||||
{
|
||||
uint stateAnimKitId = unitData.StateAnimKitID;
|
||||
|
||||
if (unit.IsCreature())
|
||||
{
|
||||
var spawnTrackingStateData = unit.GetSpawnTrackingStateDataForPlayer(receiver);
|
||||
if (spawnTrackingStateData != null)
|
||||
stateAnimKitId = spawnTrackingStateData.StateAnimKitId.GetValueOrDefault(0);
|
||||
}
|
||||
|
||||
return stateAnimKitId;
|
||||
}
|
||||
}
|
||||
|
||||
public class ChrCustomizationChoice : IComparable<ChrCustomizationChoice>
|
||||
@@ -7505,25 +7568,26 @@ namespace Game.Entities
|
||||
{
|
||||
data.WriteUInt32(DisplayID);
|
||||
data.WriteUInt32(SpellVisualID);
|
||||
data.WriteUInt32(StateSpellVisualID);
|
||||
data.WriteUInt32(SpawnTrackingStateAnimID);
|
||||
data.WriteUInt32(SpawnTrackingStateAnimKitID);
|
||||
data.WriteInt32(((List<uint>)StateWorldEffectIDs).Count);
|
||||
data.WriteUInt32(GetViewerDependentStateSpellVisualID(this, owner, receiver));
|
||||
data.WriteUInt32(GetViewerDependentStateAnimID(this, owner, receiver));
|
||||
data.WriteUInt32(GetViewerDependentStateAnimKitID(this, owner, receiver));
|
||||
var stateWorldEffects = GetViewerDependentStateWorldEffectIDs(this, owner, receiver);
|
||||
data.WriteInt32(stateWorldEffects.Count);
|
||||
data.WriteUInt32(StateWorldEffectsQuestObjectiveID);
|
||||
for (int i = 0; i < ((List<uint>)StateWorldEffectIDs).Count; ++i)
|
||||
for (int i = 0; i < stateWorldEffects.Count; ++i)
|
||||
{
|
||||
data.WriteUInt32(((List<uint>)StateWorldEffectIDs)[i]);
|
||||
data.WriteUInt32(stateWorldEffects[i]);
|
||||
}
|
||||
data.WritePackedGuid(CreatedBy);
|
||||
data.WritePackedGuid(GuildGUID);
|
||||
data.WriteUInt32(GetViewerGameObjectFlags(this, owner, receiver));
|
||||
data.WriteUInt32(GetViewerDependentGameObjectFlags(this, owner, receiver));
|
||||
Quaternion rotation = ParentRotation;
|
||||
data.WriteFloat(rotation.X);
|
||||
data.WriteFloat(rotation.Y);
|
||||
data.WriteFloat(rotation.Z);
|
||||
data.WriteFloat(rotation.W);
|
||||
data.WriteUInt32(FactionTemplate);
|
||||
data.WriteInt8(GetViewerGameObjectState(this, owner, receiver));
|
||||
data.WriteInt8(GetViewerDependentGameObjectState(this, owner, receiver));
|
||||
data.WriteInt8(TypeID);
|
||||
data.WriteUInt8(PercentHealth);
|
||||
data.WriteUInt32(ArtKit);
|
||||
@@ -7558,10 +7622,11 @@ namespace Game.Entities
|
||||
{
|
||||
if (changesMask[1])
|
||||
{
|
||||
data.WriteBits(((List<uint>)StateWorldEffectIDs).Count, 32);
|
||||
for (int i = 0; i < ((List<uint>)StateWorldEffectIDs).Count; ++i)
|
||||
var stateWorldEffects = GetViewerDependentStateWorldEffectIDs(this, owner, receiver);
|
||||
data.WriteBits(stateWorldEffects.Count, 32);
|
||||
for (int i = 0; i < stateWorldEffects.Count; ++i)
|
||||
{
|
||||
data.WriteUInt32(((List<uint>)StateWorldEffectIDs)[i]);
|
||||
data.WriteUInt32(stateWorldEffects[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7616,15 +7681,15 @@ namespace Game.Entities
|
||||
}
|
||||
if (changesMask[6])
|
||||
{
|
||||
data.WriteUInt32(StateSpellVisualID);
|
||||
data.WriteUInt32(GetViewerDependentStateSpellVisualID(this, owner, receiver));
|
||||
}
|
||||
if (changesMask[7])
|
||||
{
|
||||
data.WriteUInt32(SpawnTrackingStateAnimID);
|
||||
data.WriteUInt32(GetViewerDependentStateAnimID(this, owner, receiver));
|
||||
}
|
||||
if (changesMask[8])
|
||||
{
|
||||
data.WriteUInt32(SpawnTrackingStateAnimKitID);
|
||||
data.WriteUInt32(GetViewerDependentStateAnimKitID(this, owner, receiver));
|
||||
}
|
||||
if (changesMask[9])
|
||||
{
|
||||
@@ -7640,7 +7705,7 @@ namespace Game.Entities
|
||||
}
|
||||
if (changesMask[12])
|
||||
{
|
||||
data.WriteUInt32(GetViewerGameObjectFlags(this, owner, receiver));
|
||||
data.WriteUInt32(GetViewerDependentGameObjectFlags(this, owner, receiver));
|
||||
}
|
||||
if (changesMask[13])
|
||||
{
|
||||
@@ -7655,7 +7720,7 @@ namespace Game.Entities
|
||||
}
|
||||
if (changesMask[15])
|
||||
{
|
||||
data.WriteInt8(GetViewerGameObjectState(this, owner, receiver));
|
||||
data.WriteInt8(GetViewerDependentGameObjectState(this, owner, receiver));
|
||||
}
|
||||
if (changesMask[16])
|
||||
{
|
||||
@@ -7725,7 +7790,7 @@ namespace Game.Entities
|
||||
_changesMask.ResetAll();
|
||||
}
|
||||
|
||||
uint GetViewerGameObjectFlags(GameObjectFieldData gameObjectData, GameObject gameObject, Player receiver)
|
||||
uint GetViewerDependentGameObjectFlags(GameObjectFieldData gameObjectData, GameObject gameObject, Player receiver)
|
||||
{
|
||||
uint flags = gameObjectData.Flags;
|
||||
if (gameObject.GetGoType() == GameObjectTypes.Chest)
|
||||
@@ -7735,10 +7800,55 @@ namespace Game.Entities
|
||||
return flags;
|
||||
}
|
||||
|
||||
sbyte GetViewerGameObjectState(GameObjectFieldData gameObjectData, GameObject gameObject, Player receiver)
|
||||
sbyte GetViewerDependentGameObjectState(GameObjectFieldData gameObjectData, GameObject gameObject, Player receiver)
|
||||
{
|
||||
return (sbyte)gameObject.GetGoStateFor(receiver.GetGUID());
|
||||
}
|
||||
|
||||
List<uint> GetViewerDependentStateWorldEffectIDs(GameObjectFieldData gameObjectData, GameObject gameObject, Player receiver)
|
||||
{
|
||||
List<uint> stateWorldEffects = gameObjectData.StateWorldEffectIDs;
|
||||
|
||||
var spawnTrackingStateData = gameObject.GetSpawnTrackingStateDataForPlayer(receiver);
|
||||
if (spawnTrackingStateData != null)
|
||||
stateWorldEffects = spawnTrackingStateData.StateWorldEffects;
|
||||
|
||||
return stateWorldEffects;
|
||||
}
|
||||
|
||||
uint GetViewerDependentStateSpellVisualID(GameObjectFieldData gameObjectData, GameObject gameObject, Player receiver)
|
||||
{
|
||||
uint stateSpellVisual = gameObjectData.StateSpellVisualID;
|
||||
|
||||
var spawnTrackingStateData = gameObject.GetSpawnTrackingStateDataForPlayer(receiver);
|
||||
if (spawnTrackingStateData != null)
|
||||
stateSpellVisual = spawnTrackingStateData.StateSpellVisualId.GetValueOrDefault(0);
|
||||
|
||||
return stateSpellVisual;
|
||||
}
|
||||
|
||||
uint GetViewerDependentStateAnimID(GameObjectFieldData gameObjectData, GameObject gameObject, Player receiver)
|
||||
{
|
||||
uint stateAnimId = Global.DB2Mgr.GetEmptyAnimStateID();
|
||||
|
||||
var spawnTrackingStateData = gameObject.GetSpawnTrackingStateDataForPlayer(receiver);
|
||||
if (spawnTrackingStateData != null)
|
||||
stateAnimId = spawnTrackingStateData.StateAnimId.GetValueOrDefault((ushort)stateAnimId);
|
||||
|
||||
return stateAnimId;
|
||||
}
|
||||
|
||||
uint GetViewerDependentStateAnimKitID(GameObjectFieldData gameObjectData, GameObject gameObject, Player receiver)
|
||||
{
|
||||
uint stateAnimKitId = gameObjectData.SpawnTrackingStateAnimKitID;
|
||||
|
||||
var spawnTrackingStateData = gameObject.GetSpawnTrackingStateDataForPlayer(receiver);
|
||||
if (spawnTrackingStateData != null)
|
||||
stateAnimKitId = spawnTrackingStateData.StateAnimKitId.GetValueOrDefault(0);
|
||||
|
||||
return stateAnimKitId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class DynamicObjectData : HasChangesMask
|
||||
|
||||
@@ -867,6 +867,8 @@ namespace Game.Entities
|
||||
|
||||
public virtual Loot GetLootForPlayer(Player player) { return null; }
|
||||
|
||||
public virtual SpawnTrackingStateData GetSpawnTrackingStateDataForPlayer(Player player) { return null; }
|
||||
|
||||
public virtual void BuildValuesCreate(WorldPacket data, UpdateFieldFlag flags, Player target) { }
|
||||
public virtual void BuildValuesUpdate(WorldPacket data, UpdateFieldFlag flags, Player target) { }
|
||||
|
||||
@@ -1272,6 +1274,15 @@ namespace Game.Entities
|
||||
if (!obj.IsPrivateObject() && !Global.ConditionMgr.IsObjectMeetingVisibilityByObjectIdConditions((uint)obj.GetTypeId(), obj.GetEntry(), this))
|
||||
return false;
|
||||
|
||||
// Spawn tracking
|
||||
Player player = ToPlayer();
|
||||
if (player != null)
|
||||
{
|
||||
SpawnTrackingStateData spawnTrackingStateData = obj.GetSpawnTrackingStateDataForPlayer(player);
|
||||
if (spawnTrackingStateData != null && !spawnTrackingStateData.Visible)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool corpseVisibility = false;
|
||||
if (distanceCheck)
|
||||
{
|
||||
@@ -1304,7 +1315,6 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
WorldObject viewpoint = this;
|
||||
Player player = ToPlayer();
|
||||
if (player != null)
|
||||
viewpoint = player.GetViewpoint();
|
||||
|
||||
|
||||
@@ -821,9 +821,11 @@ namespace Game.Entities
|
||||
uint questID = result.Read<uint>(0);
|
||||
|
||||
Quest quest = Global.ObjectMgr.GetQuestTemplate(questID);
|
||||
if (quest == null)
|
||||
continue;
|
||||
|
||||
var questStatusData = m_QuestStatus.LookupByKey(questID);
|
||||
if (questStatusData != null && questStatusData.Slot < SharedConst.MaxQuestLogSize && quest != null)
|
||||
if (questStatusData != null && questStatusData.Slot < SharedConst.MaxQuestLogSize)
|
||||
{
|
||||
byte storageIndex = result.Read<byte>(1);
|
||||
|
||||
@@ -845,6 +847,42 @@ namespace Game.Entities
|
||||
while (result.NextRow());
|
||||
}
|
||||
}
|
||||
|
||||
void _LoadQuestStatusObjectiveSpawnTrackings(SQLResult result)
|
||||
{
|
||||
if (!result.IsEmpty())
|
||||
{
|
||||
do
|
||||
{
|
||||
uint questID = result.Read<uint>(0);
|
||||
Quest quest = Global.ObjectMgr.GetQuestTemplate(questID);
|
||||
if (quest == null)
|
||||
continue;
|
||||
|
||||
var itr = m_QuestStatus.LookupByKey(questID);
|
||||
if (itr != null && itr.Slot < SharedConst.MaxQuestLogSize)
|
||||
{
|
||||
QuestStatusData questStatusData = itr;
|
||||
sbyte storageIndex = result.Read<sbyte>(1);
|
||||
var objectiveItr = quest.Objectives.Find(objective => objective.StorageIndex == storageIndex);
|
||||
if (objectiveItr != null)
|
||||
{
|
||||
uint spawnTrackingId = result.Read<uint>(2);
|
||||
|
||||
if (Global.ObjectMgr.IsQuestObjectiveForSpawnTracking(spawnTrackingId, objectiveItr.Id))
|
||||
questStatusData.SpawnTrackingList.Add((storageIndex, spawnTrackingId));
|
||||
else
|
||||
Log.outError(LogFilter.Player, $"Player::_LoadQuestStatusObjectiveSpawnTrackings: Player '{GetName()}' ({GetGUID()}) has objective {objectiveItr.Id} (quest {questID}) with unrelated spawn tracking {spawnTrackingId}.");
|
||||
}
|
||||
else
|
||||
Log.outError(LogFilter.Player, $"Player::_LoadQuestStatusObjectiveSpawnTrackings: Player '{GetName()}' ({GetGUID()}) has quest {questID} out of range objective index {storageIndex}.");
|
||||
}
|
||||
else
|
||||
Log.outError(LogFilter.Player, $"Player::_LoadQuestStatusObjectiveSpawnTrackings: Player {GetName()} ({GetGUID()}) does not have quest {questID} but has objective spawn trackings for it.");
|
||||
} while (result.NextRow());
|
||||
}
|
||||
}
|
||||
|
||||
void _LoadQuestStatusRewarded(SQLResult result)
|
||||
{
|
||||
if (!result.IsEmpty())
|
||||
@@ -2189,6 +2227,22 @@ namespace Game.Entities
|
||||
stmt.AddValue(3, GetQuestSlotObjectiveData(data.Slot, obj));
|
||||
trans.Append(stmt);
|
||||
}
|
||||
|
||||
// Save spawn trackings
|
||||
stmt = CharacterDatabase.GetPreparedStatement( CharStatements.DEL_CHAR_QUESTSTATUS_OBJECTIVES_SPAWN_TRACKING_BY_QUEST);
|
||||
stmt.AddValue(0, GetGUID().GetCounter());
|
||||
stmt.AddValue(1, save.Key);
|
||||
trans.Append(stmt);
|
||||
|
||||
foreach (var (questObjectiveStorageIndex, spawnTrackingId) in data.SpawnTrackingList)
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.REP_CHAR_QUESTSTATUS_OBJECTIVES_SPAWN_TRACKING);
|
||||
stmt.AddValue(0, GetGUID().GetCounter());
|
||||
stmt.AddValue(1, save.Key);
|
||||
stmt.AddValue(2, questObjectiveStorageIndex);
|
||||
stmt.AddValue(3, spawnTrackingId);
|
||||
trans.Append(stmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2203,6 +2257,11 @@ namespace Game.Entities
|
||||
stmt.AddValue(0, GetGUID().GetCounter());
|
||||
stmt.AddValue(1, save.Key);
|
||||
trans.Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.DEL_CHAR_QUESTSTATUS_OBJECTIVES_SPAWN_TRACKING_BY_QUEST);
|
||||
stmt.AddValue(0, GetGUID().GetCounter());
|
||||
stmt.AddValue(1, save.Key);
|
||||
trans.Append(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3427,6 +3486,7 @@ namespace Game.Entities
|
||||
// after spell load, learn rewarded spell if need also
|
||||
_LoadQuestStatus(holder.GetResult(PlayerLoginQueryLoad.QuestStatus));
|
||||
_LoadQuestStatusObjectives(holder.GetResult(PlayerLoginQueryLoad.QuestStatusObjectives));
|
||||
_LoadQuestStatusObjectiveSpawnTrackings(holder.GetResult(PlayerLoginQueryLoad.QuestStatusSpawnTracking));
|
||||
_LoadQuestStatusRewarded(holder.GetResult(PlayerLoginQueryLoad.QuestStatusRew));
|
||||
_LoadDailyQuestStatus(holder.GetResult(PlayerLoginQueryLoad.DailyQuestStatus));
|
||||
_LoadWeeklyQuestStatus(holder.GetResult(PlayerLoginQueryLoad.WeeklyQuestStatus));
|
||||
@@ -4407,6 +4467,10 @@ namespace Game.Entities
|
||||
stmt.AddValue(0, guid);
|
||||
trans.Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.DEL_CHAR_QUESTSTATUS_OBJECTIVES_SPAWN_TRACKING);
|
||||
stmt.AddValue(0, guid);
|
||||
trans.Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.DEL_CHAR_QUESTSTATUS_REWARDED);
|
||||
stmt.AddValue(0, guid);
|
||||
trans.Append(stmt);
|
||||
|
||||
@@ -753,6 +753,8 @@ namespace Game.Entities
|
||||
QuestStatusData questStatusData = m_QuestStatus.LookupByKey(questId);
|
||||
QuestStatus oldStatus = questStatusData.Status;
|
||||
|
||||
SendForceSpawnTrackingUpdate(questId);
|
||||
|
||||
// check for repeatable quests status reset
|
||||
SetQuestSlot(logSlot, questId);
|
||||
questStatusData.Slot = logSlot;
|
||||
@@ -836,6 +838,8 @@ namespace Game.Entities
|
||||
{
|
||||
if (quest_id != 0)
|
||||
{
|
||||
SendForceSpawnTrackingUpdate(quest_id);
|
||||
|
||||
SetQuestStatus(quest_id, QuestStatus.Complete);
|
||||
|
||||
QuestStatusData questStatus = m_QuestStatus.LookupByKey(quest_id);
|
||||
@@ -2610,6 +2614,32 @@ namespace Game.Entities
|
||||
bool updatePhaseShift = false;
|
||||
bool updateZoneAuras = false;
|
||||
|
||||
bool anyObjectiveChangedSpawnTrackingState = false;
|
||||
bool isObjectiveTypeForSpawnTracking = false;
|
||||
|
||||
if (objectiveType == QuestObjectiveType.Monster ||
|
||||
objectiveType == QuestObjectiveType.GameObject ||
|
||||
objectiveType == QuestObjectiveType.TalkTo ||
|
||||
objectiveType == QuestObjectiveType.WinPetBattleAgainstNpc)
|
||||
isObjectiveTypeForSpawnTracking = true;
|
||||
|
||||
SpawnMetadata data = null;
|
||||
if (isObjectiveTypeForSpawnTracking)
|
||||
{
|
||||
if (victimGuid.IsGameObject())
|
||||
{
|
||||
GameObject gameObject = ObjectAccessor.GetGameObject(this, victimGuid);
|
||||
if (gameObject != null)
|
||||
data = Global.ObjectMgr.GetSpawnMetadata(SpawnObjectType.GameObject, gameObject.GetSpawnId());
|
||||
}
|
||||
else if (victimGuid.IsCreatureOrVehicle())
|
||||
{
|
||||
Creature creature = ObjectAccessor.GetCreatureOrPetOrVehicle(this, victimGuid);
|
||||
if (creature != null)
|
||||
data = Global.ObjectMgr.GetSpawnMetadata(SpawnObjectType.Creature, creature.GetSpawnId());
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var objectiveStatusData in m_questObjectiveStatus.LookupByKey((objectiveType, objectId)))
|
||||
{
|
||||
uint questId = objectiveStatusData.QuestStatusPair.QuestID;
|
||||
@@ -2719,6 +2749,41 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
if (data != null && data.spawnTrackingQuestObjectiveId != 0 && data.spawnTrackingData != null)
|
||||
{
|
||||
if (objective.Id == data.spawnTrackingQuestObjectiveId)
|
||||
{
|
||||
// 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))
|
||||
{
|
||||
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;
|
||||
|
||||
SpawnTrackingState state = GetSpawnTrackingStateByObjective(data.spawnTrackingData.SpawnTrackingId, objective.Id);
|
||||
responseInfo.Visible = data.spawnTrackingStates[(int)state].Visible;
|
||||
|
||||
response.SpawnTrackingResponses.Add(responseInfo);
|
||||
SendPacket(response);
|
||||
}
|
||||
|
||||
anyObjectiveChangedSpawnTrackingState = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (objectiveWasComplete != objectiveIsNowComplete)
|
||||
anyObjectiveChangedCompletionState = true;
|
||||
|
||||
@@ -2752,7 +2817,7 @@ namespace Game.Entities
|
||||
|
||||
}
|
||||
|
||||
if (anyObjectiveChangedCompletionState)
|
||||
if (anyObjectiveChangedCompletionState || anyObjectiveChangedSpawnTrackingState)
|
||||
UpdateVisibleObjectInteractions(true, false, false, true);
|
||||
|
||||
if (updatePhaseShift)
|
||||
@@ -3138,6 +3203,8 @@ namespace Game.Entities
|
||||
moneyReward = (uint)(GetQuestMoneyReward(quest) + (int)(quest.GetRewMoneyMaxLevel() * WorldConfig.GetFloatValue(WorldCfg.RateDropMoney)));
|
||||
}
|
||||
|
||||
SendForceSpawnTrackingUpdate(questId);
|
||||
|
||||
if (quest.HasFlag(QuestFlags.TrackingEvent))
|
||||
return;
|
||||
|
||||
@@ -3348,6 +3415,51 @@ namespace Game.Entities
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SendForceSpawnTrackingUpdate(uint questId)
|
||||
{
|
||||
if (questId != 0)
|
||||
{
|
||||
ForceSpawnTrackingUpdate data = new();
|
||||
data.QuestID = questId;
|
||||
SendPacket(data);
|
||||
}
|
||||
}
|
||||
|
||||
public QuestObjective GetActiveQuestObjectiveForForSpawnTracking(uint spawnTrackingId)
|
||||
{
|
||||
var questObjectiveList = Global.ObjectMgr.GetSpawnTrackingQuestObjectiveList(spawnTrackingId);
|
||||
if (questObjectiveList != null)
|
||||
foreach (QuestObjective questObjective in questObjectiveList)
|
||||
if (FindQuestSlot(questObjective.QuestID) < SharedConst.MaxQuestLogSize)
|
||||
return questObjective;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public SpawnTrackingState GetSpawnTrackingStateByObjective(uint spawnTrackingId, uint questObjectiveId)
|
||||
{
|
||||
if (spawnTrackingId != 0 && questObjectiveId != 0 && Global.ObjectMgr.IsQuestObjectiveForSpawnTracking(spawnTrackingId, questObjectiveId))
|
||||
{
|
||||
QuestObjective questObjective = Global.ObjectMgr.GetQuestObjective(questObjectiveId);
|
||||
if (questObjective != null)
|
||||
{
|
||||
if (IsQuestRewarded(questObjective.QuestID) || IsQuestObjectiveComplete(questObjective.QuestID, questObjective.Id))
|
||||
return SpawnTrackingState.Complete;
|
||||
else if (GetQuestStatus(questObjective.QuestID) != QuestStatus.None)
|
||||
{
|
||||
var itr = m_QuestStatus.LookupByKey(questObjective.QuestID);
|
||||
if (itr != null && itr.Slot < SharedConst.MaxQuestLogSize)
|
||||
if (itr.SpawnTrackingList.Contains((questObjective.StorageIndex, spawnTrackingId)))
|
||||
return SpawnTrackingState.Complete;
|
||||
|
||||
return SpawnTrackingState.Active;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SpawnTrackingState.None;
|
||||
}
|
||||
|
||||
public bool HasQuestForGO(int GOId)
|
||||
{
|
||||
foreach (var objectiveStatusData in m_questObjectiveStatus.LookupByKey((QuestObjectiveType.GameObject, GOId)))
|
||||
@@ -3389,7 +3501,16 @@ namespace Game.Entities
|
||||
ObjectFieldData objMask = new();
|
||||
GameObjectFieldData goMask = new();
|
||||
|
||||
if (m_questObjectiveStatus.ContainsKey((QuestObjectiveType.GameObject, (int)gameObject.GetEntry())) || gameObject.GetGoInfo().GetConditionID1() != 0)
|
||||
SpawnMetadata data = Global.ObjectMgr.GetSpawnMetadata(SpawnObjectType.GameObject, gameObject.GetSpawnId());
|
||||
if (data != null && data.spawnTrackingQuestObjectiveId != 0 && data.spawnTrackingData != null)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else if (m_questObjectiveStatus.ContainsKey((QuestObjectiveType.GameObject, (int)gameObject.GetEntry())) || gameObject.GetGoInfo().GetConditionID1() != 0)
|
||||
objMask.MarkChanged(gameObject.m_objectData.DynamicFlags);
|
||||
else
|
||||
{
|
||||
@@ -3430,6 +3551,16 @@ namespace Game.Entities
|
||||
if (creature.m_unitData.NpcFlags2 != 0)
|
||||
unitMask.MarkChanged(m_unitData.NpcFlags2);
|
||||
|
||||
SpawnMetadata data = Global.ObjectMgr.GetSpawnMetadata(SpawnObjectType.Creature, creature.GetSpawnId());
|
||||
if (data != null && data.spawnTrackingQuestObjectiveId != 0 && data.spawnTrackingData != null)
|
||||
{
|
||||
objMask.MarkChanged(objMask.DynamicFlags);
|
||||
unitMask.MarkChanged(unitMask.StateWorldEffectIDs);
|
||||
unitMask.MarkChanged(unitMask.StateSpellVisualID);
|
||||
unitMask.MarkChanged(unitMask.StateAnimID);
|
||||
unitMask.MarkChanged(unitMask.StateAnimKitID);
|
||||
}
|
||||
|
||||
if (objMask.GetUpdateMask().IsAnySet() || unitMask.GetUpdateMask().IsAnySet())
|
||||
creature.BuildValuesUpdateForPlayerWithMask(udata, objMask.GetUpdateMask(), unitMask.GetUpdateMask(), this);
|
||||
|
||||
|
||||
@@ -5524,7 +5524,6 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
SetDisplayId(model.DisplayID, true);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.StateAnimID), DB2Mgr.GetEmptyAnimStateID());
|
||||
}
|
||||
|
||||
//Creature
|
||||
|
||||
@@ -172,7 +172,6 @@ namespace Game.Entities
|
||||
SetGoState(goinfo.MoTransport.allowstopping == 0 ? GameObjectState.Ready : GameObjectState.Active);
|
||||
SetGoType(GameObjectTypes.MapObjTransport);
|
||||
SetGoAnimProgress(255);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.SpawnTrackingStateAnimID), Global.DB2Mgr.GetEmptyAnimStateID());
|
||||
SetName(goinfo.name);
|
||||
SetLocalRotation(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
SetParentRotation(Quaternion.Identity);
|
||||
|
||||
Reference in New Issue
Block a user