Core/Units: moved stats modifiers and multipliers into a struct for future ports of the remaining secondary stats

This commit is contained in:
Ovahlord committed 2026-06-12 11:55:12 +02:00
1 parent 38784337a2
commit 0f6a99bd85
6 files changed
+96 -83

No files matched your search

+1 -1
View File
@@ -773,7 +773,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
if (pInfo->armor > 0)
SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor));
for (StatType stat : AllStats)
for (StatType stat : AllPrimaryStats)
GetStats().SetBaseStatValue(stat, pInfo->stats[AsUnderlyingType(stat)]);
}
else // not exist in DB, use some default fake data
+4 -4
View File
@@ -2230,7 +2230,7 @@ void Player::GiveLevel(uint8 level)
packet.PowerDelta[4] = 0;
packet.PowerDelta[5] = 0;
for (StatType stat : AllStats)
for (StatType stat : AllPrimaryStats)
packet.StatDelta[AsUnderlyingType(stat)] = int32(info.stats[AsUnderlyingType(stat)]) - GetStats().GetBaseStatValue(stat);
SendDirectMessage(packet.Write());
@@ -2250,7 +2250,7 @@ void Player::GiveLevel(uint8 level)
SetCreateMana(basemana);
// save base values (bonuses already included in stored stats)
for (StatType stat : AllStats)
for (StatType stat : AllPrimaryStats)
GetStats().SetBaseStatValue(stat, info.stats[AsUnderlyingType(stat)]);
InitTalentForLevel();
@@ -2380,7 +2380,7 @@ void Player::InitStatsForLevel(bool reapplyMods)
SetCreateMana(basemana);
// save base values (bonuses already included in stored stats
for (StatType stat : AllStats)
for (StatType stat : AllPrimaryStats)
GetStats().SetBaseStatValue(stat, info.stats[AsUnderlyingType(stat)]);
//reset rating fields values
@@ -20030,7 +20030,7 @@ void Player::_SaveStats(CharacterDatabaseTransaction& trans) const
for (uint8 i = 0; i < MAX_POWERS_PER_CLASS; ++i)
stmt->setUInt32(index++, GetMaxPower(PowerType(i)));
for (StatType stat : AllStats)
for (StatType stat : AllPrimaryStats)
stmt->setUInt32(index++, GetStat(stat));
for (int i = 0; i < MAX_SPELL_SCHOOL; ++i)
+64 -58
View File
@@ -23,11 +23,8 @@
Stats::~Stats() = default;
Stats::Stats(Unit* owner) : _owner(owner), _baseStats({ }), _baseStatModifiers({ }), _basePctMultipliers({ }),
_totalModifiers({ }), _totalPctMultipliers({ })
Stats::Stats(Unit* owner) : _owner(owner), _primaryStatData({ })
{
_basePctMultipliers.fill(1.0);
_totalPctMultipliers.fill(1.0);
}
/// Returns the unmodified base value of the specified stat.
@@ -36,7 +33,7 @@ Stats::Stats(Unit* owner) : _owner(owner), _baseStats({ }), _baseStatModifiers({
/// @return returns the base value fo the specified stat
int32 Stats::GetBaseStatValue(StatType statType) const
{
return _baseStats[AsUnderlyingType(statType)];
return _primaryStatData[AsUnderlyingType(statType)].BaseStat;
}
/// Sets the unmodified base value of the specified stat and
@@ -46,7 +43,7 @@ int32 Stats::GetBaseStatValue(StatType statType) const
/// @param value The new base value that will be set
void Stats::SetBaseStatValue(StatType statType, int32 value)
{
_baseStats[AsUnderlyingType(statType)] = value;
_primaryStatData[AsUnderlyingType(statType)].BaseStat= value;
updateStat(statType);
}
@@ -56,7 +53,7 @@ void Stats::SetBaseStatValue(StatType statType, int32 value)
/// @param value The amount of the modifier that will be applied
void Stats::AddBaseStatModifier(StatType statType, int32 value)
{
_baseStatModifiers[AsUnderlyingType(statType)] += value;
_primaryStatData[AsUnderlyingType(statType)].BaseStatModifier += value;
updateStat(statType);
}
@@ -66,7 +63,7 @@ void Stats::AddBaseStatModifier(StatType statType, int32 value)
/// @param value The amount of the modifier that will be removed
void Stats::RemoveBaseStatModifier(StatType statType, int32 value)
{
_baseStatModifiers[AsUnderlyingType(statType)] -= value;
_primaryStatData[AsUnderlyingType(statType)].BaseStatModifier -= value;
updateStat(statType);
}
@@ -75,19 +72,19 @@ void Stats::RemoveBaseStatModifier(StatType statType, int32 value)
/// @param statType The stat which multiplier value will be updated
void Stats::UpdateBaseStatMultiplier(StatType statType)
{
if (statType == StatType::AllStats || statType == StatType::AllStats2)
if (statType == StatType::AllPrimaryStats || statType == StatType::AllPrimaryStats2)
{
for (StatType stat : AllStats)
for (StatType stat : AllPrimaryStats)
{
float multiplier = getAuraMultiplierForStatType(SPELL_AURA_MOD_PERCENT_STAT, stat);
_basePctMultipliers[AsUnderlyingType(stat)] = multiplier;
_primaryStatData[AsUnderlyingType(stat)].BasePctMultiplier = multiplier;
updateStat(stat);
}
}
else
{
float multiplier = getAuraMultiplierForStatType(SPELL_AURA_MOD_PERCENT_STAT, statType);
_basePctMultipliers[AsUnderlyingType(statType)] = multiplier;
_primaryStatData[AsUnderlyingType(statType)].BasePctMultiplier = multiplier;
updateStat(statType);
}
}
@@ -97,19 +94,19 @@ void Stats::UpdateBaseStatMultiplier(StatType statType)
/// @param statType The stat which modifier value will be updated
void Stats::UpdateTotalStatModifier(StatType statType)
{
if (statType == StatType::AllStats || statType == StatType::AllStats2)
if (statType == StatType::AllPrimaryStats || statType == StatType::AllPrimaryStats2)
{
for (StatType stat : AllStats)
for (StatType stat : AllPrimaryStats)
{
int32 modifier = getAuraModifierForStatType(SPELL_AURA_MOD_STAT, stat);
_totalModifiers[AsUnderlyingType(stat)] = modifier;
_primaryStatData[AsUnderlyingType(stat)].TotalModifier = modifier;
updateStat(stat);
}
}
else
{
int32 modifier = getAuraModifierForStatType(SPELL_AURA_MOD_STAT, statType);
_totalModifiers[AsUnderlyingType(statType)] = modifier;
_primaryStatData[AsUnderlyingType(statType)].TotalModifier = modifier;
updateStat(statType);
}
}
@@ -119,19 +116,19 @@ void Stats::UpdateTotalStatModifier(StatType statType)
/// @param statType The stat which multiplier value will be updated
void Stats::UpdateTotalStatMultiplier(StatType statType)
{
if (statType == StatType::AllStats || statType == StatType::AllStats2)
if (statType == StatType::AllPrimaryStats || statType == StatType::AllPrimaryStats2)
{
for (StatType stat : AllStats)
for (StatType stat : AllPrimaryStats)
{
float multiplier = getAuraMultiplierForStatType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, stat);
_totalPctMultipliers[AsUnderlyingType(stat)] = multiplier;
_primaryStatData[AsUnderlyingType(stat)].TotalPctMultiplier = multiplier;
updateStat(stat);
}
}
else
{
float multiplier = getAuraMultiplierForStatType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, statType);
_totalPctMultipliers[AsUnderlyingType(statType)] = multiplier;
_primaryStatData[AsUnderlyingType(statType)].TotalPctMultiplier = multiplier;
updateStat(statType);
}
}
@@ -200,41 +197,9 @@ void Stats::updateStat(StatType statType)
{
int32 negStatValue = 0;
int32 posStatValue = 0;
int32 statValue = 0;
// ==== Calculate the base flat value (Level stats and item/enchantment mods)
int32 baseStatValue = _baseStats[AsUnderlyingType(statType)];
int32 baseModifier = _baseStatModifiers[AsUnderlyingType(statType)];
if (baseModifier > 0)
posStatValue += baseModifier;
else
negStatValue += baseModifier;
int32 flatStatValue = baseStatValue + baseModifier;
// ==== Calculate the total base value (Base pct multiplier auras)
double basePctMultiplier = _basePctMultipliers[AsUnderlyingType(statType)];
int32 baseTotalValue = static_cast<int32>(std::round(flatStatValue * basePctMultiplier));
if (flatStatValue < baseTotalValue)
posStatValue += baseTotalValue - flatStatValue;
else
negStatValue += baseTotalValue - flatStatValue;
// ==== Calculate the total value (Total value buff auras)
int32 totalModifier = _totalModifiers[AsUnderlyingType(statType)];
if (totalModifier > 0)
posStatValue += totalModifier;
else
negStatValue += totalModifier;
int32 totalValue = baseTotalValue + totalModifier;
// ==== Calculate the total value (Total pct multipliers)
double totalPctMultiplier = _totalPctMultipliers[AsUnderlyingType(statType)];
int32 statValue = static_cast<int32>(std::round(totalValue * totalPctMultiplier));
if (totalValue < statValue)
posStatValue += statValue - totalValue;
else
negStatValue += statValue - totalValue;
calculateStatValues(_primaryStatData[AsUnderlyingType(statType)], statValue, posStatValue, negStatValue);
// ==== Apply the stats
_owner->SetInt32Value(UNIT_FIELD_STAT0 + AsUnderlyingType(statType), statValue);
@@ -286,22 +251,63 @@ void Stats::updateStat(StatType statType)
combatRatingMask |= aurEff->GetMiscValue();
}
Player* player = Object::ToPlayer(_owner);
if (combatRatingMask)
{
Player* player = Object::ToPlayer(_owner);
for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
if ((combatRatingMask & (1 << rating)) != 0)
player->ApplyRatingMod(CombatRating(rating), 0, true);
player->ApplyRatingMod(static_cast<CombatRating>(rating), 0, true);
}
}
}
void Stats::calculateStatValues(StatData const& statData, int32& statValue, int32& posStatValue, int32& negStatValue)
{
negStatValue = 0;
posStatValue = 0;
// ==== Calculate the base flat value (Level stats and item/enchantment mods)
int32 baseStatValue = statData.BaseStat;
int32 baseModifier = statData.BaseStatModifier;
if (baseModifier > 0)
posStatValue += baseModifier;
else
negStatValue += baseModifier;
int32 flatStatValue = baseStatValue + baseModifier;
// ==== Calculate the total base value (Base pct multiplier auras)
double basePctMultiplier = statData.BasePctMultiplier;
int32 baseTotalValue = static_cast<int32>(std::round(flatStatValue * basePctMultiplier));
if (flatStatValue < baseTotalValue)
posStatValue += baseTotalValue - flatStatValue;
else
negStatValue += baseTotalValue - flatStatValue;
// ==== Calculate the total value (Total value buff auras)
int32 totalModifier = statData.TotalModifier;
if (totalModifier > 0)
posStatValue += totalModifier;
else
negStatValue += totalModifier;
int32 totalValue = baseTotalValue + totalModifier;
// ==== Calculate the total value (Total pct multipliers)
double totalPctMultiplier = statData.TotalPctMultiplier;
statValue = static_cast<int32>(std::round(totalValue * totalPctMultiplier));
if (totalValue < statValue)
posStatValue += statValue - totalValue;
else
negStatValue += statValue - totalValue;
}
float Stats::getAuraMultiplierForStatType(AuraType auraType, StatType statType) const
{
float multiplier = _owner->GetTotalAuraMultiplier(auraType, [&](AuraEffect const* aurEff)
{
StatType auraStatType = static_cast<StatType>(aurEff->GetMiscValue());
if (auraStatType == StatType::AllStats || auraStatType == StatType::AllStats2 || auraStatType == statType)
if (auraStatType == StatType::AllPrimaryStats || auraStatType == StatType::AllPrimaryStats2 || auraStatType == statType)
return true;
return false;
@@ -315,7 +321,7 @@ int32 Stats::getAuraModifierForStatType(AuraType auraType, StatType statType) co
int32 modifier = _owner->GetTotalAuraModifier(auraType, [&](AuraEffect const* aurEff)
{
StatType auraStatType = static_cast<StatType>(aurEff->GetMiscValue());
if (auraStatType == StatType::AllStats || auraStatType == StatType::AllStats2 || auraStatType == statType)
if (auraStatType == StatType::AllPrimaryStats || auraStatType == StatType::AllPrimaryStats2 || auraStatType == statType)
return true;
return false;
+21 -14
View File
@@ -27,17 +27,18 @@ enum AuraType : uint32;
enum class StatType : int8
{
AllStats2 = -2, // There is only one spell using this and it also states that it increases all stats
AllStats = -1,
Strength = 0,
Agility = 1,
Stamina = 2,
Intellect = 3,
Spirit = 4,
Max
// Primary Stats
AllPrimaryStats2 = -2, // There is only one spell using this and it also states that it increases all stats
AllPrimaryStats = -1,
Strength = 0,
Agility = 1,
Stamina = 2,
Intellect = 3,
Spirit = 4,
Max,
};
static constexpr std::array<StatType, AsUnderlyingType(StatType::Max)> AllStats =
static constexpr std::array<StatType, AsUnderlyingType(StatType::Max)> AllPrimaryStats =
{
StatType::Strength,
StatType::Agility,
@@ -46,6 +47,15 @@ static constexpr std::array<StatType, AsUnderlyingType(StatType::Max)> AllStats
StatType::Spirit
};
struct StatData
{
int32 BaseStat = 0;
int32 BaseStatModifier = 0;
int32 TotalModifier = 0;
double BasePctMultiplier = 1.0;
double TotalPctMultiplier = 1.0;
};
class TC_GAME_API Stats
{
public:
@@ -70,13 +80,10 @@ public:
private:
Unit* _owner;
std::array<int32, AsUnderlyingType(StatType::Max)> _baseStats;
std::array<int32, AsUnderlyingType(StatType::Max)> _baseStatModifiers;
std::array<double, AsUnderlyingType(StatType::Max)> _basePctMultipliers;
std::array<int32, AsUnderlyingType(StatType::Max)> _totalModifiers;
std::array<double, AsUnderlyingType(StatType::Max)> _totalPctMultipliers;
std::array<StatData, AsUnderlyingType(StatType::Max)> _primaryStatData;
void updateStat(StatType statType);
void calculateStatValues(StatData const& statData, int32& statValue, int32& posStatValue, int32& negStatValue);
float getAuraMultiplierForStatType(AuraType auraType, StatType statType) const;
int32 getAuraModifierForStatType(AuraType auraType, StatType statType) const;
+3 -3
View File
@@ -3284,7 +3284,7 @@ void ObjectMgr::LoadPetLevelInfo()
pLevelInfo->armor = fields[9].GetUInt32();
for (StatType stat : AllStats)
for (StatType stat : AllPrimaryStats)
pLevelInfo->stats[AsUnderlyingType(stat)] = fields[AsUnderlyingType(stat) + 4].GetUInt16();
++count;
@@ -3732,7 +3732,7 @@ void ObjectMgr::LoadPlayerInfo()
continue;
}
for (StatType stat : AllStats)
for (StatType stat : AllPrimaryStats)
raceStatModifiers[current_race].StatModifier[AsUnderlyingType(stat)] = fields[AsUnderlyingType(stat) + 1].GetInt16();
} while (raceStatsResult->NextRow());
@@ -3781,7 +3781,7 @@ void ObjectMgr::LoadPlayerInfo()
playerInfo->levelInfo = std::make_unique<PlayerLevelInfo[]>(sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL));
PlayerLevelInfo& levelInfo = playerInfo->levelInfo[current_level - 1];
for (StatType stat : AllStats)
for (StatType stat : AllPrimaryStats)
levelInfo.stats[AsUnderlyingType(stat)] = fields[AsUnderlyingType(stat) + 2].GetUInt16() + raceStatModifiers[race].StatModifier[AsUnderlyingType(stat)];
}
}
@@ -3570,7 +3570,7 @@ void AuraEffect::HandleAuraModStat(AuraApplication const* aurApp, uint8 mode, bo
return;
StatType stat = static_cast<StatType>(GetMiscValue());
if (stat < StatType::AllStats2 || stat >= StatType::Max)
if (stat < StatType::AllPrimaryStats2 || stat >= StatType::Max)
{
TC_LOG_ERROR("spells", "WARNING: Spell %u effect %u has an unsupported misc value (%i) for SPELL_AURA_MOD_STAT ", GetId(), GetEffIndex(), GetMiscValue());
return;
@@ -3586,7 +3586,7 @@ void AuraEffect::HandleModPercentStat(AuraApplication const* aurApp, uint8 mode,
return;
StatType stat = static_cast<StatType>(GetMiscValue());
if (stat < StatType::AllStats2 || stat >= StatType::Max)
if (stat < StatType::AllPrimaryStats2 || stat >= StatType::Max)
{
TC_LOG_ERROR("spells", "WARNING: Spell %u effect %u has an unsupported misc value (%i) for SPELL_AURA_MOD_PERCENT_STAT ", GetId(), GetEffIndex(), GetMiscValue());
return;
@@ -3676,7 +3676,7 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8
return;
StatType stat = static_cast<StatType>(GetMiscValue());
if (stat < StatType::AllStats2 || stat >= StatType::Max)
if (stat < StatType::AllPrimaryStats2 || stat >= StatType::Max)
{
TC_LOG_ERROR("spells", "WARNING: Spell %u effect %u has an unsupported misc value (%i) for SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE ", GetId(), GetEffIndex(), GetMiscValue());
return;