aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp139
-rw-r--r--src/server/game/Entities/Creature/Creature.h11
-rw-r--r--src/server/game/Entities/Creature/CreatureData.h30
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp11
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp98
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h4
-rw-r--r--src/server/game/Server/Packets/CombatLogPacketsCommon.cpp25
7 files changed, 117 insertions, 201 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 0b09a1a2316..d4f83a03d87 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -253,9 +253,8 @@ CreatureDifficulty const* CreatureTemplate::GetDifficulty(Difficulty difficulty)
{
DefaultCreatureDifficulty()
{
- DeltaLevelMin = 0;
- DeltaLevelMax = 0;
- ContentTuningID = 0;
+ MinLevel = 1;
+ MaxLevel = 1;
HealthScalingExpansion = 0;
HealthModifier = 1.f;
ManaModifier = 1.f;
@@ -618,17 +617,15 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/,
if (updateLevel)
SelectLevel();
- else if (!IsGuardian())
+
+ // Do not update guardian stats here - they are handled in Guardian::InitStatsForLevel()
+ if (!IsGuardian())
{
uint32 previousHealth = GetHealth();
UpdateLevelDependantStats(); // We still re-initialize level dependant stats on entry update
if (previousHealth > 0)
SetHealth(previousHealth);
- }
- // Do not update guardian stats here - they are handled in Guardian::InitStatsForLevel()
- if (!IsGuardian())
- {
SetMeleeDamageSchool(SpellSchools(cInfo->dmgschool));
SetStatFlatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_HOLY]));
SetStatFlatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FIRE]));
@@ -1552,25 +1549,23 @@ void Creature::SaveToDB(uint32 mapid, std::vector<Difficulty> const& spawnDiffic
void Creature::SelectLevel()
{
// Level
- ApplyLevelScaling();
- int32 levelWithDelta = m_unitData->ScalingLevelMax + m_unitData->ScalingLevelDelta;
- uint8 level = RoundToInterval<int32>(levelWithDelta, 1, STRONG_MAX_LEVEL);
- SetLevel(level);
-
- UpdateLevelDependantStats();
+ CreatureDifficulty const* difficulty = GetCreatureDifficulty();
+ if (difficulty->MinLevel != difficulty->MaxLevel)
+ SetLevel(urand(difficulty->MinLevel, difficulty->MaxLevel));
+ else
+ SetLevel(difficulty->MinLevel);
}
void Creature::UpdateLevelDependantStats()
{
CreatureTemplate const* cInfo = GetCreatureTemplate();
uint32 rank = IsPet() ? 0 : cInfo->rank;
- uint8 level = GetLevel();
- CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(level, cInfo->unit_class);
+ CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(GetLevel(), cInfo->unit_class);
// health
float healthmod = _GetHealthMod(rank);
- uint32 basehp = GetMaxHealthByLevel(level);
+ uint32 basehp = stats->GenerateHealth(m_creatureDifficulty);
uint32 health = uint32(basehp * healthmod);
SetCreateHealth(health);
@@ -1595,7 +1590,7 @@ void Creature::UpdateLevelDependantStats()
}
// damage
- float basedamage = GetBaseDamageForLevel(level);
+ float basedamage = stats->GenerateBaseDamage(m_creatureDifficulty);
float weaponBaseMinDamage = basedamage;
float weaponBaseMaxDamage = basedamage * 1.5f;
@@ -1612,7 +1607,7 @@ void Creature::UpdateLevelDependantStats()
SetStatFlatModifier(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower);
SetStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, stats->RangedAttackPower);
- float armor = GetBaseArmorForLevel(level);
+ float armor = (float)stats->GenerateArmor(m_creatureDifficulty); /// @todo Why is this treated as uint32 when it's a float?
SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, armor);
}
@@ -2946,84 +2941,6 @@ void Creature::AllLootRemovedFromCorpse()
m_respawnTime = std::max<time_t>(m_corpseRemoveTime + m_respawnDelay, m_respawnTime);
}
-bool Creature::HasScalableLevels() const
-{
- return m_unitData->ContentTuningID != 0;
-}
-
-void Creature::ApplyLevelScaling()
-{
- CreatureDifficulty const* creatureDifficulty = GetCreatureDifficulty();
-
- if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(creatureDifficulty->ContentTuningID, 0))
- {
- SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ScalingLevelMin), levels->MinLevel);
- SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ScalingLevelMax), levels->MaxLevel);
- }
-
- int32 mindelta = std::min(creatureDifficulty->DeltaLevelMax, creatureDifficulty->DeltaLevelMin);
- int32 maxdelta = std::max(creatureDifficulty->DeltaLevelMax, creatureDifficulty->DeltaLevelMin);
- int32 delta = mindelta == maxdelta ? mindelta : irand(mindelta, maxdelta);
-
- SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ScalingLevelDelta), delta);
- SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ContentTuningID), creatureDifficulty->ContentTuningID);
-}
-
-uint64 Creature::GetMaxHealthByLevel(uint8 level) const
-{
- CreatureTemplate const* cInfo = GetCreatureTemplate();
- CreatureDifficulty const* creatureDifficulty = GetCreatureDifficulty();
- float baseHealth = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureHealth, level, creatureDifficulty->GetHealthScalingExpansion(), creatureDifficulty->ContentTuningID, Classes(cInfo->unit_class), 0);
- return std::max(baseHealth * creatureDifficulty->HealthModifier, 1.0f);
-}
-
-float Creature::GetHealthMultiplierForTarget(WorldObject const* target) const
-{
- if (!HasScalableLevels())
- return 1.0f;
-
- uint8 levelForTarget = GetLevelForTarget(target);
- if (GetLevel() < levelForTarget)
- return 1.0f;
-
- return double(GetMaxHealthByLevel(levelForTarget)) / double(GetCreateHealth());
-}
-
-float Creature::GetBaseDamageForLevel(uint8 level) const
-{
- CreatureTemplate const* cInfo = GetCreatureTemplate();
- CreatureDifficulty const* creatureDifficulty = GetCreatureDifficulty();
- return sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureAutoAttackDps, level, creatureDifficulty->GetHealthScalingExpansion(), creatureDifficulty->ContentTuningID, Classes(cInfo->unit_class), 0);
-}
-
-float Creature::GetDamageMultiplierForTarget(WorldObject const* target) const
-{
- if (!HasScalableLevels())
- return 1.0f;
-
- uint8 levelForTarget = GetLevelForTarget(target);
-
- return GetBaseDamageForLevel(levelForTarget) / GetBaseDamageForLevel(GetLevel());
-}
-
-float Creature::GetBaseArmorForLevel(uint8 level) const
-{
- CreatureTemplate const* cInfo = GetCreatureTemplate();
- CreatureDifficulty const* creatureDifficulty = GetCreatureDifficulty();
- float baseArmor = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureArmor, level, creatureDifficulty->GetHealthScalingExpansion(), creatureDifficulty->ContentTuningID, Classes(cInfo->unit_class), 0);
- return baseArmor * creatureDifficulty->ArmorModifier;
-}
-
-float Creature::GetArmorMultiplierForTarget(WorldObject const* target) const
-{
- if (!HasScalableLevels())
- return 1.0f;
-
- uint8 levelForTarget = GetLevelForTarget(target);
-
- return GetBaseArmorForLevel(levelForTarget) / GetBaseArmorForLevel(GetLevel());
-}
-
uint8 Creature::GetLevelForTarget(WorldObject const* target) const
{
if (Unit const* unitTarget = target->ToUnit())
@@ -3033,34 +2950,6 @@ uint8 Creature::GetLevelForTarget(WorldObject const* target) const
uint8 level = unitTarget->GetLevel() + sWorld->getIntConfig(CONFIG_WORLD_BOSS_LEVEL_DIFF);
return RoundToInterval<uint8>(level, 1u, 255u);
}
-
- // If this creature should scale level, adapt level depending of target level
- // between UNIT_FIELD_SCALING_LEVEL_MIN and UNIT_FIELD_SCALING_LEVEL_MAX
- if (HasScalableLevels())
- {
- int32 scalingLevelMin = m_unitData->ScalingLevelMin;
- int32 scalingLevelMax = m_unitData->ScalingLevelMax;
- int32 scalingLevelDelta = m_unitData->ScalingLevelDelta;
- int32 scalingFactionGroup = m_unitData->ScalingFactionGroup;
- int32 targetLevel = unitTarget->m_unitData->EffectiveLevel;
- if (!targetLevel)
- targetLevel = unitTarget->GetLevel();
-
- int32 targetLevelDelta = 0;
-
- if (Player const* playerTarget = target->ToPlayer())
- {
- if (scalingFactionGroup && sFactionTemplateStore.AssertEntry(sChrRacesStore.AssertEntry(playerTarget->GetRace())->FactionID)->FactionGroup != scalingFactionGroup)
- scalingLevelMin = scalingLevelMax;
-
- int32 maxCreatureScalingLevel = playerTarget->m_activePlayerData->MaxCreatureScalingLevel;
- targetLevelDelta = std::min(maxCreatureScalingLevel > 0 ? maxCreatureScalingLevel - targetLevel : 0, *playerTarget->m_activePlayerData->ScalingPlayerLevelDelta);
- }
-
- int32 levelWithDelta = targetLevel + targetLevelDelta;
- int32 level = RoundToInterval(levelWithDelta, scalingLevelMin, scalingLevelMax) + scalingLevelDelta;
- return RoundToInterval(level, 1, MAX_LEVEL + 3);
- }
}
return Unit::GetLevelForTarget(target);
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 46aa837a386..15902806b85 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -160,19 +160,8 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
bool isElite() const;
bool isWorldBoss() const;
- bool HasScalableLevels() const;
- void ApplyLevelScaling();
uint8 GetLevelForTarget(WorldObject const* target) const override;
- uint64 GetMaxHealthByLevel(uint8 level) const;
- float GetHealthMultiplierForTarget(WorldObject const* target) const override;
-
- float GetBaseDamageForLevel(uint8 level) const;
- float GetDamageMultiplierForTarget(WorldObject const* target) const override;
-
- float GetBaseArmorForLevel(uint8 level) const;
- float GetArmorMultiplierForTarget(WorldObject const* target) const override;
-
bool IsInEvadeMode() const { return HasUnitState(UNIT_STATE_EVADE); }
bool IsEvadingAttacks() const { return IsInEvadeMode() || CanNotReachTarget(); }
diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h
index 949c4ab3fa7..0777e2b69c7 100644
--- a/src/server/game/Entities/Creature/CreatureData.h
+++ b/src/server/game/Entities/Creature/CreatureData.h
@@ -460,9 +460,8 @@ struct CreatureModel
struct CreatureDifficulty
{
- int16 DeltaLevelMin;
- int16 DeltaLevelMax;
- int32 ContentTuningID;
+ uint8 MinLevel;
+ uint8 MaxLevel;
int32 HealthScalingExpansion;
float HealthModifier;
float ManaModifier;
@@ -581,11 +580,30 @@ struct TC_GAME_API CreatureTemplate
// Defines base stats for creatures (used to calculate HP/mana/armor/attackpower/rangedattackpower/all damage).
struct TC_GAME_API CreatureBaseStats
{
- uint32 BaseMana;
- uint32 AttackPower;
- uint32 RangedAttackPower;
+ std::array<uint32, CURRENT_EXPANSION + 1> BaseHealth;
+ uint32 BaseMana = 0;
+ uint32 BaseArmor = 0;
+ uint32 AttackPower = 0;
+ uint32 RangedAttackPower = 0;
+ std::array<float, CURRENT_EXPANSION + 1> BaseDamage;
// Helpers
+
+ uint32 GenerateHealth(CreatureDifficulty const* difficulty) const { return uint32(ceil(BaseHealth[difficulty->GetHealthScalingExpansion()] * difficulty->HealthModifier)); }
+
+ uint32 GenerateMana(CreatureDifficulty const* difficulty) const
+ {
+ // Mana can be 0.
+ if (!BaseMana)
+ return 0;
+
+ return uint32(ceil(BaseMana * difficulty->ManaModifier));
+ }
+
+ uint32 GenerateArmor(CreatureDifficulty const* difficulty) const { return uint32(ceil(BaseArmor * difficulty->ArmorModifier)); }
+
+ float GenerateBaseDamage(CreatureDifficulty const* difficulty) const { return BaseDamage[difficulty->GetHealthScalingExpansion()]; }
+
static CreatureBaseStats const* GetBaseStats(uint8 level, uint8 unitClass);
};
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 067b2f6b74f..490cab96296 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -905,15 +905,17 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
{
// remove elite bonuses included in DB values
CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(petlevel, cinfo->unit_class);
- ApplyLevelScaling();
+ float healthmod = _GetHealthMod(cinfo->rank);
+ uint32 basehp = stats->GenerateHealth(m_creatureDifficulty);
+ uint32 health = uint32(basehp * healthmod);
+ uint32 mana = stats->GenerateMana(m_creatureDifficulty);
- CreatureDifficulty const* creatureDifficulty = GetCreatureDifficulty();
- SetCreateHealth(std::max(sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureHealth, petlevel, creatureDifficulty->GetHealthScalingExpansion(), m_unitData->ContentTuningID, Classes(cinfo->unit_class), 0) * creatureDifficulty->HealthModifier * _GetHealthMod(cinfo->rank), 1.0f));
SetCreateMana(stats->BaseMana);
SetCreateStat(STAT_STRENGTH, 22);
SetCreateStat(STAT_AGILITY, 22);
SetCreateStat(STAT_STAMINA, 25);
SetCreateStat(STAT_INTELLECT, 28);
+ SetCreateStat(STAT_SPIRIT, 27);
}
// Power
@@ -1068,7 +1070,8 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
* should be copied here (or moved to another method or if that function should be called here
* or not just for this default case)
*/
- float basedamage = GetBaseDamageForLevel(petlevel);
+ CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(petlevel, cinfo->unit_class);
+ float basedamage = stats->GenerateBaseDamage(m_creatureDifficulty);
float weaponBaseMinDamage = basedamage;
float weaponBaseMaxDamage = basedamage * 1.5f;
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 6820e1a60f3..bfae9397b9a 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -921,13 +921,13 @@ void ObjectMgr::LoadCreatureTemplateDifficulty()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3 4 5
- QueryResult result = WorldDatabase.Query("SELECT Entry, DifficultyID, LevelScalingDeltaMin, LevelScalingDeltaMax, ContentTuningID, HealthScalingExpansion, "
- // 6 7 8 9 10 11 12
+ // 0 1 2 3 4
+ QueryResult result = WorldDatabase.Query("SELECT Entry, DifficultyID, MinLevel, MaxLevel, HealthScalingExpansion, "
+ // 5 6 7 8 9 10 11
"HealthModifier, ManaModifier, ArmorModifier, DamageModifier, CreatureDifficultyID, TypeFlags, TypeFlags2, "
- // 13 14 15 16 17
+ // 12 13 14 15 16
"LootID, PickPocketLootID, SkinLootID, GoldMin, GoldMax,"
- // 18 19 20 21 22 23 24 25
+ // 17 18 19 20 21 22 23 24
"StaticFlags1, StaticFlags2, StaticFlags3, StaticFlags4, StaticFlags5, StaticFlags6, StaticFlags7, StaticFlags8 "
"FROM creature_template_difficulty ORDER BY Entry");
@@ -953,29 +953,50 @@ void ObjectMgr::LoadCreatureTemplateDifficulty()
}
CreatureDifficulty creatureDifficulty;
- creatureDifficulty.DeltaLevelMin = fields[2].GetInt16();
- creatureDifficulty.DeltaLevelMax = fields[3].GetInt16();
- creatureDifficulty.ContentTuningID = fields[4].GetInt32();
- creatureDifficulty.HealthScalingExpansion = fields[5].GetInt32();
- creatureDifficulty.HealthModifier = fields[6].GetFloat();
- creatureDifficulty.ManaModifier = fields[7].GetFloat();
- creatureDifficulty.ArmorModifier = fields[8].GetFloat();
- creatureDifficulty.DamageModifier = fields[9].GetFloat();
- creatureDifficulty.CreatureDifficultyID = fields[10].GetInt32();
- creatureDifficulty.TypeFlags = fields[11].GetUInt32();
- creatureDifficulty.TypeFlags2 = fields[12].GetUInt32();
- creatureDifficulty.LootID = fields[13].GetUInt32();
- creatureDifficulty.PickPocketLootID = fields[14].GetUInt32();
- creatureDifficulty.SkinLootID = fields[15].GetUInt32();
- creatureDifficulty.GoldMin = fields[16].GetUInt32();
- creatureDifficulty.GoldMax = fields[17].GetUInt32();
- creatureDifficulty.StaticFlags = CreatureStaticFlagsHolder(CreatureStaticFlags(fields[18].GetUInt32()), CreatureStaticFlags2(fields[19].GetUInt32()),
- CreatureStaticFlags3(fields[20].GetUInt32()), CreatureStaticFlags4(fields[21].GetUInt32()), CreatureStaticFlags5(fields[22].GetUInt32()),
- CreatureStaticFlags6(fields[23].GetUInt32()), CreatureStaticFlags7(fields[24].GetUInt32()), CreatureStaticFlags8(fields[25].GetUInt32()));
+ creatureDifficulty.MinLevel = fields[2].GetUInt8();
+ creatureDifficulty.MaxLevel = fields[3].GetUInt8();
+ creatureDifficulty.HealthScalingExpansion = fields[4].GetInt32();
+ creatureDifficulty.HealthModifier = fields[5].GetFloat();
+ creatureDifficulty.ManaModifier = fields[6].GetFloat();
+ creatureDifficulty.ArmorModifier = fields[7].GetFloat();
+ creatureDifficulty.DamageModifier = fields[8].GetFloat();
+ creatureDifficulty.CreatureDifficultyID = fields[9].GetInt32();
+ creatureDifficulty.TypeFlags = fields[10].GetUInt32();
+ creatureDifficulty.TypeFlags2 = fields[11].GetUInt32();
+ creatureDifficulty.LootID = fields[12].GetUInt32();
+ creatureDifficulty.PickPocketLootID = fields[13].GetUInt32();
+ creatureDifficulty.SkinLootID = fields[14].GetUInt32();
+ creatureDifficulty.GoldMin = fields[15].GetUInt32();
+ creatureDifficulty.GoldMax = fields[16].GetUInt32();
+ creatureDifficulty.StaticFlags = CreatureStaticFlagsHolder(CreatureStaticFlags(fields[17].GetUInt32()), CreatureStaticFlags2(fields[18].GetUInt32()),
+ CreatureStaticFlags3(fields[19].GetUInt32()), CreatureStaticFlags4(fields[20].GetUInt32()), CreatureStaticFlags5(fields[21].GetUInt32()),
+ CreatureStaticFlags6(fields[22].GetUInt32()), CreatureStaticFlags7(fields[23].GetUInt32()), CreatureStaticFlags8(fields[24].GetUInt32()));
// TODO: Check if this still applies
creatureDifficulty.DamageModifier *= Creature::_GetDamageMod(itr->second.rank);
+ if (creatureDifficulty.MinLevel == 0 || creatureDifficulty.MaxLevel == 0)
+ {
+ if (creatureDifficulty.MinLevel == 0)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `creature_template_difficulty` lists creature (ID: {}) has MinLevel set to 0 but the allowed minimum is 1. Ignored and set to 1.", entry);
+ creatureDifficulty.MinLevel = 1;
+ }
+
+ if (creatureDifficulty.MaxLevel == 0)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `creature_template_difficulty` lists creature (ID: {}) has MaxLevel set to 0 but the allowed minimum is 1. Ignored and set to 1.", entry);
+ creatureDifficulty.MaxLevel = 1;
+ }
+ }
+
+ if (creatureDifficulty.MinLevel > creatureDifficulty.MaxLevel)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `creature_template_difficulty` lists creature (ID: {}) with a higher MinLevel ({}) than MaxLevel ({}). MaxLevel will be set to MinLevel value.",
+ entry, creatureDifficulty.MinLevel, creatureDifficulty.MaxLevel);
+ creatureDifficulty.MinLevel = creatureDifficulty.MaxLevel;
+ }
+
if (creatureDifficulty.HealthScalingExpansion < EXPANSION_LEVEL_CURRENT || creatureDifficulty.HealthScalingExpansion >= MAX_EXPANSIONS)
{
TC_LOG_ERROR("sql.sql", "Table `creature_template_difficulty` lists creature (ID: {}) with invalid `HealthScalingExpansion` {}. Ignored and set to 0.",
@@ -9957,8 +9978,8 @@ CreatureBaseStats const* ObjectMgr::GetCreatureBaseStats(uint8 level, uint8 unit
void ObjectMgr::LoadCreatureClassLevelStats()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3 4
- QueryResult result = WorldDatabase.Query("SELECT level, class, basemana, attackpower, rangedattackpower FROM creature_classlevelstats");
+
+ QueryResult result = WorldDatabase.Query("SELECT level, class, basehp0, basehp1, basehp2, basemana, basearmor, attackpower, rangedattackpower, damage_base, damage_exp1, damage_exp2 FROM creature_classlevelstats");
if (!result)
{
@@ -9979,10 +10000,29 @@ void ObjectMgr::LoadCreatureClassLevelStats()
CreatureBaseStats stats;
- stats.BaseMana = fields[2].GetUInt32();
+ for (uint8 i = 0; i <= CURRENT_EXPANSION; ++i)
+ {
+ stats.BaseHealth[i] = fields[2 + i].GetUInt16();
+
+ if (stats.BaseHealth[i] == 0)
+ {
+ TC_LOG_ERROR("sql.sql", "Creature base stats for class {}, level {} has invalid zero base HP[{}] - set to 1", Class, Level, i);
+ stats.BaseHealth[i] = 1;
+ }
+
+ stats.BaseDamage[i] = fields[9 + i].GetFloat();
+ if (stats.BaseDamage[i] < 0.0f)
+ {
+ TC_LOG_ERROR("sql.sql", "Creature base stats for class {}, level {} has invalid negative base damage[{}] - set to 0.0", Class, Level, i);
+ stats.BaseDamage[i] = 0.0f;
+ }
+ }
+
+ stats.BaseMana = fields[5].GetUInt16();
+ stats.BaseArmor = fields[6].GetUInt16();
- stats.AttackPower = fields[3].GetUInt16();
- stats.RangedAttackPower = fields[4].GetUInt16();
+ stats.AttackPower = fields[7].GetUInt16();
+ stats.RangedAttackPower = fields[8].GetUInt16();
_creatureBaseStatsStore[MAKE_PAIR16(Level, Class)] = stats;
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 73c902986da..3564b062a61 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -102,7 +102,7 @@ enum Expansions
MAX_ACCOUNT_EXPANSIONS
};
-#define CURRENT_EXPANSION EXPANSION_DRAGONFLIGHT
+#define CURRENT_EXPANSION EXPANSION_WRATH_OF_THE_LICH_KING
constexpr uint32 GetMaxLevelForExpansion(uint32 expansion)
{
@@ -113,7 +113,7 @@ constexpr uint32 GetMaxLevelForExpansion(uint32 expansion)
case EXPANSION_THE_BURNING_CRUSADE:
return 70;
case EXPANSION_WRATH_OF_THE_LICH_KING:
- case EXPANSION_CATACLYSM: // since we do support retail accounts, we will make all newer expansions follow the support max level
+ case EXPANSION_CATACLYSM: // since we do support retail accounts, we will make all newer expansions follow the supported max level
case EXPANSION_MISTS_OF_PANDARIA:
case EXPANSION_WARLORDS_OF_DRAENOR:
case EXPANSION_LEGION:
diff --git a/src/server/game/Server/Packets/CombatLogPacketsCommon.cpp b/src/server/game/Server/Packets/CombatLogPacketsCommon.cpp
index ea221bb43b3..9bf1696e9cc 100644
--- a/src/server/game/Server/Packets/CombatLogPacketsCommon.cpp
+++ b/src/server/game/Server/Packets/CombatLogPacketsCommon.cpp
@@ -78,7 +78,6 @@ bool ContentTuningParams::GenerateDataForUnits<Creature, Player>(Creature* attac
TargetLevel = target->GetLevel();
Expansion = creatureDifficulty->HealthScalingExpansion;
TargetScalingLevelDelta = int8(attacker->m_unitData->ScalingLevelDelta);
- TargetContentTuningID = creatureDifficulty->ContentTuningID;
return true;
}
@@ -96,14 +95,13 @@ bool ContentTuningParams::GenerateDataForUnits<Player, Creature>(Player* attacke
TargetLevel = target->GetLevel();
Expansion = creatureDifficulty->HealthScalingExpansion;
TargetScalingLevelDelta = int8(target->m_unitData->ScalingLevelDelta);
- TargetContentTuningID = creatureDifficulty->ContentTuningID;
return true;
}
template<>
bool ContentTuningParams::GenerateDataForUnits<Creature, Creature>(Creature* attacker, Creature* target)
{
- Creature* accessor = target->HasScalableLevels() ? target : attacker;
+ Creature* accessor = attacker;
CreatureTemplate const* creatureTemplate = accessor->GetCreatureTemplate();
CreatureDifficulty const* creatureDifficulty = creatureTemplate->GetDifficulty(accessor->GetMap()->GetDifficultyID());
@@ -113,7 +111,6 @@ bool ContentTuningParams::GenerateDataForUnits<Creature, Creature>(Creature* att
TargetLevel = target->GetLevel();
Expansion = creatureDifficulty->HealthScalingExpansion;
TargetScalingLevelDelta = int8(accessor->m_unitData->ScalingLevelDelta);
- TargetContentTuningID = creatureDifficulty->ContentTuningID;
return true;
}
@@ -121,28 +118,8 @@ template<>
bool ContentTuningParams::GenerateDataForUnits<Unit, Unit>(Unit* attacker, Unit* target)
{
if (Player* playerAttacker = attacker->ToPlayer())
- {
if (Player* playerTarget = target->ToPlayer())
return GenerateDataForUnits(playerAttacker, playerTarget);
- else if (Creature* creatureTarget = target->ToCreature())
- {
- if (creatureTarget->HasScalableLevels())
- return GenerateDataForUnits(playerAttacker, creatureTarget);
- }
- }
- else if (Creature* creatureAttacker = attacker->ToCreature())
- {
- if (Player* playerTarget = target->ToPlayer())
- {
- if (creatureAttacker->HasScalableLevels())
- return GenerateDataForUnits(creatureAttacker, playerTarget);
- }
- else if (Creature* creatureTarget = target->ToCreature())
- {
- if (creatureAttacker->HasScalableLevels() || creatureTarget->HasScalableLevels())
- return GenerateDataForUnits(creatureAttacker, creatureTarget);
- }
- }
return false;
}