diff --git a/Source/Framework/Database/Databases/HotfixDatabase.cs b/Source/Framework/Database/Databases/HotfixDatabase.cs index 9605c49ed..a97a3fc52 100644 --- a/Source/Framework/Database/Databases/HotfixDatabase.cs +++ b/Source/Framework/Database/Databases/HotfixDatabase.cs @@ -690,6 +690,11 @@ namespace Framework.Database "ItemContextPickerID, Flags, ContentTuningID, MapID FROM map_difficulty"); PrepareStatement(HotfixStatements.SEL_MAP_DIFFICULTY_LOCALE, "SELECT ID, Message_lang FROM map_difficulty_locale WHERE locale = ?"); + // MapDifficultyXCondition.db2 + PrepareStatement(HotfixStatements.SEL_MAP_DIFFICULTY_X_CONDITION, "SELECT ID, FailureDescription, PlayerConditionID, OrderIndex, MapDifficultyID" + + " FROM map_difficulty_x_condition"); + PrepareStatement(HotfixStatements.SEL_MAP_DIFFICULTY_X_CONDITION_LOCALE, "SELECT ID, FailureDescription_lang FROM map_difficulty_x_condition_locale WHERE locale = ?"); + // ModifierTree.db2 PrepareStatement(HotfixStatements.SEL_MODIFIER_TREE, "SELECT ID, Parent, Operator, Amount, Type, Asset, SecondaryAsset, TertiaryAsset FROM modifier_tree"); @@ -1487,6 +1492,9 @@ namespace Framework.Database SEL_MAP_DIFFICULTY, SEL_MAP_DIFFICULTY_LOCALE, + SEL_MAP_DIFFICULTY_X_CONDITION, + SEL_MAP_DIFFICULTY_X_CONDITION_LOCALE, + SEL_MODIFIER_TREE, SEL_MOUNT, diff --git a/Source/Game/DataStorage/CliDB.cs b/Source/Game/DataStorage/CliDB.cs index a83fa22cb..9538654dc 100644 --- a/Source/Game/DataStorage/CliDB.cs +++ b/Source/Game/DataStorage/CliDB.cs @@ -205,6 +205,7 @@ namespace Game.DataStorage MailTemplateStorage = ReadDB2("MailTemplate.db2", HotfixStatements.SEL_MAIL_TEMPLATE, HotfixStatements.SEL_MAIL_TEMPLATE_LOCALE); MapStorage = ReadDB2("Map.db2", HotfixStatements.SEL_MAP, HotfixStatements.SEL_MAP_LOCALE); MapDifficultyStorage = ReadDB2("MapDifficulty.db2", HotfixStatements.SEL_MAP_DIFFICULTY, HotfixStatements.SEL_MAP_DIFFICULTY_LOCALE); + MapDifficultyXConditionStorage = ReadDB2("MapDifficultyXCondition.db2", HotfixStatements.SEL_MAP_DIFFICULTY_X_CONDITION, HotfixStatements.SEL_MAP_DIFFICULTY_X_CONDITION_LOCALE); ModifierTreeStorage = ReadDB2("ModifierTree.db2", HotfixStatements.SEL_MODIFIER_TREE); MountCapabilityStorage = ReadDB2("MountCapability.db2", HotfixStatements.SEL_MOUNT_CAPABILITY); MountStorage = ReadDB2("Mount.db2", HotfixStatements.SEL_MOUNT, HotfixStatements.SEL_MOUNT_LOCALE); @@ -561,6 +562,7 @@ namespace Game.DataStorage public static DB6Storage MailTemplateStorage; public static DB6Storage MapStorage; public static DB6Storage MapDifficultyStorage; + public static DB6Storage MapDifficultyXConditionStorage; public static DB6Storage ModifierTreeStorage; public static DB6Storage MountCapabilityStorage; public static DB6Storage MountStorage; diff --git a/Source/Game/DataStorage/DB2Manager.cs b/Source/Game/DataStorage/DB2Manager.cs index d1ae657c5..d3a918b0a 100644 --- a/Source/Game/DataStorage/DB2Manager.cs +++ b/Source/Game/DataStorage/DB2Manager.cs @@ -376,6 +376,19 @@ namespace Game.DataStorage CliDB.MapDifficultyStorage.Clear(); + List mapDifficultyConditions = new List(); + foreach (var mapDifficultyCondition in CliDB.MapDifficultyXConditionStorage.Values) + mapDifficultyConditions.Add(mapDifficultyCondition); + + mapDifficultyConditions = mapDifficultyConditions.OrderBy(p => p.OrderIndex).ToList(); + + foreach (var mapDifficultyCondition in mapDifficultyConditions) + { + PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(mapDifficultyCondition.PlayerConditionID); + if (playerCondition != null) + _mapDifficultyConditions.Add(mapDifficultyCondition.MapDifficultyID, Tuple.Create(mapDifficultyCondition.Id, playerCondition)); + } + foreach (var mount in CliDB.MountStorage.Values) _mountsBySpellId[mount.SourceSpellID] = mount; @@ -1674,12 +1687,17 @@ namespace Game.DataStorage return mapDiff; } + public List> GetMapDifficultyConditions(uint mapDifficultyId) + { + return _mapDifficultyConditions.LookupByKey(mapDifficultyId); + } + public MountRecord GetMount(uint spellId) { return _mountsBySpellId.LookupByKey(spellId); } - MountRecord GetMountById(uint id) + public MountRecord GetMountById(uint id) { return CliDB.MountStorage.LookupByKey(id); } @@ -2286,6 +2304,7 @@ namespace Game.DataStorage MultiMap _itemSetSpells = new MultiMap(); MultiMap _itemSpecOverrides = new MultiMap(); Dictionary> _mapDifficulties = new Dictionary>(); + MultiMap> _mapDifficultyConditions = new MultiMap>(); Dictionary _mountsBySpellId = new Dictionary(); MultiMap _mountCapabilitiesByType = new MultiMap(); MultiMap _mountDisplays = new MultiMap(); diff --git a/Source/Game/DataStorage/Structs/M_Records.cs b/Source/Game/DataStorage/Structs/M_Records.cs index 9a441ab59..3a9cc12cd 100644 --- a/Source/Game/DataStorage/Structs/M_Records.cs +++ b/Source/Game/DataStorage/Structs/M_Records.cs @@ -116,6 +116,15 @@ namespace Game.DataStorage } } + public sealed class MapDifficultyXConditionRecord + { + public uint Id; + public LocalizedString FailureDescription; + public uint PlayerConditionID; + public int OrderIndex; + public uint MapDifficultyID; + } + public sealed class ModifierTreeRecord { public uint Id; diff --git a/Source/Game/Entities/Player/Player.Map.cs b/Source/Game/Entities/Player/Player.Map.cs index 924611ad7..7bab41851 100644 --- a/Source/Game/Entities/Player/Player.Map.cs +++ b/Source/Game/Entities/Player/Player.Map.cs @@ -493,32 +493,53 @@ namespace Game.Entities public bool Satisfy(AccessRequirement ar, uint target_map, bool report = false) { - if (!IsGameMaster() && ar != null) + if (!IsGameMaster()) { byte LevelMin = 0; byte LevelMax = 0; + uint failedMapDifficultyXCondition = 0; + uint missingItem = 0; + uint missingQuest = 0; + uint missingAchievement = 0; MapRecord mapEntry = CliDB.MapStorage.LookupByKey(target_map); if (mapEntry == null) return false; + Difficulty target_difficulty = GetDifficultyID(mapEntry); + MapDifficultyRecord mapDiff = Global.DB2Mgr.GetDownscaledMapDifficultyData(target_map, ref target_difficulty); if (!WorldConfig.GetBoolValue(WorldCfg.InstanceIgnoreLevel)) { - if (ar.levelMin != 0 && GetLevel() < ar.levelMin) - LevelMin = ar.levelMin; - if (ar.levelMax != 0 && GetLevel() > ar.levelMax) - LevelMax = ar.levelMax; + var mapDifficultyConditions = Global.DB2Mgr.GetMapDifficultyConditions(mapDiff.Id); + foreach (var pair in mapDifficultyConditions) + { + if (!ConditionManager.IsPlayerMeetingCondition(this, pair.Item2)) + { + failedMapDifficultyXCondition = pair.Item1; + break; + } + } } - uint missingItem = 0; - if (ar.item != 0) + if (ar != null) { - if (!HasItemCount(ar.item) && + if (!WorldConfig.GetBoolValue(WorldCfg.InstanceIgnoreLevel)) + { + if (ar.levelMin != 0 && GetLevel() < ar.levelMin) + LevelMin = ar.levelMin; + if (ar.levelMax != 0 && GetLevel() > ar.levelMax) + LevelMax = ar.levelMax; + } + + if (ar.item != 0) + { + if (!HasItemCount(ar.item) && (ar.item2 == 0 || !HasItemCount(ar.item2))) - missingItem = ar.item; + missingItem = ar.item; + } + else if (ar.item2 != 0 && !HasItemCount(ar.item2)) + missingItem = ar.item2; } - else if (ar.item2 != 0 && !HasItemCount(ar.item2)) - missingItem = ar.item2; if (Global.DisableMgr.IsDisabledFor(DisableType.Map, target_map, this)) { @@ -526,13 +547,11 @@ namespace Game.Entities return false; } - uint missingQuest = 0; if (GetTeam() == Team.Alliance && ar.quest_A != 0 && !GetQuestRewardStatus(ar.quest_A)) missingQuest = ar.quest_A; else if (GetTeam() == Team.Horde && ar.quest_H != 0 && !GetQuestRewardStatus(ar.quest_H)) missingQuest = ar.quest_H; - uint missingAchievement = 0; Player leader = this; ObjectGuid leaderGuid = GetGroup() != null ? GetGroup().GetLeaderGUID() : GetGUID(); if (leaderGuid != GetGUID()) @@ -542,16 +561,14 @@ namespace Game.Entities if (leader == null || !leader.HasAchieved(ar.achievement)) missingAchievement = ar.achievement; - Difficulty target_difficulty = GetDifficultyID(mapEntry); - MapDifficultyRecord mapDiff = Global.DB2Mgr.GetDownscaledMapDifficultyData(target_map, ref target_difficulty); - if (LevelMin != 0 || LevelMax != 0 || missingItem != 0 || missingQuest != 0 || missingAchievement != 0) + if (LevelMin != 0 || LevelMax != 0 || failedMapDifficultyXCondition != 0 || missingItem != 0 || missingQuest != 0 || missingAchievement != 0) { if (report) { if (missingQuest != 0 && !string.IsNullOrEmpty(ar.questFailedText)) SendSysMessage("{0}", ar.questFailedText); - else if (mapDiff.Message.HasString(Global.WorldMgr.GetDefaultDbcLocale())) // if (missingAchievement) covered by this case - SendTransferAborted(target_map, TransferAbortReason.Difficulty, (byte)target_difficulty); + else if (mapDiff.Message[Global.WorldMgr.GetDefaultDbcLocale()][0] != '\0' || failedMapDifficultyXCondition != 0) // if (missingAchievement) covered by this case + SendTransferAborted(target_map, TransferAbortReason.Difficulty, (byte)target_difficulty, failedMapDifficultyXCondition); else if (missingItem != 0) GetSession().SendNotification(Global.ObjectMgr.GetCypherString(CypherStrings.LevelMinrequiredAndItem), LevelMin, Global.ObjectMgr.GetItemTemplate(missingItem).GetName()); else if (LevelMin != 0) @@ -722,12 +739,13 @@ namespace Game.Entities SendPacket(data); } - public void SendTransferAborted(uint mapid, TransferAbortReason reason, byte arg = 0) + public void SendTransferAborted(uint mapid, TransferAbortReason reason, byte arg = 0, uint mapDifficultyXConditionID = 0) { TransferAborted transferAborted = new TransferAborted(); transferAborted.MapID = mapid; transferAborted.Arg = arg; transferAborted.TransfertAbort = reason; + transferAborted.MapDifficultyXConditionID = mapDifficultyXConditionID; SendPacket(transferAborted); } diff --git a/Source/Game/Maps/Map.cs b/Source/Game/Maps/Map.cs index e9e989896..10db969d2 100644 --- a/Source/Game/Maps/Map.cs +++ b/Source/Game/Maps/Map.cs @@ -2763,6 +2763,10 @@ namespace Game.Maps { Cypher.Assert(mode == 1); Cypher.Assert(obj.GetMap() == this); + + if (IsBattlegroundOrArena()) + return; + SpawnObjectType type; switch (obj.GetTypeId()) { @@ -2777,7 +2781,7 @@ namespace Game.Maps } SpawnData data = Global.ObjectMgr.GetSpawnData(type, spawnId); - if (data == null || !data.spawnGroupData.flags.HasAnyFlag(SpawnGroupFlags.DynamicSpawnRate)) + if (data == null || data.spawnGroupData == null || !!data.spawnGroupData.flags.HasAnyFlag(SpawnGroupFlags.DynamicSpawnRate)) return; if (!_zonePlayerCountMap.ContainsKey(obj.GetZoneId())) diff --git a/Source/Game/Networking/Packets/MovementPackets.cs b/Source/Game/Networking/Packets/MovementPackets.cs index 70e666f6a..77e89e470 100644 --- a/Source/Game/Networking/Packets/MovementPackets.cs +++ b/Source/Game/Networking/Packets/MovementPackets.cs @@ -566,14 +566,14 @@ namespace Game.Networking.Packets { _worldPacket.WriteUInt32(MapID); _worldPacket.WriteUInt8(Arg); - _worldPacket.WriteInt32(MapDifficultyXConditionID); + _worldPacket.WriteUInt32(MapDifficultyXConditionID); _worldPacket.WriteBits(TransfertAbort, 5); _worldPacket.FlushBits(); } public uint MapID; public byte Arg; - public int MapDifficultyXConditionID; + public uint MapDifficultyXConditionID; public TransferAbortReason TransfertAbort; }