aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Player/Player.cpp72
-rw-r--r--src/server/game/Entities/Player/Player.h5
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp21
3 files changed, 55 insertions, 43 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index c0a9397bda6..b8cf9aa206d 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -7272,22 +7272,36 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply, bool updateItemA
TC_LOG_DEBUG("entities.player.items", "Player::_ApplyItemMods: completed");
}
-void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply, bool only_level_scale /*= false*/)
+ScalingStatDistributionEntry const* Player::GetScalingStatDistributionFor(ItemTemplate const& itemTemplate) const
{
- if (slot >= INVENTORY_SLOT_BAG_END || !proto)
- return;
+ if (!itemTemplate.ScalingStatDistribution)
+ return nullptr;
- ScalingStatDistributionEntry const* ssd = proto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(proto->ScalingStatDistribution) : nullptr;
- if (only_level_scale && !ssd)
- return;
+ return sScalingStatDistributionStore.LookupEntry(itemTemplate.ScalingStatDistribution);
+}
+
+ScalingStatValuesEntry const* Player::GetScalingStatValuesFor(ItemTemplate const& itemTemplate) const
+{
+ if (!itemTemplate.ScalingStatValue)
+ return nullptr;
+
+ ScalingStatDistributionEntry const* ssd = GetScalingStatDistributionFor(itemTemplate);
+ if (!ssd)
+ return nullptr;
// req. check at equip, but allow use for extended range if range limit max level, set proper level
- uint32 ssd_level = getLevel();
- if (ssd && ssd_level > ssd->MaxLevel)
- ssd_level = ssd->MaxLevel;
+ uint32 const ssd_level = std::min(uint32(getLevel()), ssd->MaxLevel);
+ return sScalingStatValuesStore.LookupEntry(ssd_level);
+}
- ScalingStatValuesEntry const* ssv = proto->ScalingStatValue ? sScalingStatValuesStore.LookupEntry(ssd_level) : nullptr;
- if (only_level_scale && !ssv)
+void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply, bool only_level_scale /*= false*/)
+{
+ if (slot >= INVENTORY_SLOT_BAG_END || !proto)
+ return;
+
+ ScalingStatDistributionEntry const* ssd = GetScalingStatDistributionFor(*proto);
+ ScalingStatValuesEntry const* ssv = GetScalingStatValuesFor(*proto);
+ if (only_level_scale && (!ssd || !ssv))
return;
for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
@@ -7527,7 +7541,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
WeaponAttackType attType = Player::GetAttackBySlot(slot);
if (attType != MAX_ATTACK && CanUseAttackType(attType))
- _ApplyWeaponDamage(slot, proto, ssv, apply);
+ _ApplyWeaponDamage(slot, proto, apply);
// Druids get feral AP bonus from weapon dps (also use DPS from ScalingStatValue)
if (getClass() == CLASS_DRUID)
@@ -7546,12 +7560,13 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
}
}
-void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingStatValuesEntry const* ssv, bool apply)
+void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, bool apply)
{
WeaponAttackType attType = Player::GetAttackBySlot(slot);
if (attType == MAX_ATTACK)
return;
+ ScalingStatValuesEntry const* ssv = GetScalingStatValuesFor(*proto);
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
{
float minDamage = proto->Damage[i].DamageMin;
@@ -7581,22 +7596,21 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
if (!apply)
{
- SetBaseWeaponDamage(attType, MINDAMAGE, BASE_MINDAMAGE, 0);
- SetBaseWeaponDamage(attType, MAXDAMAGE, BASE_MAXDAMAGE, 0);
+ for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
+ {
+ SetBaseWeaponDamage(attType, MINDAMAGE, 0.f, i);
+ SetBaseWeaponDamage(attType, MAXDAMAGE, 0.f, i);
+ }
- SetBaseWeaponDamage(attType, MINDAMAGE, 0.f, 1);
- SetBaseWeaponDamage(attType, MAXDAMAGE, 0.f, 1);
+ if (attType == BASE_ATTACK)
+ {
+ SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, BASE_MINDAMAGE);
+ SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, BASE_MAXDAMAGE);
+ }
}
if (proto->Delay && !IsInFeralForm())
- {
- if (slot == EQUIPMENT_SLOT_RANGED)
- SetAttackTime(RANGED_ATTACK, apply ? proto->Delay: BASE_ATTACK_TIME);
- else if (slot == EQUIPMENT_SLOT_MAINHAND)
- SetAttackTime(BASE_ATTACK, apply ? proto->Delay: BASE_ATTACK_TIME);
- else if (slot == EQUIPMENT_SLOT_OFFHAND)
- SetAttackTime(OFF_ATTACK, apply ? proto->Delay: BASE_ATTACK_TIME);
- }
+ SetAttackTime(attType, apply ? proto->Delay : BASE_ATTACK_TIME);
// No need to modify any physical damage for ferals as it is calculated from stats only
if (IsInFeralForm())
@@ -12190,12 +12204,13 @@ void Player::RemoveItem(uint8 bag, uint8 slot, bool update)
{
if (slot < INVENTORY_SLOT_BAG_END)
{
- ItemTemplate const* pProto = pItem->GetTemplate();
// item set bonuses applied only at equip and removed at unequip, and still active for broken items
-
- if (pProto && pProto->ItemSet)
+ ItemTemplate const* pProto = ASSERT_NOTNULL(pItem->GetTemplate());
+ if (pProto->ItemSet)
RemoveItemsSetItem(this, pProto);
+ // remove here before _ApplyItemMods (for example to register correct damages of unequipped weapon)
+ m_items[slot] = nullptr;
_ApplyItemMods(pItem, slot, false, update);
// remove item dependent auras and casts (only weapon and armor slots)
@@ -12232,7 +12247,6 @@ void Player::RemoveItem(uint8 bag, uint8 slot, bool update)
}
}
- m_items[slot] = nullptr;
SetGuidValue(PLAYER_FIELD_INV_SLOT_HEAD + (slot * 2), ObjectGuid::Empty);
if (slot < EQUIPMENT_SLOT_END)
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 9ca4caa2ee7..2b31206b920 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -46,6 +46,7 @@ struct ItemSetEffect;
struct ItemTemplate;
struct Loot;
struct Mail;
+struct ScalingStatDistributionEntry;
struct ScalingStatValuesEntry;
struct TrainerSpell;
struct VendorItem;
@@ -1826,8 +1827,10 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void _RemoveAllItemMods();
void _ApplyAllItemMods();
void _ApplyAllLevelScaleItemMods(bool apply);
+ ScalingStatDistributionEntry const* GetScalingStatDistributionFor(ItemTemplate const& itemTemplate) const;
+ ScalingStatValuesEntry const* GetScalingStatValuesFor(ItemTemplate const& itemTemplate) const;
void _ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply, bool only_level_scale = false);
- void _ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingStatValuesEntry const* ssv, bool apply);
+ void _ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, bool apply);
void _ApplyAmmoBonuses();
bool EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot) const;
void ToggleMetaGemsActive(uint8 exceptslot, bool apply);
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 30f8cc26479..a77c128e2de 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -1867,9 +1867,7 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
if (!target->CanUseAttackType(BASE_ATTACK))
{
if (Item* pItem = target->ToPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND))
- {
- target->ToPlayer()->_ApplyWeaponDamage(EQUIPMENT_SLOT_MAINHAND, pItem->GetTemplate(), nullptr, apply);
- }
+ target->ToPlayer()->_ApplyWeaponDamage(EQUIPMENT_SLOT_MAINHAND, pItem->GetTemplate(), apply);
}
}
@@ -2277,10 +2275,9 @@ void AuraEffect::HandleAuraModDisarm(AuraApplication const* aurApp, uint8 mode,
Unit* target = aurApp->GetTarget();
- AuraType type = GetAuraType();
-
//Prevent handling aura twice
- if ((apply) ? target->GetAuraEffectsByType(type).size() > 1 : target->HasAuraType(type))
+ AuraType type = GetAuraType();
+ if (apply ? target->GetAuraEffectsByType(type).size() > 1 : target->HasAuraType(type))
return;
uint32 field, flag, slot;
@@ -2309,8 +2306,10 @@ void AuraEffect::HandleAuraModDisarm(AuraApplication const* aurApp, uint8 mode,
return;
}
- // if disarm aura is to be removed, remove the flag first to reapply damage/aura mods
- if (!apply)
+ // set/remove flag before weapon bonuses so it's properly reflected in CanUseAttackType
+ if (apply)
+ target->SetFlag(field, flag);
+ else
target->RemoveFlag(field, flag);
// Handle damage modification, shapeshifted druids are not affected
@@ -2324,17 +2323,13 @@ void AuraEffect::HandleAuraModDisarm(AuraApplication const* aurApp, uint8 mode,
player->ApplyItemDependentAuras(item, !apply);
if (attackType != MAX_ATTACK)
{
- player->_ApplyWeaponDamage(slot, item->GetTemplate(), nullptr, !apply);
+ player->_ApplyWeaponDamage(slot, item->GetTemplate(), !apply);
if (!apply) // apply case already handled on item dependent aura removal (if any)
player->UpdateWeaponDependentAuras(attackType);
}
}
}
- // if disarm effects should be applied, wait to set flag until damage mods are unapplied
- if (apply)
- target->SetFlag(field, flag);
-
if (target->GetTypeId() == TYPEID_UNIT && target->ToCreature()->GetCurrentEquipmentId())
target->UpdateDamagePhysical(attType);
}