feat(Core/Items): Implemented elemental weapon damage. Source: Trinit… (#13050)

...yCore.
This commit is contained in:
UltraNix
2022-10-08 19:34:52 +02:00
committed by GitHub
parent 02b3f74d6d
commit e390087efd
13 changed files with 778 additions and 287 deletions
@@ -2156,7 +2156,7 @@ void Creature::LoadSpellTemplateImmunity()
} }
} }
bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo) bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell)
{ {
if (!spellInfo) if (!spellInfo)
return false; return false;
@@ -2178,7 +2178,7 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo)
if (immunedToAllEffects) if (immunedToAllEffects)
return true; return true;
return Unit::IsImmunedToSpell(spellInfo); return Unit::IsImmunedToSpell(spellInfo, spell);
} }
bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const
+3 -3
View File
@@ -96,7 +96,7 @@ public:
[[nodiscard]] bool IsValidTrainerForPlayer(Player* player, uint32* npcFlags = nullptr) const; [[nodiscard]] bool IsValidTrainerForPlayer(Player* player, uint32* npcFlags = nullptr) const;
bool CanCreatureAttack(Unit const* victim, bool skipDistCheck = false) const; bool CanCreatureAttack(Unit const* victim, bool skipDistCheck = false) const;
void LoadSpellTemplateImmunity(); void LoadSpellTemplateImmunity();
bool IsImmunedToSpell(SpellInfo const* spellInfo) override; bool IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell = nullptr) override;
[[nodiscard]] bool HasMechanicTemplateImmunity(uint32 mask) const; [[nodiscard]] bool HasMechanicTemplateImmunity(uint32 mask) const;
// redefine Unit::IsImmunedToSpell // redefine Unit::IsImmunedToSpell
@@ -155,7 +155,7 @@ public:
return (getLevel() / 2 + uint32(GetStat(STAT_STRENGTH) / 20)); return (getLevel() / 2 + uint32(GetStat(STAT_STRENGTH) / 20));
} }
[[nodiscard]] SpellSchoolMask GetMeleeDamageSchoolMask() const override { return m_meleeDamageSchoolMask; } [[nodiscard]] SpellSchoolMask GetMeleeDamageSchoolMask(WeaponAttackType /*attackType*/ = BASE_ATTACK, uint8 /*damageIndex*/ = 0) const override { return m_meleeDamageSchoolMask; }
void SetMeleeDamageSchool(SpellSchools school) { m_meleeDamageSchoolMask = SpellSchoolMask(1 << school); } void SetMeleeDamageSchool(SpellSchools school) { m_meleeDamageSchoolMask = SpellSchoolMask(1 << school); }
void _AddCreatureSpellCooldown(uint32 spell_id, uint16 categoryId, uint32 end_time); void _AddCreatureSpellCooldown(uint32 spell_id, uint16 categoryId, uint32 end_time);
@@ -178,7 +178,7 @@ public:
void UpdateMaxHealth() override; void UpdateMaxHealth() override;
void UpdateMaxPower(Powers power) override; void UpdateMaxPower(Powers power) override;
void UpdateAttackPowerAndDamage(bool ranged = false) override; void UpdateAttackPowerAndDamage(bool ranged = false) override;
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) override; void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage, uint8 damageIndex) override;
void SetCanDualWield(bool value) override; void SetCanDualWield(bool value) override;
[[nodiscard]] int8 GetOriginalEquipmentId() const { return m_originalEquipmentId; } [[nodiscard]] int8 GetOriginalEquipmentId() const { return m_originalEquipmentId; }
+55 -44
View File
@@ -6740,21 +6740,11 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
if (proto->ArcaneRes) if (proto->ArcaneRes)
HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(proto->ArcaneRes), apply); HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(proto->ArcaneRes), apply);
WeaponAttackType attType = BASE_ATTACK; uint8 attType = Player::GetAttackBySlot(slot);
if (attType != MAX_ATTACK)
if (slot == EQUIPMENT_SLOT_RANGED && (
proto->InventoryType == INVTYPE_RANGED || proto->InventoryType == INVTYPE_THROWN ||
proto->InventoryType == INVTYPE_RANGEDRIGHT))
{ {
attType = RANGED_ATTACK;
}
else if (slot == EQUIPMENT_SLOT_OFFHAND)
{
attType = OFF_ATTACK;
}
if (CanUseAttackType(attType))
_ApplyWeaponDamage(slot, proto, ssv, apply); _ApplyWeaponDamage(slot, proto, ssv, apply);
}
// Druids get feral AP bonus from weapon dps (also use DPS from ScalingStatValue) // Druids get feral AP bonus from weapon dps (also use DPS from ScalingStatValue)
if (getClass() == CLASS_DRUID) if (getClass() == CLASS_DRUID)
@@ -6797,45 +6787,56 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
ssv = ScalingStatValue ? sScalingStatValuesStore.LookupEntry(ssd_level) : nullptr; ssv = ScalingStatValue ? sScalingStatValuesStore.LookupEntry(ssd_level) : nullptr;
} }
WeaponAttackType attType = BASE_ATTACK; uint8 attType = Player::GetAttackBySlot(slot);
float damage = 0.0f; if (!IsInFeralForm() && apply && !CanUseAttackType(attType))
if (slot == EQUIPMENT_SLOT_RANGED && (
proto->InventoryType == INVTYPE_RANGED || proto->InventoryType == INVTYPE_THROWN ||
proto->InventoryType == INVTYPE_RANGEDRIGHT))
{ {
attType = RANGED_ATTACK; return;
}
else if (slot == EQUIPMENT_SLOT_OFFHAND)
{
attType = OFF_ATTACK;
} }
float minDamage = proto->Damage[0].DamageMin; for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
float maxDamage = proto->Damage[0].DamageMax;
// If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage
if (ssv)
{ {
int32 extraDPS = ssv->getDPSMod(ScalingStatValue); float minDamage = proto->Damage[i].DamageMin;
if (extraDPS) float maxDamage = proto->Damage[i].DamageMax;
// If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage
if (ssv)
{ {
float average = extraDPS * proto->Delay / 1000.0f; int32 extraDPS = ssv->getDPSMod(ScalingStatValue);
minDamage = 0.7f * average; if (extraDPS)
maxDamage = 1.3f * average; {
float average = extraDPS * proto->Delay / 1000.0f;
minDamage = 0.7f * average;
maxDamage = 1.3f * average;
}
}
if (apply)
{
if (minDamage > 0.f)
{
SetBaseWeaponDamage(WeaponAttackType(attType), MINDAMAGE, minDamage, i);
}
if (maxDamage > 0.f)
{
SetBaseWeaponDamage(WeaponAttackType(attType), MAXDAMAGE, maxDamage, i);
}
} }
} }
if (minDamage > 0) if (!apply)
{ {
damage = apply ? minDamage : BASE_MINDAMAGE; for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
SetBaseWeaponDamage(attType, MINDAMAGE, damage); {
} SetBaseWeaponDamage(WeaponAttackType(attType), MINDAMAGE, 0.f, i);
SetBaseWeaponDamage(WeaponAttackType(attType), MAXDAMAGE, 0.f, i);
}
if (maxDamage > 0) if (attType == BASE_ATTACK)
{ {
damage = apply ? maxDamage : BASE_MAXDAMAGE; SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, BASE_MINDAMAGE);
SetBaseWeaponDamage(attType, MAXDAMAGE, damage); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, BASE_MAXDAMAGE);
}
} }
if (proto->Delay && !IsInFeralForm()) if (proto->Delay && !IsInFeralForm())
@@ -6852,8 +6853,18 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
if (IsInFeralForm()) if (IsInFeralForm())
return; return;
if (CanModifyStats() && (damage || proto->Delay)) if (CanModifyStats() && (GetWeaponDamageRange(WeaponAttackType(attType), MAXDAMAGE) || proto->Delay))
UpdateDamagePhysical(attType); UpdateDamagePhysical(WeaponAttackType(attType));
}
SpellSchoolMask Player::GetMeleeDamageSchoolMask(WeaponAttackType attackType /*= BASE_ATTACK*/, uint8 damageIndex /*= 0*/) const
{
if (Item const* weapon = GetWeaponForAttack(attackType, true))
{
return SpellSchoolMask(1 << weapon->GetTemplate()->Damage[damageIndex].DamageType);
}
return SPELL_SCHOOL_MASK_NORMAL;
} }
void Player::_ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackType, bool apply) void Player::_ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackType, bool apply)
+3 -1
View File
@@ -1905,7 +1905,7 @@ public:
void UpdateRating(CombatRating cr); void UpdateRating(CombatRating cr);
void UpdateAllRatings(); void UpdateAllRatings();
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) override; void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage, uint8 damageIndex) override;
void UpdateDefenseBonusesMod(); void UpdateDefenseBonusesMod();
inline void RecalculateRating(CombatRating cr) { ApplyRatingMod(cr, 0, true);} inline void RecalculateRating(CombatRating cr) { ApplyRatingMod(cr, 0, true);}
@@ -2147,6 +2147,8 @@ public:
void ResetAllPowers(); void ResetAllPowers();
SpellSchoolMask GetMeleeDamageSchoolMask(WeaponAttackType attackType = BASE_ATTACK, uint8 damageIndex = 0) const override;
void _ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackType, bool apply); void _ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackType, bool apply);
void _ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply); void _ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply);
void _ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply); void _ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply);
+40 -11
View File
@@ -59,25 +59,31 @@ void Unit::UpdateAllResistances()
void Unit::UpdateDamagePhysical(WeaponAttackType attType) void Unit::UpdateDamagePhysical(WeaponAttackType attType)
{ {
float minDamage = 0.0f; float totalMin = 0.f;
float maxDamage = 0.0f; float totalMax = 0.f;
CalculateMinMaxDamage(attType, false, true, minDamage, maxDamage); for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
{
float tmpMin, tmpMax;
CalculateMinMaxDamage(attType, false, true, tmpMin, tmpMax, i);
totalMin += tmpMin;
totalMax += tmpMax;
}
switch (attType) switch (attType)
{ {
case BASE_ATTACK: case BASE_ATTACK:
default: default:
SetStatFloatValue(UNIT_FIELD_MINDAMAGE, minDamage); SetStatFloatValue(UNIT_FIELD_MINDAMAGE, totalMin);
SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxDamage); SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, totalMax);
break; break;
case OFF_ATTACK: case OFF_ATTACK:
SetStatFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, minDamage); SetStatFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, totalMin);
SetStatFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, maxDamage); SetStatFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, totalMax);
break; break;
case RANGED_ATTACK: case RANGED_ATTACK:
SetStatFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, minDamage); SetStatFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, totalMin);
SetStatFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, maxDamage); SetStatFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, totalMax);
break; break;
} }
} }
@@ -525,8 +531,23 @@ void Player::UpdateShieldBlockValue()
SetUInt32Value(PLAYER_SHIELD_BLOCK, GetShieldBlockValue()); SetUInt32Value(PLAYER_SHIELD_BLOCK, GetShieldBlockValue());
} }
void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage, uint8 damageIndex)
{ {
// Only proto damage, not affected by any mods
if (damageIndex != 0)
{
minDamage = 0.0f;
maxDamage = 0.0f;
if (!IsInFeralForm() && CanUseAttackType(attType))
{
minDamage = GetWeaponDamageRange(attType, MINDAMAGE, damageIndex);
maxDamage = GetWeaponDamageRange(attType, MAXDAMAGE, damageIndex);
}
return;
}
UnitMods unitMod; UnitMods unitMod;
switch (attType) switch (attType)
@@ -1075,8 +1096,16 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged)
} }
} }
void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage, uint8 damageIndex /*= 0*/)
{ {
// creatures only have one damage
if (damageIndex != 0)
{
minDamage = 0.f;
maxDamage = 0.f;
return;
}
UnitMods unitMod; UnitMods unitMod;
float variance = 1.0f; float variance = 1.0f;
switch (attType) switch (attType)
File diff suppressed because it is too large Load Diff
+38 -22
View File
@@ -23,6 +23,7 @@
#include "FollowerRefMgr.h" #include "FollowerRefMgr.h"
#include "FollowerReference.h" #include "FollowerReference.h"
#include "HostileRefMgr.h" #include "HostileRefMgr.h"
#include "ItemTemplate.h"
#include "MotionMaster.h" #include "MotionMaster.h"
#include "Object.h" #include "Object.h"
#include "Optional.h" #include "Optional.h"
@@ -251,7 +252,9 @@ enum UnitModifierType
enum WeaponDamageRange enum WeaponDamageRange
{ {
MINDAMAGE, MINDAMAGE,
MAXDAMAGE MAXDAMAGE,
MAX_WEAPON_DAMAGE_RANGE
}; };
enum UnitMods enum UnitMods
@@ -762,9 +765,14 @@ private:
uint32 m_resist; uint32 m_resist;
uint32 m_block; uint32 m_block;
uint32 m_cleanDamage; uint32 m_cleanDamage;
// amalgamation constructor (used for proc)
DamageInfo(DamageInfo const& dmg1, DamageInfo const& dmg2);
public: public:
explicit DamageInfo(Unit* _attacker, Unit* _victim, uint32 _damage, SpellInfo const* _spellInfo, SpellSchoolMask _schoolMask, DamageEffectType _damageType, uint32 cleanDamage = 0); explicit DamageInfo(Unit* _attacker, Unit* _victim, uint32 _damage, SpellInfo const* _spellInfo, SpellSchoolMask _schoolMask, DamageEffectType _damageType, uint32 cleanDamage = 0);
explicit DamageInfo(CalcDamageInfo& dmgInfo); explicit DamageInfo(CalcDamageInfo const& dmgInfo); // amalgamation wrapper
DamageInfo(CalcDamageInfo const& dmgInfo, uint8 damageIndex);
DamageInfo(SpellNonMeleeDamage const& spellNonMeleeDamage, DamageEffectType damageType); DamageInfo(SpellNonMeleeDamage const& spellNonMeleeDamage, DamageEffectType damageType);
void ModifyDamage(int32 amount); void ModifyDamage(int32 amount);
@@ -868,10 +876,15 @@ struct CalcDamageInfo
{ {
Unit* attacker; // Attacker Unit* attacker; // Attacker
Unit* target; // Target for damage Unit* target; // Target for damage
uint32 damageSchoolMask;
uint32 damage; struct
uint32 absorb; {
uint32 resist; uint32 damageSchoolMask;
uint32 damage;
uint32 absorb;
uint32 resist;
} damages[MAX_ITEM_PROTO_DAMAGES];
uint32 blocked_amount; uint32 blocked_amount;
uint32 HitInfo; uint32 HitInfo;
uint32 TargetState; uint32 TargetState;
@@ -1331,7 +1344,7 @@ public:
bool IsWithinCombatRange(Unit const* obj, float dist2compare) const; bool IsWithinCombatRange(Unit const* obj, float dist2compare) const;
bool IsWithinMeleeRange(Unit const* obj, float dist = 0.f) const; bool IsWithinMeleeRange(Unit const* obj, float dist = 0.f) const;
float GetMeleeRange(Unit const* target) const; float GetMeleeRange(Unit const* target) const;
[[nodiscard]] virtual SpellSchoolMask GetMeleeDamageSchoolMask() const; virtual SpellSchoolMask GetMeleeDamageSchoolMask(WeaponAttackType attackType = BASE_ATTACK, uint8 damageIndex = 0) const = 0;
bool GetRandomContactPoint(Unit const* target, float& x, float& y, float& z, bool force = false) const; bool GetRandomContactPoint(Unit const* target, float& x, float& y, float& z, bool force = false) const;
uint32 m_extraAttacks; uint32 m_extraAttacks;
bool m_canDualWield; bool m_canDualWield;
@@ -1540,7 +1553,7 @@ public:
void HandleEmoteCommand(uint32 emoteId); void HandleEmoteCommand(uint32 emoteId);
void AttackerStateUpdate (Unit* victim, WeaponAttackType attType = BASE_ATTACK, bool extra = false, bool ignoreCasting = false); void AttackerStateUpdate (Unit* victim, WeaponAttackType attType = BASE_ATTACK, bool extra = false, bool ignoreCasting = false);
void CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* damageInfo, WeaponAttackType attackType = BASE_ATTACK, const bool sittingVictim = false); void CalculateMeleeDamage(Unit* victim, CalcDamageInfo* damageInfo, WeaponAttackType attackType = BASE_ATTACK, const bool sittingVictim = false);
void DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss); void DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss);
void HandleProcExtraAttackFor(Unit* victim, uint32 count); void HandleProcExtraAttackFor(Unit* victim, uint32 count);
@@ -1570,10 +1583,11 @@ public:
static void ApplyResilience(Unit const* victim, float* crit, int32* damage, bool isCrit, CombatRating type); static void ApplyResilience(Unit const* victim, float* crit, int32* damage, bool isCrit, CombatRating type);
float MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const; [[nodiscard]] float MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const;
SpellMissInfo MeleeSpellHitResult(Unit* victim, SpellInfo const* spell); [[nodiscard]] SpellMissInfo MeleeSpellHitResult(Unit* victim, SpellInfo const* spell);
SpellMissInfo MagicSpellHitResult(Unit* victim, SpellInfo const* spell); [[nodiscard]] SpellMissInfo MagicSpellHitResult(Unit* victim, SpellInfo const* spell);
SpellMissInfo SpellHitResult(Unit* victim, SpellInfo const* spell, bool canReflect = false); [[nodiscard]] SpellMissInfo SpellHitResult(Unit* victim, SpellInfo const* spell, bool canReflect = false);
[[nodiscard]] SpellMissInfo SpellHitResult(Unit* victim, Spell const* spell, bool canReflect = false);
[[nodiscard]] float GetUnitDodgeChance() const; [[nodiscard]] float GetUnitDodgeChance() const;
[[nodiscard]] float GetUnitParryChance() const; [[nodiscard]] float GetUnitParryChance() const;
@@ -2091,10 +2105,10 @@ public:
virtual void UpdateAttackPowerAndDamage(bool ranged = false) = 0; virtual void UpdateAttackPowerAndDamage(bool ranged = false) = 0;
virtual void UpdateDamagePhysical(WeaponAttackType attType); virtual void UpdateDamagePhysical(WeaponAttackType attType);
float GetTotalAttackPowerValue(WeaponAttackType attType, Unit* pVictim = nullptr) const; float GetTotalAttackPowerValue(WeaponAttackType attType, Unit* pVictim = nullptr) const;
[[nodiscard]] float GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange type) const; [[nodiscard]] float GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange type, uint8 damageIndex = 0) const;
void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; } void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value, uint8 damageIndex = 0) { m_weaponDamage[attType][damageRange][damageIndex] = value; }
virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) = 0; virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage, uint8 damageIndex = 0) = 0;
uint32 CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct); uint32 CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, uint8 itemDamagesMask = 0);
float GetAPMultiplier(WeaponAttackType attType, bool normalized); float GetAPMultiplier(WeaponAttackType attType, bool normalized);
bool isInFrontInMap(Unit const* target, float distance, float arc = M_PI) const; bool isInFrontInMap(Unit const* target, float distance, float arc = M_PI) const;
@@ -2179,8 +2193,8 @@ public:
uint32 SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint8 effIndex, float TotalMod = 0.0f, uint32 stack = 1); uint32 SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint8 effIndex, float TotalMod = 0.0f, uint32 stack = 1);
uint32 SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1); uint32 SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1);
uint32 MeleeDamageBonusDone(Unit* pVictim, uint32 damage, WeaponAttackType attType, SpellInfo const* spellProto = nullptr); uint32 MeleeDamageBonusDone(Unit* pVictim, uint32 damage, WeaponAttackType attType, SpellInfo const* spellProto = nullptr, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL);
uint32 MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto = nullptr); uint32 MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto = nullptr, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL);
bool isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType = BASE_ATTACK); bool isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType = BASE_ATTACK);
bool isBlockCritical(); bool isBlockCritical();
@@ -2201,12 +2215,14 @@ public:
void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply, SpellImmuneBlockType blockType = SPELL_BLOCK_TYPE_ALL); void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply, SpellImmuneBlockType blockType = SPELL_BLOCK_TYPE_ALL);
void ApplySpellDispelImmunity(SpellInfo const* spellProto, DispelType type, bool apply); void ApplySpellDispelImmunity(SpellInfo const* spellProto, DispelType type, bool apply);
virtual bool IsImmunedToSpell(SpellInfo const* spellInfo); virtual bool IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell = nullptr);
// redefined in Creature // redefined in Creature
[[nodiscard]] bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const; [[nodiscard]] bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const;
bool IsImmunedToDamage(SpellInfo const* spellInfo) const; [[nodiscard]] bool IsImmunedToDamage(SpellInfo const* spellInfo) const;
[[nodiscard]] bool IsImmunedToDamage(Spell const* spell) const;
[[nodiscard]] bool IsImmunedToSchool(SpellSchoolMask meleeSchoolMask) const; [[nodiscard]] bool IsImmunedToSchool(SpellSchoolMask meleeSchoolMask) const;
bool IsImmunedToSchool(SpellInfo const* spellInfo) const; [[nodiscard]] bool IsImmunedToSchool(SpellInfo const* spellInfo) const;
[[nodiscard]] bool IsImmunedToSchool(Spell const* spell) const;
[[nodiscard]] bool IsImmunedToDamageOrSchool(SpellSchoolMask meleeSchoolMask) const; [[nodiscard]] bool IsImmunedToDamageOrSchool(SpellSchoolMask meleeSchoolMask) const;
bool IsImmunedToDamageOrSchool(SpellInfo const* spellInfo) const; bool IsImmunedToDamageOrSchool(SpellInfo const* spellInfo) const;
virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const; virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const;
@@ -2484,7 +2500,7 @@ protected:
uint32 m_interruptMask; uint32 m_interruptMask;
float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END]; float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END];
float m_weaponDamage[MAX_ATTACK][2]; float m_weaponDamage[MAX_ATTACK][MAX_WEAPON_DAMAGE_RANGE][MAX_ITEM_PROTO_DAMAGES];
bool m_canModifyStats; bool m_canModifyStats;
VisibleAuraMap m_visibleAuras; VisibleAuraMap m_visibleAuras;
+7 -3
View File
@@ -2428,9 +2428,11 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*=
// Calculate hit result // Calculate hit result
if (m_originalCaster) if (m_originalCaster)
{ {
targetInfo.missCondition = m_originalCaster->SpellHitResult(target, m_spellInfo, m_canReflect); targetInfo.missCondition = m_originalCaster->SpellHitResult(target, this, m_canReflect);
if (m_skipCheck && targetInfo.missCondition != SPELL_MISS_IMMUNE) if (m_skipCheck && targetInfo.missCondition != SPELL_MISS_IMMUNE)
{
targetInfo.missCondition = SPELL_MISS_NONE; targetInfo.missCondition = SPELL_MISS_NONE;
}
} }
else else
targetInfo.missCondition = SPELL_MISS_EVADE; //SPELL_MISS_NONE; targetInfo.missCondition = SPELL_MISS_EVADE; //SPELL_MISS_NONE;
@@ -2458,7 +2460,7 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*=
if (targetInfo.missCondition == SPELL_MISS_REFLECT) if (targetInfo.missCondition == SPELL_MISS_REFLECT)
{ {
// Calculate reflected spell result on caster // Calculate reflected spell result on caster
targetInfo.reflectResult = m_caster->SpellHitResult(m_caster, m_spellInfo, m_canReflect); targetInfo.reflectResult = m_caster->SpellHitResult(m_caster, this, m_canReflect);
if (targetInfo.reflectResult == SPELL_MISS_REFLECT) // Impossible reflect again, so simply deflect spell if (targetInfo.reflectResult == SPELL_MISS_REFLECT) // Impossible reflect again, so simply deflect spell
targetInfo.reflectResult = SPELL_MISS_PARRY; targetInfo.reflectResult = SPELL_MISS_PARRY;
@@ -2971,8 +2973,10 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
return SPELL_MISS_EVADE; return SPELL_MISS_EVADE;
// For delayed spells immunity may be applied between missile launch and hit - check immunity for that case // For delayed spells immunity may be applied between missile launch and hit - check immunity for that case
if (m_spellInfo->Speed && ((m_damage > 0 && unit->IsImmunedToDamage(m_spellInfo)) || unit->IsImmunedToSchool(m_spellInfo) || unit->IsImmunedToSpell(m_spellInfo))) if (m_spellInfo->Speed && ((m_damage > 0 && unit->IsImmunedToDamage(this)) || unit->IsImmunedToSchool(this) || unit->IsImmunedToSpell(m_spellInfo, this)))
{
return SPELL_MISS_IMMUNE; return SPELL_MISS_IMMUNE;
}
// disable effects to which unit is immune // disable effects to which unit is immune
SpellMissInfo returnVal = SPELL_MISS_IMMUNE; SpellMissInfo returnVal = SPELL_MISS_IMMUNE;
+2
View File
@@ -589,6 +589,8 @@ public:
[[nodiscard]] TriggerCastFlags GetTriggeredCastFlags() const { return _triggeredCastFlags; } [[nodiscard]] TriggerCastFlags GetTriggeredCastFlags() const { return _triggeredCastFlags; }
[[nodiscard]] SpellSchoolMask GetSpellSchoolMask() const { return m_spellSchoolMask; }
protected: protected:
bool HasGlobalCooldown() const; bool HasGlobalCooldown() const;
void TriggerGlobalCooldown(); void TriggerGlobalCooldown();
+21 -7
View File
@@ -593,8 +593,14 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
if (Player* caster = m_caster->ToPlayer()) if (Player* caster = m_caster->ToPlayer())
{ {
// Add Ammo and Weapon damage plus RAP * 0.1 // Add Ammo and Weapon damage plus RAP * 0.1
float dmg_min = caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE); float dmg_min = 0.f;
float dmg_max = caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE); float dmg_max = 0.f;
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
{
dmg_min += caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE, i);
dmg_max += caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE, i);
}
if (dmg_max == 0.0f && dmg_min > dmg_max) if (dmg_max == 0.0f && dmg_min > dmg_max)
{ {
damage += int32(dmg_min); damage += int32(dmg_min);
@@ -616,9 +622,17 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
// Add main hand dps * effect[2] amount // Add main hand dps * effect[2] amount
if (Player* player = m_caster->ToPlayer()) if (Player* player = m_caster->ToPlayer())
{ {
float mindamage, maxdamage; float minTotal = 0.f;
player->CalculateMinMaxDamage(BASE_ATTACK, false, false, mindamage, maxdamage); float maxTotal = 0.f;
float average = (mindamage + maxdamage) / 2; for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
{
float tmpMin, tmpMax;
player->CalculateMinMaxDamage(BASE_ATTACK, false, false, tmpMin, tmpMax, i);
minTotal += tmpMin;
maxTotal += tmpMax;
}
float average = (minTotal + maxTotal) / 2;
int32 count = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, EFFECT_2); int32 count = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, EFFECT_2);
damage += count * int32(average * IN_MILLISECONDS) / m_caster->GetAttackTime(BASE_ATTACK); damage += count * int32(average * IN_MILLISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
} }
@@ -3644,8 +3658,8 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
uint32 eff_damage(std::max(weaponDamage, 0)); uint32 eff_damage(std::max(weaponDamage, 0));
// Add melee damage bonuses (also check for negative) // Add melee damage bonuses (also check for negative)
eff_damage = m_caster->MeleeDamageBonusDone(unitTarget, eff_damage, m_attackType, m_spellInfo); eff_damage = m_caster->MeleeDamageBonusDone(unitTarget, eff_damage, m_attackType, m_spellInfo, m_spellSchoolMask);
eff_damage = unitTarget->MeleeDamageBonusTaken(m_caster, eff_damage, m_attackType, m_spellInfo); eff_damage = unitTarget->MeleeDamageBonusTaken(m_caster, eff_damage, m_attackType, m_spellInfo, m_spellSchoolMask);
// Meteor like spells (divided damage to targets) // Meteor like spells (divided damage to targets)
if (m_spellInfo->HasAttribute(SPELL_ATTR0_CU_SHARE_DAMAGE)) if (m_spellInfo->HasAttribute(SPELL_ATTR0_CU_SHARE_DAMAGE))
@@ -15,6 +15,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "Player.h"
#include "ScriptMgr.h" #include "ScriptMgr.h"
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "SpellScript.h" #include "SpellScript.h"
@@ -131,13 +132,25 @@ struct boss_viscidus : public BossAI
me->RemoveAurasDueToSpell(SPELL_INVIS_SELF); me->RemoveAurasDueToSpell(SPELL_INVIS_SELF);
} }
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType effType, SpellSchoolMask) override void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType effType, SpellSchoolMask spellSchoolMask) override
{ {
if (me->HealthBelowPct(5)) if (me->HealthBelowPct(5))
damage = 0; damage = 0;
if (!attacker || _phase != PHASE_MELEE) if (!attacker)
{
return; return;
}
if (_phase != PHASE_MELEE)
{
if (_phase == PHASE_FROST && effType == DIRECT_DAMAGE && (spellSchoolMask & SPELL_SCHOOL_MASK_FROST) != 0)
{
++_hitcounter;
}
return;
}
if (effType == DIRECT_DAMAGE) if (effType == DIRECT_DAMAGE)
++_hitcounter; ++_hitcounter;
@@ -183,14 +196,23 @@ struct boss_viscidus : public BossAI
Talk(EMOTE_CRACK); Talk(EMOTE_CRACK);
} }
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override void SpellHit(Unit* caster, SpellInfo const* spellInfo) override
{ {
if (spell->Id == SPELL_REJOIN_VISCIDUS) if (spellInfo->Id == SPELL_REJOIN_VISCIDUS)
{ {
me->RemoveAuraFromStack(SPELL_VISCIDUS_SHRINKS); me->RemoveAuraFromStack(SPELL_VISCIDUS_SHRINKS);
} }
if ((spell->GetSchoolMask() & SPELL_SCHOOL_MASK_FROST) && _phase == PHASE_FROST) SpellSchoolMask spellSchoolMask = spellInfo->GetSchoolMask();
if (spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && spellInfo->EquippedItemSubClassMask & (1 << ITEM_SUBCLASS_WEAPON_WAND))
{
if (Item* pItem = caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK))
{
spellSchoolMask = SpellSchoolMask(1 << pItem->GetTemplate()->Damage[0].DamageType);
}
}
if ((spellSchoolMask & SPELL_SCHOOL_MASK_FROST) && _phase == PHASE_FROST)
{ {
++_hitcounter; ++_hitcounter;
+6 -3
View File
@@ -648,10 +648,13 @@ class spell_dk_dancing_rune_weapon : public AuraScript
{ {
target = player->GetMeleeHitRedirectTarget(target); target = player->GetMeleeHitRedirectTarget(target);
CalcDamageInfo damageInfo; CalcDamageInfo damageInfo;
player->CalculateMeleeDamage(target, 0, &damageInfo, eventInfo.GetDamageInfo()->GetAttackType()); player->CalculateMeleeDamage(target, &damageInfo, eventInfo.GetDamageInfo()->GetAttackType());
Unit::DealDamageMods(target, damageInfo.damage, &damageInfo.absorb); for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
{
Unit::DealDamageMods(target, damageInfo.damages[i].damage, &damageInfo.damages[i].absorb);
damageInfo.damages[i].damage /= 2.0f;
}
damageInfo.attacker = dancingRuneWeapon; damageInfo.attacker = dancingRuneWeapon;
damageInfo.damage /= 2.0f;
dancingRuneWeapon->SendAttackStateUpdate(&damageInfo); dancingRuneWeapon->SendAttackStateUpdate(&damageInfo);
dancingRuneWeapon->DealMeleeDamage(&damageInfo, true); dancingRuneWeapon->DealMeleeDamage(&damageInfo, true);
} }
+8 -2
View File
@@ -567,8 +567,14 @@ class spell_warr_rend : public AuraScript
// $0.2 * (($MWB + $mwb) / 2 + $AP / 14 * $MWS) bonus per tick // $0.2 * (($MWB + $mwb) / 2 + $AP / 14 * $MWS) bonus per tick
float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
int32 mws = caster->GetAttackTime(BASE_ATTACK); int32 mws = caster->GetAttackTime(BASE_ATTACK);
float mwbMin = caster->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE); float mwbMin = 0.f;
float mwbMax = caster->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE); float mwbMax = 0.f;
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
{
mwbMin += caster->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE, i);
mwbMax += caster->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE, i);
}
float mwb = ((mwbMin + mwbMax) / 2 + ap * mws / 14000) * 0.2f; float mwb = ((mwbMin + mwbMax) / 2 + ap * mws / 14000) * 0.2f;
amount += int32(caster->ApplyEffectModifiers(GetSpellInfo(), aurEff->GetEffIndex(), mwb)); amount += int32(caster->ApplyEffectModifiers(GetSpellInfo(), aurEff->GetEffIndex(), mwb));