diff options
-rw-r--r-- | sql/updates/world/master/2020_05_02_01_world.sql | 7 | ||||
-rw-r--r-- | src/server/game/DataStores/GameTables.cpp | 20 | ||||
-rw-r--r-- | src/server/game/DataStores/GameTables.h | 40 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 67 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/CreatureData.h | 41 | ||||
-rw-r--r-- | src/server/game/Entities/Pet/Pet.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 9 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 49 | ||||
-rw-r--r-- | src/server/game/Server/Packets/CombatLogPacketsCommon.cpp | 21 | ||||
-rw-r--r-- | src/tools/map_extractor/System.cpp | 17 |
10 files changed, 103 insertions, 172 deletions
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 00000000000..ba0f927c713 --- /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`; diff --git a/src/server/game/DataStores/GameTables.cpp b/src/server/game/DataStores/GameTables.cpp index 8340bef7ca0..a8f83354675 100644 --- a/src/server/game/DataStores/GameTables.cpp +++ b/src/server/game/DataStores/GameTables.cpp @@ -24,7 +24,6 @@ #include <fstream> #include <sstream> -GameTable<GtArmorMitigationByLvlEntry> sArmorMitigationByLvlGameTable; GameTable<GtArtifactKnowledgeMultiplierEntry> sArtifactKnowledgeMultiplierGameTable; GameTable<GtArtifactLevelXPEntry> sArtifactLevelXPGameTable; GameTable<GtBarberShopCostBaseEntry> sBarberShopCostBaseGameTable; @@ -33,9 +32,7 @@ GameTable<GtCombatRatingsEntry> sCombatRatingsGameTable; GameTable<GtCombatRatingsMultByILvl> sCombatRatingsMultByILvlGameTable; GameTable<GtHpPerStaEntry> sHpPerStaGameTable; GameTable<GtItemSocketCostPerLevelEntry> sItemSocketCostPerLevelGameTable; -GameTable<GtNpcDamageByClassEntry> sNpcDamageByClassGameTable[MAX_EXPANSIONS]; GameTable<GtNpcManaCostScalerEntry> sNpcManaCostScalerGameTable; -GameTable<GtNpcTotalHpEntry> sNpcTotalHpGameTable[MAX_EXPANSIONS]; GameTable<GtSpellScalingEntry> sSpellScalingGameTable; GameTable<GtStaminaMultByILvl> sStaminaMultByILvlGameTable; GameTable<GtXpEntry> sXpGameTable; @@ -112,7 +109,6 @@ void LoadGameTables(std::string const& dataPath) #define LOAD_GT(store, file) gameTableCount += LoadGameTable(bad_gt_files, store, gtPath / file); ++expectedGameTableCount; - LOAD_GT(sArmorMitigationByLvlGameTable, "ArmorMitigationByLvl.txt"); LOAD_GT(sArtifactKnowledgeMultiplierGameTable, "ArtifactKnowledgeMultiplier.txt"); LOAD_GT(sArtifactLevelXPGameTable, "ArtifactLevelXP.txt"); LOAD_GT(sBarberShopCostBaseGameTable, "BarberShopCostBase.txt"); @@ -121,23 +117,7 @@ void LoadGameTables(std::string const& dataPath) LOAD_GT(sCombatRatingsMultByILvlGameTable, "CombatRatingsMultByILvl.txt"); LOAD_GT(sItemSocketCostPerLevelGameTable, "ItemSocketCostPerLevel.txt"); LOAD_GT(sHpPerStaGameTable, "HpPerSta.txt"); - LOAD_GT(sNpcDamageByClassGameTable[0], "NpcDamageByClass.txt"); - LOAD_GT(sNpcDamageByClassGameTable[1], "NpcDamageByClassExp1.txt"); - LOAD_GT(sNpcDamageByClassGameTable[2], "NpcDamageByClassExp2.txt"); - LOAD_GT(sNpcDamageByClassGameTable[3], "NpcDamageByClassExp3.txt"); - LOAD_GT(sNpcDamageByClassGameTable[4], "NpcDamageByClassExp4.txt"); - LOAD_GT(sNpcDamageByClassGameTable[5], "NpcDamageByClassExp5.txt"); - LOAD_GT(sNpcDamageByClassGameTable[6], "NpcDamageByClassExp6.txt"); - LOAD_GT(sNpcDamageByClassGameTable[7], "NpcDamageByClassExp7.txt"); LOAD_GT(sNpcManaCostScalerGameTable, "NPCManaCostScaler.txt"); - LOAD_GT(sNpcTotalHpGameTable[0], "NpcTotalHp.txt"); - LOAD_GT(sNpcTotalHpGameTable[1], "NpcTotalHpExp1.txt"); - LOAD_GT(sNpcTotalHpGameTable[2], "NpcTotalHpExp2.txt"); - LOAD_GT(sNpcTotalHpGameTable[3], "NpcTotalHpExp3.txt"); - LOAD_GT(sNpcTotalHpGameTable[4], "NpcTotalHpExp4.txt"); - LOAD_GT(sNpcTotalHpGameTable[5], "NpcTotalHpExp5.txt"); - LOAD_GT(sNpcTotalHpGameTable[6], "NpcTotalHpExp6.txt"); - LOAD_GT(sNpcTotalHpGameTable[7], "NpcTotalHpExp7.txt"); LOAD_GT(sSpellScalingGameTable, "SpellScaling.txt"); LOAD_GT(sStaminaMultByILvlGameTable, "StaminaMultByILvl.txt"); LOAD_GT(sXpGameTable, "xp.txt"); diff --git a/src/server/game/DataStores/GameTables.h b/src/server/game/DataStores/GameTables.h index 14f108c1399..16f5f26dae2 100644 --- a/src/server/game/DataStores/GameTables.h +++ b/src/server/game/DataStores/GameTables.h @@ -24,11 +24,6 @@ enum InventoryType : uint8; -struct GtArmorMitigationByLvlEntry -{ - float Mitigation = 0.0f; -}; - struct GtArtifactKnowledgeMultiplierEntry { float Multiplier = 0.0f; @@ -115,43 +110,11 @@ struct GtItemSocketCostPerLevelEntry float SocketCost = 0.0f; }; -struct GtNpcDamageByClassEntry -{ - float Rogue = 0.0f; - float Druid = 0.0f; - float Hunter = 0.0f; - float Mage = 0.0f; - float Paladin = 0.0f; - float Priest = 0.0f; - float Shaman = 0.0f; - float Warlock = 0.0f; - float Warrior = 0.0f; - float DeathKnight = 0.0f; - float Monk = 0.0f; - float DemonHunter = 0.0f; -}; - struct GtNpcManaCostScalerEntry { float Scaler = 0.0f; }; -struct GtNpcTotalHpEntry -{ - float Rogue = 0.0f; - float Druid = 0.0f; - float Hunter = 0.0f; - float Mage = 0.0f; - float Paladin = 0.0f; - float Priest = 0.0f; - float Shaman = 0.0f; - float Warlock = 0.0f; - float Warrior = 0.0f; - float DeathKnight = 0.0f; - float Monk = 0.0f; - float DemonHunter = 0.0f; -}; - struct GtSpellScalingEntry { float Rogue = 0.0f; @@ -213,7 +176,6 @@ private: std::vector<T> _data; }; -TC_GAME_API extern GameTable<GtArmorMitigationByLvlEntry> sArmorMitigationByLvlGameTable; TC_GAME_API extern GameTable<GtArtifactKnowledgeMultiplierEntry> sArtifactKnowledgeMultiplierGameTable; TC_GAME_API extern GameTable<GtArtifactLevelXPEntry> sArtifactLevelXPGameTable; TC_GAME_API extern GameTable<GtBarberShopCostBaseEntry> sBarberShopCostBaseGameTable; @@ -222,9 +184,7 @@ TC_GAME_API extern GameTable<GtCombatRatingsEntry> sCombatRatin TC_GAME_API extern GameTable<GtCombatRatingsMultByILvl> sCombatRatingsMultByILvlGameTable; TC_GAME_API extern GameTable<GtHpPerStaEntry> sHpPerStaGameTable; TC_GAME_API extern GameTable<GtItemSocketCostPerLevelEntry> sItemSocketCostPerLevelGameTable; -TC_GAME_API extern GameTable<GtNpcDamageByClassEntry> sNpcDamageByClassGameTable[MAX_EXPANSIONS]; TC_GAME_API extern GameTable<GtNpcManaCostScalerEntry> sNpcManaCostScalerGameTable; -TC_GAME_API extern GameTable<GtNpcTotalHpEntry> sNpcTotalHpGameTable[MAX_EXPANSIONS]; TC_GAME_API extern GameTable<GtSpellScalingEntry> sSpellScalingGameTable; TC_GAME_API extern GameTable<GtStaminaMultByILvl> sStaminaMultByILvlGameTable; TC_GAME_API extern GameTable<GtXpEntry> sXpGameTable; diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index f9f68237d0d..bafab099086 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -24,6 +24,7 @@ #include "CreatureAISelector.h" #include "CreatureGroups.h" #include "DatabaseEnv.h" +#include "DB2Stores.h" #include "Formulas.h" #include "GameEventMgr.h" #include "GameTime.h" @@ -215,6 +216,27 @@ WorldPacket CreatureTemplate::BuildQueryData(LocaleConstant loc) const return *queryTemp.Write(); } +CreatureLevelScaling const* CreatureTemplate::GetLevelScaling(Difficulty difficulty) const +{ + auto it = scalingStore.find(difficulty); + if (it != scalingStore.end()) + return &it->second; + + struct DefaultCreatureLevelScaling : public CreatureLevelScaling + { + DefaultCreatureLevelScaling() + { + MinLevel = 0; + MaxLevel = 0; + DeltaLevelMin = 0; + DeltaLevelMax = 0; + ContentTuningID = 0; + } + }; + static const DefaultCreatureLevelScaling defScaling; + return &defScaling; +} + bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) { if (Unit* victim = ObjectAccessor::GetUnit(m_owner, m_victim)) @@ -1372,17 +1394,17 @@ void Creature::SelectLevel() uint8 level = minlevel == maxlevel ? minlevel : urand(minlevel, maxlevel); SetLevel(level); - if (HasScalableLevels()) - { - SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ScalingLevelMin), cInfo->levelScaling->MinLevel); - SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ScalingLevelMax), cInfo->levelScaling->MaxLevel); + CreatureLevelScaling const* scaling = cInfo->GetLevelScaling(GetMap()->GetDifficultyID()); - int8 mindelta = std::min(cInfo->levelScaling->DeltaLevelMax, cInfo->levelScaling->DeltaLevelMin); - int8 maxdelta = std::max(cInfo->levelScaling->DeltaLevelMax, cInfo->levelScaling->DeltaLevelMin); - int8 delta = mindelta == maxdelta ? mindelta : irand(mindelta, maxdelta); + SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ScalingLevelMin), scaling->MinLevel); + SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ScalingLevelMax), scaling->MaxLevel); - SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ScalingLevelDelta), delta); - } + int32 mindelta = std::min(scaling->DeltaLevelMax, scaling->DeltaLevelMin); + int32 maxdelta = std::max(scaling->DeltaLevelMax, scaling->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), scaling->ContentTuningID); UpdateLevelDependantStats(); } @@ -1391,12 +1413,13 @@ void Creature::UpdateLevelDependantStats() { CreatureTemplate const* cInfo = GetCreatureTemplate(); uint32 rank = IsPet() ? 0 : cInfo->rank; - CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(getLevel(), cInfo->unit_class); + uint8 level = getLevel(); + CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(level, cInfo->unit_class); // health float healthmod = _GetHealthMod(rank); - uint32 basehp = stats->GenerateHealth(cInfo); + uint32 basehp = GetMaxHealthByLevel(level); uint32 health = uint32(basehp * healthmod); SetCreateHealth(health); @@ -1422,7 +1445,7 @@ void Creature::UpdateLevelDependantStats() SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, (float)health); // damage - float basedamage = stats->GenerateBaseDamage(cInfo); + float basedamage = GetBaseDamageForLevel(level); float weaponBaseMinDamage = basedamage; float weaponBaseMaxDamage = basedamage * 1.5f; @@ -1439,7 +1462,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 = (float)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(UNIT_MOD_ARMOR, BASE_VALUE, armor); } @@ -2670,14 +2693,17 @@ void Creature::AllLootRemovedFromCorpse() bool Creature::HasScalableLevels() const { CreatureTemplate const* cinfo = GetCreatureTemplate(); - return cinfo->levelScaling.is_initialized(); + CreatureLevelScaling const* scaling = cinfo->GetLevelScaling(GetMap()->GetDifficultyID()); + + return (scaling->MinLevel != 0 && scaling->MaxLevel != 0); } uint64 Creature::GetMaxHealthByLevel(uint8 level) const { CreatureTemplate const* cInfo = GetCreatureTemplate(); - CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(level, cInfo->unit_class); - return stats->GenerateHealth(cInfo); + CreatureLevelScaling const* scaling = cInfo->GetLevelScaling(GetMap()->GetDifficultyID()); + float baseHealth = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureHealth, level, cInfo->HealthScalingExpansion, scaling->ContentTuningID, Classes(cInfo->unit_class)); + return baseHealth * cInfo->ModHealth * cInfo->ModHealthExtra; } float Creature::GetHealthMultiplierForTarget(WorldObject const* target) const @@ -2695,8 +2721,8 @@ float Creature::GetHealthMultiplierForTarget(WorldObject const* target) const float Creature::GetBaseDamageForLevel(uint8 level) const { CreatureTemplate const* cInfo = GetCreatureTemplate(); - CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(level, cInfo->unit_class); - return stats->GenerateBaseDamage(cInfo); + CreatureLevelScaling const* scaling = cInfo->GetLevelScaling(GetMap()->GetDifficultyID()); + return sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureAutoAttackDps, level, cInfo->HealthScalingExpansion, scaling->ContentTuningID, Classes(cInfo->unit_class)); } float Creature::GetDamageMultiplierForTarget(WorldObject const* target) const @@ -2712,8 +2738,9 @@ float Creature::GetDamageMultiplierForTarget(WorldObject const* target) const float Creature::GetBaseArmorForLevel(uint8 level) const { CreatureTemplate const* cInfo = GetCreatureTemplate(); - CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(level, cInfo->unit_class); - return stats->GenerateArmor(cInfo); + CreatureLevelScaling const* scaling = cInfo->GetLevelScaling(GetMap()->GetDifficultyID()); + float baseArmor = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureArmor, level, cInfo->HealthScalingExpansion, scaling->ContentTuningID, Classes(cInfo->unit_class)); + return baseArmor * cInfo->ModArmor; } float Creature::GetArmorMultiplierForTarget(WorldObject const* target) const diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h index d5657ced163..c7adebf0887 100644 --- a/src/server/game/Entities/Creature/CreatureData.h +++ b/src/server/game/Entities/Creature/CreatureData.h @@ -288,7 +288,7 @@ enum CreatureFlagsExtra : uint32 CREATURE_FLAG_EXTRA_DUNGEON_BOSS = 0x10000000, // creature is a dungeon boss (SET DYNAMICALLY, DO NOT ADD IN DB) CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING = 0x20000000, // creature ignore pathfinding CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK = 0x40000000, // creature is immune to knockback effects - CREATURE_FLAG_EXTRA_UNUSED_31 = 0x80000000, + CREATURE_FLAG_EXTRA_UNUSED_31 = 0x80000000, // Masks CREATURE_FLAG_EXTRA_UNUSED = (CREATURE_FLAG_EXTRA_UNUSED_11 | CREATURE_FLAG_EXTRA_UNUSED_12 | CREATURE_FLAG_EXTRA_UNUSED_13 | @@ -309,14 +309,6 @@ const uint32 MAX_CREATURE_NAMES = 4; const uint32 MAX_CREATURE_SPELLS = 8; const uint32 MAX_CREATURE_DIFFICULTIES = 3; -struct CreatureLevelScaling -{ - uint16 MinLevel; - uint16 MaxLevel; - int16 DeltaLevelMin; - int16 DeltaLevelMax; -}; - struct CreatureModel { static CreatureModel const DefaultInvisibleModel; @@ -333,6 +325,15 @@ struct CreatureModel float Probability; }; +struct CreatureLevelScaling +{ + uint16 MinLevel; + uint16 MaxLevel; + int16 DeltaLevelMin; + int16 DeltaLevelMax; + int32 ContentTuningID; +}; + // from `creature_template` table struct TC_GAME_API CreatureTemplate { @@ -348,7 +349,7 @@ struct TC_GAME_API CreatureTemplate uint32 GossipMenuId; int16 minlevel; int16 maxlevel; - Optional<CreatureLevelScaling> levelScaling; + std::unordered_map<Difficulty, CreatureLevelScaling> scalingStore; int32 HealthScalingExpansion; uint32 RequiredExpansion; uint32 VignetteID; /// @todo Read Vignette.db2 @@ -408,6 +409,7 @@ struct TC_GAME_API CreatureTemplate CreatureModel const* GetModelWithDisplayId(uint32 displayId) const; CreatureModel const* GetFirstInvisibleModel() const; CreatureModel const* GetFirstVisibleModel() const; + CreatureLevelScaling const* GetLevelScaling(Difficulty difficulty) const; // helpers SkillType GetRequiredLootSkill() const @@ -477,20 +479,11 @@ 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 BaseHealth[MAX_EXPANSIONS]; uint32 BaseMana; - uint32 BaseArmor; uint32 AttackPower; uint32 RangedAttackPower; - float BaseDamage[MAX_EXPANSIONS]; // Helpers - - uint32 GenerateHealth(CreatureTemplate const* info) const - { - return uint32(ceil(BaseHealth[info->HealthScalingExpansion] * info->ModHealth * info->ModHealthExtra)); - } - uint32 GenerateMana(CreatureTemplate const* info) const { // Mana can be 0. @@ -500,16 +493,6 @@ struct TC_GAME_API CreatureBaseStats return uint32(ceil(BaseMana * info->ModMana * info->ModManaExtra)); } - uint32 GenerateArmor(CreatureTemplate const* info) const - { - return uint32(ceil(BaseArmor * info->ModArmor)); - } - - float GenerateBaseDamage(CreatureTemplate const* info) const - { - return BaseDamage[info->HealthScalingExpansion]; - } - 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 8852af1be8c..53dbc7b484c 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -840,7 +840,9 @@ bool Guardian::InitStatsForLevel(uint8 petlevel) { // remove elite bonuses included in DB values CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(petlevel, cinfo->unit_class); - SetCreateHealth(stats->BaseHealth[cinfo->HealthScalingExpansion]); + CreatureLevelScaling const* scaling = cinfo->GetLevelScaling(GetMap()->GetDifficultyID()); + + SetCreateHealth(sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureHealth, petlevel, cinfo->HealthScalingExpansion, scaling->ContentTuningID, Classes(cinfo->unit_class)) * cinfo->ModHealth * cinfo->ModHealthExtra); SetCreateMana(stats->BaseMana); SetCreateStat(STAT_STRENGTH, 22); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index ad69398d494..e3441184188 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -1640,14 +1640,13 @@ uint32 Unit::CalcArmorReducedDamage(Unit* attacker, Unit* victim, const uint32 d return damage; uint8 attackerLevel = attacker->GetLevelForTarget(victim); - if (attackerLevel > sArmorMitigationByLvlGameTable.GetTableRowCount()) - attackerLevel = sArmorMitigationByLvlGameTable.GetTableRowCount(); + // Expansion and ContentTuningID necessary? Does Player get a ContentTuningID too ? + float armorConstant = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::ArmorConstant, attackerLevel, -2, 0, Classes(attacker->getClass())); - GtArmorMitigationByLvlEntry const* ambl = sArmorMitigationByLvlGameTable.GetRow(attackerLevel); - if (!ambl) + if (!armorConstant) return damage; - float mitigation = std::min(armor / (armor + ambl->Mitigation), 0.85f); + float mitigation = std::min(armor / (armor + armorConstant), 0.85f); return std::max<uint32>(damage * (1.0f - mitigation), 1); } diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index f519c69948f..e26fe6308ee 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -704,8 +704,8 @@ void ObjectMgr::LoadCreatureScalingData() { uint32 oldMSTime = getMSTime(); - // 0 1 2 3 4 - QueryResult result = WorldDatabase.Query("SELECT Entry, LevelScalingMin, LevelScalingMax, LevelScalingDeltaMin, LevelScalingDeltaMax FROM creature_template_scaling"); + // 0 1 2 3 4 5 6 + QueryResult result = WorldDatabase.Query("SELECT Entry, DifficultyID, LevelScalingMin, LevelScalingMax, LevelScalingDeltaMin, LevelScalingDeltaMax, ContentTuningID FROM creature_template_scaling ORDER BY Entry"); if (!result) { @@ -719,8 +719,9 @@ void ObjectMgr::LoadCreatureScalingData() Field* fields = result->Fetch(); uint32 entry = fields[0].GetUInt32(); + Difficulty difficulty = Difficulty(fields[1].GetUInt8()); - CreatureTemplateContainer::iterator itr = _creatureTemplateStore.find(entry); + auto itr = _creatureTemplateStore.find(entry); if (itr == _creatureTemplateStore.end()) { TC_LOG_ERROR("sql.sql", "Creature template (Entry: %u) does not exist but has a record in `creature_template_scaling`", entry); @@ -728,11 +729,13 @@ void ObjectMgr::LoadCreatureScalingData() } CreatureLevelScaling creatureLevelScaling; - creatureLevelScaling.MinLevel = fields[1].GetUInt16(); - creatureLevelScaling.MaxLevel = fields[2].GetUInt16(); - creatureLevelScaling.DeltaLevelMin = fields[3].GetInt16(); - creatureLevelScaling.DeltaLevelMax = fields[4].GetInt16(); - itr->second.levelScaling = creatureLevelScaling; + creatureLevelScaling.MinLevel = fields[2].GetUInt16(); + creatureLevelScaling.MaxLevel = fields[3].GetUInt16(); + creatureLevelScaling.DeltaLevelMin = fields[4].GetInt16(); + creatureLevelScaling.DeltaLevelMax = fields[5].GetInt16(); + creatureLevelScaling.ContentTuningID = fields[6].GetInt32(); + + itr->second.scalingStore[difficulty] = creatureLevelScaling; ++count; } while (result->NextRow()); @@ -2232,6 +2235,8 @@ ObjectGuid::LowType ObjectMgr::AddCreatureData(uint32 entry, uint32 mapId, float if (!map) return UI64LIT(0); + CreatureLevelScaling const* scaling = cInfo->GetLevelScaling(map->GetDifficultyID()); + ObjectGuid::LowType guid = GenerateCreatureSpawnId(); CreatureData& data = NewOrExistCreatureData(guid); data.id = entry; @@ -2245,7 +2250,7 @@ ObjectGuid::LowType ObjectMgr::AddCreatureData(uint32 entry, uint32 mapId, float data.spawntimesecs = spawntimedelay; data.spawndist = 0; data.currentwaypoint = 0; - data.curhealth = stats->GenerateHealth(cInfo); + data.curhealth = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureHealth, level, cInfo->HealthScalingExpansion, scaling->ContentTuningID, Classes(cInfo->unit_class)) * cInfo->ModHealth * cInfo->ModHealthExtra; data.curmana = stats->GenerateMana(cInfo); data.movementType = cInfo->MovementType; data.spawnDifficulties.push_back(DIFFICULTY_NONE); @@ -9222,12 +9227,6 @@ CreatureBaseStats const* ObjectMgr::GetCreatureBaseStats(uint8 level, uint8 unit { DefaultCreatureBaseStats() { - BaseArmor = 1; - for (uint8 j = 0; j < MAX_EXPANSIONS; ++j) - { - BaseHealth[j] = 1; - BaseDamage[j] = 0.0f; - } BaseMana = 0; AttackPower = 0; RangedAttackPower = 0; @@ -9240,8 +9239,8 @@ CreatureBaseStats const* ObjectMgr::GetCreatureBaseStats(uint8 level, uint8 unit void ObjectMgr::LoadCreatureClassLevelStats() { uint32 oldMSTime = getMSTime(); - // 0 1 2 3 4 5 - QueryResult result = WorldDatabase.Query("SELECT level, class, basemana, basearmor, attackpower, rangedattackpower FROM creature_classlevelstats"); + // 0 1 2 3 4 + QueryResult result = WorldDatabase.Query("SELECT level, class, basemana, attackpower, rangedattackpower FROM creature_classlevelstats"); if (!result) { @@ -9262,22 +9261,10 @@ void ObjectMgr::LoadCreatureClassLevelStats() CreatureBaseStats stats; - for (uint8 i = 0; i < MAX_EXPANSIONS; ++i) - { - stats.BaseHealth[i] = GetGameTableColumnForClass(sNpcTotalHpGameTable[i].GetRow(Level), Class); - stats.BaseDamage[i] = GetGameTableColumnForClass(sNpcDamageByClassGameTable[i].GetRow(Level), Class); - if (stats.BaseDamage[i] < 0.0f) - { - TC_LOG_ERROR("sql.sql", "Creature base stats for class %u, level %u has invalid negative base damage[%u] - set to 0.0", Class, Level, i); - stats.BaseDamage[i] = 0.0f; - } - } - stats.BaseMana = fields[2].GetUInt32(); - stats.BaseArmor = fields[3].GetUInt32(); - stats.AttackPower = fields[4].GetUInt16(); - stats.RangedAttackPower = fields[5].GetUInt16(); + stats.AttackPower = fields[3].GetUInt16(); + stats.RangedAttackPower = fields[4].GetUInt16(); _creatureBaseStatsStore[MAKE_PAIR16(Level, Class)] = stats; diff --git a/src/server/game/Server/Packets/CombatLogPacketsCommon.cpp b/src/server/game/Server/Packets/CombatLogPacketsCommon.cpp index fc5af6e5fbe..f70f96234f0 100644 --- a/src/server/game/Server/Packets/CombatLogPacketsCommon.cpp +++ b/src/server/game/Server/Packets/CombatLogPacketsCommon.cpp @@ -64,6 +64,7 @@ namespace WorldPackets bool ContentTuningParams::GenerateDataForUnits<Creature, Player>(Creature* attacker, Player* target) { CreatureTemplate const* creatureTemplate = attacker->GetCreatureTemplate(); + CreatureLevelScaling const* creatureScaling = creatureTemplate->GetLevelScaling(attacker->GetMap()->GetDifficultyID()); Type = TYPE_CREATURE_TO_PLAYER_DAMAGE; PlayerLevelDelta = target->m_activePlayerData->ScalingPlayerLevelDelta; @@ -71,9 +72,9 @@ namespace WorldPackets TargetItemLevel = 0; ScalingHealthItemLevelCurveID = target->m_unitData->ScalingHealthItemLevelCurveID; TargetLevel = target->getLevel(); - Expansion = creatureTemplate->RequiredExpansion; - TargetMinScalingLevel = uint8(creatureTemplate->levelScaling->MinLevel); - TargetMaxScalingLevel = uint8(creatureTemplate->levelScaling->MaxLevel); + Expansion = creatureTemplate->HealthScalingExpansion; + TargetMinScalingLevel = uint8(creatureScaling->MinLevel); + TargetMaxScalingLevel = uint8(creatureScaling->MaxLevel); TargetScalingLevelDelta = int8(attacker->m_unitData->ScalingLevelDelta); return true; } @@ -82,6 +83,7 @@ namespace WorldPackets bool ContentTuningParams::GenerateDataForUnits<Player, Creature>(Player* attacker, Creature* target) { CreatureTemplate const* creatureTemplate = target->GetCreatureTemplate(); + CreatureLevelScaling const* creatureScaling = creatureTemplate->GetLevelScaling(target->GetMap()->GetDifficultyID()); Type = TYPE_PLAYER_TO_CREATURE_DAMAGE; PlayerLevelDelta = attacker->m_activePlayerData->ScalingPlayerLevelDelta; @@ -89,9 +91,9 @@ namespace WorldPackets TargetItemLevel = 0; ScalingHealthItemLevelCurveID = target->m_unitData->ScalingHealthItemLevelCurveID; TargetLevel = target->getLevel(); - Expansion = creatureTemplate->RequiredExpansion; - TargetMinScalingLevel = uint8(creatureTemplate->levelScaling->MinLevel); - TargetMaxScalingLevel = uint8(creatureTemplate->levelScaling->MaxLevel); + Expansion = creatureTemplate->HealthScalingExpansion; + TargetMinScalingLevel = uint8(creatureScaling->MinLevel); + TargetMaxScalingLevel = uint8(creatureScaling->MaxLevel); TargetScalingLevelDelta = int8(target->m_unitData->ScalingLevelDelta); return true; } @@ -101,14 +103,15 @@ namespace WorldPackets { Creature* accessor = target->HasScalableLevels() ? target : attacker; CreatureTemplate const* creatureTemplate = accessor->GetCreatureTemplate(); + CreatureLevelScaling const* creatureScaling = creatureTemplate->GetLevelScaling(accessor->GetMap()->GetDifficultyID()); Type = TYPE_CREATURE_TO_CREATURE_DAMAGE; PlayerLevelDelta = 0; PlayerItemLevel = 0; TargetLevel = target->getLevel(); - Expansion = creatureTemplate->RequiredExpansion; - TargetMinScalingLevel = uint8(creatureTemplate->levelScaling->MinLevel); - TargetMaxScalingLevel = uint8(creatureTemplate->levelScaling->MaxLevel); + Expansion = creatureTemplate->HealthScalingExpansion; + TargetMinScalingLevel = uint8(creatureScaling->MinLevel); + TargetMaxScalingLevel = uint8(creatureScaling->MaxLevel); TargetScalingLevelDelta = int8(accessor->m_unitData->ScalingLevelDelta); return true; } diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index 8f2be503c56..05e0867daa5 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -1356,7 +1356,6 @@ void ExtractGameTables() DB2FileInfo GameTables[] = { - { 1385707, "ArmorMitigationByLvl.txt" }, { 1582086, "ArtifactKnowledgeMultiplier.txt" }, { 1391662, "ArtifactLevelXP.txt" }, { 1892815, "AzeriteBaseExperiencePerLevel.txt" }, @@ -1375,23 +1374,7 @@ void ExtractGameTables() { 2012881, "ItemLevelByLevel.txt" }, { 1726830, "ItemLevelSquish.txt" }, { 1391643, "ItemSocketCostPerLevel.txt" }, - { 1391644, "NpcDamageByClass.txt" }, - { 1391645, "NpcDamageByClassExp1.txt" }, - { 1391646, "NpcDamageByClassExp2.txt" }, - { 1391647, "NpcDamageByClassExp3.txt" }, - { 1391648, "NpcDamageByClassExp4.txt" }, - { 1391649, "NpcDamageByClassExp5.txt" }, - { 1391650, "NpcDamageByClassExp6.txt" }, - { 1536195, "NpcDamageByClassExp7.txt" }, { 1391651, "NPCManaCostScaler.txt" }, - { 1391652, "NpcTotalHp.txt" }, - { 1391653, "NpcTotalHpExp1.txt" }, - { 1391654, "NpcTotalHpExp2.txt" }, - { 1391655, "NpcTotalHpExp3.txt" }, - { 1391656, "NpcTotalHpExp4.txt" }, - { 1391657, "NpcTotalHpExp5.txt" }, - { 1391658, "NpcTotalHpExp6.txt" }, - { 1536196, "NpcTotalHpExp7.txt" }, { 1391659, "SandboxScaling.txt" }, { 1391660, "SpellScaling.txt" }, { 1980632, "StaminaMultByILvl.txt" }, |