feat(Core/Items): Implemented elemental weapon damage. Source: Trinit… (#13050)
...yCore.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|||||||
@@ -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,22 +6787,16 @@ 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;
|
{
|
||||||
|
float minDamage = proto->Damage[i].DamageMin;
|
||||||
|
float maxDamage = proto->Damage[i].DamageMax;
|
||||||
|
|
||||||
// If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage
|
// If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage
|
||||||
if (ssv)
|
if (ssv)
|
||||||
@@ -6826,16 +6810,33 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minDamage > 0)
|
if (apply)
|
||||||
{
|
{
|
||||||
damage = apply ? minDamage : BASE_MINDAMAGE;
|
if (minDamage > 0.f)
|
||||||
SetBaseWeaponDamage(attType, MINDAMAGE, damage);
|
{
|
||||||
|
SetBaseWeaponDamage(WeaponAttackType(attType), MINDAMAGE, minDamage, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxDamage > 0)
|
if (maxDamage > 0.f)
|
||||||
{
|
{
|
||||||
damage = apply ? maxDamage : BASE_MAXDAMAGE;
|
SetBaseWeaponDamage(WeaponAttackType(attType), MAXDAMAGE, maxDamage, i);
|
||||||
SetBaseWeaponDamage(attType, MAXDAMAGE, damage);
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!apply)
|
||||||
|
{
|
||||||
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
|
{
|
||||||
|
SetBaseWeaponDamage(WeaponAttackType(attType), MINDAMAGE, 0.f, i);
|
||||||
|
SetBaseWeaponDamage(WeaponAttackType(attType), MAXDAMAGE, 0.f, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attType == BASE_ATTACK)
|
||||||
|
{
|
||||||
|
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, BASE_MINDAMAGE);
|
||||||
|
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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -118,9 +118,19 @@ DamageInfo::DamageInfo(Unit* _attacker, Unit* _victim, uint32 _damage, SpellInfo
|
|||||||
m_block = 0;
|
m_block = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DamageInfo::DamageInfo(CalcDamageInfo& dmgInfo)
|
DamageInfo::DamageInfo(CalcDamageInfo const& dmgInfo) : DamageInfo(DamageInfo(dmgInfo, 0), DamageInfo(dmgInfo, 1))
|
||||||
: m_attacker(dmgInfo.attacker), m_victim(dmgInfo.target), m_damage(dmgInfo.damage), m_spellInfo(nullptr), m_schoolMask(SpellSchoolMask(dmgInfo.damageSchoolMask)),
|
{
|
||||||
m_damageType(DIRECT_DAMAGE), m_attackType(dmgInfo.attackType), m_absorb(dmgInfo.absorb), m_resist(dmgInfo.resist), m_block(dmgInfo.blocked_amount),
|
}
|
||||||
|
|
||||||
|
DamageInfo::DamageInfo(DamageInfo const& dmg1, DamageInfo const& dmg2)
|
||||||
|
: m_attacker(dmg1.m_attacker), m_victim(dmg1.m_victim), m_damage(dmg1.m_damage + dmg2.m_damage), m_spellInfo(dmg1.m_spellInfo), m_schoolMask(SpellSchoolMask(dmg1.m_schoolMask | dmg2.m_schoolMask)),
|
||||||
|
m_damageType(dmg1.m_damageType), m_attackType(dmg1.m_attackType), m_absorb(dmg1.m_absorb + dmg2.m_absorb), m_resist(dmg1.m_resist + dmg2.m_resist), m_block(dmg1.m_block)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DamageInfo::DamageInfo(CalcDamageInfo const& dmgInfo, uint8 damageIndex)
|
||||||
|
: m_attacker(dmgInfo.attacker), m_victim(dmgInfo.target), m_damage(dmgInfo.damages[damageIndex].damage), m_spellInfo(nullptr), m_schoolMask(SpellSchoolMask(dmgInfo.damages[damageIndex].damageSchoolMask)),
|
||||||
|
m_damageType(DIRECT_DAMAGE), m_attackType(dmgInfo.attackType), m_absorb(dmgInfo.damages[damageIndex].absorb), m_resist(dmgInfo.damages[damageIndex].resist), m_block(dmgInfo.blocked_amount),
|
||||||
m_cleanDamage(dmgInfo.cleanDamage)
|
m_cleanDamage(dmgInfo.cleanDamage)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -268,8 +278,11 @@ Unit::Unit(bool isWorldObject) : WorldObject(isWorldObject),
|
|||||||
|
|
||||||
for (uint8 i = 0; i < MAX_ATTACK; ++i)
|
for (uint8 i = 0; i < MAX_ATTACK; ++i)
|
||||||
{
|
{
|
||||||
m_weaponDamage[i][MINDAMAGE] = BASE_MINDAMAGE;
|
m_weaponDamage[i][MINDAMAGE][0] = BASE_MINDAMAGE;
|
||||||
m_weaponDamage[i][MAXDAMAGE] = BASE_MAXDAMAGE;
|
m_weaponDamage[i][MAXDAMAGE][0] = BASE_MAXDAMAGE;
|
||||||
|
|
||||||
|
m_weaponDamage[i][MINDAMAGE][1] = 0.f;
|
||||||
|
m_weaponDamage[i][MAXDAMAGE][1] = 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8 i = 0; i < MAX_STATS; ++i)
|
for (uint8 i = 0; i < MAX_STATS; ++i)
|
||||||
@@ -1437,16 +1450,21 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO for melee need create structure as in
|
// TODO for melee need create structure as in
|
||||||
void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* damageInfo, WeaponAttackType attackType, const bool sittingVictim)
|
void Unit::CalculateMeleeDamage(Unit* victim, CalcDamageInfo* damageInfo, WeaponAttackType attackType, const bool sittingVictim)
|
||||||
{
|
{
|
||||||
damageInfo->attacker = this;
|
damageInfo->attacker = this;
|
||||||
damageInfo->target = victim;
|
damageInfo->target = victim;
|
||||||
damageInfo->damageSchoolMask = GetMeleeDamageSchoolMask();
|
|
||||||
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
|
{
|
||||||
|
damageInfo->damages[i].damageSchoolMask = GetMeleeDamageSchoolMask(attackType, i);
|
||||||
|
damageInfo->damages[i].damage = 0;
|
||||||
|
damageInfo->damages[i].absorb = 0;
|
||||||
|
damageInfo->damages[i].resist = 0;
|
||||||
|
}
|
||||||
|
|
||||||
damageInfo->attackType = attackType;
|
damageInfo->attackType = attackType;
|
||||||
damageInfo->damage = 0;
|
|
||||||
damageInfo->cleanDamage = 0;
|
damageInfo->cleanDamage = 0;
|
||||||
damageInfo->absorb = 0;
|
|
||||||
damageInfo->resist = 0;
|
|
||||||
damageInfo->blocked_amount = 0;
|
damageInfo->blocked_amount = 0;
|
||||||
|
|
||||||
damageInfo->TargetState = 0;
|
damageInfo->TargetState = 0;
|
||||||
@@ -1478,8 +1496,25 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Physical Immune check
|
// School Immune check
|
||||||
if (damageInfo->target->IsImmunedToDamageOrSchool(SpellSchoolMask(damageInfo->damageSchoolMask)))
|
uint8 immunedMask = 0;
|
||||||
|
bool hasNonPhysicalSchoolMask = false;
|
||||||
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
|
{
|
||||||
|
if (damageInfo->target->IsImmunedToDamageOrSchool(SpellSchoolMask(damageInfo->damages[i].damageSchoolMask)))
|
||||||
|
{
|
||||||
|
immunedMask |= (1 << i);
|
||||||
|
if (damageInfo->damages[i].damageSchoolMask != SPELL_SCHOOL_MASK_NORMAL)
|
||||||
|
{
|
||||||
|
hasNonPhysicalSchoolMask = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// School Immune check
|
||||||
|
if (immunedMask & ((1 << 0) | (1 << 1)))
|
||||||
|
{
|
||||||
|
if (hasNonPhysicalSchoolMask || immunedMask == ((1 << 0) | (1 << 1)))
|
||||||
{
|
{
|
||||||
damageInfo->HitInfo |= HITINFO_NORMALSWING;
|
damageInfo->HitInfo |= HITINFO_NORMALSWING;
|
||||||
damageInfo->TargetState = VICTIMSTATE_IS_IMMUNE;
|
damageInfo->TargetState = VICTIMSTATE_IS_IMMUNE;
|
||||||
@@ -1487,23 +1522,46 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
|
|||||||
damageInfo->procEx |= PROC_EX_IMMUNE;
|
damageInfo->procEx |= PROC_EX_IMMUNE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
damage += CalculateDamage(damageInfo->attackType, false, true);
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
|
{
|
||||||
|
// only players have secondary weapon damage
|
||||||
|
if (i > 0 && GetTypeId() != TYPEID_PLAYER)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (immunedMask & (1 << i))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpellSchoolMask schoolMask = SpellSchoolMask(damageInfo->damages[i].damageSchoolMask);
|
||||||
|
bool const addPctMods = (schoolMask & SPELL_SCHOOL_MASK_NORMAL);
|
||||||
|
|
||||||
|
uint32 damage = 0;
|
||||||
|
uint8 itemDamagesMask = (GetTypeId() == TYPEID_PLAYER) ? (1 << i) : 0;
|
||||||
|
|
||||||
|
damage += CalculateDamage(damageInfo->attackType, false, addPctMods, itemDamagesMask);
|
||||||
// Add melee damage bonus
|
// Add melee damage bonus
|
||||||
damage = MeleeDamageBonusDone(damageInfo->target, damage, damageInfo->attackType);
|
damage = MeleeDamageBonusDone(damageInfo->target, damage, damageInfo->attackType, nullptr, schoolMask);
|
||||||
damage = damageInfo->target->MeleeDamageBonusTaken(this, damage, damageInfo->attackType);
|
damage = damageInfo->target->MeleeDamageBonusTaken(this, damage, damageInfo->attackType, nullptr, schoolMask);
|
||||||
|
|
||||||
// Script Hook For CalculateMeleeDamage -- Allow scripts to change the Damage pre class mitigation calculations
|
// Script Hook For CalculateMeleeDamage -- Allow scripts to change the Damage pre class mitigation calculations
|
||||||
sScriptMgr->ModifyMeleeDamage(damageInfo->target, damageInfo->attacker, damage);
|
sScriptMgr->ModifyMeleeDamage(damageInfo->target, damageInfo->attacker, damage);
|
||||||
|
|
||||||
// Calculate armor reduction
|
// Calculate armor reduction
|
||||||
if (IsDamageReducedByArmor((SpellSchoolMask)(damageInfo->damageSchoolMask)))
|
if (IsDamageReducedByArmor((SpellSchoolMask)(damageInfo->damages[i].damageSchoolMask)))
|
||||||
{
|
{
|
||||||
damageInfo->damage = Unit::CalcArmorReducedDamage(this, damageInfo->target, damage, nullptr, 0, damageInfo->attackType);
|
damageInfo->damages[i].damage = Unit::CalcArmorReducedDamage(this, damageInfo->target, damage, nullptr, 0, damageInfo->attackType);
|
||||||
damageInfo->cleanDamage += damage - damageInfo->damage;
|
damageInfo->cleanDamage += damage - damageInfo->damages[i].damage;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
damageInfo->damage = damage;
|
{
|
||||||
|
damageInfo->damages[i].damage = damage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
damageInfo->hitOutCome = RollMeleeOutcomeAgainst(damageInfo->target, damageInfo->attackType);
|
damageInfo->hitOutCome = RollMeleeOutcomeAgainst(damageInfo->target, damageInfo->attackType);
|
||||||
|
|
||||||
@@ -1518,14 +1576,23 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
|
|||||||
damageInfo->HitInfo |= HITINFO_MISS | HITINFO_SWINGNOHITSOUND;
|
damageInfo->HitInfo |= HITINFO_MISS | HITINFO_SWINGNOHITSOUND;
|
||||||
damageInfo->TargetState = VICTIMSTATE_EVADES;
|
damageInfo->TargetState = VICTIMSTATE_EVADES;
|
||||||
damageInfo->procEx |= PROC_EX_EVADE;
|
damageInfo->procEx |= PROC_EX_EVADE;
|
||||||
damageInfo->damage = 0;
|
|
||||||
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
|
{
|
||||||
|
damageInfo->damages[i].damage = 0;
|
||||||
|
}
|
||||||
|
|
||||||
damageInfo->cleanDamage = 0;
|
damageInfo->cleanDamage = 0;
|
||||||
return;
|
return;
|
||||||
case MELEE_HIT_MISS:
|
case MELEE_HIT_MISS:
|
||||||
damageInfo->HitInfo |= HITINFO_MISS;
|
damageInfo->HitInfo |= HITINFO_MISS;
|
||||||
damageInfo->TargetState = VICTIMSTATE_INTACT;
|
damageInfo->TargetState = VICTIMSTATE_INTACT;
|
||||||
damageInfo->procEx |= PROC_EX_MISS;
|
damageInfo->procEx |= PROC_EX_MISS;
|
||||||
damageInfo->damage = 0;
|
|
||||||
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
|
{
|
||||||
|
damageInfo->damages[i].damage = 0;
|
||||||
|
}
|
||||||
damageInfo->cleanDamage = 0;
|
damageInfo->cleanDamage = 0;
|
||||||
break;
|
break;
|
||||||
case MELEE_HIT_NORMAL:
|
case MELEE_HIT_NORMAL:
|
||||||
@@ -1539,17 +1606,22 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
|
|||||||
|
|
||||||
damageInfo->procEx |= PROC_EX_CRITICAL_HIT;
|
damageInfo->procEx |= PROC_EX_CRITICAL_HIT;
|
||||||
// Crit bonus calc
|
// Crit bonus calc
|
||||||
damageInfo->damage += damageInfo->damage;
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
|
{
|
||||||
|
damageInfo->damages[i].damage *= 2;
|
||||||
|
|
||||||
float mod = 0.0f;
|
float mod = 0.0f;
|
||||||
// Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
|
// Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
|
||||||
if (damageInfo->attackType == RANGED_ATTACK)
|
if (damageInfo->attackType == RANGED_ATTACK)
|
||||||
|
{
|
||||||
mod += damageInfo->target->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE);
|
mod += damageInfo->target->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mod += damageInfo->target->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE);
|
mod += damageInfo->target->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE);
|
||||||
|
|
||||||
// Increase crit damage from SPELL_AURA_MOD_CRIT_DAMAGE_BONUS
|
// Increase crit damage from SPELL_AURA_MOD_CRIT_DAMAGE_BONUS
|
||||||
mod += (GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, damageInfo->damageSchoolMask) - 1.0f) * 100;
|
mod += (GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, damageInfo->damages[i].damageSchoolMask) - 1.0f) * 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 crTypeMask = damageInfo->target->GetCreatureTypeMask();
|
uint32 crTypeMask = damageInfo->target->GetCreatureTypeMask();
|
||||||
@@ -1557,22 +1629,36 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
|
|||||||
// Increase crit damage from SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
|
// Increase crit damage from SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
|
||||||
mod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask);
|
mod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask);
|
||||||
if (mod != 0)
|
if (mod != 0)
|
||||||
AddPct(damageInfo->damage, mod);
|
{
|
||||||
|
AddPct(damageInfo->damages[i].damage, mod);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MELEE_HIT_PARRY:
|
case MELEE_HIT_PARRY:
|
||||||
damageInfo->TargetState = VICTIMSTATE_PARRY;
|
damageInfo->TargetState = VICTIMSTATE_PARRY;
|
||||||
damageInfo->procEx |= PROC_EX_PARRY;
|
damageInfo->procEx |= PROC_EX_PARRY;
|
||||||
damageInfo->cleanDamage += damageInfo->damage;
|
damageInfo->cleanDamage = 0;
|
||||||
damageInfo->damage = 0;
|
|
||||||
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
|
{
|
||||||
|
damageInfo->cleanDamage += damageInfo->damages[i].damage;
|
||||||
|
damageInfo->damages[i].damage = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MELEE_HIT_DODGE:
|
case MELEE_HIT_DODGE:
|
||||||
damageInfo->TargetState = VICTIMSTATE_DODGE;
|
damageInfo->TargetState = VICTIMSTATE_DODGE;
|
||||||
damageInfo->procEx |= PROC_EX_DODGE;
|
damageInfo->procEx |= PROC_EX_DODGE;
|
||||||
damageInfo->cleanDamage += damageInfo->damage;
|
damageInfo->cleanDamage = 0;
|
||||||
damageInfo->damage = 0;
|
|
||||||
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
|
{
|
||||||
|
damageInfo->cleanDamage += damageInfo->damages[i].damage;
|
||||||
|
damageInfo->damages[i].damage = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MELEE_HIT_BLOCK:
|
case MELEE_HIT_BLOCK:
|
||||||
|
{
|
||||||
damageInfo->TargetState = VICTIMSTATE_HIT;
|
damageInfo->TargetState = VICTIMSTATE_HIT;
|
||||||
damageInfo->HitInfo |= HITINFO_BLOCK;
|
damageInfo->HitInfo |= HITINFO_BLOCK;
|
||||||
damageInfo->procEx |= PROC_EX_BLOCK;
|
damageInfo->procEx |= PROC_EX_BLOCK;
|
||||||
@@ -1580,17 +1666,35 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
|
|||||||
// double blocked amount if block is critical
|
// double blocked amount if block is critical
|
||||||
if (damageInfo->target->isBlockCritical())
|
if (damageInfo->target->isBlockCritical())
|
||||||
damageInfo->blocked_amount += damageInfo->blocked_amount;
|
damageInfo->blocked_amount += damageInfo->blocked_amount;
|
||||||
if (damageInfo->blocked_amount >= damageInfo->damage)
|
|
||||||
|
uint32 remainingBlock = damageInfo->blocked_amount;
|
||||||
|
uint8 fullBlockMask = 0;
|
||||||
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
{
|
{
|
||||||
damageInfo->TargetState = VICTIMSTATE_BLOCKS;
|
if (remainingBlock && remainingBlock >= damageInfo->damages[i].damage)
|
||||||
damageInfo->blocked_amount = damageInfo->damage;
|
{
|
||||||
damageInfo->procEx |= PROC_EX_FULL_BLOCK;
|
fullBlockMask |= (1 << i);
|
||||||
|
|
||||||
|
remainingBlock -= damageInfo->damages[i].damage;
|
||||||
|
damageInfo->cleanDamage += damageInfo->damages[i].damage;
|
||||||
|
damageInfo->damages[i].damage = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
damageInfo->procEx |= PROC_EX_NORMAL_HIT;
|
{
|
||||||
damageInfo->damage -= damageInfo->blocked_amount;
|
damageInfo->cleanDamage += remainingBlock;
|
||||||
damageInfo->cleanDamage += damageInfo->blocked_amount;
|
damageInfo->damages[i].damage -= remainingBlock;
|
||||||
|
remainingBlock = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// full block
|
||||||
|
if (fullBlockMask == ((1 << 0) | (1 << 1)))
|
||||||
|
{
|
||||||
|
damageInfo->TargetState = VICTIMSTATE_BLOCKS;
|
||||||
|
damageInfo->blocked_amount -= remainingBlock;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case MELEE_HIT_GLANCING:
|
case MELEE_HIT_GLANCING:
|
||||||
{
|
{
|
||||||
damageInfo->HitInfo |= HITINFO_GLANCING;
|
damageInfo->HitInfo |= HITINFO_GLANCING;
|
||||||
@@ -1600,16 +1704,25 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
|
|||||||
if (leveldif > 3)
|
if (leveldif > 3)
|
||||||
leveldif = 3;
|
leveldif = 3;
|
||||||
float reducePercent = 1 - leveldif * 0.1f;
|
float reducePercent = 1 - leveldif * 0.1f;
|
||||||
damageInfo->cleanDamage += damageInfo->damage - uint32(reducePercent * damageInfo->damage);
|
|
||||||
damageInfo->damage = uint32(reducePercent * damageInfo->damage);
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
|
{
|
||||||
|
uint32 reducedDamage = uint32(reducePercent * damageInfo->damages[i].damage);
|
||||||
|
damageInfo->cleanDamage += damageInfo->damages[i].damage - reducedDamage;
|
||||||
|
damageInfo->damages[i].damage = reducedDamage;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MELEE_HIT_CRUSHING:
|
case MELEE_HIT_CRUSHING:
|
||||||
damageInfo->HitInfo |= HITINFO_CRUSHING;
|
damageInfo->HitInfo |= HITINFO_CRUSHING;
|
||||||
damageInfo->TargetState = VICTIMSTATE_HIT;
|
damageInfo->TargetState = VICTIMSTATE_HIT;
|
||||||
damageInfo->procEx |= PROC_EX_NORMAL_HIT;
|
damageInfo->procEx |= PROC_EX_NORMAL_HIT;
|
||||||
|
|
||||||
// 150% normal damage
|
// 150% normal damage
|
||||||
damageInfo->damage += (damageInfo->damage / 2);
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
|
{
|
||||||
|
damageInfo->damages[i].damage += (damageInfo->damages[i].damage / 2);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -1619,43 +1732,70 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
|
|||||||
if (!(damageInfo->HitInfo & HITINFO_MISS))
|
if (!(damageInfo->HitInfo & HITINFO_MISS))
|
||||||
damageInfo->HitInfo |= HITINFO_AFFECTS_VICTIM;
|
damageInfo->HitInfo |= HITINFO_AFFECTS_VICTIM;
|
||||||
|
|
||||||
// attackType is checked already for BASE_ATTACK or OFF_ATTACK so it can't be RANGED_ATTACK here
|
uint32 tmpHitInfo[MAX_ITEM_PROTO_DAMAGES] = { };
|
||||||
int32 dmg = damageInfo->damage;
|
|
||||||
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
|
{
|
||||||
|
int32 dmg = damageInfo->damages[i].damage;
|
||||||
int32 cleanDamage = damageInfo->cleanDamage;
|
int32 cleanDamage = damageInfo->cleanDamage;
|
||||||
|
// attackType is checked already for BASE_ATTACK or OFF_ATTACK so it can't be RANGED_ATTACK here
|
||||||
if (CanApplyResilience())
|
if (CanApplyResilience())
|
||||||
{
|
{
|
||||||
int32 resilienceReduction = dmg;
|
int32 resilienceReduction = damageInfo->damages[i].damage;
|
||||||
Unit::ApplyResilience(victim, nullptr, &resilienceReduction, (damageInfo->hitOutCome == MELEE_HIT_CRIT), CR_CRIT_TAKEN_MELEE);
|
Unit::ApplyResilience(victim, nullptr, &resilienceReduction, (damageInfo->hitOutCome == MELEE_HIT_CRIT), CR_CRIT_TAKEN_MELEE);
|
||||||
|
|
||||||
resilienceReduction = dmg - resilienceReduction;
|
resilienceReduction = damageInfo->damages[i].damage - resilienceReduction;
|
||||||
dmg -= resilienceReduction;
|
dmg -= resilienceReduction;
|
||||||
cleanDamage += resilienceReduction;
|
cleanDamage += resilienceReduction;
|
||||||
}
|
}
|
||||||
|
|
||||||
damageInfo->damage = std::max(0, dmg);
|
damageInfo->damages[i].damage = std::max(0, dmg);
|
||||||
damageInfo->cleanDamage = std::max(0, cleanDamage);
|
damageInfo->cleanDamage = std::max(0, cleanDamage);
|
||||||
|
|
||||||
// Calculate absorb resist
|
// Calculate absorb resist
|
||||||
if (damageInfo->damage > 0)
|
if (damageInfo->damages[i].damage > 0)
|
||||||
{
|
{
|
||||||
damageInfo->procVictim |= PROC_FLAG_TAKEN_DAMAGE;
|
damageInfo->procVictim |= PROC_FLAG_TAKEN_DAMAGE;
|
||||||
|
|
||||||
// Calculate absorb & resists
|
// Calculate absorb & resists
|
||||||
|
DamageInfo dmgInfo(*damageInfo, i);
|
||||||
DamageInfo dmgInfo(*damageInfo);
|
|
||||||
Unit::CalcAbsorbResist(dmgInfo);
|
Unit::CalcAbsorbResist(dmgInfo);
|
||||||
damageInfo->absorb = dmgInfo.GetAbsorb();
|
damageInfo->damages[i].absorb = dmgInfo.GetAbsorb();
|
||||||
damageInfo->resist = dmgInfo.GetResist();
|
damageInfo->damages[i].resist = dmgInfo.GetResist();
|
||||||
|
|
||||||
if (damageInfo->absorb)
|
if (damageInfo->damages[i].absorb)
|
||||||
{
|
{
|
||||||
damageInfo->HitInfo |= (damageInfo->damage - damageInfo->absorb == 0 ? HITINFO_FULL_ABSORB : HITINFO_PARTIAL_ABSORB);
|
tmpHitInfo[i] |= (damageInfo->damages[i].damage - damageInfo->damages[i].absorb == 0 ? HITINFO_FULL_ABSORB : HITINFO_PARTIAL_ABSORB);
|
||||||
damageInfo->procEx |= PROC_EX_ABSORB;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (damageInfo->resist)
|
if (damageInfo->damages[i].resist)
|
||||||
damageInfo->HitInfo |= (damageInfo->damage - damageInfo->resist == 0 ? HITINFO_FULL_RESIST : HITINFO_PARTIAL_RESIST);
|
{
|
||||||
|
tmpHitInfo[i] |= (damageInfo->damages[i].damage - damageInfo->damages[i].resist == 0 ? HITINFO_FULL_RESIST : HITINFO_PARTIAL_RESIST);
|
||||||
|
}
|
||||||
|
|
||||||
damageInfo->damage = dmgInfo.GetDamage();
|
damageInfo->damages[i].damage = dmgInfo.GetDamage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set proper HitInfo flags
|
||||||
|
if ((tmpHitInfo[0] & HITINFO_FULL_ABSORB) != 0)
|
||||||
|
{
|
||||||
|
// set partial absorb when secondary damage isn't full absorbed
|
||||||
|
damageInfo->HitInfo |= ((tmpHitInfo[1] & HITINFO_PARTIAL_ABSORB) != 0) ? HITINFO_PARTIAL_ABSORB : HITINFO_FULL_ABSORB;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
damageInfo->HitInfo |= (tmpHitInfo[0] & HITINFO_PARTIAL_ABSORB);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((tmpHitInfo[0] & HITINFO_FULL_RESIST) != 0)
|
||||||
|
{
|
||||||
|
// set partial resist when secondary damage isn't full resisted
|
||||||
|
damageInfo->HitInfo |= ((tmpHitInfo[1] & HITINFO_PARTIAL_RESIST) != 0) ? HITINFO_PARTIAL_RESIST : HITINFO_FULL_RESIST;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
damageInfo->HitInfo |= (tmpHitInfo[0] & HITINFO_PARTIAL_RESIST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1663,8 +1803,15 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
|
|||||||
{
|
{
|
||||||
Unit* victim = damageInfo->target;
|
Unit* victim = damageInfo->target;
|
||||||
|
|
||||||
if (!victim->IsAlive() || victim->IsInFlight() || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks()))
|
auto canTakeMeleeDamage = [&]()
|
||||||
|
{
|
||||||
|
return victim->IsAlive() && !victim->HasUnitState(UNIT_STATE_IN_FLIGHT) && (victim->GetTypeId() != TYPEID_UNIT || !victim->ToCreature()->IsEvadingAttacks());
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!canTakeMeleeDamage())
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Hmmmm dont like this emotes client must by self do all animations
|
// Hmmmm dont like this emotes client must by self do all animations
|
||||||
if (damageInfo->HitInfo & HITINFO_CRITICALHIT)
|
if (damageInfo->HitInfo & HITINFO_CRITICALHIT)
|
||||||
@@ -1704,12 +1851,20 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
|
{
|
||||||
|
if (!canTakeMeleeDamage() || (!damageInfo->damages[i].damage && !damageInfo->damages[i].absorb && !damageInfo->damages[i].resist))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Call default DealDamage
|
// Call default DealDamage
|
||||||
CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->absorb, damageInfo->attackType, damageInfo->hitOutCome);
|
CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->damages[i].absorb, damageInfo->attackType, damageInfo->hitOutCome);
|
||||||
Unit::DealDamage(this, victim, damageInfo->damage, &cleanDamage, DIRECT_DAMAGE, SpellSchoolMask(damageInfo->damageSchoolMask), nullptr, durabilityLoss);
|
Unit::DealDamage(this, victim, damageInfo->damages[i].damage, &cleanDamage, DIRECT_DAMAGE, SpellSchoolMask(damageInfo->damages[i].damageSchoolMask), nullptr, durabilityLoss);
|
||||||
|
}
|
||||||
|
|
||||||
// If this is a creature and it attacks from behind it has a probability to daze it's victim
|
// If this is a creature and it attacks from behind it has a probability to daze it's victim
|
||||||
if (damageInfo->damage && ((damageInfo->hitOutCome == MELEE_HIT_CRIT || damageInfo->hitOutCome == MELEE_HIT_CRUSHING || damageInfo->hitOutCome == MELEE_HIT_NORMAL || damageInfo->hitOutCome == MELEE_HIT_GLANCING) &&
|
if ((damageInfo->damages[0].damage + damageInfo->damages[1].damage) && ((damageInfo->hitOutCome == MELEE_HIT_CRIT || damageInfo->hitOutCome == MELEE_HIT_CRUSHING || damageInfo->hitOutCome == MELEE_HIT_NORMAL || damageInfo->hitOutCome == MELEE_HIT_GLANCING) &&
|
||||||
GetTypeId() != TYPEID_PLAYER && !ToCreature()->IsControlledByPlayer() && !victim->HasInArc(M_PI, this)
|
GetTypeId() != TYPEID_PLAYER && !ToCreature()->IsControlledByPlayer() && !victim->HasInArc(M_PI, this)
|
||||||
&& (victim->GetTypeId() == TYPEID_PLAYER || !victim->ToCreature()->isWorldBoss()) && !victim->IsVehicle()))
|
&& (victim->GetTypeId() == TYPEID_PLAYER || !victim->ToCreature()->isWorldBoss()) && !victim->IsVehicle()))
|
||||||
{
|
{
|
||||||
@@ -1738,7 +1893,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
|
|||||||
ToPlayer()->CastItemCombatSpell(victim, damageInfo->attackType, damageInfo->procVictim, damageInfo->procEx);
|
ToPlayer()->CastItemCombatSpell(victim, damageInfo->attackType, damageInfo->procVictim, damageInfo->procEx);
|
||||||
|
|
||||||
// Do effect if any damage done to target
|
// Do effect if any damage done to target
|
||||||
if (damageInfo->damage)
|
if (damageInfo->damages[0].damage + damageInfo->damages[1].damage)
|
||||||
{
|
{
|
||||||
// We're going to call functions which can modify content of the list during iteration over it's elements
|
// We're going to call functions which can modify content of the list during iteration over it's elements
|
||||||
// Let's copy the list so we can prevent iterator invalidation
|
// Let's copy the list so we can prevent iterator invalidation
|
||||||
@@ -1826,7 +1981,6 @@ bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* s
|
|||||||
|
|
||||||
uint32 Unit::CalcArmorReducedDamage(Unit const* attacker, Unit const* victim, const uint32 damage, SpellInfo const* spellInfo, uint8 attackerLevel, WeaponAttackType /*attackType*/)
|
uint32 Unit::CalcArmorReducedDamage(Unit const* attacker, Unit const* victim, const uint32 damage, SpellInfo const* spellInfo, uint8 attackerLevel, WeaponAttackType /*attackType*/)
|
||||||
{
|
{
|
||||||
uint32 newdamage = 0;
|
|
||||||
float armor = float(victim->GetArmor());
|
float armor = float(victim->GetArmor());
|
||||||
|
|
||||||
// Ignore enemy armor by SPELL_AURA_MOD_TARGET_RESISTANCE aura
|
// Ignore enemy armor by SPELL_AURA_MOD_TARGET_RESISTANCE aura
|
||||||
@@ -1904,9 +2058,7 @@ uint32 Unit::CalcArmorReducedDamage(Unit const* attacker, Unit const* victim, co
|
|||||||
if (tmpvalue > 0.75f)
|
if (tmpvalue > 0.75f)
|
||||||
tmpvalue = 0.75f;
|
tmpvalue = 0.75f;
|
||||||
|
|
||||||
newdamage = uint32(damage - (damage * tmpvalue));
|
return uint32(std::ceil(std::max(damage * (1.0f - tmpvalue), 0.0f)));
|
||||||
|
|
||||||
return (newdamage > 1) ? newdamage : 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float Unit::GetEffectiveResistChance(Unit const* owner, SpellSchoolMask schoolMask, Unit const* victim)
|
float Unit::GetEffectiveResistChance(Unit const* owner, SpellSchoolMask schoolMask, Unit const* victim)
|
||||||
@@ -2414,10 +2566,14 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType /*= BASE_A
|
|||||||
// attack can be redirected to another target
|
// attack can be redirected to another target
|
||||||
victim = GetMeleeHitRedirectTarget(victim);
|
victim = GetMeleeHitRedirectTarget(victim);
|
||||||
CalcDamageInfo damageInfo;
|
CalcDamageInfo damageInfo;
|
||||||
CalculateMeleeDamage(victim, 0, &damageInfo, attType, sittingVictim);
|
CalculateMeleeDamage(victim, &damageInfo, attType, sittingVictim);
|
||||||
|
|
||||||
// Send log damage message to client
|
// Send log damage message to client
|
||||||
Unit::DealDamageMods(victim, damageInfo.damage, &damageInfo.absorb);
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
|
{
|
||||||
|
Unit::DealDamageMods(victim, damageInfo.damages[i].damage, &damageInfo.damages[i].absorb);
|
||||||
|
}
|
||||||
|
|
||||||
SendAttackStateUpdate(&damageInfo);
|
SendAttackStateUpdate(&damageInfo);
|
||||||
|
|
||||||
//TriggerAurasProcOnEvent(damageInfo);
|
//TriggerAurasProcOnEvent(damageInfo);
|
||||||
@@ -2427,15 +2583,15 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType /*= BASE_A
|
|||||||
DealMeleeDamage(&damageInfo, true);
|
DealMeleeDamage(&damageInfo, true);
|
||||||
|
|
||||||
DamageInfo dmgInfo(damageInfo);
|
DamageInfo dmgInfo(damageInfo);
|
||||||
Unit::ProcDamageAndSpell(damageInfo.attacker, damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, damageInfo.damage,
|
Unit::ProcDamageAndSpell(damageInfo.attacker, damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, dmgInfo.GetDamage(),
|
||||||
damageInfo.attackType, nullptr, nullptr, -1, nullptr, &dmgInfo);
|
damageInfo.attackType, nullptr, nullptr, -1, nullptr, &dmgInfo);
|
||||||
|
|
||||||
if (GetTypeId() == TYPEID_PLAYER)
|
if (GetTypeId() == TYPEID_PLAYER)
|
||||||
LOG_DEBUG("entities.unit", "AttackerStateUpdate: (Player) {} attacked {} for {} dmg, absorbed {}, blocked {}, resisted {}.",
|
LOG_DEBUG("entities.unit", "AttackerStateUpdate: (Player) {} attacked {} for {} dmg, absorbed {}, blocked {}, resisted {}.",
|
||||||
GetGUID().ToString(), victim->GetGUID().ToString(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist);
|
GetGUID().ToString(), victim->GetGUID().ToString(), dmgInfo.GetDamage(), dmgInfo.GetAbsorb(), dmgInfo.GetBlock(), dmgInfo.GetResist());
|
||||||
else
|
else
|
||||||
LOG_DEBUG("entities.unit", "AttackerStateUpdate: (NPC) {} attacked {} for {} dmg, absorbed {}, blocked {}, resisted {}.",
|
LOG_DEBUG("entities.unit", "AttackerStateUpdate: (NPC) {} attacked {} for {} dmg, absorbed {}, blocked {}, resisted {}.",
|
||||||
GetGUID().ToString(), victim->GetGUID().ToString(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist);
|
GetGUID().ToString(), victim->GetGUID().ToString(), dmgInfo.GetDamage(), dmgInfo.GetAbsorb(), dmgInfo.GetBlock(), dmgInfo.GetResist());
|
||||||
|
|
||||||
// Let the pet know we've started attacking someting. Handles melee attacks only
|
// Let the pet know we've started attacking someting. Handles melee attacks only
|
||||||
// Spells such as auto-shot and others handled in WorldSession::HandleCastSpellOpcode
|
// Spells such as auto-shot and others handled in WorldSession::HandleCastSpellOpcode
|
||||||
@@ -2764,13 +2920,30 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(Unit const* victim, WeaponAttackTy
|
|||||||
return MELEE_HIT_NORMAL;
|
return MELEE_HIT_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Unit::CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct)
|
uint32 Unit::CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, uint8 itemDamagesMask /*= 0*/)
|
||||||
{
|
{
|
||||||
float minDamage = 0.0f;
|
float minDamage = 0.0f;
|
||||||
float maxDamage = 0.0f;
|
float maxDamage = 0.0f;
|
||||||
|
|
||||||
if (normalized || !addTotalPct)
|
if (normalized || !addTotalPct || itemDamagesMask)
|
||||||
CalculateMinMaxDamage(attType, normalized, addTotalPct, minDamage, maxDamage);
|
{
|
||||||
|
// get both by default
|
||||||
|
if (!itemDamagesMask)
|
||||||
|
{
|
||||||
|
itemDamagesMask = (1 << 0) | (1 << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
|
{
|
||||||
|
if (itemDamagesMask & (1 << i))
|
||||||
|
{
|
||||||
|
float minTmp, maxTmp;
|
||||||
|
CalculateMinMaxDamage(attType, normalized, addTotalPct, minTmp, maxTmp, i);
|
||||||
|
minDamage += minTmp;
|
||||||
|
maxDamage += maxTmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (attType)
|
switch (attType)
|
||||||
@@ -2790,14 +2963,15 @@ uint32 Unit::CalculateDamage(WeaponAttackType attType, bool normalized, bool add
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pussywizard: this check only in "else" section, proper check is also in CalculateMinMaxDamage
|
|
||||||
if (minDamage > maxDamage)
|
|
||||||
minDamage = maxDamage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxDamage == 0.0f)
|
minDamage = std::max(0.f, minDamage);
|
||||||
maxDamage = 5.0f;
|
maxDamage = std::max(0.f, maxDamage);
|
||||||
|
|
||||||
|
if (minDamage > maxDamage)
|
||||||
|
{
|
||||||
|
std::swap(minDamage, maxDamage);
|
||||||
|
}
|
||||||
|
|
||||||
return urand(uint32(minDamage), uint32(maxDamage));
|
return urand(uint32(minDamage), uint32(maxDamage));
|
||||||
}
|
}
|
||||||
@@ -3290,6 +3464,96 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spell, bool Ca
|
|||||||
return SPELL_MISS_NONE;
|
return SPELL_MISS_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SpellMissInfo Unit::SpellHitResult(Unit* victim, Spell const* spell, bool CanReflect)
|
||||||
|
{
|
||||||
|
SpellInfo const* spellInfo = spell->GetSpellInfo();
|
||||||
|
|
||||||
|
// Check for immune
|
||||||
|
if (victim->IsImmunedToSpell(spellInfo, spell))
|
||||||
|
{
|
||||||
|
return SPELL_MISS_IMMUNE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All positive spells can`t miss
|
||||||
|
// TODO: client not show miss log for this spells - so need find info for this in dbc and use it!
|
||||||
|
if ((spellInfo->IsPositive() || spellInfo->HasEffect(SPELL_EFFECT_DISPEL))
|
||||||
|
&& (!IsHostileTo(victim))) // prevent from affecting enemy by "positive" spell
|
||||||
|
{
|
||||||
|
return SPELL_MISS_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for immune
|
||||||
|
// xinef: check for school immunity only
|
||||||
|
if (victim->IsImmunedToSchool(spell))
|
||||||
|
{
|
||||||
|
return SPELL_MISS_IMMUNE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this == victim)
|
||||||
|
{
|
||||||
|
return SPELL_MISS_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return evade for units in evade mode
|
||||||
|
if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks() && !spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE) &&
|
||||||
|
!spellInfo->HasAttribute(SPELL_ATTR0_CU_IGNORE_EVADE))
|
||||||
|
{
|
||||||
|
return SPELL_MISS_EVADE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try victim reflect spell
|
||||||
|
if (CanReflect)
|
||||||
|
{
|
||||||
|
int32 reflectchance = victim->GetTotalAuraModifier(SPELL_AURA_REFLECT_SPELLS);
|
||||||
|
Unit::AuraEffectList const& mReflectSpellsSchool = victim->GetAuraEffectsByType(SPELL_AURA_REFLECT_SPELLS_SCHOOL);
|
||||||
|
for (Unit::AuraEffectList::const_iterator i = mReflectSpellsSchool.begin(); i != mReflectSpellsSchool.end(); ++i)
|
||||||
|
{
|
||||||
|
if ((*i)->GetMiscValue() & spell->GetSpellSchoolMask())
|
||||||
|
{
|
||||||
|
reflectchance += (*i)->GetAmount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reflectchance > 0 && roll_chance_i(reflectchance))
|
||||||
|
{
|
||||||
|
// Start triggers for remove charges if need (trigger only for victim, and mark as active spell)
|
||||||
|
//ProcDamageAndSpell(victim, PROC_FLAG_NONE, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_EX_REFLECT, 1, BASE_ATTACK, spell);
|
||||||
|
return SPELL_MISS_REFLECT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (spellInfo->DmgClass)
|
||||||
|
{
|
||||||
|
case SPELL_DAMAGE_CLASS_RANGED:
|
||||||
|
case SPELL_DAMAGE_CLASS_MELEE:
|
||||||
|
return MeleeSpellHitResult(victim, spellInfo);
|
||||||
|
case SPELL_DAMAGE_CLASS_NONE:
|
||||||
|
{
|
||||||
|
if (spellInfo->SpellFamilyName)
|
||||||
|
{
|
||||||
|
return SPELL_MISS_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Xinef: apply DAMAGE_CLASS_MAGIC conditions to damaging DAMAGE_CLASS_NONE spells
|
||||||
|
for (uint8 i = EFFECT_0; i < MAX_SPELL_EFFECTS; ++i)
|
||||||
|
{
|
||||||
|
if (spellInfo->Effects[i].Effect && spellInfo->Effects[i].Effect != SPELL_EFFECT_SCHOOL_DAMAGE)
|
||||||
|
{
|
||||||
|
if (spellInfo->Effects[i].ApplyAuraName != SPELL_AURA_PERIODIC_DAMAGE)
|
||||||
|
{
|
||||||
|
return SPELL_MISS_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[[fallthrough]];
|
||||||
|
}
|
||||||
|
case SPELL_DAMAGE_CLASS_MAGIC:
|
||||||
|
return MagicSpellHitResult(victim, spellInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SPELL_MISS_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
uint32 Unit::GetDefenseSkillValue(Unit const* target) const
|
uint32 Unit::GetDefenseSkillValue(Unit const* target) const
|
||||||
{
|
{
|
||||||
if (GetTypeId() == TYPEID_PLAYER)
|
if (GetTypeId() == TYPEID_PLAYER)
|
||||||
@@ -6078,43 +6342,57 @@ void Unit::SendAttackStateUpdate(CalcDamageInfo* damageInfo)
|
|||||||
{
|
{
|
||||||
LOG_DEBUG("entities.unit", "WORLD: Sending SMSG_ATTACKERSTATEUPDATE");
|
LOG_DEBUG("entities.unit", "WORLD: Sending SMSG_ATTACKERSTATEUPDATE");
|
||||||
|
|
||||||
|
uint32 tmpDamage[MAX_ITEM_PROTO_DAMAGES] = { };
|
||||||
|
uint32 tmpAbsorb[MAX_ITEM_PROTO_DAMAGES] = { };
|
||||||
|
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||||
|
{
|
||||||
//IF we are in cheat mode we swap absorb with damage and set damage to 0, this way we can still debug damage but our hp bar will not drop
|
//IF we are in cheat mode we swap absorb with damage and set damage to 0, this way we can still debug damage but our hp bar will not drop
|
||||||
uint32 damage = damageInfo->damage;
|
tmpDamage[i] = damageInfo->damages[i].damage;
|
||||||
uint32 absorb = damageInfo->absorb;
|
tmpAbsorb[i] = damageInfo->damages[i].absorb;
|
||||||
if (damageInfo->target->GetTypeId() == TYPEID_PLAYER && damageInfo->target->ToPlayer()->GetCommandStatus(CHEAT_GOD))
|
if (damageInfo->target->GetTypeId() == TYPEID_PLAYER && damageInfo->target->ToPlayer()->GetCommandStatus(CHEAT_GOD))
|
||||||
{
|
{
|
||||||
absorb = damage;
|
tmpAbsorb[i] = tmpDamage[i];
|
||||||
damage = 0;
|
tmpDamage[i] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 count = 1;
|
uint32 count = 1;
|
||||||
size_t maxsize = 4 + 5 + 5 + 4 + 4 + 1 + 4 + 4 + 4 + 4 + 4 + 1 + 4 + 4 + 4 + 4 + 4 * 12;
|
if (tmpDamage[1] || tmpAbsorb[1] || damageInfo->damages[1].resist)
|
||||||
|
{
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t const maxsize = 4 + 5 + 5 + 4 + 4 + 1 + count * (4 + 4 + 4 + 4 + 4) + 1 + 4 + 4 + 4 + 4 + 4 * 12;
|
||||||
WorldPacket data(SMSG_ATTACKERSTATEUPDATE, maxsize); // we guess size
|
WorldPacket data(SMSG_ATTACKERSTATEUPDATE, maxsize); // we guess size
|
||||||
data << uint32(damageInfo->HitInfo);
|
data << uint32(damageInfo->HitInfo);
|
||||||
data << damageInfo->attacker->GetPackGUID();
|
data << damageInfo->attacker->GetPackGUID();
|
||||||
data << damageInfo->target->GetPackGUID();
|
data << damageInfo->target->GetPackGUID();
|
||||||
data << uint32(damage); // Full damage
|
data << uint32(tmpDamage[0] + tmpDamage[1]); // Full damage
|
||||||
int32 overkill = damage - damageInfo->target->GetHealth();
|
int32 overkill = tmpDamage[0] + tmpDamage[1] - damageInfo->target->GetHealth();
|
||||||
data << uint32(overkill < 0 ? 0 : overkill); // Overkill
|
data << uint32(overkill < 0 ? 0 : overkill); // Overkill
|
||||||
data << uint8(count); // Sub damage count
|
data << uint8(count); // Sub damage count
|
||||||
|
|
||||||
for (uint32 i = 0; i < count; ++i)
|
for (uint32 i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
data << uint32(damageInfo->damageSchoolMask); // School of sub damage
|
data << uint32(damageInfo->damages[i].damageSchoolMask); // School of sub damage
|
||||||
data << float(damage); // sub damage
|
data << float(tmpDamage[i]); // sub damage
|
||||||
data << uint32(damage); // Sub Damage
|
data << uint32(tmpDamage[i]); // Sub Damage
|
||||||
}
|
}
|
||||||
|
|
||||||
if (damageInfo->HitInfo & (HITINFO_FULL_ABSORB | HITINFO_PARTIAL_ABSORB))
|
if (damageInfo->HitInfo & (HITINFO_FULL_ABSORB | HITINFO_PARTIAL_ABSORB))
|
||||||
{
|
{
|
||||||
for (uint32 i = 0; i < count; ++i)
|
for (uint32 i = 0; i < count; ++i)
|
||||||
data << uint32(absorb); // Absorb
|
{
|
||||||
|
data << uint32(tmpAbsorb[i]); // Absorb
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (damageInfo->HitInfo & (HITINFO_FULL_RESIST | HITINFO_PARTIAL_RESIST))
|
if (damageInfo->HitInfo & (HITINFO_FULL_RESIST | HITINFO_PARTIAL_RESIST))
|
||||||
{
|
{
|
||||||
for (uint32 i = 0; i < count; ++i)
|
for (uint32 i = 0; i < count; ++i)
|
||||||
data << uint32(damageInfo->resist); // Resist
|
{
|
||||||
|
data << uint32(damageInfo->damages[i].resist); // Resist
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data << uint8(damageInfo->TargetState);
|
data << uint8(damageInfo->TargetState);
|
||||||
@@ -6153,10 +6431,17 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 /*SwingType
|
|||||||
dmgInfo.HitInfo = HitInfo;
|
dmgInfo.HitInfo = HitInfo;
|
||||||
dmgInfo.attacker = this;
|
dmgInfo.attacker = this;
|
||||||
dmgInfo.target = target;
|
dmgInfo.target = target;
|
||||||
dmgInfo.damage = Damage - AbsorbDamage - Resist - BlockedAmount;
|
|
||||||
dmgInfo.damageSchoolMask = damageSchoolMask;
|
dmgInfo.damages[0].damage = Damage - AbsorbDamage - Resist - BlockedAmount;
|
||||||
dmgInfo.absorb = AbsorbDamage;
|
dmgInfo.damages[0].damageSchoolMask = damageSchoolMask;
|
||||||
dmgInfo.resist = Resist;
|
dmgInfo.damages[0].absorb = AbsorbDamage;
|
||||||
|
dmgInfo.damages[0].resist = Resist;
|
||||||
|
|
||||||
|
dmgInfo.damages[1].damage = 0;
|
||||||
|
dmgInfo.damages[1].damageSchoolMask = 0;
|
||||||
|
dmgInfo.damages[1].absorb = 0;
|
||||||
|
dmgInfo.damages[1].resist = 0;
|
||||||
|
|
||||||
dmgInfo.TargetState = TargetState;
|
dmgInfo.TargetState = TargetState;
|
||||||
dmgInfo.blocked_amount = BlockedAmount;
|
dmgInfo.blocked_amount = BlockedAmount;
|
||||||
SendAttackStateUpdate(&dmgInfo);
|
SendAttackStateUpdate(&dmgInfo);
|
||||||
@@ -12327,6 +12612,11 @@ int32 Unit::SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask)
|
|||||||
|
|
||||||
bool Unit::IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const
|
bool Unit::IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const
|
||||||
{
|
{
|
||||||
|
if (meleeSchoolMask == SPELL_SCHOOL_MASK_NONE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// If m_immuneToDamage type contain magic, IMMUNE damage.
|
// If m_immuneToDamage type contain magic, IMMUNE damage.
|
||||||
SpellImmuneList const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
|
SpellImmuneList const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
|
||||||
for (SpellImmuneList::const_iterator itr = damageList.begin(); itr != damageList.end(); ++itr)
|
for (SpellImmuneList::const_iterator itr = damageList.begin(); itr != damageList.end(); ++itr)
|
||||||
@@ -12354,6 +12644,11 @@ bool Unit::IsImmunedToDamage(SpellInfo const* spellInfo) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32 schoolMask = spellInfo->GetSchoolMask();
|
uint32 schoolMask = spellInfo->GetSchoolMask();
|
||||||
|
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// If m_immuneToDamage type contain magic, IMMUNE damage.
|
// If m_immuneToDamage type contain magic, IMMUNE damage.
|
||||||
SpellImmuneList const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
|
SpellImmuneList const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
|
||||||
for (SpellImmuneList::const_iterator itr = damageList.begin(); itr != damageList.end(); ++itr)
|
for (SpellImmuneList::const_iterator itr = damageList.begin(); itr != damageList.end(); ++itr)
|
||||||
@@ -12363,8 +12658,50 @@ bool Unit::IsImmunedToDamage(SpellInfo const* spellInfo) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Unit::IsImmunedToDamage(Spell const* spell) const
|
||||||
|
{
|
||||||
|
SpellInfo const* spellInfo = spell->GetSpellInfo();
|
||||||
|
if (!spellInfo)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) && !HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) || spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 schoolMask = spell->GetSpellSchoolMask();
|
||||||
|
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If m_immuneToDamage type contain magic, IMMUNE damage.
|
||||||
|
SpellImmuneList const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
|
||||||
|
for (SpellImmuneList::const_iterator itr = damageList.begin(); itr != damageList.end(); ++itr)
|
||||||
|
{
|
||||||
|
if ((itr->type & schoolMask) == schoolMask)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Unit::IsImmunedToSchool(SpellSchoolMask meleeSchoolMask) const
|
bool Unit::IsImmunedToSchool(SpellSchoolMask meleeSchoolMask) const
|
||||||
{
|
{
|
||||||
|
if (meleeSchoolMask == SPELL_SCHOOL_MASK_NONE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// If m_immuneToSchool type contain this school type, IMMUNE damage.
|
// If m_immuneToSchool type contain this school type, IMMUNE damage.
|
||||||
SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
|
SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
|
||||||
for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
|
for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
|
||||||
@@ -12380,6 +12717,11 @@ bool Unit::IsImmunedToSchool(SpellInfo const* spellInfo) const
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
uint32 schoolMask = spellInfo->GetSchoolMask();
|
uint32 schoolMask = spellInfo->GetSchoolMask();
|
||||||
|
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (spellInfo->Id != 42292 && spellInfo->Id != 59752 && spellInfo->Id != 19574 && spellInfo->Id != 34471)
|
if (spellInfo->Id != 42292 && spellInfo->Id != 59752 && spellInfo->Id != 19574 && spellInfo->Id != 34471)
|
||||||
{
|
{
|
||||||
// If m_immuneToSchool type contain this school type, IMMUNE damage.
|
// If m_immuneToSchool type contain this school type, IMMUNE damage.
|
||||||
@@ -12392,8 +12734,43 @@ bool Unit::IsImmunedToSchool(SpellInfo const* spellInfo) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Unit::IsImmunedToSchool(Spell const* spell) const
|
||||||
|
{
|
||||||
|
SpellInfo const* spellInfo = spell->GetSpellInfo();
|
||||||
|
if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) && !HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 schoolMask = spell->GetSpellSchoolMask();
|
||||||
|
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spellInfo->Id != 42292 && spellInfo->Id != 59752 && spellInfo->Id != 19574 && spellInfo->Id != 34471)
|
||||||
|
{
|
||||||
|
// If m_immuneToSchool type contain this school type, IMMUNE damage.
|
||||||
|
SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
|
||||||
|
for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
|
||||||
|
{
|
||||||
|
if ((itr->type & schoolMask) == schoolMask && !spellInfo->CanPierceImmuneAura(sSpellMgr->GetSpellInfo(itr->spellId)))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Unit::IsImmunedToDamageOrSchool(SpellSchoolMask meleeSchoolMask) const
|
bool Unit::IsImmunedToDamageOrSchool(SpellSchoolMask meleeSchoolMask) const
|
||||||
{
|
{
|
||||||
|
if (meleeSchoolMask == SPELL_SCHOOL_MASK_NONE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return IsImmunedToDamage(meleeSchoolMask) || IsImmunedToSchool(meleeSchoolMask);
|
return IsImmunedToDamage(meleeSchoolMask) || IsImmunedToSchool(meleeSchoolMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12402,7 +12779,7 @@ bool Unit::IsImmunedToDamageOrSchool(SpellInfo const* spellInfo) const
|
|||||||
return IsImmunedToDamage(spellInfo) || IsImmunedToSchool(spellInfo);
|
return IsImmunedToDamage(spellInfo) || IsImmunedToSchool(spellInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo)
|
bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell)
|
||||||
{
|
{
|
||||||
if (!spellInfo)
|
if (!spellInfo)
|
||||||
return false;
|
return false;
|
||||||
@@ -12466,17 +12843,28 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (spellInfo->Id != 42292 && spellInfo->Id != 59752 && spellInfo->Id != 19574 && spellInfo->Id != 34471)
|
if (spellInfo->Id != 42292 && spellInfo->Id != 59752 && spellInfo->Id != 19574 && spellInfo->Id != 34471)
|
||||||
|
{
|
||||||
|
SpellSchoolMask spellSchoolMask = spellInfo->GetSchoolMask();
|
||||||
|
if (spell)
|
||||||
|
{
|
||||||
|
spellSchoolMask = spell->GetSpellSchoolMask();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spellSchoolMask != SPELL_SCHOOL_MASK_NONE)
|
||||||
{
|
{
|
||||||
SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
|
SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
|
||||||
for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
|
for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
|
||||||
{
|
{
|
||||||
SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->spellId);
|
SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->spellId);
|
||||||
if (((itr->type & spellInfo->GetSchoolMask()) == spellInfo->GetSchoolMask())
|
if (((itr->type & spellSchoolMask) == spellSchoolMask)
|
||||||
&& (!immuneSpellInfo || immuneSpellInfo->IsPositive()) && !spellInfo->IsPositive()
|
&& (!immuneSpellInfo || immuneSpellInfo->IsPositive()) && !spellInfo->IsPositive()
|
||||||
&& !spellInfo->CanPierceImmuneAura(immuneSpellInfo))
|
&& !spellInfo->CanPierceImmuneAura(immuneSpellInfo))
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -12549,7 +12937,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) cons
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto)
|
uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto, SpellSchoolMask damageSchoolMask /*= SPELL_SCHOOL_MASK_NORMAL*/)
|
||||||
{
|
{
|
||||||
if (!victim || pdamage == 0)
|
if (!victim || pdamage == 0)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -12560,7 +12948,7 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
|
|||||||
if (GetEntry() == 27893)
|
if (GetEntry() == 27893)
|
||||||
{
|
{
|
||||||
if (Unit* owner = GetOwner())
|
if (Unit* owner = GetOwner())
|
||||||
return owner->MeleeDamageBonusDone(victim, pdamage, attType, spellProto) / 2;
|
return owner->MeleeDamageBonusDone(victim, pdamage, attType, spellProto, damageSchoolMask) / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12618,19 +13006,17 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
|
|||||||
// Done total percent damage auras
|
// Done total percent damage auras
|
||||||
float DoneTotalMod = 1.0f;
|
float DoneTotalMod = 1.0f;
|
||||||
|
|
||||||
// Some spells don't benefit from pct done mods
|
// mods for SPELL_SCHOOL_MASK_NORMAL are already factored in base melee damage calculation
|
||||||
if (spellProto)
|
if (!(damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL))
|
||||||
{
|
{
|
||||||
|
// Some spells don't benefit from pct done mods
|
||||||
AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
|
AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
|
||||||
for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
|
for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
|
||||||
{
|
{
|
||||||
if (!spellProto->ValidateAttribute6SpellDamageMods(this, *i, false))
|
if (!spellProto || (spellProto->ValidateAttribute6SpellDamageMods(this, *i, false) &&
|
||||||
continue;
|
sScriptMgr->IsNeedModMeleeDamagePercent(this, *i, DoneTotalMod, spellProto)))
|
||||||
|
{
|
||||||
if (!sScriptMgr->IsNeedModMeleeDamagePercent(this, *i, DoneTotalMod, spellProto))
|
if (((*i)->GetMiscValue() & damageSchoolMask))
|
||||||
continue;
|
|
||||||
|
|
||||||
if (((*i)->GetMiscValue() & spellProto->GetSchoolMask()) && !((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
|
|
||||||
{
|
{
|
||||||
if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
|
if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
|
||||||
AddPct(DoneTotalMod, (*i)->GetAmount());
|
AddPct(DoneTotalMod, (*i)->GetAmount());
|
||||||
@@ -12641,6 +13027,7 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AuraEffectList const& mDamageDoneVersus = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS);
|
AuraEffectList const& mDamageDoneVersus = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS);
|
||||||
for (AuraEffectList::const_iterator i = mDamageDoneVersus.begin(); i != mDamageDoneVersus.end(); ++i)
|
for (AuraEffectList::const_iterator i = mDamageDoneVersus.begin(); i != mDamageDoneVersus.end(); ++i)
|
||||||
@@ -12752,7 +13139,7 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
|
|||||||
return uint32(std::max(tmpDamage, 0.0f));
|
return uint32(std::max(tmpDamage, 0.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto)
|
uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto/*= nullptr*/, SpellSchoolMask damageSchoolMask /*= SPELL_SCHOOL_MASK_NORMAL*/)
|
||||||
{
|
{
|
||||||
if (pdamage == 0)
|
if (pdamage == 0)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -12762,7 +13149,7 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
|
|||||||
// ..taken
|
// ..taken
|
||||||
AuraEffectList const& mDamageTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_TAKEN);
|
AuraEffectList const& mDamageTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_TAKEN);
|
||||||
for (AuraEffectList::const_iterator i = mDamageTaken.begin(); i != mDamageTaken.end(); ++i)
|
for (AuraEffectList::const_iterator i = mDamageTaken.begin(); i != mDamageTaken.end(); ++i)
|
||||||
if ((*i)->GetMiscValue() & (spellProto ? spellProto->GetSchoolMask() : attacker->GetMeleeDamageSchoolMask()))
|
if ((*i)->GetMiscValue() & damageSchoolMask)
|
||||||
TakenFlatBenefit += (*i)->GetAmount();
|
TakenFlatBenefit += (*i)->GetAmount();
|
||||||
|
|
||||||
if (attType != RANGED_ATTACK)
|
if (attType != RANGED_ATTACK)
|
||||||
@@ -12773,7 +13160,7 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
|
|||||||
// Taken total percent damage auras
|
// Taken total percent damage auras
|
||||||
float TakenTotalMod = 1.0f;
|
float TakenTotalMod = 1.0f;
|
||||||
|
|
||||||
TakenTotalMod *= GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, spellProto ? spellProto->GetSchoolMask() : attacker->GetMeleeDamageSchoolMask());
|
TakenTotalMod *= GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, damageSchoolMask);
|
||||||
|
|
||||||
// .. taken pct (special attacks)
|
// .. taken pct (special attacks)
|
||||||
if (spellProto)
|
if (spellProto)
|
||||||
@@ -12839,7 +13226,7 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
|
|||||||
bool addModifier = false;
|
bool addModifier = false;
|
||||||
AuraEffectList const& ResIgnoreAuras = attacker->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
|
AuraEffectList const& ResIgnoreAuras = attacker->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
|
||||||
for (AuraEffectList::const_iterator j = ResIgnoreAuras.begin(); j != ResIgnoreAuras.end(); ++j)
|
for (AuraEffectList::const_iterator j = ResIgnoreAuras.begin(); j != ResIgnoreAuras.end(); ++j)
|
||||||
if ((*j)->GetMiscValue() & (spellProto ? spellProto->GetSchoolMask() : SPELL_SCHOOL_MASK_NORMAL))
|
if ((*j)->GetMiscValue() & damageSchoolMask)
|
||||||
{
|
{
|
||||||
ApplyPct(ignoreModifier, (*j)->GetAmount());
|
ApplyPct(ignoreModifier, (*j)->GetAmount());
|
||||||
addModifier = true;
|
addModifier = true;
|
||||||
@@ -14881,12 +15268,12 @@ float Unit::GetTotalAttackPowerValue(WeaponAttackType attType, Unit* victim) con
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float Unit::GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange type) const
|
float Unit::GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange type, uint8 damageIndex /*= 0*/) const
|
||||||
{
|
{
|
||||||
if (attType == OFF_ATTACK && !haveOffhandWeapon())
|
if (attType == OFF_ATTACK && !haveOffhandWeapon())
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
|
||||||
return m_weaponDamage[attType][type];
|
return m_weaponDamage[attType][type][damageIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::SetLevel(uint8 lvl, bool showLevelChange)
|
void Unit::SetLevel(uint8 lvl, bool showLevelChange)
|
||||||
@@ -16253,11 +16640,6 @@ void Unit::TriggerAurasProcOnEvent(ProcEventInfo& eventInfo, std::list<AuraAppli
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SpellSchoolMask Unit::GetMeleeDamageSchoolMask() const
|
|
||||||
{
|
|
||||||
return SPELL_SCHOOL_MASK_NORMAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player* Unit::GetSpellModOwner() const
|
Player* Unit::GetSpellModOwner() const
|
||||||
{
|
{
|
||||||
if (Player* player = const_cast<Unit*>(this)->ToPlayer())
|
if (Player* player = const_cast<Unit*>(this)->ToPlayer())
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
uint32 damageSchoolMask;
|
uint32 damageSchoolMask;
|
||||||
uint32 damage;
|
uint32 damage;
|
||||||
uint32 absorb;
|
uint32 absorb;
|
||||||
uint32 resist;
|
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;
|
||||||
|
|
||||||
|
|||||||
@@ -2428,10 +2428,12 @@ 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;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user