diff --git a/client_files/export/main.cpp b/client_files/export/main.cpp index 79807e1ef..34e137726 100644 --- a/client_files/export/main.cpp +++ b/client_files/export/main.cpp @@ -32,6 +32,7 @@ #include "../../common/repositories/skill_caps_repository.h" #include "../../common/file.h" #include "../../common/events/player_event_logs.h" +#include "../../common/skill_caps.h" EQEmuLogSys LogSys; WorldContentService content_service; @@ -213,17 +214,16 @@ void ExportSkillCaps(SharedDatabase* db) return; } - const uint8 skill_cap_max_level = ( - RuleI(Character, SkillCapMaxLevel) > 0 ? - RuleI(Character, SkillCapMaxLevel) : - RuleI(Character, MaxLevel) - ); - for (uint8 class_id = Class::Warrior; class_id <= Class::Berserker; class_id++) { for (uint8 skill_id = EQ::skills::Skill1HBlunt; skill_id <= EQ::skills::Skill2HPiercing; skill_id++) { if (SkillUsable(db, skill_id, class_id)) { uint32 previous_cap = 0; - for (uint8 level = 1; level <= skill_cap_max_level; level++) { + + for ( + uint8 level = 1; + level <= SkillCaps::GetSkillCapMaxLevel(class_id, static_cast(skill_id)); + level++ + ) { uint32 cap = GetSkill(db, skill_id, class_id, level); if (cap < previous_cap) { cap = previous_cap; diff --git a/common/skill_caps.cpp b/common/skill_caps.cpp index c76eab372..c8b75c4f5 100644 --- a/common/skill_caps.cpp +++ b/common/skill_caps.cpp @@ -1,6 +1,15 @@ #include "skill_caps.h" #include "timer.h" +// cache the skill cap max level in the database +std::map skill_max_level = {}; + +uint8 skill_cap_max_level = ( + RuleI(Character, SkillCapMaxLevel) > 0 ? + RuleI(Character, SkillCapMaxLevel) : + RuleI(Character, MaxLevel) +); + SkillCaps *SkillCaps::SetContentDatabase(Database *db) { m_content_database = db; @@ -8,15 +17,30 @@ SkillCaps *SkillCaps::SetContentDatabase(Database *db) return this; } +int32_t SkillCaps::GetSkillCapMaxLevel(uint8 class_id, EQ::skills::SkillType skill_id) +{ + // pull the max value defined in the database if it exists + auto it = skill_max_level.find((class_id * 1000000) + skill_id); + if (it != skill_max_level.end()) { + return it->second; + } + + return skill_cap_max_level; +} + SkillCapsRepository::SkillCaps SkillCaps::GetSkillCap(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level) { - if (!IsPlayerClass(class_id)) { + if (!IsPlayerClass(class_id) || static_cast(skill_id) > EQ::skills::HIGHEST_SKILL + 1) { return SkillCapsRepository::NewEntity(); } - const uint64_t key = (class_id * 1000000) + (level * 1000) + static_cast(skill_id); + const uint8 max_level = GetSkillCapMaxLevel(class_id, skill_id); + if (level > max_level) { + level = max_level; + } - auto pos = m_skill_caps.find(key); + const uint64_t key = (class_id * 1000000) + (level * 1000) + static_cast(skill_id); + auto pos = m_skill_caps.find(key); if (pos != m_skill_caps.end()) { return pos->second; } @@ -30,19 +54,12 @@ uint8 SkillCaps::GetSkillTrainLevel(uint8 class_id, EQ::skills::SkillType skill_ !IsPlayerClass(class_id) || class_id > Class::PLAYER_CLASS_COUNT || static_cast(skill_id) > (EQ::skills::HIGHEST_SKILL + 1) - ) { + ) { return 0; } - const uint8 skill_cap_max_level = ( - RuleI(Character, SkillCapMaxLevel) > 0 ? - RuleI(Character, SkillCapMaxLevel) : - RuleI(Character, MaxLevel) - ); - const uint8 max_level = level > skill_cap_max_level ? level : skill_cap_max_level; const uint64_t key = (class_id * 1000000) + (level * 1000) + static_cast(skill_id); - for (uint8 current_level = 1; current_level <= max_level; current_level++) { auto pos = m_skill_caps.find(key); if (pos != m_skill_caps.end()) { @@ -55,21 +72,38 @@ uint8 SkillCaps::GetSkillTrainLevel(uint8 class_id, EQ::skills::SkillType skill_ void SkillCaps::LoadSkillCaps() { - const auto& l = SkillCapsRepository::All(*m_content_database); + const auto &l = SkillCapsRepository::All(*m_content_database); m_skill_caps.clear(); - for (const auto& e: l) { + for (const auto &e: l) { if ( e.level < 1 || !IsPlayerClass(e.class_id) || static_cast(e.skill_id) >= EQ::skills::SkillCount - ) { + ) { continue; } const uint64_t key = (e.class_id * 1000000) + (e.level * 1000) + e.skill_id; m_skill_caps[key] = e; + + const int max_level_key = (e.class_id * 1000000) + e.skill_id; + auto it = skill_max_level.find(max_level_key); + if (it != skill_max_level.end()) { + // Key found, update the value if the new level is higher + if (e.level > it->second) { + it->second = e.level; + } + // we never want to exceed the defined rule skill cap max level + if (it->second > skill_cap_max_level) { + it->second = skill_cap_max_level; + } + } + else { + // Key not found, insert the new key-value pair + skill_max_level[max_level_key] = e.level; + } } LogInfo( diff --git a/common/skill_caps.h b/common/skill_caps.h index 24b278c23..9630ed7d7 100644 --- a/common/skill_caps.h +++ b/common/skill_caps.h @@ -13,6 +13,7 @@ public: uint8 GetSkillTrainLevel(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level); void LoadSkillCaps(); void ReloadSkillCaps(); + static int32_t GetSkillCapMaxLevel(uint8 class_id, EQ::skills::SkillType skill_id); SkillCaps *SetContentDatabase(Database *db); private: