Core/Players: Fixed traits not updating aura values when changing rank
Port From (https://github.com/TrinityCore/TrinityCore/commit/e6b553b913152667bcd1cfb79790ec70790d0f6e)
This commit is contained in:
@@ -2141,7 +2141,7 @@ namespace Game.Entities
|
|||||||
SendPacket(new SendUnlearnSpells());
|
SendPacket(new SendUnlearnSpells());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LearnSpell(uint spellId, bool dependent, uint fromSkill = 0, bool suppressMessaging = false, int? traitDefinitionId = null)
|
public void LearnSpell(uint spellId, bool dependent, uint fromSkill = 0, bool suppressMessaging = false, PlayerSpellTrait trait = null)
|
||||||
{
|
{
|
||||||
PlayerSpell spell = m_spells.LookupByKey(spellId);
|
PlayerSpell spell = m_spells.LookupByKey(spellId);
|
||||||
|
|
||||||
@@ -2149,7 +2149,7 @@ namespace Game.Entities
|
|||||||
bool active = !disabled || spell.Active;
|
bool active = !disabled || spell.Active;
|
||||||
bool favorite = spell != null ? spell.Favorite : false;
|
bool favorite = spell != null ? spell.Favorite : false;
|
||||||
|
|
||||||
bool learning = AddSpell(spellId, active, true, dependent, false, false, fromSkill, favorite, traitDefinitionId);
|
bool learning = AddSpell(spellId, active, true, dependent, false, false, fromSkill, favorite, trait);
|
||||||
|
|
||||||
// prevent duplicated entires in spell book, also not send if not in world (loading)
|
// prevent duplicated entires in spell book, also not send if not in world (loading)
|
||||||
if (learning && IsInWorld)
|
if (learning && IsInWorld)
|
||||||
@@ -2158,7 +2158,8 @@ namespace Game.Entities
|
|||||||
LearnedSpellInfo learnedSpellInfo = new();
|
LearnedSpellInfo learnedSpellInfo = new();
|
||||||
learnedSpellInfo.SpellID = spellId;
|
learnedSpellInfo.SpellID = spellId;
|
||||||
learnedSpellInfo.Favorite = favorite;
|
learnedSpellInfo.Favorite = favorite;
|
||||||
learnedSpellInfo.TraitDefinitionID = traitDefinitionId;
|
if (trait != null)
|
||||||
|
learnedSpellInfo.TraitDefinitionID = trait.DefinitionId;
|
||||||
learnedSpells.SuppressMessaging = suppressMessaging;
|
learnedSpells.SuppressMessaging = suppressMessaging;
|
||||||
learnedSpells.ClientLearnedSpellData.Add(learnedSpellInfo);
|
learnedSpells.ClientLearnedSpellData.Add(learnedSpellInfo);
|
||||||
SendPacket(learnedSpells);
|
SendPacket(learnedSpells);
|
||||||
@@ -2216,7 +2217,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
bool cur_active = pSpell.Active;
|
bool cur_active = pSpell.Active;
|
||||||
bool cur_dependent = pSpell.Dependent;
|
bool cur_dependent = pSpell.Dependent;
|
||||||
int? traitDefinitionId = pSpell.TraitDefinitionId;
|
PlayerSpellTrait trait = pSpell.Trait;
|
||||||
|
|
||||||
if (disabled)
|
if (disabled)
|
||||||
{
|
{
|
||||||
@@ -2380,9 +2381,9 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (traitDefinitionId.HasValue)
|
if (trait != null)
|
||||||
{
|
{
|
||||||
var traitDefinition = CliDB.TraitDefinitionStorage.LookupByKey(traitDefinitionId.Value);
|
var traitDefinition = CliDB.TraitDefinitionStorage.LookupByKey(trait.DefinitionId);
|
||||||
if (traitDefinition != null)
|
if (traitDefinition != null)
|
||||||
RemoveOverrideSpell(traitDefinition.OverridesSpellID, spellId);
|
RemoveOverrideSpell(traitDefinition.OverridesSpellID, spellId);
|
||||||
}
|
}
|
||||||
@@ -2480,7 +2481,7 @@ namespace Game.Entities
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AddSpell(uint spellId, bool active, bool learning, bool dependent, bool disabled, bool loading = false, uint fromSkill = 0, bool favorite = false, int? traitDefinitionId = null)
|
bool AddSpell(uint spellId, bool active, bool learning, bool dependent, bool disabled, bool loading = false, uint fromSkill = 0, bool favorite = false, PlayerSpellTrait? trait = null)
|
||||||
{
|
{
|
||||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spellId, Difficulty.None);
|
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spellId, Difficulty.None);
|
||||||
if (spellInfo == null)
|
if (spellInfo == null)
|
||||||
@@ -2559,16 +2560,16 @@ namespace Game.Entities
|
|||||||
dependent_set = true;
|
dependent_set = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spell.TraitDefinitionId != traitDefinitionId)
|
if (spell.Trait != trait)
|
||||||
{
|
{
|
||||||
if (spell.TraitDefinitionId.HasValue)
|
if (spell.Trait != null)
|
||||||
{
|
{
|
||||||
TraitDefinitionRecord traitDefinition = CliDB.TraitDefinitionStorage.LookupByKey(spell.TraitDefinitionId.Value);
|
TraitDefinitionRecord traitDefinition = CliDB.TraitDefinitionStorage.LookupByKey(spell.Trait.DefinitionId);
|
||||||
if (traitDefinition != null)
|
if (traitDefinition != null)
|
||||||
RemoveOverrideSpell((uint)traitDefinition.OverridesSpellID, spellId);
|
RemoveOverrideSpell(traitDefinition.OverridesSpellID, spellId);
|
||||||
}
|
}
|
||||||
|
|
||||||
spell.TraitDefinitionId = traitDefinitionId;
|
spell.Trait = trait;
|
||||||
}
|
}
|
||||||
|
|
||||||
spell.Favorite = favorite;
|
spell.Favorite = favorite;
|
||||||
@@ -2655,8 +2656,7 @@ namespace Game.Entities
|
|||||||
newspell.Dependent = dependent;
|
newspell.Dependent = dependent;
|
||||||
newspell.Disabled = disabled;
|
newspell.Disabled = disabled;
|
||||||
newspell.Favorite = favorite;
|
newspell.Favorite = favorite;
|
||||||
if (traitDefinitionId.HasValue)
|
newspell.Trait = trait;
|
||||||
newspell.TraitDefinitionId = traitDefinitionId.Value;
|
|
||||||
|
|
||||||
// replace spells in action bars and spellbook to bigger rank if only one spell rank must be accessible
|
// replace spells in action bars and spellbook to bigger rank if only one spell rank must be accessible
|
||||||
if (newspell.Active && !newspell.Disabled && spellInfo.IsRanked())
|
if (newspell.Active && !newspell.Disabled && spellInfo.IsRanked())
|
||||||
@@ -2725,51 +2725,14 @@ namespace Game.Entities
|
|||||||
|
|
||||||
if (castSpell)
|
if (castSpell)
|
||||||
{
|
{
|
||||||
CastSpellExtraArgs args = new(TriggerCastFlags.FullMask);
|
CastSpell(this, spellId, true);
|
||||||
|
|
||||||
if (traitDefinitionId.HasValue)
|
|
||||||
{
|
|
||||||
TraitConfig traitConfig = GetTraitConfig((int)(uint)m_activePlayerData.ActiveCombatTraitConfigID);
|
|
||||||
if (traitConfig != null)
|
|
||||||
{
|
|
||||||
int traitEntryIndex = traitConfig.Entries.FindIndexIf(traitEntry =>
|
|
||||||
{
|
|
||||||
return CliDB.TraitNodeEntryStorage.LookupByKey(traitEntry.TraitNodeEntryID)?.TraitDefinitionID == traitDefinitionId;
|
|
||||||
});
|
|
||||||
|
|
||||||
int rank = 0;
|
|
||||||
if (traitEntryIndex >= 0)
|
|
||||||
rank = traitConfig.Entries[traitEntryIndex].Rank + traitConfig.Entries[traitEntryIndex].GrantedRanks;
|
|
||||||
|
|
||||||
if (rank > 0)
|
|
||||||
{
|
|
||||||
var traitDefinitionEffectPoints = TraitMgr.GetTraitDefinitionEffectPointModifiers(traitDefinitionId.Value);
|
|
||||||
if (traitDefinitionEffectPoints != null)
|
|
||||||
{
|
|
||||||
foreach (TraitDefinitionEffectPointsRecord traitDefinitionEffectPoint in traitDefinitionEffectPoints)
|
|
||||||
{
|
|
||||||
if (traitDefinitionEffectPoint.EffectIndex >= spellInfo.GetEffects().Count)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
float basePoints = Global.DB2Mgr.GetCurveValueAt((uint)traitDefinitionEffectPoint.CurveID, rank);
|
|
||||||
if (traitDefinitionEffectPoint.GetOperationType() == TraitPointsOperationType.Multiply)
|
|
||||||
basePoints *= spellInfo.GetEffect((uint)traitDefinitionEffectPoint.EffectIndex).CalcBaseValue(this, null, 0, -1);
|
|
||||||
|
|
||||||
args.AddSpellMod(SpellValueMod.BasePoint0 + traitDefinitionEffectPoint.EffectIndex, (int)basePoints);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CastSpell(this, spellId, args);
|
|
||||||
if (spellInfo.HasEffect(SpellEffectName.SkillStep))
|
if (spellInfo.HasEffect(SpellEffectName.SkillStep))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (traitDefinitionId.HasValue)
|
if (trait != null)
|
||||||
{
|
{
|
||||||
TraitDefinitionRecord traitDefinition = CliDB.TraitDefinitionStorage.LookupByKey(traitDefinitionId.Value);
|
TraitDefinitionRecord traitDefinition = CliDB.TraitDefinitionStorage.LookupByKey(trait.DefinitionId);
|
||||||
if (traitDefinition != null && traitDefinition.OverridesSpellID != 0)
|
if (traitDefinition != null && traitDefinition.OverridesSpellID != 0)
|
||||||
AddOverrideSpell(traitDefinition.OverridesSpellID, spellId);
|
AddOverrideSpell(traitDefinition.OverridesSpellID, spellId);
|
||||||
}
|
}
|
||||||
@@ -4043,6 +4006,6 @@ namespace Game.Entities
|
|||||||
public bool Dependent;
|
public bool Dependent;
|
||||||
public bool Disabled;
|
public bool Disabled;
|
||||||
public bool Favorite;
|
public bool Favorite;
|
||||||
public int? TraitDefinitionId;
|
public PlayerSpellTrait Trait;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1014,9 +1014,8 @@ namespace Game.Entities
|
|||||||
List<TraitEntryPacket> costEntries = new();
|
List<TraitEntryPacket> costEntries = new();
|
||||||
|
|
||||||
// apply new traits
|
// apply new traits
|
||||||
for (var i = 0; i < newConfig.Entries.Count; ++i)
|
foreach (TraitEntryPacket newEntry in newConfig.Entries)
|
||||||
{
|
{
|
||||||
TraitEntryPacket newEntry = newConfig.Entries[i];
|
|
||||||
int oldEntryIndex = editedConfig.Entries.FindIndexIf(ufEntry => ufEntry.TraitNodeID == newEntry.TraitNodeID && ufEntry.TraitNodeEntryID == newEntry.TraitNodeEntryID);
|
int oldEntryIndex = editedConfig.Entries.FindIndexIf(ufEntry => ufEntry.TraitNodeID == newEntry.TraitNodeID && ufEntry.TraitNodeEntryID == newEntry.TraitNodeEntryID);
|
||||||
if (oldEntryIndex < 0)
|
if (oldEntryIndex < 0)
|
||||||
{
|
{
|
||||||
@@ -1033,8 +1032,11 @@ namespace Game.Entities
|
|||||||
AddDynamicUpdateFieldValue(newTraitConfig.ModifyValue(newTraitConfig.Entries), newUfEntry);
|
AddDynamicUpdateFieldValue(newTraitConfig.ModifyValue(newTraitConfig.Entries), newUfEntry);
|
||||||
|
|
||||||
if (applyTraits)
|
if (applyTraits)
|
||||||
|
{
|
||||||
|
ApplyTraitEntry(newEntry.TraitNodeEntryID, 0, 0, false);
|
||||||
ApplyTraitEntry(newUfEntry.TraitNodeEntryID, newUfEntry.Rank, 0, true);
|
ApplyTraitEntry(newUfEntry.TraitNodeEntryID, newUfEntry.Rank, 0, true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (newEntry.Rank != editedConfig.Entries[oldEntryIndex].Rank || newEntry.GrantedRanks != editedConfig.Entries[oldEntryIndex].GrantedRanks)
|
else if (newEntry.Rank != editedConfig.Entries[oldEntryIndex].Rank || newEntry.GrantedRanks != editedConfig.Entries[oldEntryIndex].GrantedRanks)
|
||||||
{
|
{
|
||||||
if (consumeCurrencies && newEntry.Rank > editedConfig.Entries[oldEntryIndex].Rank)
|
if (consumeCurrencies && newEntry.Rank > editedConfig.Entries[oldEntryIndex].Rank)
|
||||||
@@ -1080,9 +1082,8 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < newConfig.SubTrees.Count; ++i)
|
foreach (TraitSubTreeCachePacket newSubTree in newConfig.SubTrees)
|
||||||
{
|
{
|
||||||
var newSubTree = newConfig.SubTrees[i];
|
|
||||||
int oldSubTreeIndex = editedConfig.SubTrees.FindIndexIf(ufSubTree => ufSubTree.TraitSubTreeID == newSubTree.TraitSubTreeID);
|
int oldSubTreeIndex = editedConfig.SubTrees.FindIndexIf(ufSubTree => ufSubTree.TraitSubTreeID == newSubTree.TraitSubTreeID);
|
||||||
|
|
||||||
List<TraitEntry> subTreeEntries = new();
|
List<TraitEntry> subTreeEntries = new();
|
||||||
@@ -1094,6 +1095,7 @@ namespace Game.Entities
|
|||||||
newUfEntry.Rank = newSubTree.Entries[j].Rank;
|
newUfEntry.Rank = newSubTree.Entries[j].Rank;
|
||||||
newUfEntry.GrantedRanks = newSubTree.Entries[j].GrantedRanks;
|
newUfEntry.GrantedRanks = newSubTree.Entries[j].GrantedRanks;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldSubTreeIndex < 0)
|
if (oldSubTreeIndex < 0)
|
||||||
{
|
{
|
||||||
TraitSubTreeCache newUfSubTree = new();
|
TraitSubTreeCache newUfSubTree = new();
|
||||||
@@ -1182,13 +1184,24 @@ namespace Game.Entities
|
|||||||
|
|
||||||
if (traitDefinition.SpellID != 0)
|
if (traitDefinition.SpellID != 0)
|
||||||
{
|
{
|
||||||
|
Cypher.Assert(traitNodeEntry.TraitDefinitionID <= 0xFFFFFF && rank + grantedRanks <= 0xFF);
|
||||||
|
|
||||||
if (apply)
|
if (apply)
|
||||||
LearnSpell(traitDefinition.SpellID, true, 0, false, traitNodeEntry.TraitDefinitionID);
|
LearnSpell(traitDefinition.SpellID, true, 0, false, new PlayerSpellTrait(traitNodeEntry.TraitDefinitionID, rank + grantedRanks));
|
||||||
else
|
else
|
||||||
RemoveSpell(traitDefinition.SpellID);
|
RemoveSpell(traitDefinition.SpellID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PlayerSpellTrait GetTraitInfoForSpell(uint spellId)
|
||||||
|
{
|
||||||
|
PlayerSpell spell = m_spells.LookupByKey(spellId);
|
||||||
|
if (spell != null)
|
||||||
|
return spell.Trait;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public void SetTraitConfigUseStarterBuild(int traitConfigId, bool useStarterBuild)
|
public void SetTraitConfigUseStarterBuild(int traitConfigId, bool useStarterBuild)
|
||||||
{
|
{
|
||||||
int configIndex = m_activePlayerData.TraitConfigs.FindIndexIf(traitConfig =>
|
int configIndex = m_activePlayerData.TraitConfigs.FindIndexIf(traitConfig =>
|
||||||
|
|||||||
@@ -8068,4 +8068,28 @@ namespace Game.Entities
|
|||||||
public uint? InstanceId;
|
public uint? InstanceId;
|
||||||
public uint? LfgDungeonsId;
|
public uint? LfgDungeonsId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class PlayerSpellTrait
|
||||||
|
{
|
||||||
|
public int DefinitionId;
|
||||||
|
public int Rank;
|
||||||
|
|
||||||
|
public PlayerSpellTrait(int definitionId, int rank)
|
||||||
|
{
|
||||||
|
DefinitionId = definitionId;
|
||||||
|
Rank = rank;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return obj is PlayerSpellTrait trait &&
|
||||||
|
DefinitionId == trait.DefinitionId &&
|
||||||
|
Rank == trait.Rank;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(DefinitionId, Rank);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -4107,7 +4107,38 @@ namespace Game.Spells
|
|||||||
|
|
||||||
Unit casterUnit = null;
|
Unit casterUnit = null;
|
||||||
if (caster != null)
|
if (caster != null)
|
||||||
|
{
|
||||||
casterUnit = caster.ToUnit();
|
casterUnit = caster.ToUnit();
|
||||||
|
Player playerCaster = caster.ToPlayer();
|
||||||
|
if (playerCaster != null)
|
||||||
|
{
|
||||||
|
PlayerSpellTrait trait = playerCaster.GetTraitInfoForSpell(_spellInfo.Id);
|
||||||
|
if (trait != null)
|
||||||
|
{
|
||||||
|
var traitDefinitionEffectPoints = TraitMgr.GetTraitDefinitionEffectPointModifiers(trait.DefinitionId);
|
||||||
|
if (traitDefinitionEffectPoints != null)
|
||||||
|
{
|
||||||
|
var pointsOverride = traitDefinitionEffectPoints.Find(p => p.EffectIndex == EffectIndex);
|
||||||
|
if (pointsOverride != null)
|
||||||
|
{
|
||||||
|
float traitBasePoints = Global.DB2Mgr.GetCurveValueAt((uint)pointsOverride.CurveID, trait.Rank);
|
||||||
|
switch (pointsOverride.GetOperationType())
|
||||||
|
{
|
||||||
|
case TraitPointsOperationType.Set:
|
||||||
|
value = traitBasePoints;
|
||||||
|
break;
|
||||||
|
case TraitPointsOperationType.Multiply:
|
||||||
|
value *= traitBasePoints;
|
||||||
|
break;
|
||||||
|
case TraitPointsOperationType.None:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Scaling.Variance != 0)
|
if (Scaling.Variance != 0)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user