From 1d4a30cc2d4c84b6fee63b0b2f6524f379f43997 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Sat, 3 Feb 2024 17:39:25 -0500 Subject: [PATCH] Core/Players: Learn parent skilllines if they are missing while learning child skills Port From (https://github.com/TrinityCore/TrinityCore/commit/9022f2374884b966c3ecf7199c52498140775668) --- Source/Game/Entities/Player/Player.DB.cs | 32 ++++++++++++++------ Source/Game/Entities/Player/Player.Spells.cs | 22 +++++++++++--- Source/Game/Globals/ObjectManager.cs | 11 +++++++ Source/Game/Spells/SpellEffects.cs | 4 +-- 4 files changed, 54 insertions(+), 15 deletions(-) diff --git a/Source/Game/Entities/Player/Player.DB.cs b/Source/Game/Entities/Player/Player.DB.cs index 667f30c02..945e1d22d 100644 --- a/Source/Game/Entities/Player/Player.DB.cs +++ b/Source/Game/Entities/Player/Player.DB.cs @@ -333,7 +333,6 @@ namespace Game.Entities void _LoadSkills(SQLResult result) { Race race = GetRace(); - uint count = 0; Dictionary loadedSkillValues = new(); List loadedProfessionsWithoutSlot = new(); // fixup old characters if (!result.IsEmpty()) @@ -414,22 +413,37 @@ namespace Game.Entities while (result.NextRow()); } // 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 - foreach (var skill in loadedSkillValues) + foreach (var (skillId, skillValue) in loadedSkillValues) { - LearnSkillRewardedSpells(skill.Key, skill.Value, race); - List childSkillLines = Global.DB2Mgr.GetSkillLinesForParentSkill(skill.Key); + LearnSkillRewardedSpells(skillId, skillValue, race); + + // enable parent skill line if missing + var skillEntry = CliDB.SkillLineStorage.LookupByKey(skillId); + if (skillEntry.ParentSkillLineID != 0 && skillEntry.ParentTierIndex > 0 && GetSkillStep(skillEntry.ParentSkillLineID) < skillEntry.ParentTierIndex) + { + var rcEntry = Global.DB2Mgr.GetSkillRaceClassInfo(skillEntry.ParentSkillLineID, GetRace(), GetClass()); + if (rcEntry != null) + { + var tier = Global.ObjectMgr.GetSkillTier(rcEntry.SkillTierID); + if (tier != null) + SetSkill(skillEntry.ParentSkillLineID, (uint)skillEntry.ParentTierIndex, Math.Max(GetPureSkillValue(skillEntry.ParentSkillLineID), 1u), tier.GetValueForTierIndex(skillEntry.ParentTierIndex - 1)); + } + } + + List childSkillLines = Global.DB2Mgr.GetSkillLinesForParentSkill(skillId); if (childSkillLines != null) { - foreach (var childItr in childSkillLines) + foreach (var childSkillLine in childSkillLines) { if (mSkillStatus.Count >= SkillConst.MaxPlayerSkills) break; - if (!mSkillStatus.ContainsKey(childItr.Id)) + if (!mSkillStatus.ContainsKey(childSkillLine.Id)) { - SetSkillLineId(count, (ushort)childItr.Id); - SetSkillStartingRank(count, 1); - mSkillStatus.Add(childItr.Id, new SkillStatusData(count, SkillState.Unchanged)); + uint pos = (uint)mSkillStatus.Count; + SetSkillLineId(pos, (ushort)childSkillLine.Id); + SetSkillStartingRank(pos, 1); + mSkillStatus.Add(childSkillLine.Id, new SkillStatusData(pos, SkillState.Unchanged)); } } } diff --git a/Source/Game/Entities/Player/Player.Spells.cs b/Source/Game/Entities/Player/Player.Spells.cs index 50a0ff211..0cc0e2314 100644 --- a/Source/Game/Entities/Player/Player.Spells.cs +++ b/Source/Game/Entities/Player/Player.Spells.cs @@ -1097,6 +1097,18 @@ namespace Game.Entities // Activate and update skill line if (newVal != 0) { + // enable parent skill line if missing + if (skillEntry.ParentSkillLineID != 0 && skillEntry.ParentTierIndex > 0 && GetSkillStep(skillEntry.ParentSkillLineID) < skillEntry.ParentTierIndex) + { + var rcEntry = Global.DB2Mgr.GetSkillRaceClassInfo(skillEntry.ParentSkillLineID, GetRace(), GetClass()); + if (rcEntry != null) + { + var tier = Global.ObjectMgr.GetSkillTier(rcEntry.SkillTierID); + if (tier != null) + SetSkill(skillEntry.ParentSkillLineID, (uint)skillEntry.ParentTierIndex, Math.Max(GetPureSkillValue(skillEntry.ParentSkillLineID), 1u), tier.GetValueForTierIndex(skillEntry.ParentTierIndex - 1)); + } + } + // if skill value is going down, update enchantments before setting the new value if (newVal < currVal) UpdateSkillEnchantments(id, currVal, (ushort)newVal); @@ -1231,7 +1243,7 @@ namespace Game.Entities if (tier != null) { ushort skillval = GetPureSkillValue((SkillType)skillEntry.ParentSkillLineID); - SetSkill(skillEntry.ParentSkillLineID, (uint)skillEntry.ParentTierIndex, Math.Max(skillval, (ushort)1), tier.Value[skillEntry.ParentTierIndex - 1]); + SetSkill(skillEntry.ParentSkillLineID, (uint)skillEntry.ParentTierIndex, Math.Max(skillval, (ushort)1), tier.GetValueForTierIndex(skillEntry.ParentTierIndex - 1)); } } } @@ -2094,7 +2106,7 @@ namespace Game.Entities case SkillRangeType.Rank: { SkillTiersEntry tier = Global.ObjectMgr.GetSkillTier(rcInfo.SkillTierID); - ushort maxValue = (ushort)tier.Value[0]; + ushort maxValue = (ushort)tier.GetValueForTierIndex(0); ushort skillValue = 1; if (rcInfo.Flags.HasAnyFlag(SkillRaceClassInfoFlags.AlwaysMaxValue)) skillValue = maxValue; @@ -2291,7 +2303,7 @@ namespace Game.Entities case SkillRangeType.Rank: { var tier = Global.ObjectMgr.GetSkillTier(rcInfo.SkillTierID); - new_skill_max_value = (ushort)tier.Value[prevSkill.step - 1]; + new_skill_max_value = (ushort)tier.GetValueForTierIndex(prevSkill.step - 1); break; } default: @@ -2799,7 +2811,7 @@ namespace Game.Entities case SkillRangeType.Rank: { var tier = Global.ObjectMgr.GetSkillTier(rcInfo.SkillTierID); - new_skill_max_value = (ushort)tier.Value[spellLearnSkill.step - 1]; + new_skill_max_value = (ushort)tier.GetValueForTierIndex(spellLearnSkill.step - 1); break; } default: @@ -2876,6 +2888,7 @@ namespace Game.Entities // return true (for send learn packet) only if spell active (in case ranked spells) and not replace old spell return active && !disabled && !superceded_old; } + public override bool HasSpell(uint spellId) { var spell = m_spells.LookupByKey(spellId); @@ -2884,6 +2897,7 @@ namespace Game.Entities return false; } + public bool HasActiveSpell(uint spellId) { var spell = m_spells.LookupByKey(spellId); diff --git a/Source/Game/Globals/ObjectManager.cs b/Source/Game/Globals/ObjectManager.cs index 1c2cd7476..096325203 100644 --- a/Source/Game/Globals/ObjectManager.cs +++ b/Source/Game/Globals/ObjectManager.cs @@ -11686,6 +11686,17 @@ namespace Game { public uint Id; public uint[] Value = new uint[SkillConst.MaxSkillStep]; + + public uint GetValueForTierIndex(int tierIndex) + { + if (tierIndex >= SkillConst.MaxSkillStep) + tierIndex = (int)SkillConst.MaxSkillStep - 1; + + while (Value[tierIndex] == 0 && tierIndex > 0) + --tierIndex; + + return Value[tierIndex]; + } } public class TerrainSwapInfo diff --git a/Source/Game/Spells/SpellEffects.cs b/Source/Game/Spells/SpellEffects.cs index 3584e646c..7159fb07b 100644 --- a/Source/Game/Spells/SpellEffects.cs +++ b/Source/Game/Spells/SpellEffects.cs @@ -1962,7 +1962,7 @@ namespace Game.Spells return; ushort skillval = Math.Max((ushort)1, playerTarget.GetPureSkillValue(skillid)); - ushort maxSkillVal = (ushort)tier.Value[damage - 1]; + ushort maxSkillVal = (ushort)tier.GetValueForTierIndex(damage - 1); if (rcEntry.Flags.HasAnyFlag(SkillRaceClassInfoFlags.AlwaysMaxValue)) skillval = maxSkillVal; @@ -4297,7 +4297,7 @@ namespace Game.Spells return; ushort skillval = Math.Max((ushort)1, playerTarget.GetPureSkillValue(skillid)); - ushort maxSkillVal = (ushort)tier.Value[damage - 1]; + ushort maxSkillVal = (ushort)tier.GetValueForTierIndex(damage - 1); if (rcEntry.Flags.HasAnyFlag(SkillRaceClassInfoFlags.AlwaysMaxValue)) skillval = maxSkillVal;