aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2025-06-14 14:55:06 +0200
committerShauren <shauren.trinity@gmail.com>2025-06-14 14:55:06 +0200
commite6b553b913152667bcd1cfb79790ec70790d0f6e (patch)
tree740b16f0d018204e500cbd7fb48c7adccd6f34f2
parentf94d87b00fe384df055d197fe957db083e4fd3c6 (diff)
Core/Players: Fixed traits not updating aura values when changing rank
-rw-r--r--src/server/game/Entities/Player/Player.cpp98
-rw-r--r--src/server/game/Entities/Player/Player.h15
-rw-r--r--src/server/game/Handlers/TraitHandler.cpp10
-rw-r--r--src/server/game/Spells/SpellInfo.cpp29
4 files changed, 81 insertions, 71 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index b4174fe0a91..f48bb73995e 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -2754,7 +2754,7 @@ WorldLocation const* Player::GetStoredAuraTeleportLocation(uint32 spellId) const
return nullptr;
}
-bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent, bool disabled, bool loading /*= false*/, int32 fromSkill /*= 0*/, bool favorite /*= false*/, Optional<int32> traitDefinitionId /*= {}*/)
+bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent, bool disabled, bool loading /*= false*/, int32 fromSkill /*= 0*/, bool favorite /*= false*/, Optional<PlayerSpellTrait> trait /*= {}*/)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
if (!spellInfo)
@@ -2834,13 +2834,13 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent
dependent_set = true;
}
- if (itr->second.TraitDefinitionId != traitDefinitionId)
+ if (itr->second.Trait != trait)
{
- if (itr->second.TraitDefinitionId)
- if (TraitDefinitionEntry const* traitDefinition = sTraitDefinitionStore.LookupEntry(*itr->second.TraitDefinitionId))
+ if (itr->second.Trait)
+ if (TraitDefinitionEntry const* traitDefinition = sTraitDefinitionStore.LookupEntry(itr->second.Trait->DefinitionId))
RemoveOverrideSpell(traitDefinition->OverridesSpellID, spellId);
- itr->second.TraitDefinitionId = traitDefinitionId;
+ itr->second.Trait = trait;
}
itr->second.favorite = favorite;
@@ -2918,7 +2918,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent
LearnSpell(prev_spell, true, fromSkill);
}
- std::pair<PlayerSpellMap::iterator, bool> inserted = m_spells.emplace(std::piecewise_construct, std::forward_as_tuple(spellId), std::forward_as_tuple());
+ std::pair<PlayerSpellMap::iterator, bool> inserted = m_spells.try_emplace(spellId);
PlayerSpell& newspell = inserted.first->second;
// learning a previous rank might have given us this spell already from a skill autolearn, most likely with PLAYERSPELL_NEW state
// we dont want to do double insert if this happened during load from db so we force state to CHANGED, just in case
@@ -2927,8 +2927,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent
newspell.dependent = dependent;
newspell.disabled = disabled;
newspell.favorite = favorite;
- if (traitDefinitionId)
- newspell.TraitDefinitionId = *traitDefinitionId;
+ newspell.Trait = trait;
// 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())
@@ -2994,48 +2993,13 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent
if (castSpell)
{
- CastSpellExtraArgs args;
- args.SetTriggerFlags(TRIGGERED_FULL_MASK);
-
- if (traitDefinitionId)
- {
- if (UF::TraitConfig const* traitConfig = GetTraitConfig(m_activePlayerData->ActiveCombatTraitConfigID))
- {
- int32 traitEntryIndex = traitConfig->Entries.FindIndexIf([traitDefinitionId](UF::TraitEntry const& traitEntry)
- {
- return sTraitNodeEntryStore.AssertEntry(traitEntry.TraitNodeEntryID)->TraitDefinitionID == traitDefinitionId;
- });
- int32 rank = 0;
- if (traitEntryIndex >= 0)
- rank = traitConfig->Entries[traitEntryIndex].Rank + traitConfig->Entries[traitEntryIndex].GrantedRanks;
-
- if (rank > 0)
- {
- if (std::vector<TraitDefinitionEffectPointsEntry const*> const* traitDefinitionEffectPoints = TraitMgr::GetTraitDefinitionEffectPointModifiers(*traitDefinitionId))
- {
- for (TraitDefinitionEffectPointsEntry const* traitDefinitionEffectPoint : *traitDefinitionEffectPoints)
- {
- if (traitDefinitionEffectPoint->EffectIndex >= int32(spellInfo->GetEffects().size()))
- continue;
-
- float basePoints = sDB2Manager.GetCurveValueAt(traitDefinitionEffectPoint->CurveID, rank);
- if (traitDefinitionEffectPoint->GetOperationType() == TraitPointsOperationType::Multiply)
- basePoints *= spellInfo->GetEffect(SpellEffIndex(traitDefinitionEffectPoint->EffectIndex)).CalcBaseValue(this, nullptr, 0, -1);
-
- args.AddSpellMod(SpellValueMod(SPELLVALUE_BASE_POINT0 + traitDefinitionEffectPoint->EffectIndex), basePoints);
- }
- }
- }
- }
- }
-
- CastSpell(this, spellId, args);
+ CastSpell(this, spellId, true);
if (spellInfo->HasEffect(SPELL_EFFECT_SKILL_STEP))
return false;
}
- if (traitDefinitionId)
- if (TraitDefinitionEntry const* traitDefinition = sTraitDefinitionStore.LookupEntry(*traitDefinitionId))
+ if (trait)
+ if (TraitDefinitionEntry const* traitDefinition = sTraitDefinitionStore.LookupEntry(trait->DefinitionId))
if (traitDefinition->OverridesSpellID)
AddOverrideSpell(traitDefinition->OverridesSpellID, spellId);
@@ -3206,7 +3170,7 @@ bool Player::HandlePassiveSpellLearn(SpellInfo const* spellInfo)
return need_cast && (!spellInfo->CasterAuraState || HasAuraState(AuraStateType(spellInfo->CasterAuraState)));
}
-void Player::LearnSpell(uint32 spell_id, bool dependent, int32 fromSkill /*= 0*/, bool suppressMessaging /*= false*/, Optional<int32> traitDefinitionId /*= {}*/)
+void Player::LearnSpell(uint32 spell_id, bool dependent, int32 fromSkill /*= 0*/, bool suppressMessaging /*= false*/, Optional<PlayerSpellTrait> trait /*= {}*/)
{
PlayerSpellMap::iterator itr = m_spells.find(spell_id);
@@ -3214,7 +3178,7 @@ void Player::LearnSpell(uint32 spell_id, bool dependent, int32 fromSkill /*= 0*/
bool active = disabled ? itr->second.active : true;
bool favorite = itr != m_spells.end() ? itr->second.favorite : false;
- bool learning = AddSpell(spell_id, active, true, dependent, false, false, fromSkill, favorite, traitDefinitionId);
+ bool learning = AddSpell(spell_id, active, true, dependent, false, false, fromSkill, favorite, trait);
// prevent duplicated entires in spell book, also not send if not in world (loading)
if (learning && IsInWorld())
@@ -3223,7 +3187,8 @@ void Player::LearnSpell(uint32 spell_id, bool dependent, int32 fromSkill /*= 0*/
WorldPackets::Spells::LearnedSpellInfo& learnedSpellInfo = learnedSpells.ClientLearnedSpellData.emplace_back();
learnedSpellInfo.SpellID = spell_id;
learnedSpellInfo.Favorite = favorite;
- learnedSpellInfo.TraitDefinitionID = traitDefinitionId;
+ if (trait)
+ learnedSpellInfo.TraitDefinitionID = int32(trait->DefinitionId);
learnedSpells.SuppressMessaging = suppressMessaging;
SendDirectMessage(learnedSpells.Write());
}
@@ -3278,7 +3243,7 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled /*= false*/, bool learn_
bool cur_active = itr->second.active;
bool cur_dependent = itr->second.dependent;
- Optional<int32> traitDefinitionId = itr->second.TraitDefinitionId;
+ Optional<PlayerSpellTrait> trait = itr->second.Trait;
if (disabled)
{
@@ -3437,8 +3402,8 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled /*= false*/, bool learn_
}
}
- if (traitDefinitionId)
- if (TraitDefinitionEntry const* traitDefinition = sTraitDefinitionStore.LookupEntry(*traitDefinitionId))
+ if (trait)
+ if (TraitDefinitionEntry const* traitDefinition = sTraitDefinitionStore.LookupEntry(trait->DefinitionId))
RemoveOverrideSpell(traitDefinition->OverridesSpellID, spell_id);
m_overrideSpells.erase(spell_id);
@@ -17643,9 +17608,6 @@ void Player::_LoadEquipmentSets(PreparedQueryResult result)
if (ObjectGuid::LowType guid = fields[6 + i].GetUInt64())
eqSet.Data.Pieces[i] = ObjectGuid::Create<HighGuid::Item>(guid);
- eqSet.Data.Appearances.fill(0);
- eqSet.Data.Enchants.fill(0);
-
if (eqSet.Data.SetID >= MAX_EQUIPMENT_SET_INDEX) // client limit
continue;
@@ -17676,7 +17638,6 @@ void Player::_LoadTransmogOutfits(PreparedQueryResult result)
eqSet.Data.SetIcon = fields[3].GetString();
eqSet.Data.IgnoreMask = fields[4].GetUInt32();
eqSet.State = EQUIPMENT_SET_UNCHANGED;
- eqSet.Data.Pieces.fill(ObjectGuid::Empty);
for (uint32 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i)
eqSet.Data.Appearances[i] = fields[5 + i].GetInt32();
@@ -28789,7 +28750,7 @@ void Player::ApplyTraitEntryChanges(int32 editedConfigId, WorldPackets::Traits::
// remove traits not found in new config
std::set<int32, std::greater<>> entryIndicesToRemove;
- for (int32 i = 0; i < int32(editedConfig.Entries.size()); ++i)
+ for (int32 i = 0; i < std::ssize(editedConfig.Entries); ++i)
{
UF::TraitEntry const& oldEntry = editedConfig.Entries[i];
auto entryItr = std::ranges::find_if(newConfig.Entries, makeTraitEntryFinder(oldEntry.TraitNodeID, oldEntry.TraitNodeEntryID));
@@ -28812,9 +28773,8 @@ void Player::ApplyTraitEntryChanges(int32 editedConfigId, WorldPackets::Traits::
std::vector<WorldPackets::Traits::TraitEntry> costEntries;
// apply new traits
- for (std::size_t i = 0; i < newConfig.Entries.size(); ++i)
+ for (WorldPackets::Traits::TraitEntry const& newEntry : newConfig.Entries)
{
- WorldPackets::Traits::TraitEntry const& newEntry = newConfig.Entries[i];
int32 oldEntryIndex = editedConfig.Entries.FindIndexIf(makeTraitEntryFinder(newEntry.TraitNodeID, newEntry.TraitNodeEntryID));
if (oldEntryIndex < 0)
{
@@ -28851,7 +28811,10 @@ void Player::ApplyTraitEntryChanges(int32 editedConfigId, WorldPackets::Traits::
.ModifyValue(&UF::TraitEntry::GrantedRanks), newEntry.GrantedRanks);
if (applyTraits)
+ {
+ ApplyTraitEntry(newEntry.TraitNodeEntryID, 0, 0, false);
ApplyTraitEntry(newEntry.TraitNodeEntryID, newEntry.Rank, newEntry.GrantedRanks, true);
+ }
}
}
@@ -28880,9 +28843,8 @@ void Player::ApplyTraitEntryChanges(int32 editedConfigId, WorldPackets::Traits::
}
}
- for (std::size_t i = 0; i < newConfig.SubTrees.size(); ++i)
+ for (WorldPackets::Traits::TraitSubTreeCache const& newSubTree : newConfig.SubTrees)
{
- WorldPackets::Traits::TraitSubTreeCache const& newSubTree = newConfig.SubTrees[i];
int32 oldSubTreeIndex = editedConfig.SubTrees.FindIndexIf([&](UF::TraitSubTreeCache const& ufSubTree) { return ufSubTree.TraitSubTreeID == newSubTree.TraitSubTreeID; });
std::vector<UF::TraitEntry> subTreeEntries;
subTreeEntries.resize(newSubTree.Entries.size());
@@ -28894,6 +28856,7 @@ void Player::ApplyTraitEntryChanges(int32 editedConfigId, WorldPackets::Traits::
newUfEntry.Rank = newSubTree.Entries[j].Rank;
newUfEntry.GrantedRanks = newSubTree.Entries[j].GrantedRanks;
}
+
if (oldSubTreeIndex < 0)
{
UF::TraitSubTreeCache& newUfSubTree = AddDynamicUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData)
@@ -28972,7 +28935,7 @@ void Player::ApplyTraitConfig(int32 configId, bool apply)
ApplyTraitEntry(traitEntry.TraitNodeEntryID, traitEntry.Rank, traitEntry.GrantedRanks, apply);
}
-void Player::ApplyTraitEntry(int32 traitNodeEntryId, int32 /*rank*/, int32 /*grantedRanks*/, bool apply)
+void Player::ApplyTraitEntry(int32 traitNodeEntryId, int32 rank, int32 grantedRanks, bool apply)
{
TraitNodeEntryEntry const* traitNodeEntry = sTraitNodeEntryStore.LookupEntry(traitNodeEntryId);
if (!traitNodeEntry)
@@ -28984,8 +28947,10 @@ void Player::ApplyTraitEntry(int32 traitNodeEntryId, int32 /*rank*/, int32 /*gra
if (traitDefinition->SpellID)
{
+ ASSERT(traitNodeEntry->TraitDefinitionID <= 0xFFFFFF && rank + grantedRanks <= 0xFF);
+
if (apply)
- LearnSpell(traitDefinition->SpellID, true, 0, false, traitNodeEntry->TraitDefinitionID);
+ LearnSpell(traitDefinition->SpellID, true, 0, false, PlayerSpellTrait{ .DefinitionId = traitNodeEntry->TraitDefinitionID, .Rank = rank + grantedRanks });
else
RemoveSpell(traitDefinition->SpellID);
}
@@ -29064,6 +29029,13 @@ void Player::SetTraitConfigUseSharedActionBars(int32 traitConfigId, bool usesSha
m_traitConfigStates[traitConfigId] = PLAYERSPELL_CHANGED;
}
+Optional<PlayerSpellTrait> Player::GetTraitInfoForSpell(uint32 spellId) const
+{
+ if (PlayerSpell const* spell = Trinity::Containers::MapGetValuePtr(m_spells, spellId))
+ return spell->Trait;
+ return {};
+}
+
void Player::SetReputation(uint32 factionentry, int32 value)
{
GetReputationMgr().SetReputation(sFactionStore.LookupEntry(factionentry), value);
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 7389695ce38..bdce5bc9b76 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -200,6 +200,14 @@ enum PlayerSpellState : uint8
PLAYERSPELL_TEMPORARY = 4
};
+struct PlayerSpellTrait
+{
+ int32 DefinitionId : 24;
+ int32 Rank : 8;
+
+ friend bool operator==(PlayerSpellTrait const&, PlayerSpellTrait const&) noexcept = default;
+};
+
struct PlayerSpell
{
PlayerSpellState state;
@@ -207,7 +215,7 @@ struct PlayerSpell
bool dependent : 1; // learned as result another spell learn, skill grow, quest reward, etc
bool disabled : 1; // first rank has been learned in result talent learn but currently talent unlearned, save max learned ranks
bool favorite : 1;
- Optional<int32> TraitDefinitionId;
+ Optional<PlayerSpellTrait> Trait;
};
struct StoredAuraTeleportLocation
@@ -1891,8 +1899,8 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
void SendProficiency(ItemClass itemClass, uint32 itemSubclassMask) const;
void SendKnownSpells();
void SendUnlearnSpells();
- bool AddSpell(uint32 spellId, bool active, bool learning, bool dependent, bool disabled, bool loading = false, int32 fromSkill = 0, bool favorite = false, Optional<int32> traitDefinitionId = {});
- void LearnSpell(uint32 spell_id, bool dependent, int32 fromSkill = 0, bool suppressMessaging = false, Optional<int32> traitDefinitionId = {});
+ bool AddSpell(uint32 spellId, bool active, bool learning, bool dependent, bool disabled, bool loading = false, int32 fromSkill = 0, bool favorite = false, Optional<PlayerSpellTrait> trait = {});
+ void LearnSpell(uint32 spell_id, bool dependent, int32 fromSkill = 0, bool suppressMessaging = false, Optional<PlayerSpellTrait> trait = {});
void RemoveSpell(uint32 spell_id, bool disabled = false, bool learn_low_rank = true, bool suppressMessaging = false);
void ResetSpells(bool myClassOnly = false);
void LearnCustomSpells();
@@ -1986,6 +1994,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
void SetActiveCombatTraitConfigID(int32 traitConfigId) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ActiveCombatTraitConfigID), traitConfigId); }
void SetTraitConfigUseStarterBuild(int32 traitConfigId, bool useStarterBuild);
void SetTraitConfigUseSharedActionBars(int32 traitConfigId, bool usesSharedActionBars, bool isLastSelectedSavedConfig);
+ Optional<PlayerSpellTrait> GetTraitInfoForSpell(uint32 spellId) const;
uint32 GetFreePrimaryProfessionPoints() const { return m_activePlayerData->CharacterPoints; }
void SetFreePrimaryProfessions(uint16 profs) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::CharacterPoints), profs); }
diff --git a/src/server/game/Handlers/TraitHandler.cpp b/src/server/game/Handlers/TraitHandler.cpp
index 1e1de92a139..086e25bc0b4 100644
--- a/src/server/game/Handlers/TraitHandler.cpp
+++ b/src/server/game/Handlers/TraitHandler.cpp
@@ -47,7 +47,7 @@ void WorldSession::HandleTraitsCommitConfig(WorldPackets::Traits::TraitsCommitCo
auto findEntry = [](WorldPackets::Traits::TraitConfig& config, int32 traitNodeId, int32 traitNodeEntryId) -> WorldPackets::Traits::TraitEntry*
{
- auto entryItr = std::find_if(config.Entries.begin(), config.Entries.end(), [=](WorldPackets::Traits::TraitEntry const& traitEntry)
+ auto entryItr = std::ranges::find_if(config.Entries, [=](WorldPackets::Traits::TraitEntry const& traitEntry)
{
return traitEntry.TraitNodeID == traitNodeId && traitEntry.TraitNodeEntryID == traitNodeEntryId;
});
@@ -118,10 +118,10 @@ void WorldSession::HandleTraitsCommitConfig(WorldPackets::Traits::TraitsCommitCo
if (newEntry.Rank)
traitEntry->Rank = newEntry.Rank;
else
- newConfigState.Entries.erase(std::remove_if(newConfigState.Entries.begin(), newConfigState.Entries.end(), [&newEntry](WorldPackets::Traits::TraitEntry const& traitEntry)
+ std::erase_if(newConfigState.Entries, [&newEntry](WorldPackets::Traits::TraitEntry const& traitEntry)
{
return traitEntry.TraitNodeID == newEntry.TraitNodeID && traitEntry.TraitNodeEntryID == newEntry.TraitNodeEntryID;
- }), newConfigState.Entries.end());
+ });
}
else
newConfigState.Entries.emplace_back() = newEntry;
@@ -152,7 +152,7 @@ void WorldSession::HandleClassTalentsRequestNewConfig(WorldPackets::Traits::Clas
if ((classTalentsRequestNewConfig.Config.CombatConfigFlags & TraitCombatConfigFlags::ActiveForSpec) != TraitCombatConfigFlags::None)
return;
- int64 configCount = std::count_if(_player->m_activePlayerData->TraitConfigs.begin(), _player->m_activePlayerData->TraitConfigs.end(), [](UF::TraitConfig const& traitConfig)
+ int64 configCount = std::ranges::count_if(_player->m_activePlayerData->TraitConfigs, [](UF::TraitConfig const& traitConfig)
{
return static_cast<TraitConfigType>(*traitConfig.Type) == TraitConfigType::Combat
&& (static_cast<TraitCombatConfigFlags>(*traitConfig.CombatConfigFlags) & TraitCombatConfigFlags::ActiveForSpec) == TraitCombatConfigFlags::None;
@@ -179,7 +179,7 @@ void WorldSession::HandleClassTalentsRequestNewConfig(WorldPackets::Traits::Clas
for (UF::TraitEntry const& grantedEntry : TraitMgr::GetGrantedTraitEntriesForConfig(classTalentsRequestNewConfig.Config, _player))
{
- auto entryItr = std::find_if(classTalentsRequestNewConfig.Config.Entries.begin(), classTalentsRequestNewConfig.Config.Entries.end(),
+ auto entryItr = std::ranges::find_if(classTalentsRequestNewConfig.Config.Entries,
[&](WorldPackets::Traits::TraitEntry const& entry) { return entry.TraitNodeID == grantedEntry.TraitNodeID && entry.TraitNodeEntryID == grantedEntry.TraitNodeEntryID; });
WorldPackets::Traits::TraitEntry& newEntry = entryItr != classTalentsRequestNewConfig.Config.Entries.end() ? *entryItr : classTalentsRequestNewConfig.Config.Entries.emplace_back();
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 12d9947db55..7e81e5570f2 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -35,6 +35,7 @@
#include "Spell.h"
#include "SpellAuraEffects.h"
#include "SpellMgr.h"
+#include "TraitMgr.h"
#include "Vehicle.h"
#include <G3D/g3dmath.h>
#include <bit>
@@ -503,7 +504,35 @@ int32 SpellEffectInfo::CalcValue(WorldObject const* caster /*= nullptr*/, int32
Unit const* casterUnit = nullptr;
if (caster)
+ {
casterUnit = caster->ToUnit();
+ if (Player const* playerCaster = caster->ToPlayer())
+ {
+ if (Optional<PlayerSpellTrait> trait = playerCaster->GetTraitInfoForSpell(_spellInfo->Id))
+ {
+ if (std::vector<TraitDefinitionEffectPointsEntry const*> const* traitDefinitionEffectPoints = TraitMgr::GetTraitDefinitionEffectPointModifiers(trait->DefinitionId))
+ {
+ auto pointsOverride = std::ranges::find(*traitDefinitionEffectPoints, EffectIndex, &TraitDefinitionEffectPointsEntry::EffectIndex);
+ if (pointsOverride != traitDefinitionEffectPoints->end())
+ {
+ float traitBasePoints = sDB2Manager.GetCurveValueAt((*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)
{