diff options
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 72 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 5 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 21 |
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); } |