diff options
author | Shauren <shauren.trinity@gmail.com> | 2023-12-04 19:42:12 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2023-12-04 19:42:12 +0100 |
commit | 9022f2374884b966c3ecf7199c52498140775668 (patch) | |
tree | b74d0e5c87417d0e194166fa9595f0e83f893e78 | |
parent | 1f7ee02defd7df02a045ecabef79e1c558bf3cec (diff) |
Core/Players: Learn parent skilllines if they are missing while learning child skills
Closes #29482
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 36 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 17 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.h | 8 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 4 |
4 files changed, 47 insertions, 18 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 4fc2bdd5bb8..b3258b28756 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -3152,7 +3152,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent case SKILL_RANGE_RANK: { SkillTiersEntry const* tier = sObjectMgr->GetSkillTier(rcInfo->SkillTierID); - new_skill_max_value = tier->Value[spellLearnSkill->step - 1]; + new_skill_max_value = tier->GetValueForTierIndex(spellLearnSkill->step - 1); break; } default: @@ -3427,7 +3427,7 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled /*= false*/, bool learn_ case SKILL_RANGE_RANK: { SkillTiersEntry const* tier = sObjectMgr->GetSkillTier(rcInfo->SkillTierID); - new_skill_max_value = tier->Value[prevSkill->step - 1]; + new_skill_max_value = tier->GetValueForTierIndex(prevSkill->step - 1); break; } default: @@ -5886,6 +5886,12 @@ void Player::SetSkill(uint32 id, uint16 step, uint16 newVal, uint16 maxVal) // Activate and update skill line if (newVal) { + // enable parent skill line if missing + if (skillEntry->ParentSkillLineID && skillEntry->ParentTierIndex > 0 && GetSkillStep(skillEntry->ParentSkillLineID) < skillEntry->ParentTierIndex) + if (SkillRaceClassInfoEntry const* rcEntry = sDB2Manager.GetSkillRaceClassInfo(skillEntry->ParentSkillLineID, GetRace(), GetClass())) + if (SkillTiersEntry const* tier = sObjectMgr->GetSkillTier(rcEntry->SkillTierID)) + SetSkill(skillEntry->ParentSkillLineID, skillEntry->ParentTierIndex, std::max<uint16>(GetPureSkillValue(skillEntry->ParentSkillLineID), 1), tier->GetValueForTierIndex(skillEntry->ParentTierIndex - 1)); + // if skill value is going down, update enchantments before setting the new value if (newVal < currVal) UpdateSkillEnchantments(id, currVal, newVal); @@ -6015,7 +6021,7 @@ void Player::SetSkill(uint32 id, uint16 step, uint16 newVal, uint16 maxVal) if (SkillTiersEntry const* tier = sObjectMgr->GetSkillTier(rcEntry->SkillTierID)) { uint16 skillval = GetPureSkillValue(skillEntry->ParentSkillLineID); - SetSkill(skillEntry->ParentSkillLineID, skillEntry->ParentTierIndex, std::max<uint16>(skillval, 1), tier->Value[skillEntry->ParentTierIndex - 1]); + SetSkill(skillEntry->ParentSkillLineID, skillEntry->ParentTierIndex, std::max<uint16>(skillval, 1), tier->GetValueForTierIndex(skillEntry->ParentTierIndex - 1)); } } } @@ -24354,7 +24360,7 @@ void Player::LearnDefaultSkill(SkillRaceClassInfoEntry const* rcInfo) case SKILL_RANGE_RANK: { SkillTiersEntry const* tier = sObjectMgr->GetSkillTier(rcInfo->SkillTierID); - uint16 maxValue = tier->Value[0]; + uint16 maxValue = tier->GetValueForTierIndex(0); uint16 skillValue = 1; if (rcInfo->Flags & SKILL_FLAG_ALWAYS_MAX_VALUE) skillValue = maxValue; @@ -26201,7 +26207,6 @@ void Player::_LoadSkills(PreparedQueryResult result) // SetPQuery(PLAYER_LOGIN_QUERY_LOADSKILLS, "SELECT skill, value, max, professionSlot FROM character_skills WHERE guid = '{}'", GUID_LOPART(m_guid)); Races race = Races(GetRace()); - uint32 count = 0; std::unordered_map<uint32, uint32> loadedSkillValues; std::vector<uint16> loadedProfessionsWithoutSlot; // fixup old characters if (result) @@ -26286,18 +26291,27 @@ void Player::_LoadSkills(PreparedQueryResult result) } // Learn skill rewarded spells after all skills have been loaded to prevent learning a skill from them before its loaded with proper value from DB - for (auto const& skill : loadedSkillValues) + for (auto const& [skillId, skillValue] : loadedSkillValues) { - LearnSkillRewardedSpells(skill.first, skill.second, race); - if (std::vector<SkillLineEntry const*> const* childSkillLines = sDB2Manager.GetSkillLinesForParentSkill(skill.first)) + LearnSkillRewardedSpells(skillId, skillValue, race); + + // enable parent skill line if missing + SkillLineEntry const* skillEntry = sSkillLineStore.LookupEntry(skillId); + if (skillEntry->ParentSkillLineID && skillEntry->ParentTierIndex > 0 && GetSkillStep(skillEntry->ParentSkillLineID) < skillEntry->ParentTierIndex) + if (SkillRaceClassInfoEntry const* rcEntry = sDB2Manager.GetSkillRaceClassInfo(skillEntry->ParentSkillLineID, GetRace(), GetClass())) + if (SkillTiersEntry const* tier = sObjectMgr->GetSkillTier(rcEntry->SkillTierID)) + SetSkill(skillEntry->ParentSkillLineID, skillEntry->ParentTierIndex, std::max<uint16>(GetPureSkillValue(skillEntry->ParentSkillLineID), 1), tier->GetValueForTierIndex(skillEntry->ParentTierIndex - 1)); + + if (std::vector<SkillLineEntry const*> const* childSkillLines = sDB2Manager.GetSkillLinesForParentSkill(skillId)) { for (auto childItr = childSkillLines->begin(); childItr != childSkillLines->end() && mSkillStatus.size() < PLAYER_MAX_SKILLS; ++childItr) { if (mSkillStatus.find((*childItr)->ID) == mSkillStatus.end()) { - SetSkillLineId(count, (*childItr)->ID); - SetSkillStartingRank(count, 1); - mSkillStatus.insert(SkillStatusMap::value_type((*childItr)->ID, SkillStatusData(count, SKILL_UNCHANGED))); + uint32 pos = mSkillStatus.size(); + SetSkillLineId(pos, (*childItr)->ID); + SetSkillStartingRank(pos, 1); + mSkillStatus.insert(SkillStatusMap::value_type((*childItr)->ID, SkillStatusData(pos, SKILL_UNCHANGED))); } } } diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 5dc45d50536..27456a6e6d3 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -7907,6 +7907,23 @@ int32 ObjectMgr::GetFishingBaseSkillLevel(AreaTableEntry const* areaEntry) const return 0; } +SkillTiersEntry const* ObjectMgr::GetSkillTier(uint32 skillTierId) const +{ + auto itr = _skillTiers.find(skillTierId); + return itr != _skillTiers.end() ? &itr->second : nullptr; +} + +uint32 SkillTiersEntry::GetValueForTierIndex(uint32 tierIndex) const +{ + if (tierIndex >= MAX_SKILL_STEP) + tierIndex = MAX_SKILL_STEP - 1; + + while (Value[tierIndex] == 0 && tierIndex > 0) + --tierIndex; + + return Value[tierIndex]; +} + void ObjectMgr::LoadPetNames() { uint32 oldMSTime = getMSTime(); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 5a86448d870..bf90e20bb6a 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -969,6 +969,8 @@ struct SkillTiersEntry { uint32 ID; // 0 uint32 Value[MAX_SKILL_STEP]; // 1-16 + + uint32 GetValueForTierIndex(uint32 tierIndex) const; }; SkillRangeType GetSkillRangeType(SkillRaceClassInfoEntry const* rcEntry); @@ -1409,11 +1411,7 @@ class TC_GAME_API ObjectMgr int32 GetFishingBaseSkillLevel(AreaTableEntry const* areaEntry) const; - SkillTiersEntry const* GetSkillTier(uint32 skillTierId) const - { - auto itr = _skillTiers.find(skillTierId); - return itr != _skillTiers.end() ? &itr->second : nullptr; - } + SkillTiersEntry const* GetSkillTier(uint32 skillTierId) const; void ReturnOrDeleteOldMails(bool serverUp); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index d81288454fc..1895edd06b1 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -2318,7 +2318,7 @@ void Spell::EffectLearnSkill() return; uint16 skillval = std::max<uint16>(1, playerTarget->GetPureSkillValue(skillid)); - uint16 maxSkillVal = tier->Value[damage - 1]; + uint16 maxSkillVal = tier->GetValueForTierIndex(damage - 1); if (rcEntry->Flags & SKILL_FLAG_ALWAYS_MAX_VALUE) skillval = maxSkillVal; @@ -4566,7 +4566,7 @@ void Spell::EffectSkill() return; uint16 skillval = std::max<uint16>(1, playerTarget->GetPureSkillValue(skillid)); - uint16 maxSkillVal = tier->Value[damage - 1]; + uint16 maxSkillVal = tier->GetValueForTierIndex(damage - 1); if (rcEntry->Flags & SKILL_FLAG_ALWAYS_MAX_VALUE) skillval = maxSkillVal; |