aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/hotfixes/3.4.x/2023_11_23_00_hotfixes.sql4
-rw-r--r--src/server/database/Database/Implementation/HotfixDatabase.cpp4
-rw-r--r--src/server/game/Achievements/CriteriaHandler.cpp4
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.cpp4
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp14
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp9
-rw-r--r--src/server/game/DataStores/DB2Stores.h1
-rw-r--r--src/server/game/DataStores/DB2Structure.h66
-rw-r--r--src/server/game/Entities/Item/Item.cpp26
-rw-r--r--src/server/game/Entities/Item/Item.h5
-rw-r--r--src/server/game/Entities/Item/ItemTemplate.h4
-rw-r--r--src/server/game/Entities/Player/Player.cpp58
-rw-r--r--src/server/game/Entities/Player/Player.h4
-rw-r--r--src/server/game/Spells/Spell.cpp6
-rw-r--r--src/server/game/Spells/SpellEffects.cpp2
15 files changed, 145 insertions, 66 deletions
diff --git a/sql/updates/hotfixes/3.4.x/2023_11_23_00_hotfixes.sql b/sql/updates/hotfixes/3.4.x/2023_11_23_00_hotfixes.sql
index 6b58c6925c8..542e3ef69d1 100644
--- a/sql/updates/hotfixes/3.4.x/2023_11_23_00_hotfixes.sql
+++ b/sql/updates/hotfixes/3.4.x/2023_11_23_00_hotfixes.sql
@@ -55,7 +55,7 @@ CREATE TABLE `scaling_stat_values` (
`ID` int(10) unsigned NOT NULL DEFAULT '0',
`Charlevel` int(11) NOT NULL DEFAULT '0',
`WeaponDPS1H` int(11) NOT NULL DEFAULT '0',
- `WeaponDPS2h` int(11) NOT NULL DEFAULT '0',
+ `WeaponDPS2H` int(11) NOT NULL DEFAULT '0',
`SpellcasterDPS1H` int(11) NOT NULL DEFAULT '0',
`SpellcasterDPS2H` int(11) NOT NULL DEFAULT '0',
`RangedDPS` int(11) NOT NULL DEFAULT '0',
@@ -63,7 +63,7 @@ CREATE TABLE `scaling_stat_values` (
`SpellPower` int(11) NOT NULL DEFAULT '0',
`ShoulderBudget` int(11) NOT NULL DEFAULT '0',
`TrinketBudget` int(11) NOT NULL DEFAULT '0',
- `WeaponBudget` int(11) NOT NULL DEFAULT '0',
+ `WeaponBudget1H` int(11) NOT NULL DEFAULT '0',
`PrimaryBudget` int(11) NOT NULL DEFAULT '0',
`RangedBudget` int(11) NOT NULL DEFAULT '0',
`TertiaryBudget` int(11) NOT NULL DEFAULT '0',
diff --git a/src/server/database/Database/Implementation/HotfixDatabase.cpp b/src/server/database/Database/Implementation/HotfixDatabase.cpp
index 32506a8fcb6..6cdea6df445 100644
--- a/src/server/database/Database/Implementation/HotfixDatabase.cpp
+++ b/src/server/database/Database/Implementation/HotfixDatabase.cpp
@@ -1327,8 +1327,8 @@ void HotfixDatabaseConnection::DoPrepareStatements()
PREPARE_MAX_ID_STMT(HOTFIX_SEL_SCALING_STAT_DISTRIBUTION, "SELECT MAX(ID) + 1 FROM scaling_stat_distribution", CONNECTION_SYNCH);
// ScalingStatValues.db2
- PrepareStatement(HOTFIX_SEL_SCALING_STAT_VALUES, "SELECT ID, Charlevel, WeaponDPS1H, WeaponDPS2h, SpellcasterDPS1H, SpellcasterDPS2H, RangedDPS, "
- "WandDPS, SpellPower, ShoulderBudget, TrinketBudget, WeaponBudget, PrimaryBudget, RangedBudget, TertiaryBudget, ClothShoulderArmor, "
+ PrepareStatement(HOTFIX_SEL_SCALING_STAT_VALUES, "SELECT ID, Charlevel, WeaponDPS1H, WeaponDPS2H, SpellcasterDPS1H, SpellcasterDPS2H, RangedDPS, "
+ "WandDPS, SpellPower, ShoulderBudget, TrinketBudget, WeaponBudget1H, PrimaryBudget, RangedBudget, TertiaryBudget, ClothShoulderArmor, "
"LeatherShoulderArmor, MailShoulderArmor, PlateShoulderArmor, ClothCloakArmor, ClothChestArmor, LeatherChestArmor, MailChestArmor, "
"PlateChestArmor FROM scaling_stat_values WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
PREPARE_MAX_ID_STMT(HOTFIX_SEL_SCALING_STAT_VALUES, "SELECT MAX(ID) + 1 FROM scaling_stat_values", CONNECTION_SYNCH);
diff --git a/src/server/game/Achievements/CriteriaHandler.cpp b/src/server/game/Achievements/CriteriaHandler.cpp
index 27398cd0c7e..bea97f7ab09 100644
--- a/src/server/game/Achievements/CriteriaHandler.cpp
+++ b/src/server/game/Achievements/CriteriaHandler.cpp
@@ -410,7 +410,7 @@ bool CriteriaData::Meets(uint32 criteriaId, Player const* source, WorldObject co
ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId);
if (!itemTemplate)
return false;
- return itemTemplate->GetBaseItemLevel() >= EquippedItem.ItemLevel && itemTemplate->GetQuality() >= EquippedItem.Quality;
+ return itemTemplate->GetItemLevel() >= EquippedItem.ItemLevel && itemTemplate->GetQuality() >= EquippedItem.Quality;
}
case CRITERIA_DATA_TYPE_MAP_ID:
return source->GetMapId() == Map.Id;
@@ -1718,7 +1718,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
{
// miscValue1 is itemid
ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
- if (!item || item->GetBaseItemLevel() < reqValue)
+ if (!item || item->GetItemLevel() < reqValue)
return false;
break;
}
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
index 39949525630..ab4fe0f99e4 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
@@ -84,7 +84,7 @@ AuctionsBucketKey AuctionsBucketKey::ForItem(Item const* item)
AuctionsBucketKey AuctionsBucketKey::ForCommodity(ItemTemplate const* itemTemplate)
{
- return { itemTemplate->GetId(), uint16(itemTemplate->GetBaseItemLevel()), 0, 0 };
+ return { itemTemplate->GetId(), uint16(itemTemplate->GetItemLevel()), 0, 0 };
}
void AuctionsBucketData::BuildBucketInfo(WorldPackets::AuctionHouse::BucketInfo* bucketInfo, Player const* player) const
@@ -884,7 +884,7 @@ void AuctionHouseObject::AddAuction(CharacterDatabaseTransaction trans, AuctionP
break;
case ITEM_CLASS_GEM:
case ITEM_CLASS_ITEM_ENHANCEMENT:
- bucket->SortLevel = itemTemplate->GetBaseItemLevel();
+ bucket->SortLevel = itemTemplate->GetItemLevel();
break;
case ITEM_CLASS_CONSUMABLE:
bucket->SortLevel = std::max<uint8>(1, bucket->RequiredLevel);
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp
index 65d6d7cf8c0..066652b81bd 100644
--- a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp
@@ -232,10 +232,10 @@ bool AuctionBotSeller::Initialize()
case ITEM_CLASS_WEAPON:
{
if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MIN_ITEM_LEVEL))
- if (prototype->GetBaseItemLevel() < value)
+ if (prototype->GetItemLevel() < value)
continue;
if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MAX_ITEM_LEVEL))
- if (prototype->GetBaseItemLevel() > value)
+ if (prototype->GetItemLevel() > value)
continue;
if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MIN_REQ_LEVEL))
if (prototype->GetBaseRequiredLevel() < static_cast<int32>(value))
@@ -316,10 +316,10 @@ bool AuctionBotSeller::Initialize()
case ITEM_CLASS_TRADE_GOODS:
{
if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_MIN_ITEM_LEVEL))
- if (prototype->GetBaseItemLevel() < value)
+ if (prototype->GetItemLevel() < value)
continue;
if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_MAX_ITEM_LEVEL))
- if (prototype->GetBaseItemLevel() > value)
+ if (prototype->GetItemLevel() > value)
continue;
break;
}
@@ -327,10 +327,10 @@ bool AuctionBotSeller::Initialize()
case ITEM_CLASS_QUIVER:
{
if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONTAINER_MIN_ITEM_LEVEL))
- if (prototype->GetBaseItemLevel() < value)
+ if (prototype->GetItemLevel() < value)
continue;
if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONTAINER_MAX_ITEM_LEVEL))
- if (prototype->GetBaseItemLevel() > value)
+ if (prototype->GetItemLevel() > value)
continue;
break;
}
@@ -602,7 +602,7 @@ void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConf
else
{
float divisor = ((itemProto->GetClass() == ITEM_CLASS_WEAPON || itemProto->GetClass() == ITEM_CLASS_ARMOR) ? 284.0f : 80.0f);
- float tempLevel = (itemProto->GetBaseItemLevel() == 0 ? 1.0f : itemProto->GetBaseItemLevel());
+ float tempLevel = (itemProto->GetItemLevel() == 0 ? 1.0f : itemProto->GetItemLevel());
float tempQuality = (itemProto->GetQuality() == 0 ? 1.0f : itemProto->GetQuality());
buyPrice = tempLevel * tempQuality * static_cast<float>(GetBuyModifier(itemProto))* tempLevel / divisor;
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index f0edc028f7c..6fbd316f650 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -478,6 +478,7 @@ namespace
std::unordered_set<uint8> _spellFamilyNames;
SpellProcsPerMinuteModContainer _spellProcsPerMinuteMods;
std::unordered_map<int32, std::vector<SpellVisualMissileEntry const*>> _spellVisualMissilesBySet;
+ std::unordered_map<uint32, ScalingStatValuesEntry const*> _scalingStatValuesByLevel;
TalentsByPosition _talentsByPosition;
std::unordered_map<std::pair<uint32, uint32>, TaxiPathEntry const*> _taxiPaths;
ToyItemIdsContainer _toys;
@@ -1341,6 +1342,9 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul
for (SpellVisualMissileEntry const* spellVisualMissile : sSpellVisualMissileStore)
_spellVisualMissilesBySet[spellVisualMissile->SpellVisualMissileSetID].push_back(spellVisualMissile);
+ for (ScalingStatValuesEntry const* scalingStatValue : sScalingStatValuesStore)
+ _scalingStatValuesByLevel[scalingStatValue->Charlevel] = scalingStatValue;
+
for (TalentEntry const* talentInfo : sTalentStore)
{
ASSERT(talentInfo->ClassID < MAX_CLASSES);
@@ -3051,3 +3055,8 @@ std::vector<ItemEffectEntry const*> const* DB2Manager::GetItemEffectsForItemId(u
{
return Trinity::Containers::MapGetValuePtr(_itemEffectsByItemId, itemId);
}
+
+ScalingStatValuesEntry const* DB2Manager::GetScalingStatValuesForLevel(uint32 characterLevel) const
+{
+ return Trinity::Containers::MapGetValuePtr(_scalingStatValuesByLevel, characterLevel);
+}
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index 5f75928e390..0374d9228e6 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -499,6 +499,7 @@ public:
bool IsUiMapPhase(uint32 phaseId) const;
WMOAreaTableEntry const* GetWMOAreaTable(int32 rootId, int32 adtId, int32 groupId) const;
std::vector<ItemEffectEntry const*> const* GetItemEffectsForItemId(uint32 itemId) const;
+ ScalingStatValuesEntry const* GetScalingStatValuesForLevel(uint32 characterLevel) const;
private:
friend class DB2HotfixGeneratorBase;
diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h
index 1749f8a9d65..79b80d66581 100644
--- a/src/server/game/DataStores/DB2Structure.h
+++ b/src/server/game/DataStores/DB2Structure.h
@@ -3168,7 +3168,7 @@ struct ScalingStatValuesEntry
uint32 ID;
int32 Charlevel;
int32 WeaponDPS1H;
- int32 WeaponDPS2h;
+ int32 WeaponDPS2H;
int32 SpellcasterDPS1H;
int32 SpellcasterDPS2H;
int32 RangedDPS;
@@ -3176,7 +3176,7 @@ struct ScalingStatValuesEntry
int32 SpellPower;
int32 ShoulderBudget;
int32 TrinketBudget;
- int32 WeaponBudget;
+ int32 WeaponBudget1H;
int32 PrimaryBudget;
int32 RangedBudget;
int32 TertiaryBudget;
@@ -3189,6 +3189,68 @@ struct ScalingStatValuesEntry
int32 LeatherChestArmor;
int32 MailChestArmor;
int32 PlateChestArmor;
+
+ int32 getssdMultiplier(uint32 mask) const
+ {
+ if (mask & 0x4001F)
+ {
+ if (mask & 0x00000001) return ShoulderBudget;
+ if (mask & 0x00000002) return TrinketBudget;
+ if (mask & 0x00000004) return WeaponBudget1H;
+ if (mask & 0x00000008) return PrimaryBudget;
+ if (mask & 0x00000010) return RangedBudget;
+ if (mask & 0x00040000) return TertiaryBudget;
+ }
+ return 0;
+ }
+
+ int32 getArmorMod(uint32 mask) const
+ {
+ if (mask & 0x00F001E0)
+ {
+ if (mask & 0x00000020) return ClothShoulderArmor;
+ if (mask & 0x00000040) return LeatherShoulderArmor;
+ if (mask & 0x00000080) return MailShoulderArmor;
+ if (mask & 0x00000100) return PlateShoulderArmor;
+
+ if (mask & 0x00080000) return ClothCloakArmor;
+ if (mask & 0x00100000) return ClothChestArmor;
+ if (mask & 0x00200000) return LeatherChestArmor;
+ if (mask & 0x00400000) return MailChestArmor;
+ if (mask & 0x00800000) return PlateChestArmor;
+ }
+ return 0;
+ }
+
+ int32 getDPSMod(uint32 mask) const
+ {
+ if (mask & 0x7E00)
+ {
+ if (mask & 0x00000200) return WeaponDPS1H;
+ if (mask & 0x00000400) return WeaponDPS2H;
+ if (mask & 0x00000800) return SpellcasterDPS1H;
+ if (mask & 0x00001000) return SpellcasterDPS2H;
+ if (mask & 0x00002000) return RangedDPS;
+ if (mask & 0x00004000) return WandDPS;
+ }
+ return 0;
+ }
+
+ bool isTwoHand(uint32 mask) const
+ {
+ if (mask & 0x7E00)
+ {
+ if (mask & 0x00000400) return true;
+ if (mask & 0x00001000) return true;
+ }
+ return false;
+ }
+
+ int32 getSpellBonus(uint32 mask) const
+ {
+ if (mask & 0x00008000) return SpellPower;
+ return 0;
+ }
};
struct SceneScriptEntry
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index 0fdaf2e4609..9dddf233a85 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -1139,7 +1139,7 @@ void Item::SetGem(uint16 slot, ItemDynamicFieldGems const* gem, uint32 gemScalin
BonusData gemBonus;
gemBonus.Initialize(gemTemplate);
- uint32 gemBaseItemLevel = gemTemplate->GetBaseItemLevel();
+ uint32 gemBaseItemLevel = gemTemplate->GetItemLevel();
if (gemBonus.PlayerLevelToItemLevelCurveId)
if (uint32 scaledIlvl = uint32(sDB2Manager.GetCurveValueAt(gemBonus.PlayerLevelToItemLevelCurveId, gemScalingLevel)))
gemBaseItemLevel = scaledIlvl;
@@ -1564,16 +1564,7 @@ bool Item::HasStats() const
ItemTemplate const* proto = GetTemplate();
Player const* owner = GetOwner();
for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
- if ((owner ? GetItemStatValue(i, owner) : proto->GetStatPercentEditor(i)) != 0)
- return true;
-
- return false;
-}
-
-bool Item::HasStats(WorldPackets::Item::ItemInstance const& /*itemInstance*/, BonusData const* bonus)
-{
- for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
- if (bonus->ItemStatBonusAmount[i] != 0)
+ if (proto->GetStatModifierBonusAmount(i) != 0)
return true;
return false;
@@ -1895,7 +1886,7 @@ uint32 Item::GetItemLevel(ItemTemplate const* itemTemplate, BonusData const& bon
if (!itemTemplate)
return MIN_ITEM_LEVEL;
- uint32 itemLevel = itemTemplate->GetBaseItemLevel();
+ uint32 itemLevel = itemTemplate->GetItemLevel();
if (bonusData.PlayerLevelToItemLevelCurveId)
{
@@ -1929,12 +1920,6 @@ uint32 Item::GetItemLevel(ItemTemplate const* itemTemplate, BonusData const& bon
return std::min(std::max(itemLevel, uint32(MIN_ITEM_LEVEL)), uint32(MAX_ITEM_LEVEL));
}
-float Item::GetItemStatValue(uint32 index, Player const* owner) const
-{
- ASSERT(index < MAX_ITEM_PROTO_STATS);
- return static_cast<float>(_bonusData.ItemStatBonusAmount[index]);
-}
-
ItemDisenchantLootEntry const* Item::GetDisenchantLoot(Player const* owner) const
{
if (!_bonusData.CanDisenchant)
@@ -2150,11 +2135,6 @@ void BonusData::Initialize(ItemTemplate const* proto)
Quality = proto->GetQuality();
ItemLevelBonus = 0;
RequiredLevel = proto->GetBaseRequiredLevel();
- for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
- ItemStatType[i] = proto->GetStatModifierBonusStat(i);
-
- for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
- ItemStatBonusAmount[i] = proto->GetStatModifierBonusAmount(i);
for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
ItemStatSocketCostMultiplier[i] = proto->GetStatPercentageOfSocket(i);
diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h
index 2057db84847..feea7d67df8 100644
--- a/src/server/game/Entities/Item/Item.h
+++ b/src/server/game/Entities/Item/Item.h
@@ -70,8 +70,6 @@ struct BonusData
uint32 Quality;
int32 ItemLevelBonus;
int32 RequiredLevel;
- int32 ItemStatType[MAX_ITEM_PROTO_STATS];
- int32 ItemStatBonusAmount[MAX_ITEM_PROTO_STATS];
float ItemStatSocketCostMultiplier[MAX_ITEM_PROTO_STATS];
uint32 SocketColor[MAX_ITEM_PROTO_SOCKETS];
ItemBondingType Bonding;
@@ -274,8 +272,6 @@ class TC_GAME_API Item : public Object
static uint32 GetItemLevel(ItemTemplate const* itemTemplate, BonusData const& bonusData, uint32 level, uint32 fixedLevel,
uint32 minItemLevel, uint32 minItemLevelCutoff, uint32 maxItemLevel, bool pvpBonus);
int32 GetRequiredLevel() const;
- int32 GetItemStatType(uint32 index) const { ASSERT(index < MAX_ITEM_PROTO_STATS); return _bonusData.ItemStatType[index]; }
- float GetItemStatValue(uint32 index, Player const* owner) const;
SocketColor GetSocketColor(uint32 index) const { ASSERT(index < MAX_ITEM_PROTO_SOCKETS); return SocketColor(_bonusData.SocketColor[index]); }
uint32 GetAppearanceModId() const { return m_itemData->ItemAppearanceModID; }
void SetAppearanceModId(uint32 appearanceModId) { SetUpdateFieldValue(m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::ItemAppearanceModID), appearanceModId); }
@@ -338,7 +334,6 @@ class TC_GAME_API Item : public Object
bool IsValidTransmogrificationTarget() const;
bool HasStats() const;
- static bool HasStats(WorldPackets::Item::ItemInstance const& itemInstance, BonusData const* bonus);
static bool CanTransmogrifyItemWithItem(Item const* item, ItemModifiedAppearanceEntry const* itemModifiedAppearance);
uint32 GetBuyPrice(Player const* owner, bool& standardPrice) const;
static uint32 GetBuyPrice(ItemTemplate const* proto, uint32 quality, uint32 itemLevel, bool& standardPrice);
diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h
index ddcc76d7268..ccaf8b571b4 100644
--- a/src/server/game/Entities/Item/ItemTemplate.h
+++ b/src/server/game/Entities/Item/ItemTemplate.h
@@ -786,7 +786,7 @@ struct TC_GAME_API ItemTemplate
InventoryType GetInventoryType() const { return InventoryType(ExtendedData->InventoryType); }
int32 GetAllowableClass() const { return ExtendedData->AllowableClass; }
Trinity::RaceMask<int64> GetAllowableRace() const { return ExtendedData->AllowableRace; }
- uint32 GetBaseItemLevel() const { return ExtendedData->ItemLevel; }
+ uint32 GetItemLevel() const { return ExtendedData->ItemLevel; }
int32 GetBaseRequiredLevel() const { return ExtendedData->RequiredLevel; }
uint32 GetRequiredSkill() const { return ExtendedData->RequiredSkill; }
uint32 GetRequiredSkillRank() const { return ExtendedData->RequiredSkillRank; }
@@ -826,6 +826,8 @@ struct TC_GAME_API ItemTemplate
uint8 GetRequiredExpansion() const { return ExtendedData->ExpansionID; }
int16 GetResistance(SpellSchools school) const { return ExtendedData->Resistances[school]; }
int16 GetShieldBlockValue(uint32 itemLevel) const;
+ uint16 GetScalingStatDistributionID() const { return ExtendedData->ScalingStatDistributionID; }
+ int32 GetScalingStatValue() const { return BasicData->ScalingStatValue; }
uint32 MaxDurability;
std::vector<ItemEffectEntry const*> Effects;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index f0ace58da03..87f23fa66ac 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -7705,7 +7705,7 @@ void Player::DuelComplete(DuelCompleteType type)
//---------------------------------------------------------//
-void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply, bool updateItemAuras /*= true*/)
+void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply, bool updateItemAuras /*= true*/, bool onlyForScalingItems /*= false*/)
{
if (slot >= INVENTORY_SLOT_BAG_END || !item)
return;
@@ -7723,7 +7723,7 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply, bool updateItemA
if (item->GetSocketColor(0)) //only (un)equipping of items with sockets can influence metagems, so no need to waste time with normal items
CorrectMetaGemEnchants(slot, apply);
- _ApplyItemBonuses(item, slot, apply);
+ _ApplyItemBonuses(item, slot, apply, onlyForScalingItems);
ApplyItemEquipSpell(item, apply);
if (updateItemAuras)
{
@@ -7739,28 +7739,45 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply, bool updateItemA
TC_LOG_DEBUG("entities.player.items", "Player::_ApplyItemMods: completed");
}
-void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
+void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply, bool onlyForScalingItems /*= false*/)
{
ItemTemplate const* proto = item->GetTemplate();
if (slot >= INVENTORY_SLOT_BAG_END || !proto)
return;
- uint32 itemLevel = item->GetItemLevel(this);
+ ScalingStatDistributionEntry const* ssd = sScalingStatDistributionStore.LookupEntry(proto->GetScalingStatDistributionID());
+ ScalingStatValuesEntry const* ssv = proto->GetScalingStatValue() != 0 ? sDB2Manager.GetScalingStatValuesForLevel(std::clamp<uint32>(GetLevel(), ssd->MinLevel, ssd->MaxLevel)) : nullptr;
- float combatRatingMultiplier = 1.0f;
- //if (GtCombatRatingsMultByILvl const* ratingMult = sCombatRatingsMultByILvlGameTable.GetRow(itemLevel))
- // combatRatingMultiplier = GetIlvlStatMultiplier(ratingMult, proto->GetInventoryType());
+ if (onlyForScalingItems && (!ssd || !ssv))
+ return;
for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
{
- int32 statType = item->GetItemStatType(i);
- if (statType == -1)
- continue;
+ int32 statType = 0;
+ int32 val = 0;
+
+ if (ssd && ssv)
+ {
+ statType = ssd->StatID[i];
+ if (statType == -1)
+ continue;
+
+ val = (ssv->getssdMultiplier(proto->GetScalingStatValue()) * ssd->Bonus[i]) / 10000;
+ }
+ else
+ {
+ statType = proto->GetStatModifierBonusStat(i);
+ if (statType == -1)
+ continue;
+
+ val = proto->GetStatModifierBonusAmount(i);
+ }
- float val = item->GetItemStatValue(i, this);
if (val == 0)
continue;
+ float const combatRatingMultiplier = 1.0f;
+
switch (statType)
{
case ITEM_MOD_MANA:
@@ -7982,11 +7999,24 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
}
}
+ // Apply Spell Power from ScalingStatValue if set
+ if (ssv)
+ if (int32 spellbonus = ssv->getSpellBonus(proto->GetScalingStatValue()))
+ ApplySpellPowerBonus(spellbonus, apply);
+
for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
+ {
+ SpellSchools school = SpellSchools(i);
+ int16 resistance = proto->GetResistance(school);
+ if (school == SPELL_SCHOOL_NORMAL && ssv)
+ if (uint32 ssvarmor = ssv->getArmorMod(proto->GetScalingStatValue()))
+ resistance = ssvarmor;
+
if (int16 resistance = proto->GetResistance(SpellSchools(i)))
HandleStatFlatModifier(UnitMods(UNIT_MOD_ARMOR + i), BASE_VALUE, float(resistance), apply);
+ }
- if (int16 shieldBlockValue = proto->GetShieldBlockValue(itemLevel))
+ if (int16 shieldBlockValue = proto->GetShieldBlockValue(proto->GetItemLevel()))
if (proto->GetClass() == ITEM_CLASS_ARMOR && proto->GetSubClass() == ITEM_SUBCLASS_ARMOR_SHIELD)
SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ShieldBlock), apply ? shieldBlockValue : 0);
@@ -8611,7 +8641,7 @@ void Player::_ApplyAllLevelScaleItemMods(bool apply)
if (!CanUseAttackType(Player::GetAttackBySlot(i, m_items[i]->GetTemplate()->GetInventoryType())))
continue;
- _ApplyItemMods(m_items[i], i, apply);
+ _ApplyItemMods(m_items[i], i, apply, true);
// Update item sets for heirlooms
if (sDB2Manager.GetHeirloomByItemId(m_items[i]->GetEntry()) && m_items[i]->GetTemplate()->GetItemSet())
@@ -22355,7 +22385,7 @@ bool Player::BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uin
if (crItem->maxcount != 0) // bought
{
- if (pProto->GetQuality() > ITEM_QUALITY_EPIC || (pProto->GetQuality() == ITEM_QUALITY_EPIC && pProto->GetBaseItemLevel() >= MinNewsItemLevel))
+ if (pProto->GetQuality() > ITEM_QUALITY_EPIC || (pProto->GetQuality() == ITEM_QUALITY_EPIC && pProto->GetItemLevel() >= MinNewsItemLevel))
if (Guild* guild = GetGuild())
guild->AddGuildNews(GUILD_NEWS_ITEM_PURCHASED, GetGUID(), 0, item);
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 7b9d2c03aa6..976e52fbc93 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2286,11 +2286,11 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
bool CheckAttackFitToAuraRequirement(WeaponAttackType attackType, AuraEffect const* aurEff) const override;
- void _ApplyItemMods(Item* item, uint8 slot, bool apply, bool updateItemAuras = true);
+ void _ApplyItemMods(Item* item, uint8 slot, bool apply, bool updateItemAuras = true, bool onlyForScalingItems = false);
void _RemoveAllItemMods();
void _ApplyAllItemMods();
void _ApplyAllLevelScaleItemMods(bool apply);
- void _ApplyItemBonuses(Item* item, uint8 slot, bool apply);
+ void _ApplyItemBonuses(Item* item, uint8 slot, bool apply, bool onlyForScalingItems = false);
void _ApplyWeaponDamage(uint8 slot, Item* item, bool apply);
bool EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot) const;
void ToggleMetaGemsActive(uint8 exceptslot, bool apply);
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index e4de9b8caa1..dae21c41307 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -6098,7 +6098,7 @@ SpellCastResult Spell::CheckCast(bool strict, int32* param1 /*= nullptr*/, int32
if (!pet->HaveInDiet(foodItem->GetTemplate()))
return SPELL_FAILED_WRONG_PET_FOOD;
- if (foodItem->GetTemplate()->GetBaseItemLevel() + 30 <= pet->GetLevel())
+ if (foodItem->GetTemplate()->GetItemLevel() + 30 <= pet->GetLevel())
return SPELL_FAILED_FOOD_LOWLEVEL;
if (m_caster->ToPlayer()->IsInCombat() || pet->IsInCombat())
@@ -7564,9 +7564,9 @@ SpellCastResult Spell::CheckItems(int32* param1 /*= nullptr*/, int32* param2 /*=
// Apply item level restriction if the enchanting spell has max level restrition set
if (m_CastItem && m_spellInfo->MaxLevel > 0)
{
- if (item->GetTemplate()->GetBaseItemLevel() < (uint32)m_CastItem->GetTemplate()->GetBaseRequiredLevel())
+ if (item->GetTemplate()->GetItemLevel() < (uint32)m_CastItem->GetTemplate()->GetBaseRequiredLevel())
return SPELL_FAILED_LOWLEVEL;
- if (item->GetTemplate()->GetBaseItemLevel() > m_spellInfo->MaxLevel)
+ if (item->GetTemplate()->GetItemLevel() > m_spellInfo->MaxLevel)
return SPELL_FAILED_HIGHLEVEL;
}
break;
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 50125aa4406..d6a7e320cd1 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -3491,7 +3491,7 @@ void Spell::EffectFeedPet()
ExecuteLogEffectDestroyItem(SpellEffectName(effectInfo->Effect), foodItem->GetEntry());
int32 pct;
- int32 levelDiff = int32(pet->GetLevel()) - int32(foodItem->GetTemplate()->GetBaseItemLevel());
+ int32 levelDiff = int32(pet->GetLevel()) - int32(foodItem->GetTemplate()->GetItemLevel());
if (levelDiff >= 30)
return;
else if (levelDiff >= 20)