Core/Creatures: Update creature scaling to use content tuning
Port From (https://github.com/TrinityCore/TrinityCore/commit/314a35f0cd912daed7c0663f4f13552b6747fd98)
This commit is contained in:
@@ -1150,17 +1150,17 @@ namespace Game.Entities
|
||||
byte level = (byte)(minlevel == maxlevel ? minlevel : RandomHelper.URand(minlevel, maxlevel));
|
||||
SetLevel(level);
|
||||
|
||||
if (HasScalableLevels())
|
||||
{
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ScalingLevelMin), cInfo.levelScaling.Value.MinLevel);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ScalingLevelMax), cInfo.levelScaling.Value.MaxLevel);
|
||||
CreatureLevelScaling scaling = cInfo.GetLevelScaling(GetMap().GetDifficultyID());
|
||||
|
||||
int mindelta = Math.Min(cInfo.levelScaling.Value.DeltaLevelMax, cInfo.levelScaling.Value.DeltaLevelMin);
|
||||
int maxdelta = Math.Max(cInfo.levelScaling.Value.DeltaLevelMax, cInfo.levelScaling.Value.DeltaLevelMin);
|
||||
int delta = mindelta == maxdelta ? mindelta : RandomHelper.IRand(mindelta, maxdelta);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ScalingLevelMin), scaling.MinLevel);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ScalingLevelMax), scaling.MaxLevel);
|
||||
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ScalingLevelDelta), delta);
|
||||
}
|
||||
int mindelta = Math.Min(scaling.DeltaLevelMax, scaling.DeltaLevelMin);
|
||||
int maxdelta = Math.Max(scaling.DeltaLevelMax, scaling.DeltaLevelMin);
|
||||
int delta = mindelta == maxdelta ? mindelta : RandomHelper.IRand(mindelta, maxdelta);
|
||||
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ScalingLevelDelta), delta);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ContentTuningID), scaling.ContentTuningID);
|
||||
|
||||
UpdateLevelDependantStats();
|
||||
}
|
||||
@@ -1169,12 +1169,13 @@ namespace Game.Entities
|
||||
{
|
||||
CreatureTemplate cInfo = GetCreatureTemplate();
|
||||
CreatureEliteType rank = IsPet() ? 0 : cInfo.Rank;
|
||||
CreatureBaseStats stats = Global.ObjectMgr.GetCreatureBaseStats(GetLevel(), cInfo.UnitClass);
|
||||
uint level = GetLevel();
|
||||
CreatureBaseStats stats = Global.ObjectMgr.GetCreatureBaseStats(level, cInfo.UnitClass);
|
||||
|
||||
// health
|
||||
float healthmod = _GetHealthMod(rank);
|
||||
|
||||
uint basehp = stats.GenerateHealth(cInfo);
|
||||
uint basehp = (uint)GetMaxHealthByLevel(level);
|
||||
uint health = (uint)(basehp * healthmod);
|
||||
|
||||
SetCreateHealth(health);
|
||||
@@ -1200,7 +1201,7 @@ namespace Game.Entities
|
||||
SetStatFlatModifier(UnitMods.Health, UnitModifierFlatType.Base, health);
|
||||
|
||||
//Damage
|
||||
float basedamage = stats.GenerateBaseDamage(cInfo);
|
||||
float basedamage = GetBaseDamageForLevel(level);
|
||||
float weaponBaseMinDamage = basedamage;
|
||||
float weaponBaseMaxDamage = basedamage * 1.5f;
|
||||
|
||||
@@ -1216,7 +1217,7 @@ namespace Game.Entities
|
||||
SetStatFlatModifier(UnitMods.AttackPower, UnitModifierFlatType.Base, stats.AttackPower);
|
||||
SetStatFlatModifier(UnitMods.AttackPowerRanged, UnitModifierFlatType.Base, stats.RangedAttackPower);
|
||||
|
||||
float armor = stats.GenerateArmor(cInfo); // @todo Why is this treated as uint32 when it's a float?
|
||||
float armor = GetBaseArmorForLevel(level); /// @todo Why is this treated as uint32 when it's a float?
|
||||
SetStatFlatModifier(UnitMods.Armor, UnitModifierFlatType.Base, armor);
|
||||
}
|
||||
|
||||
@@ -2352,14 +2353,17 @@ namespace Game.Entities
|
||||
public bool HasScalableLevels()
|
||||
{
|
||||
CreatureTemplate cinfo = GetCreatureTemplate();
|
||||
return cinfo.levelScaling.HasValue;
|
||||
CreatureLevelScaling scaling = cinfo.GetLevelScaling(GetMap().GetDifficultyID());
|
||||
|
||||
return (scaling.MinLevel != 0 && scaling.MaxLevel != 0);
|
||||
}
|
||||
|
||||
ulong GetMaxHealthByLevel(uint level)
|
||||
{
|
||||
CreatureTemplate cInfo = GetCreatureTemplate();
|
||||
CreatureBaseStats stats = Global.ObjectMgr.GetCreatureBaseStats(level, cInfo.UnitClass);
|
||||
return stats.GenerateHealth(cInfo);
|
||||
CreatureLevelScaling scaling = cInfo.GetLevelScaling(GetMap().GetDifficultyID());
|
||||
float baseHealth = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureHealth, level, cInfo.HealthScalingExpansion, scaling.ContentTuningID, (Class)cInfo.UnitClass);
|
||||
return (ulong)(baseHealth * cInfo.ModHealth * cInfo.ModHealthExtra);
|
||||
}
|
||||
|
||||
public override float GetHealthMultiplierForTarget(WorldObject target)
|
||||
@@ -2377,8 +2381,8 @@ namespace Game.Entities
|
||||
float GetBaseDamageForLevel(uint level)
|
||||
{
|
||||
CreatureTemplate cInfo = GetCreatureTemplate();
|
||||
CreatureBaseStats stats = Global.ObjectMgr.GetCreatureBaseStats(level, cInfo.UnitClass);
|
||||
return stats.GenerateBaseDamage(cInfo);
|
||||
CreatureLevelScaling scaling = cInfo.GetLevelScaling(GetMap().GetDifficultyID());
|
||||
return Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureAutoAttackDps, level, cInfo.HealthScalingExpansion, scaling.ContentTuningID, (Class)cInfo.UnitClass);
|
||||
}
|
||||
|
||||
public override float GetDamageMultiplierForTarget(WorldObject target)
|
||||
@@ -2394,8 +2398,9 @@ namespace Game.Entities
|
||||
float GetBaseArmorForLevel(uint level)
|
||||
{
|
||||
CreatureTemplate cInfo = GetCreatureTemplate();
|
||||
CreatureBaseStats stats = Global.ObjectMgr.GetCreatureBaseStats(level, cInfo.UnitClass);
|
||||
return stats.GenerateArmor(cInfo);
|
||||
CreatureLevelScaling scaling = cInfo.GetLevelScaling(GetMap().GetDifficultyID());
|
||||
float baseArmor = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureArmor, level, cInfo.HealthScalingExpansion, scaling.ContentTuningID, (Class)cInfo.UnitClass);
|
||||
return baseArmor * cInfo.ModArmor;
|
||||
}
|
||||
|
||||
public override float GetArmorMultiplierForTarget(WorldObject target)
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Game.Entities
|
||||
public string IconName;
|
||||
public uint GossipMenuId;
|
||||
public short Minlevel;
|
||||
public Optional<CreatureLevelScaling> levelScaling;
|
||||
public Dictionary<Difficulty, CreatureLevelScaling> scalingStorage = new Dictionary<Difficulty, CreatureLevelScaling>();
|
||||
public short Maxlevel;
|
||||
public int HealthScalingExpansion;
|
||||
public uint RequiredExpansion;
|
||||
@@ -265,23 +265,24 @@ namespace Game.Entities
|
||||
|
||||
QueryData.Stats = stats;
|
||||
}
|
||||
|
||||
public CreatureLevelScaling GetLevelScaling(Difficulty difficulty)
|
||||
{
|
||||
var creatureLevelScaling = scalingStorage.LookupByKey(difficulty);
|
||||
if (creatureLevelScaling != null)
|
||||
return creatureLevelScaling;
|
||||
|
||||
return new CreatureLevelScaling();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreatureBaseStats
|
||||
{
|
||||
public uint[] BaseHealth = new uint[(int)Expansion.Max];
|
||||
public uint BaseMana;
|
||||
public uint BaseArmor;
|
||||
public uint AttackPower;
|
||||
public uint RangedAttackPower;
|
||||
public float[] BaseDamage = new float[(int)Expansion.Max];
|
||||
|
||||
// Helpers
|
||||
public uint GenerateHealth(CreatureTemplate info)
|
||||
{
|
||||
return (uint)Math.Ceiling(BaseHealth[info.HealthScalingExpansion] * info.ModHealth * info.ModHealthExtra);
|
||||
}
|
||||
|
||||
public uint GenerateMana(CreatureTemplate info)
|
||||
{
|
||||
// Mana can be 0.
|
||||
@@ -290,16 +291,6 @@ namespace Game.Entities
|
||||
|
||||
return (uint)Math.Ceiling(BaseMana * info.ModMana * info.ModManaExtra);
|
||||
}
|
||||
|
||||
public float GenerateArmor(CreatureTemplate info)
|
||||
{
|
||||
return (float)Math.Ceiling(BaseArmor * info.ModArmor);
|
||||
}
|
||||
|
||||
public float GenerateBaseDamage(CreatureTemplate info)
|
||||
{
|
||||
return BaseDamage[info.HealthScalingExpansion];
|
||||
}
|
||||
}
|
||||
|
||||
public class CreatureLocale
|
||||
@@ -459,11 +450,12 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public struct CreatureLevelScaling
|
||||
public class CreatureLevelScaling
|
||||
{
|
||||
public ushort MinLevel;
|
||||
public ushort MaxLevel;
|
||||
public short DeltaLevelMin;
|
||||
public short DeltaLevelMax;
|
||||
public uint ContentTuningID;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1037,7 +1037,7 @@ namespace Game.Entities
|
||||
public UpdateField<ulong> MaxHealth = new UpdateField<ulong>(0, 30);
|
||||
public UpdateField<uint> Level = new UpdateField<uint>(0, 31);
|
||||
public UpdateField<int> EffectiveLevel = new UpdateField<int>(32, 33);
|
||||
public UpdateField<int> ContentTuningID = new UpdateField<int>(32, 34);
|
||||
public UpdateField<uint> ContentTuningID = new UpdateField<uint>(32, 34);
|
||||
public UpdateField<int> ScalingLevelMin = new UpdateField<int>(32, 35);
|
||||
public UpdateField<int> ScalingLevelMax = new UpdateField<int>(32, 36);
|
||||
public UpdateField<int> ScalingLevelDelta = new UpdateField<int>(32, 37);
|
||||
@@ -1186,7 +1186,7 @@ namespace Game.Entities
|
||||
data.WriteUInt64(MaxHealth);
|
||||
data.WriteUInt32(Level);
|
||||
data.WriteInt32(EffectiveLevel);
|
||||
data.WriteInt32(ContentTuningID);
|
||||
data.WriteUInt32(ContentTuningID);
|
||||
data.WriteInt32(ScalingLevelMin);
|
||||
data.WriteInt32(ScalingLevelMax);
|
||||
data.WriteInt32(ScalingLevelDelta);
|
||||
@@ -1541,7 +1541,7 @@ namespace Game.Entities
|
||||
}
|
||||
if (changesMask[34])
|
||||
{
|
||||
data.WriteInt32(ContentTuningID);
|
||||
data.WriteUInt32(ContentTuningID);
|
||||
}
|
||||
if (changesMask[35])
|
||||
{
|
||||
|
||||
@@ -487,7 +487,10 @@ namespace Game.Entities
|
||||
{
|
||||
// remove elite bonuses included in DB values
|
||||
CreatureBaseStats stats = Global.ObjectMgr.GetCreatureBaseStats(petlevel, cinfo.UnitClass);
|
||||
SetCreateHealth(stats.BaseHealth[cinfo.HealthScalingExpansion]);
|
||||
CreatureLevelScaling scaling = cinfo.GetLevelScaling(GetMap().GetDifficultyID());
|
||||
|
||||
SetCreateHealth((uint)(Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureHealth, petlevel, cinfo.HealthScalingExpansion, scaling.ContentTuningID, (Class)cinfo.UnitClass) * cinfo.ModHealth * cinfo.ModHealthExtra));
|
||||
|
||||
SetCreateMana(stats.BaseMana);
|
||||
|
||||
SetCreateStat(Stats.Strength, 22);
|
||||
|
||||
@@ -2760,14 +2760,13 @@ namespace Game.Entities
|
||||
return damage;
|
||||
|
||||
uint attackerLevel = attacker.GetLevelForTarget(victim);
|
||||
if (attackerLevel > CliDB.ArmorMitigationByLvlGameTable.GetTableRowCount())
|
||||
attackerLevel = (uint)CliDB.ArmorMitigationByLvlGameTable.GetTableRowCount();
|
||||
// Expansion and ContentTuningID necessary? Does Player get a ContentTuningID too ?
|
||||
float armorConstant = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.ArmorConstant, attackerLevel, -2, 0, attacker.GetClass());
|
||||
|
||||
GtArmorMitigationByLvlRecord ambl = CliDB.ArmorMitigationByLvlGameTable.GetRow(attackerLevel);
|
||||
if (ambl == null)
|
||||
if (armorConstant == 0)
|
||||
return damage;
|
||||
|
||||
float mitigation = Math.Min(armor / (armor + ambl.Mitigation), 0.85f);
|
||||
float mitigation = Math.Min(armor / (armor + armorConstant), 0.85f);
|
||||
return Math.Max((uint)(damage * (1.0f - mitigation)), 1);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user