aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2020-09-07 20:59:50 +0200
committerShauren <shauren.trinity@gmail.com>2020-09-07 20:59:50 +0200
commitdd21e7ff404aed1d449b09db2b7fcbe2be8536c3 (patch)
treef51435ee96abc57792a5bb4ff10f453d73b49a58 /src
parent3d4910d6baabb6e43c93b2b18012cac23cda774f (diff)
Core/Spells: Implemented using base weapon damage in spell attack power formulas
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Item/Item.h2
-rw-r--r--src/server/game/Entities/Item/ItemTemplate.cpp29
-rw-r--r--src/server/game/Entities/Item/ItemTemplate.h1
-rw-r--r--src/server/game/Entities/Player/Player.cpp35
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp8
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp31
-rw-r--r--src/server/game/Entities/Unit/Unit.h5
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;