mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Instances: Use level requirements from MapDifficultyXCondition.db2 instead of access_requirement db table
This commit is contained in:
42
sql/updates/hotfixes/master/2021_01_02_00_hotfixes.sql
Normal file
42
sql/updates/hotfixes/master/2021_01_02_00_hotfixes.sql
Normal file
@@ -0,0 +1,42 @@
|
||||
--
|
||||
-- Table structure for table `map_difficulty_x_condition`
|
||||
--
|
||||
DROP TABLE IF EXISTS `map_difficulty_x_condition`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `map_difficulty_x_condition` (
|
||||
`ID` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`FailureDescription` text,
|
||||
`PlayerConditionID` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`OrderIndex` int(11) NOT NULL DEFAULT '0',
|
||||
`MapDifficultyID` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`VerifiedBuild` int(11) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`ID`,`VerifiedBuild`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `map_difficulty_x_condition_locale`
|
||||
--
|
||||
DROP TABLE IF EXISTS `map_difficulty_x_condition_locale`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `map_difficulty_x_condition_locale` (
|
||||
`ID` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`locale` varchar(4) NOT NULL,
|
||||
`FailureDescription_lang` text,
|
||||
`VerifiedBuild` int(11) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`ID`,`locale`,`VerifiedBuild`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
/*!50500 PARTITION BY LIST COLUMNS(locale)
|
||||
(PARTITION deDE VALUES IN ('deDE') ENGINE = InnoDB,
|
||||
PARTITION esES VALUES IN ('esES') ENGINE = InnoDB,
|
||||
PARTITION esMX VALUES IN ('esMX') ENGINE = InnoDB,
|
||||
PARTITION frFR VALUES IN ('frFR') ENGINE = InnoDB,
|
||||
PARTITION itIT VALUES IN ('itIT') ENGINE = InnoDB,
|
||||
PARTITION koKR VALUES IN ('koKR') ENGINE = InnoDB,
|
||||
PARTITION ptBR VALUES IN ('ptBR') ENGINE = InnoDB,
|
||||
PARTITION ruRU VALUES IN ('ruRU') ENGINE = InnoDB,
|
||||
PARTITION zhCN VALUES IN ('zhCN') ENGINE = InnoDB,
|
||||
PARTITION zhTW VALUES IN ('zhTW') ENGINE = InnoDB) */;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
1
sql/updates/world/master/2021_01_02_00_world.sql
Normal file
1
sql/updates/world/master/2021_01_02_00_world.sql
Normal file
@@ -0,0 +1 @@
|
||||
UPDATE `access_requirement` SET `level_min`=0,`level_max`=0;
|
||||
@@ -934,6 +934,13 @@ void HotfixDatabaseConnection::DoPrepareStatements()
|
||||
PREPARE_MAX_ID_STMT(HOTFIX_SEL_MAP_DIFFICULTY, "SELECT MAX(ID) + 1 FROM map_difficulty", CONNECTION_SYNCH);
|
||||
PREPARE_LOCALE_STMT(HOTFIX_SEL_MAP_DIFFICULTY, "SELECT ID, Message_lang FROM map_difficulty_locale WHERE (`VerifiedBuild` > 0) = ? AND locale = ?", CONNECTION_SYNCH);
|
||||
|
||||
// MapDifficultyXCondition.db2
|
||||
PrepareStatement(HOTFIX_SEL_MAP_DIFFICULTY_X_CONDITION, "SELECT ID, FailureDescription, PlayerConditionID, OrderIndex, MapDifficultyID"
|
||||
" FROM map_difficulty_x_condition WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
|
||||
PREPARE_MAX_ID_STMT(HOTFIX_SEL_MAP_DIFFICULTY_X_CONDITION, "SELECT MAX(ID) + 1 FROM map_difficulty_x_condition", CONNECTION_SYNCH);
|
||||
PREPARE_LOCALE_STMT(HOTFIX_SEL_MAP_DIFFICULTY_X_CONDITION, "SELECT ID, FailureDescription_lang FROM map_difficulty_x_condition_locale"
|
||||
" WHERE (`VerifiedBuild` > 0) = ? AND locale = ?", CONNECTION_SYNCH);
|
||||
|
||||
// ModifierTree.db2
|
||||
PrepareStatement(HOTFIX_SEL_MODIFIER_TREE, "SELECT ID, Parent, Operator, Amount, Type, Asset, SecondaryAsset, TertiaryAsset FROM modifier_tree"
|
||||
" WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
|
||||
|
||||
@@ -539,6 +539,10 @@ enum HotfixDatabaseStatements : uint32
|
||||
HOTFIX_SEL_MAP_DIFFICULTY_MAX_ID,
|
||||
HOTFIX_SEL_MAP_DIFFICULTY_LOCALE,
|
||||
|
||||
HOTFIX_SEL_MAP_DIFFICULTY_X_CONDITION,
|
||||
HOTFIX_SEL_MAP_DIFFICULTY_X_CONDITION_MAX_ID,
|
||||
HOTFIX_SEL_MAP_DIFFICULTY_X_CONDITION_LOCALE,
|
||||
|
||||
HOTFIX_SEL_MODIFIER_TREE,
|
||||
HOTFIX_SEL_MODIFIER_TREE_MAX_ID,
|
||||
|
||||
|
||||
@@ -3561,6 +3561,23 @@ struct MapDifficultyLoadInfo
|
||||
}
|
||||
};
|
||||
|
||||
struct MapDifficultyXConditionLoadInfo
|
||||
{
|
||||
static DB2LoadInfo const* Instance()
|
||||
{
|
||||
static DB2FieldMeta const fields[] =
|
||||
{
|
||||
{ false, FT_INT, "ID" },
|
||||
{ false, FT_STRING, "FailureDescription" },
|
||||
{ false, FT_INT, "PlayerConditionID" },
|
||||
{ true, FT_INT, "OrderIndex" },
|
||||
{ false, FT_INT, "MapDifficultyID" },
|
||||
};
|
||||
static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, MapDifficultyXConditionMeta::Instance(), HOTFIX_SEL_MAP_DIFFICULTY_X_CONDITION);
|
||||
return &loadInfo;
|
||||
}
|
||||
};
|
||||
|
||||
struct ModifierTreeLoadInfo
|
||||
{
|
||||
static DB2LoadInfo const* Instance()
|
||||
|
||||
@@ -196,6 +196,7 @@ DB2Storage<LockEntry> sLockStore("Lock.db2", LockLoadI
|
||||
DB2Storage<MailTemplateEntry> sMailTemplateStore("MailTemplate.db2", MailTemplateLoadInfo::Instance());
|
||||
DB2Storage<MapEntry> sMapStore("Map.db2", MapLoadInfo::Instance());
|
||||
DB2Storage<MapDifficultyEntry> sMapDifficultyStore("MapDifficulty.db2", MapDifficultyLoadInfo::Instance());
|
||||
DB2Storage<MapDifficultyXConditionEntry> sMapDifficultyXConditionStore("MapDifficultyXCondition.db2", MapDifficultyXConditionLoadInfo::Instance());
|
||||
DB2Storage<ModifierTreeEntry> sModifierTreeStore("ModifierTree.db2", ModifierTreeLoadInfo::Instance());
|
||||
DB2Storage<MountCapabilityEntry> sMountCapabilityStore("MountCapability.db2", MountCapabilityLoadInfo::Instance());
|
||||
DB2Storage<MountEntry> sMountStore("Mount.db2", MountLoadInfo::Instance());
|
||||
@@ -418,6 +419,7 @@ namespace
|
||||
ItemSetSpellContainer _itemSetSpells;
|
||||
ItemSpecOverridesContainer _itemSpecOverrides;
|
||||
DB2Manager::MapDifficultyContainer _mapDifficulties;
|
||||
std::unordered_map<uint32, DB2Manager::MapDifficultyConditionsContainer> _mapDifficultyConditions;
|
||||
std::unordered_map<uint32, MountEntry const*> _mountsBySpellId;
|
||||
MountCapabilitiesByTypeContainer _mountCapabilitiesByType;
|
||||
MountDisplaysCointainer _mountDisplays;
|
||||
@@ -725,6 +727,7 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul
|
||||
LOAD_DB2(sMailTemplateStore);
|
||||
LOAD_DB2(sMapStore);
|
||||
LOAD_DB2(sMapDifficultyStore);
|
||||
LOAD_DB2(sMapDifficultyXConditionStore);
|
||||
LOAD_DB2(sModifierTreeStore);
|
||||
LOAD_DB2(sMountCapabilityStore);
|
||||
LOAD_DB2(sMountStore);
|
||||
@@ -1125,6 +1128,20 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul
|
||||
_mapDifficulties[entry->MapID][entry->DifficultyID] = entry;
|
||||
_mapDifficulties[0][0] = _mapDifficulties[1][0]; // map 0 is missing from MapDifficulty.dbc so we cheat a bit
|
||||
|
||||
std::vector<MapDifficultyXConditionEntry const*> mapDifficultyConditions;
|
||||
mapDifficultyConditions.reserve(sMapDifficultyXConditionStore.GetNumRows());
|
||||
for (MapDifficultyXConditionEntry const* mapDifficultyCondition : sMapDifficultyXConditionStore)
|
||||
mapDifficultyConditions.push_back(mapDifficultyCondition);
|
||||
|
||||
std::sort(mapDifficultyConditions.begin(), mapDifficultyConditions.end(), [](MapDifficultyXConditionEntry const* left, MapDifficultyXConditionEntry const* right)
|
||||
{
|
||||
return left->OrderIndex < right->OrderIndex;
|
||||
});
|
||||
|
||||
for (MapDifficultyXConditionEntry const* mapDifficultyCondition : mapDifficultyConditions)
|
||||
if (PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(mapDifficultyCondition->PlayerConditionID))
|
||||
_mapDifficultyConditions[mapDifficultyCondition->MapDifficultyID].emplace_back(mapDifficultyCondition->ID, playerCondition);
|
||||
|
||||
for (MountEntry const* mount : sMountStore)
|
||||
_mountsBySpellId[mount->SourceSpellID] = mount;
|
||||
|
||||
@@ -2557,6 +2574,11 @@ MapDifficultyEntry const* DB2Manager::GetDownscaledMapDifficultyData(uint32 mapI
|
||||
return mapDiff;
|
||||
}
|
||||
|
||||
DB2Manager::MapDifficultyConditionsContainer const* DB2Manager::GetMapDifficultyConditions(uint32 mapDifficultyId) const
|
||||
{
|
||||
return Trinity::Containers::MapGetValuePtr(_mapDifficultyConditions, mapDifficultyId);
|
||||
}
|
||||
|
||||
MountEntry const* DB2Manager::GetMount(uint32 spellId) const
|
||||
{
|
||||
auto itr = _mountsBySpellId.find(spellId);
|
||||
|
||||
@@ -297,6 +297,7 @@ public:
|
||||
|
||||
using ItemBonusList = std::vector<ItemBonusEntry const*>;
|
||||
using MapDifficultyContainer = std::unordered_map<uint32, std::unordered_map<uint32, MapDifficultyEntry const*>>;
|
||||
using MapDifficultyConditionsContainer = std::vector<std::pair<uint32, PlayerConditionEntry const*>>;
|
||||
using MountTypeXCapabilitySet = std::set<MountTypeXCapabilityEntry const*, MountTypeXCapabilityEntryComparator>;
|
||||
using MountXDisplayContainer = std::vector<MountXDisplayEntry const*>;
|
||||
|
||||
@@ -364,6 +365,7 @@ public:
|
||||
MapDifficultyEntry const* GetDefaultMapDifficulty(uint32 mapId, Difficulty* difficulty = nullptr) const;
|
||||
MapDifficultyEntry const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty) const;
|
||||
MapDifficultyEntry const* GetDownscaledMapDifficultyData(uint32 mapId, Difficulty &difficulty) const;
|
||||
MapDifficultyConditionsContainer const* GetMapDifficultyConditions(uint32 mapDifficultyId) const;
|
||||
MountEntry const* GetMount(uint32 spellId) const;
|
||||
MountEntry const* GetMountById(uint32 id) const;
|
||||
MountTypeXCapabilitySet const* GetMountCapabilities(uint32 mountType) const;
|
||||
|
||||
@@ -2223,6 +2223,15 @@ struct MapDifficultyEntry
|
||||
}
|
||||
};
|
||||
|
||||
struct MapDifficultyXConditionEntry
|
||||
{
|
||||
uint32 ID;
|
||||
LocalizedString FailureDescription;
|
||||
uint32 PlayerConditionID;
|
||||
int32 OrderIndex;
|
||||
uint32 MapDifficultyID;
|
||||
};
|
||||
|
||||
struct ModifierTreeEntry
|
||||
{
|
||||
uint32 ID;
|
||||
|
||||
@@ -20169,65 +20169,84 @@ void Player::SendRaidInfo()
|
||||
|
||||
bool Player::Satisfy(AccessRequirement const* ar, uint32 target_map, bool report)
|
||||
{
|
||||
if (!IsGameMaster() && ar)
|
||||
if (!IsGameMaster())
|
||||
{
|
||||
uint8 LevelMin = 0;
|
||||
uint8 LevelMax = 0;
|
||||
int32 failedMapDifficultyXCondition = 0;
|
||||
uint32 missingItem = 0;
|
||||
uint32 missingQuest = 0;
|
||||
uint32 missingAchievement = 0;
|
||||
|
||||
MapEntry const* mapEntry = sMapStore.LookupEntry(target_map);
|
||||
if (!mapEntry)
|
||||
return false;
|
||||
|
||||
if (!sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_LEVEL))
|
||||
{
|
||||
if (ar->levelMin && getLevel() < ar->levelMin)
|
||||
LevelMin = ar->levelMin;
|
||||
if (ar->levelMax && getLevel() > ar->levelMax)
|
||||
LevelMax = ar->levelMax;
|
||||
}
|
||||
|
||||
uint32 missingItem = 0;
|
||||
if (ar->item)
|
||||
{
|
||||
if (!HasItemCount(ar->item) &&
|
||||
(!ar->item2 || !HasItemCount(ar->item2)))
|
||||
missingItem = ar->item;
|
||||
}
|
||||
else if (ar->item2 && !HasItemCount(ar->item2))
|
||||
missingItem = ar->item2;
|
||||
|
||||
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, target_map, this))
|
||||
{
|
||||
GetSession()->SendNotification("%s", GetSession()->GetTrinityString(LANG_INSTANCE_CLOSED));
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 missingQuest = 0;
|
||||
if (GetTeam() == ALLIANCE && ar->quest_A && !GetQuestRewardStatus(ar->quest_A))
|
||||
missingQuest = ar->quest_A;
|
||||
else if (GetTeam() == HORDE && ar->quest_H && !GetQuestRewardStatus(ar->quest_H))
|
||||
missingQuest = ar->quest_H;
|
||||
|
||||
uint32 missingAchievement = 0;
|
||||
Player* leader = this;
|
||||
ObjectGuid leaderGuid = GetGroup() ? GetGroup()->GetLeaderGUID() : GetGUID();
|
||||
if (leaderGuid != GetGUID())
|
||||
leader = ObjectAccessor::FindPlayer(leaderGuid);
|
||||
|
||||
if (ar->achievement)
|
||||
if (!leader || !leader->HasAchieved(ar->achievement))
|
||||
missingAchievement = ar->achievement;
|
||||
|
||||
Difficulty target_difficulty = GetDifficultyID(mapEntry);
|
||||
MapDifficultyEntry const* mapDiff = sDB2Manager.GetDownscaledMapDifficultyData(target_map, target_difficulty);
|
||||
if (LevelMin || LevelMax || missingItem || missingQuest || missingAchievement)
|
||||
if (!sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_LEVEL))
|
||||
{
|
||||
if (DB2Manager::MapDifficultyConditionsContainer const* mapDifficultyConditions = sDB2Manager.GetMapDifficultyConditions(mapDiff->ID))
|
||||
{
|
||||
for (auto&& itr : *mapDifficultyConditions)
|
||||
{
|
||||
if (!ConditionMgr::IsPlayerMeetingCondition(this, itr.second))
|
||||
{
|
||||
failedMapDifficultyXCondition = itr.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ar)
|
||||
{
|
||||
if (!sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_LEVEL))
|
||||
{
|
||||
if (ar->levelMin && getLevel() < ar->levelMin)
|
||||
LevelMin = ar->levelMin;
|
||||
if (ar->levelMax && getLevel() > ar->levelMax)
|
||||
LevelMax = ar->levelMax;
|
||||
}
|
||||
|
||||
if (ar->item)
|
||||
{
|
||||
if (!HasItemCount(ar->item) &&
|
||||
(!ar->item2 || !HasItemCount(ar->item2)))
|
||||
missingItem = ar->item;
|
||||
}
|
||||
else if (ar->item2 && !HasItemCount(ar->item2))
|
||||
missingItem = ar->item2;
|
||||
|
||||
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, target_map, this))
|
||||
{
|
||||
GetSession()->SendNotification("%s", GetSession()->GetTrinityString(LANG_INSTANCE_CLOSED));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetTeam() == ALLIANCE && ar->quest_A && !GetQuestRewardStatus(ar->quest_A))
|
||||
missingQuest = ar->quest_A;
|
||||
else if (GetTeam() == HORDE && ar->quest_H && !GetQuestRewardStatus(ar->quest_H))
|
||||
missingQuest = ar->quest_H;
|
||||
|
||||
Player* leader = this;
|
||||
ObjectGuid leaderGuid = GetGroup() ? GetGroup()->GetLeaderGUID() : GetGUID();
|
||||
if (leaderGuid != GetGUID())
|
||||
leader = ObjectAccessor::FindPlayer(leaderGuid);
|
||||
|
||||
if (ar->achievement)
|
||||
if (!leader || !leader->HasAchieved(ar->achievement))
|
||||
missingAchievement = ar->achievement;
|
||||
}
|
||||
|
||||
if (LevelMin || LevelMax || failedMapDifficultyXCondition || missingItem || missingQuest || missingAchievement)
|
||||
{
|
||||
if (report)
|
||||
{
|
||||
if (missingQuest && !ar->questFailedText.empty())
|
||||
ChatHandler(GetSession()).PSendSysMessage("%s", ar->questFailedText.c_str());
|
||||
else if (mapDiff->Message[sWorld->GetDefaultDbcLocale()][0] != '\0') // if (missingAchievement) covered by this case
|
||||
SendTransferAborted(target_map, TRANSFER_ABORT_DIFFICULTY, target_difficulty);
|
||||
else if (mapDiff->Message[sWorld->GetDefaultDbcLocale()][0] != '\0' || failedMapDifficultyXCondition) // if (missingAchievement) covered by this case
|
||||
SendTransferAborted(target_map, TRANSFER_ABORT_DIFFICULTY, target_difficulty, failedMapDifficultyXCondition);
|
||||
else if (missingItem)
|
||||
GetSession()->SendNotification(GetSession()->GetTrinityString(LANG_LEVEL_MINREQUIRED_AND_ITEM), LevelMin, ASSERT_NOTNULL(sObjectMgr->GetItemTemplate(missingItem))->GetName(GetSession()->GetSessionDbcLocale()));
|
||||
else if (LevelMin)
|
||||
@@ -24396,12 +24415,13 @@ void Player::SendUpdateToOutOfRangeGroupMembers()
|
||||
pet->ResetGroupUpdateFlag();
|
||||
}
|
||||
|
||||
void Player::SendTransferAborted(uint32 mapid, TransferAbortReason reason, uint8 arg) const
|
||||
void Player::SendTransferAborted(uint32 mapid, TransferAbortReason reason, uint8 arg /*= 0*/, int32 mapDifficultyXConditionID /*= 0*/) const
|
||||
{
|
||||
WorldPackets::Movement::TransferAborted transferAborted;
|
||||
transferAborted.MapID = mapid;
|
||||
transferAborted.Arg = arg;
|
||||
transferAborted.TransfertAbort = reason;
|
||||
transferAborted.MapDifficultyXConditionID = mapDifficultyXConditionID;
|
||||
SendDirectMessage(transferAborted.Write());
|
||||
}
|
||||
|
||||
|
||||
@@ -1053,7 +1053,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
|
||||
void SendInitialPacketsBeforeAddToMap();
|
||||
void SendInitialPacketsAfterAddToMap();
|
||||
void SendSupercededSpell(uint32 oldSpell, uint32 newSpell) const;
|
||||
void SendTransferAborted(uint32 mapid, TransferAbortReason reason, uint8 arg = 0) const;
|
||||
void SendTransferAborted(uint32 mapid, TransferAbortReason reason, uint8 arg = 0, int32 mapDifficultyXConditionID = 0) const;
|
||||
void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time, bool welcome) const;
|
||||
|
||||
bool CanInteractWithQuestGiver(Object* questGiver) const;
|
||||
|
||||
Reference in New Issue
Block a user