From c1dbec58bdd01d0b3f2170e7ee4512b1ac53da26 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Wed, 20 May 2020 15:27:22 -0400 Subject: [PATCH] Core/Creatures: Update creature scaling to use content tuning Port From (https://github.com/TrinityCore/TrinityCore/commit/314a35f0cd912daed7c0663f4f13552b6747fd98) --- Source/Game/DataStorage/CliDB.cs | 20 -------- .../DataStorage/Structs/GameTablesRecords.cs | 37 -------------- Source/Game/Entities/Creature/Creature.cs | 45 +++++++++-------- Source/Game/Entities/Creature/CreatureData.cs | 32 +++++------- .../Entities/Object/Update/UpdateFields.cs | 6 +-- Source/Game/Entities/TemporarySummon.cs | 5 +- Source/Game/Entities/Unit/Unit.Combat.cs | 9 ++-- Source/Game/Globals/ObjectManager.cs | 50 +++++++------------ Source/Game/Network/Packets/SpellPackets.cs | 21 ++++---- .../world/master/2020_05_02_01_world.sql | 7 +++ 10 files changed, 85 insertions(+), 147 deletions(-) create mode 100644 sql/updates/world/master/2020_05_02_01_world.sql diff --git a/Source/Game/DataStorage/CliDB.cs b/Source/Game/DataStorage/CliDB.cs index ccee770ad..66f2f20f2 100644 --- a/Source/Game/DataStorage/CliDB.cs +++ b/Source/Game/DataStorage/CliDB.cs @@ -359,7 +359,6 @@ namespace Game.DataStorage DataPath = dataPath + "/gt/"; - ArmorMitigationByLvlGameTable = GameTableReader.Read("ArmorMitigationByLvl.txt"); ArtifactKnowledgeMultiplierGameTable = GameTableReader.Read("ArtifactKnowledgeMultiplier.txt"); ArtifactLevelXPGameTable = GameTableReader.Read("artifactLevelXP.txt"); BarberShopCostBaseGameTable = GameTableReader.Read("BarberShopCostBase.txt"); @@ -368,23 +367,7 @@ namespace Game.DataStorage CombatRatingsMultByILvlGameTable = GameTableReader.Read("CombatRatingsMultByILvl.txt"); ItemSocketCostPerLevelGameTable = GameTableReader.Read("ItemSocketCostPerLevel.txt"); HpPerStaGameTable = GameTableReader.Read("HpPerSta.txt"); - NpcDamageByClassGameTable[0] = GameTableReader.Read("NpcDamageByClass.txt"); - NpcDamageByClassGameTable[1] = GameTableReader.Read("NpcDamageByClassExp1.txt"); - NpcDamageByClassGameTable[2] = GameTableReader.Read("NpcDamageByClassExp2.txt"); - NpcDamageByClassGameTable[3] = GameTableReader.Read("NpcDamageByClassExp3.txt"); - NpcDamageByClassGameTable[4] = GameTableReader.Read("NpcDamageByClassExp4.txt"); - NpcDamageByClassGameTable[5] = GameTableReader.Read("NpcDamageByClassExp5.txt"); - NpcDamageByClassGameTable[6] = GameTableReader.Read("NpcDamageByClassExp6.txt"); - NpcDamageByClassGameTable[7] = GameTableReader.Read("NpcDamageByClassExp7.txt"); NpcManaCostScalerGameTable = GameTableReader.Read("NPCManaCostScaler.txt"); - NpcTotalHpGameTable[0] = GameTableReader.Read("NpcTotalHp.txt"); - NpcTotalHpGameTable[1] = GameTableReader.Read("NpcTotalHpExp1.txt"); - NpcTotalHpGameTable[2] = GameTableReader.Read("NpcTotalHpExp2.txt"); - NpcTotalHpGameTable[3] = GameTableReader.Read("NpcTotalHpExp3.txt"); - NpcTotalHpGameTable[4] = GameTableReader.Read("NpcTotalHpExp4.txt"); - NpcTotalHpGameTable[5] = GameTableReader.Read("NpcTotalHpExp5.txt"); - NpcTotalHpGameTable[6] = GameTableReader.Read("NpcTotalHpExp6.txt"); - NpcTotalHpGameTable[7] = GameTableReader.Read("NpcTotalHpExp7.txt"); SpellScalingGameTable = GameTableReader.Read("SpellScaling.txt"); StaminaMultByILvlGameTable = GameTableReader.Read("StaminaMultByILvl.txt"); XpGameTable = GameTableReader.Read("xp.txt"); @@ -648,7 +631,6 @@ namespace Game.DataStorage #endregion #region GameTables - public static GameTable ArmorMitigationByLvlGameTable; public static GameTable ArtifactKnowledgeMultiplierGameTable; public static GameTable ArtifactLevelXPGameTable; public static GameTable BarberShopCostBaseGameTable; @@ -657,9 +639,7 @@ namespace Game.DataStorage public static GameTable CombatRatingsMultByILvlGameTable; public static GameTable HpPerStaGameTable; public static GameTable ItemSocketCostPerLevelGameTable; - public static GameTable[] NpcDamageByClassGameTable = new GameTable[(int)Expansion.Max]; public static GameTable NpcManaCostScalerGameTable; - public static GameTable[] NpcTotalHpGameTable = new GameTable[(int)Expansion.Max]; public static GameTable SpellScalingGameTable; public static GameTable StaminaMultByILvlGameTable; public static GameTable XpGameTable; diff --git a/Source/Game/DataStorage/Structs/GameTablesRecords.cs b/Source/Game/DataStorage/Structs/GameTablesRecords.cs index 785eac0b8..deada762e 100644 --- a/Source/Game/DataStorage/Structs/GameTablesRecords.cs +++ b/Source/Game/DataStorage/Structs/GameTablesRecords.cs @@ -17,11 +17,6 @@ namespace Game.DataStorage { - public sealed class GtArmorMitigationByLvlRecord - { - public float Mitigation; - } - public sealed class GtArtifactKnowledgeMultiplierRecord { public float Multiplier; @@ -108,43 +103,11 @@ namespace Game.DataStorage public float SocketCost; } - public sealed class GtNpcDamageByClassRecord - { - public float Rogue; - public float Druid; - public float Hunter; - public float Mage; - public float Paladin; - public float Priest; - public float Shaman; - public float Warlock; - public float Warrior; - public float DeathKnight; - public float Monk; - public float DemonHunter; - } - public sealed class GtNpcManaCostScalerRecord { public float Scaler; } - public sealed class GtNpcTotalHpRecord - { - public float Rogue; - public float Druid; - public float Hunter; - public float Mage; - public float Paladin; - public float Priest; - public float Shaman; - public float Warlock; - public float Warrior; - public float DeathKnight; - public float Monk; - public float DemonHunter; - } - public sealed class GtSpellScalingRecord { public float Rogue; diff --git a/Source/Game/Entities/Creature/Creature.cs b/Source/Game/Entities/Creature/Creature.cs index 6497b2232..ce3251db8 100644 --- a/Source/Game/Entities/Creature/Creature.cs +++ b/Source/Game/Entities/Creature/Creature.cs @@ -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) diff --git a/Source/Game/Entities/Creature/CreatureData.cs b/Source/Game/Entities/Creature/CreatureData.cs index 416befbf6..3a3f5efaf 100644 --- a/Source/Game/Entities/Creature/CreatureData.cs +++ b/Source/Game/Entities/Creature/CreatureData.cs @@ -37,7 +37,7 @@ namespace Game.Entities public string IconName; public uint GossipMenuId; public short Minlevel; - public Optional levelScaling; + public Dictionary scalingStorage = new Dictionary(); 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; } } diff --git a/Source/Game/Entities/Object/Update/UpdateFields.cs b/Source/Game/Entities/Object/Update/UpdateFields.cs index e7a8922a3..154956613 100644 --- a/Source/Game/Entities/Object/Update/UpdateFields.cs +++ b/Source/Game/Entities/Object/Update/UpdateFields.cs @@ -1037,7 +1037,7 @@ namespace Game.Entities public UpdateField MaxHealth = new UpdateField(0, 30); public UpdateField Level = new UpdateField(0, 31); public UpdateField EffectiveLevel = new UpdateField(32, 33); - public UpdateField ContentTuningID = new UpdateField(32, 34); + public UpdateField ContentTuningID = new UpdateField(32, 34); public UpdateField ScalingLevelMin = new UpdateField(32, 35); public UpdateField ScalingLevelMax = new UpdateField(32, 36); public UpdateField ScalingLevelDelta = new UpdateField(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]) { diff --git a/Source/Game/Entities/TemporarySummon.cs b/Source/Game/Entities/TemporarySummon.cs index a01b50e79..783b08378 100644 --- a/Source/Game/Entities/TemporarySummon.cs +++ b/Source/Game/Entities/TemporarySummon.cs @@ -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); diff --git a/Source/Game/Entities/Unit/Unit.Combat.cs b/Source/Game/Entities/Unit/Unit.Combat.cs index 03f67cfa1..cde0314c7 100644 --- a/Source/Game/Entities/Unit/Unit.Combat.cs +++ b/Source/Game/Entities/Unit/Unit.Combat.cs @@ -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); } diff --git a/Source/Game/Globals/ObjectManager.cs b/Source/Game/Globals/ObjectManager.cs index e045a7081..9282202f9 100644 --- a/Source/Game/Globals/ObjectManager.cs +++ b/Source/Game/Globals/ObjectManager.cs @@ -2295,9 +2295,9 @@ namespace Game var time = Time.GetMSTime(); creatureBaseStatsStorage.Clear(); - // 0 1 2 3 4 5 - SQLResult result = DB.World.Query("SELECT level, class, basemana, basearmor, attackpower, rangedattackpower FROM creature_classlevelstats"); + // 0 1 2 3 4 + SQLResult result = DB.World.Query("SELECT level, class, basemana, attackpower, rangedattackpower FROM creature_classlevelstats"); if (result.IsEmpty()) { Log.outError(LogFilter.ServerLoading, "Loaded 0 creature base stats. DB table `creature_classlevelstats` is empty."); @@ -2315,22 +2315,9 @@ namespace Game CreatureBaseStats stats = new CreatureBaseStats(); - for (var i = 0; i < (int)Expansion.Max; ++i) - { - stats.BaseHealth[i] = (uint)CliDB.GetGameTableColumnForClass(CliDB.NpcTotalHpGameTable[i].GetRow(Level), (Class)_class); - stats.BaseDamage[i] = CliDB.GetGameTableColumnForClass(CliDB.NpcDamageByClassGameTable[i].GetRow(Level), (Class)_class); - if (stats.BaseDamage[i] < 0.0f) - { - Log.outError(LogFilter.Sql, "Creature base stats for class {0}, level {1} has invalid negative base damage[{2}] - set to 0.0", _class, Level, i); - stats.BaseDamage[i] = 0.0f; - } - } - stats.BaseMana = result.Read(2); - stats.BaseArmor = result.Read(3); - - stats.AttackPower = result.Read(4); - stats.RangedAttackPower = result.Read(5); + stats.AttackPower = result.Read(3); + stats.RangedAttackPower = result.Read(4); creatureBaseStatsStorage.Add(MathFunctions.MakePair16(Level, _class), stats); @@ -2417,8 +2404,8 @@ namespace Game { uint oldMSTime = Time.GetMSTime(); - // 0 1 2 3 4 - SQLResult result = DB.World.Query("SELECT Entry, LevelScalingMin, LevelScalingMax, LevelScalingDeltaMin, LevelScalingDeltaMax FROM creature_template_scaling"); + // 0 1 2 3 4 5 6 + SQLResult result = DB.World.Query("SELECT Entry, DifficultyID, LevelScalingMin, LevelScalingMax, LevelScalingDeltaMin, LevelScalingDeltaMax, ContentTuningID FROM creature_template_scaling ORDER BY Entry"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 creature template scaling definitions. DB table `creature_template_scaling` is empty."); @@ -2429,6 +2416,7 @@ namespace Game do { uint entry = result.Read(0); + Difficulty difficulty = (Difficulty)result.Read(1); var template = _creatureTemplateStorage.LookupByKey(entry); if (template == null) @@ -2437,12 +2425,14 @@ namespace Game continue; } - CreatureLevelScaling creatureLevelScaling; - creatureLevelScaling.MinLevel = result.Read(1); - creatureLevelScaling.MaxLevel = result.Read(2); - creatureLevelScaling.DeltaLevelMin = result.Read(3); - creatureLevelScaling.DeltaLevelMax = result.Read(3); - template.levelScaling.Set(creatureLevelScaling); + CreatureLevelScaling creatureLevelScaling = new CreatureLevelScaling(); + creatureLevelScaling.MinLevel = result.Read(2); + creatureLevelScaling.MaxLevel = result.Read(3); + creatureLevelScaling.DeltaLevelMin = result.Read(4); + creatureLevelScaling.DeltaLevelMax = result.Read(5); + creatureLevelScaling.ContentTuningID = result.Read(6); + + template.scalingStorage[difficulty] = creatureLevelScaling; ++count; } while (result.NextRow()); @@ -3505,6 +3495,8 @@ namespace Game if (!map) return 0; + CreatureLevelScaling scaling = cInfo.GetLevelScaling(map.GetDifficultyID()); + ulong guid = GenerateCreatureSpawnId(); CreatureData data = NewOrExistCreatureData(guid); data.id = entry; @@ -3518,7 +3510,7 @@ namespace Game data.spawntimesecs = spawntimedelay; data.spawndist = 0; data.currentwaypoint = 0; - data.curhealth = stats.GenerateHealth(cInfo); + data.curhealth = (uint)(Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureHealth, level, cInfo.HealthScalingExpansion, scaling.ContentTuningID, (Class)cInfo.UnitClass) * cInfo.ModHealth * cInfo.ModHealthExtra); data.curmana = stats.GenerateMana(cInfo); data.movementType = (byte)cInfo.MovementType; data.spawnDifficulties.Add(Difficulty.None); @@ -10710,12 +10702,6 @@ namespace Game { public DefaultCreatureBaseStats() { - BaseArmor = 1; - for (byte j = 0; j < 4; ++j) - { - BaseHealth[j] = 1; - BaseDamage[j] = 0.0f; - } BaseMana = 0; AttackPower = 0; RangedAttackPower = 0; diff --git a/Source/Game/Network/Packets/SpellPackets.cs b/Source/Game/Network/Packets/SpellPackets.cs index 4955cee21..99c5aec04 100644 --- a/Source/Game/Network/Packets/SpellPackets.cs +++ b/Source/Game/Network/Packets/SpellPackets.cs @@ -1198,15 +1198,16 @@ namespace Game.Network.Packets bool GenerateDataCreatureToPlayer(Creature attacker, Player target) { CreatureTemplate creatureTemplate = attacker.GetCreatureTemplate(); + CreatureLevelScaling creatureScaling = creatureTemplate.GetLevelScaling(attacker.GetMap().GetDifficultyID()); TuningType = ContentTuningType.CreatureToPlayerDamage; PlayerLevelDelta = (short)target.m_activePlayerData.ScalingPlayerLevelDelta; PlayerItemLevel = (ushort)target.GetAverageItemLevel(); ScalingHealthItemLevelCurveID = (ushort)target.m_unitData.ScalingHealthItemLevelCurveID; TargetLevel = (byte)target.GetLevel(); - Expansion = (byte)creatureTemplate.RequiredExpansion; - TargetMinScalingLevel = (byte)creatureTemplate.levelScaling.Value.MinLevel; - TargetMaxScalingLevel = (byte)creatureTemplate.levelScaling.Value.MaxLevel; + Expansion = (byte)creatureTemplate.HealthScalingExpansion; + TargetMinScalingLevel = (byte)creatureScaling.MinLevel; + TargetMaxScalingLevel = (byte)creatureScaling.MaxLevel; TargetScalingLevelDelta = (sbyte)attacker.m_unitData.ScalingLevelDelta; return true; } @@ -1214,15 +1215,16 @@ namespace Game.Network.Packets bool GenerateDataPlayerToCreature(Player attacker, Creature target) { CreatureTemplate creatureTemplate = target.GetCreatureTemplate(); + CreatureLevelScaling creatureScaling = creatureTemplate.GetLevelScaling(target.GetMap().GetDifficultyID()); TuningType = ContentTuningType.PlayerToCreatureDamage; PlayerLevelDelta = (short)attacker.m_activePlayerData.ScalingPlayerLevelDelta; PlayerItemLevel = (ushort)attacker.GetAverageItemLevel(); ScalingHealthItemLevelCurveID = (ushort)target.m_unitData.ScalingHealthItemLevelCurveID; TargetLevel = (byte)target.GetLevel(); - Expansion = (byte)creatureTemplate.RequiredExpansion; - TargetMinScalingLevel = (byte)creatureTemplate.levelScaling.Value.MinLevel; - TargetMaxScalingLevel = (byte)creatureTemplate.levelScaling.Value.MaxLevel; + Expansion = (byte)creatureTemplate.HealthScalingExpansion; + TargetMinScalingLevel = (byte)creatureScaling.MinLevel; + TargetMaxScalingLevel = (byte)creatureScaling.MaxLevel; TargetScalingLevelDelta = (sbyte)target.m_unitData.ScalingLevelDelta; return true; } @@ -1231,14 +1233,15 @@ namespace Game.Network.Packets { Creature accessor = target.HasScalableLevels() ? target : attacker; CreatureTemplate creatureTemplate = accessor.GetCreatureTemplate(); + CreatureLevelScaling creatureScaling = creatureTemplate.GetLevelScaling(accessor.GetMap().GetDifficultyID()); TuningType = ContentTuningType.CreatureToCreatureDamage; PlayerLevelDelta = 0; PlayerItemLevel = 0; TargetLevel = (byte)target.GetLevel(); - Expansion = (byte)creatureTemplate.RequiredExpansion; - TargetMinScalingLevel = (byte)creatureTemplate.levelScaling.Value.MinLevel; - TargetMaxScalingLevel = (byte)creatureTemplate.levelScaling.Value.MaxLevel; + Expansion = (byte)creatureTemplate.HealthScalingExpansion; + TargetMinScalingLevel = (byte)creatureScaling.MinLevel; + TargetMaxScalingLevel = (byte)creatureScaling.MaxLevel; TargetScalingLevelDelta = (sbyte)accessor.m_unitData.ScalingLevelDelta; return true; } diff --git a/sql/updates/world/master/2020_05_02_01_world.sql b/sql/updates/world/master/2020_05_02_01_world.sql new file mode 100644 index 000000000..ba0f927c7 --- /dev/null +++ b/sql/updates/world/master/2020_05_02_01_world.sql @@ -0,0 +1,7 @@ +ALTER TABLE `creature_template_scaling` + ADD COLUMN `DifficultyID` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `Entry`, + ADD COLUMN `ContentTuningID` INT(10) NOT NULL DEFAULT '0' AFTER `LevelScalingDeltaMax`, + DROP PRIMARY KEY, + ADD PRIMARY KEY (`Entry`, `DifficultyID`); + +ALTER TABLE `creature_classlevelstats` DROP `basearmor`;