diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Item/Item.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Item/ItemTemplate.cpp | 29 | ||||
-rw-r--r-- | src/server/game/Entities/Item/ItemTemplate.h | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 35 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/StatSystem.cpp | 8 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 31 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 5 |
7 files changed, 73 insertions, 38 deletions
diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h index 9861459f114..7aa3e3327da 100644 --- a/src/server/game/Entities/Item/Item.h +++ b/src/server/game/Entities/Item/Item.h @@ -331,8 +331,6 @@ class TC_GAME_API Item : public Object 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); } - uint32 GetArmor(Player const* owner) const { return GetTemplate()->GetArmor(GetItemLevel(owner)); } - void GetDamage(Player const* owner, float& minDamage, float& maxDamage) const { GetTemplate()->GetDamage(GetItemLevel(owner), minDamage, maxDamage); } uint32 GetDisplayId(Player const* owner) const; ItemModifiedAppearanceEntry const* GetItemModifiedAppearance() const; float GetRepairCostMultiplier() const { return _bonusData.RepairCostMultiplier; } diff --git a/src/server/game/Entities/Item/ItemTemplate.cpp b/src/server/game/Entities/Item/ItemTemplate.cpp index b43ff8d31c8..78b4dbe0ea7 100644 --- a/src/server/game/Entities/Item/ItemTemplate.cpp +++ b/src/server/game/Entities/Item/ItemTemplate.cpp @@ -175,16 +175,11 @@ uint32 ItemTemplate::GetArmor(uint32 itemLevel) const return uint32(shield->Quality[quality] + 0.5f); } -void ItemTemplate::GetDamage(uint32 itemLevel, float& minDamage, float& maxDamage) const +float ItemTemplate::GetDPS(uint32 itemLevel) const { - minDamage = maxDamage = 0.0f; uint32 quality = ItemQualities(GetQuality()) != ITEM_QUALITY_HEIRLOOM ? ItemQualities(GetQuality()) : ITEM_QUALITY_RARE; if (GetClass() != ITEM_CLASS_WEAPON || quality > ITEM_QUALITY_ARTIFACT) - return; - - // get the right store here - if (GetInventoryType() > INVTYPE_RANGEDRIGHT) - return; + return 0.0f; float dps = 0.0f; switch (GetInventoryType()) @@ -215,7 +210,7 @@ void ItemTemplate::GetDamage(uint32 itemLevel, float& minDamage, float& maxDamag dps = sItemDamageTwoHandStore.AssertEntry(itemLevel)->Quality[quality]; break; default: - return; + break; } break; case INVTYPE_WEAPON: @@ -227,12 +222,22 @@ void ItemTemplate::GetDamage(uint32 itemLevel, float& minDamage, float& maxDamag dps = sItemDamageOneHandStore.AssertEntry(itemLevel)->Quality[quality]; break; default: - return; + break; } - float avgDamage = dps * GetDelay() * 0.001f; - minDamage = (GetDmgVariance() * -0.5f + 1.0f) * avgDamage; - maxDamage = floor(float(avgDamage * (GetDmgVariance() * 0.5f + 1.0f) + 0.5f)); + return dps; +} + +void ItemTemplate::GetDamage(uint32 itemLevel, float& minDamage, float& maxDamage) const +{ + minDamage = maxDamage = 0.0f; + float dps = GetDPS(itemLevel); + if (dps > 0.0f) + { + float avgDamage = dps * GetDelay() * 0.001f; + minDamage = (GetDmgVariance() * -0.5f + 1.0f) * avgDamage; + maxDamage = floor(float(avgDamage * (GetDmgVariance() * 0.5f + 1.0f) + 0.5f)); + } } bool ItemTemplate::IsUsableByLootSpecialization(Player const* player, bool alwaysAllowBoundToAccount) const diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h index b1c522d5860..86ddaea9e41 100644 --- a/src/server/game/Entities/Item/ItemTemplate.h +++ b/src/server/game/Entities/Item/ItemTemplate.h @@ -826,6 +826,7 @@ struct TC_GAME_API ItemTemplate char const* GetDefaultLocaleName() const; uint32 GetArmor(uint32 itemLevel) const; + float GetDPS(uint32 itemLevel) const; void GetDamage(uint32 itemLevel, float& minDamage, float& maxDamage) const; bool IsUsableByLootSpecialization(Player const* player, bool alwaysAllowBoundToAccount) const; static std::size_t CalculateItemSpecBit(ChrSpecializationEntry const* spec); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index c9525736629..179304144a2 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -7688,21 +7688,11 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply) } } - if (uint32 armor = item->GetArmor(this)) + if (uint32 armor = proto->GetArmor(itemLevel)) HandleStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(armor), apply); - WeaponAttackType attType = BASE_ATTACK; - - if (slot == EQUIPMENT_SLOT_MAINHAND && (proto->GetInventoryType() == INVTYPE_RANGED || proto->GetInventoryType() == INVTYPE_RANGEDRIGHT)) - { - attType = RANGED_ATTACK; - } - else if (slot == EQUIPMENT_SLOT_OFFHAND) - { - attType = OFF_ATTACK; - } - - if (CanUseAttackType(attType)) + WeaponAttackType attType = GetAttackBySlot(slot, proto->GetInventoryType()); + if (attType != MAX_ATTACK && CanUseAttackType(attType)) _ApplyWeaponDamage(slot, item, apply); } @@ -7717,8 +7707,9 @@ void Player::_ApplyWeaponDamage(uint8 slot, Item* item, bool apply) else if (slot == EQUIPMENT_SLOT_OFFHAND) attType = OFF_ATTACK; + uint32 itemLevel = item->GetItemLevel(this); float minDamage, maxDamage; - item->GetDamage(this, minDamage, maxDamage); + proto->GetDamage(itemLevel, minDamage, maxDamage); if (minDamage > 0) { @@ -7736,6 +7727,22 @@ void Player::_ApplyWeaponDamage(uint8 slot, Item* item, bool apply) if (proto->GetDelay() && !(shapeshift && shapeshift->CombatRoundTime)) SetBaseAttackTime(attType, apply ? proto->GetDelay() : BASE_ATTACK_TIME); + int32 weaponBasedAttackPower = apply ? int32(proto->GetDPS(itemLevel) * 6.0f) : 0; + switch (attType) + { + case BASE_ATTACK: + SetMainHandWeaponAttackPower(weaponBasedAttackPower); + break; + case OFF_ATTACK: + SetOffHandWeaponAttackPower(weaponBasedAttackPower); + break; + case RANGED_ATTACK: + SetRangedWeaponAttackPower(weaponBasedAttackPower); + break; + default: + break; + } + if (CanModifyStats() && (damage || proto->GetDelay())) UpdateDamagePhysical(attType); } diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index 7da7282d6f9..fc19f60d77d 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -358,7 +358,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged) SetStatFlatModifier(unitMod, BASE_VALUE, val2); - float base_attPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT); + float base_attPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT); float attPowerMod = GetFlatModifierValue(unitMod, TOTAL_VALUE); float attPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f; @@ -424,7 +424,7 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo float attackPowerMod = std::max(GetAPMultiplier(attType, normalized), 0.25f); - float baseValue = GetFlatModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 3.5f * attackPowerMod; + float baseValue = GetFlatModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType, false) / 3.5f * attackPowerMod; float basePct = GetPctModifierValue(unitMod, BASE_PCT); float totalValue = GetFlatModifierValue(unitMod, TOTAL_VALUE); float totalPct = addTotalPct ? GetPctModifierValue(unitMod, TOTAL_PCT) : 1.0f; @@ -987,7 +987,7 @@ void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, weaponMaxDamage = 0.0f; } - float attackPower = GetTotalAttackPowerValue(attType); + float attackPower = GetTotalAttackPowerValue(attType, false); float attackSpeedMulti = GetAPMultiplier(attType, normalized); float baseValue = GetFlatModifierValue(unitMod, BASE_VALUE) + (attackPower / 3.5f) * variance; float basePct = GetPctModifierValue(unitMod, BASE_PCT) * attackSpeedMulti; @@ -1269,7 +1269,7 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType) float att_speed = float(GetBaseAttackTime(BASE_ATTACK))/1000.0f; - float base_value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 3.5f * att_speed + bonusDamage; + float base_value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType, false) / 3.5f * att_speed + bonusDamage; float base_pct = GetPctModifierValue(unitMod, BASE_PCT); float total_value = GetFlatModifierValue(unitMod, TOTAL_VALUE); float total_pct = GetPctModifierValue(unitMod, TOTAL_PCT); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 9aeb1397b6f..c1c3f5bfa23 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -6696,8 +6696,17 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin ApCoeffMod /= 100.0f; } - WeaponAttackType const attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK; - float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS)); + WeaponAttackType const attType = [&]() + { + if ((spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE)) + return RANGED_ATTACK; + + if (spellProto->HasAttribute(SPELL_ATTR3_REQ_OFFHAND) && !spellProto->HasAttribute(SPELL_ATTR3_MAIN_HAND)) + return OFF_ATTACK; + + return BASE_ATTACK; + }(); + float APbonus = float(victim->GetTotalAuraModifier(attType != RANGED_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS)); APbonus += GetTotalAttackPowerValue(attType); DoneTotal += int32(stack * ApCoeffMod * APbonus); } @@ -9752,18 +9761,30 @@ void Unit::UpdateResistances(uint32 school) UpdateArmor(); } -float Unit::GetTotalAttackPowerValue(WeaponAttackType attType) const +float Unit::GetTotalAttackPowerValue(WeaponAttackType attType, bool includeWeapon /*= true*/) const { if (attType == RANGED_ATTACK) { - int32 ap = m_unitData->RangedAttackPower; + float ap = m_unitData->RangedAttackPower + m_unitData->RangedAttackPowerModPos + m_unitData->RangedAttackPowerModNeg; + if (includeWeapon) + ap += std::max<float>(m_unitData->MainHandWeaponAttackPower, m_unitData->RangedWeaponAttackPower); if (ap < 0) return 0.0f; return ap * (1.0f + m_unitData->RangedAttackPowerMultiplier); } else { - int32 ap = m_unitData->AttackPower; + float ap = m_unitData->AttackPower + m_unitData->AttackPowerModPos + m_unitData->AttackPowerModNeg; + if (includeWeapon) + { + if (attType == BASE_ATTACK) + ap += std::max<float>(m_unitData->MainHandWeaponAttackPower, m_unitData->RangedWeaponAttackPower); + else + { + ap += m_unitData->OffHandWeaponAttackPower; + ap /= 2; + } + } if (ap < 0) return 0.0f; return ap * (1.0f + m_unitData->AttackPowerMultiplier); diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 9c5cdc8fb6a..b9936813d70 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1753,8 +1753,11 @@ class TC_GAME_API Unit : public WorldObject void SetRangedAttackPowerModPos(int32 attackPowerMod) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::RangedAttackPowerModPos), attackPowerMod); } void SetRangedAttackPowerModNeg(int32 attackPowerMod) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::RangedAttackPowerModNeg), attackPowerMod); } void SetRangedAttackPowerMultiplier(float attackPowerMult) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::RangedAttackPowerMultiplier), attackPowerMult); } + void SetMainHandWeaponAttackPower(int32 attackPower) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::MainHandWeaponAttackPower), attackPower); } + void SetOffHandWeaponAttackPower(int32 attackPower) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::OffHandWeaponAttackPower), attackPower); } + void SetRangedWeaponAttackPower(int32 attackPower) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::RangedWeaponAttackPower), attackPower); } virtual void UpdateDamagePhysical(WeaponAttackType attType); - float GetTotalAttackPowerValue(WeaponAttackType attType) const; + float GetTotalAttackPowerValue(WeaponAttackType attType, bool includeWeapon = true) const; float GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange type) const; void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; } virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const = 0; |