Core/Instances: Use level requirements from MapDifficultyXCondition.db2 instead of access_requirement db table

This commit is contained in:
Shauren
2021-01-02 17:55:43 +01:00
parent a68bc20b24
commit 3afed1788a
10 changed files with 170 additions and 46 deletions

View 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 */;

View File

@@ -0,0 +1 @@
UPDATE `access_requirement` SET `level_min`=0,`level_max`=0;

View File

@@ -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);

View File

@@ -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,

View File

@@ -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()

View File

@@ -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);

View File

@@ -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;

View File

@@ -2223,6 +2223,15 @@ struct MapDifficultyEntry
}
};
struct MapDifficultyXConditionEntry
{
uint32 ID;
LocalizedString FailureDescription;
uint32 PlayerConditionID;
int32 OrderIndex;
uint32 MapDifficultyID;
};
struct ModifierTreeEntry
{
uint32 ID;

View File

@@ -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());
}

View File

@@ -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;