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)
|
||||
return false;
|
||||
@@ -2178,7 +2178,7 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo)
|
||||
if (immunedToAllEffects)
|
||||
return true;
|
||||
|
||||
return Unit::IsImmunedToSpell(spellInfo);
|
||||
return Unit::IsImmunedToSpell(spellInfo, spell);
|
||||
}
|
||||
|
||||
bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const
|
||||
|
||||
@@ -96,7 +96,7 @@ public:
|
||||
[[nodiscard]] bool IsValidTrainerForPlayer(Player* player, uint32* npcFlags = nullptr) const;
|
||||
bool CanCreatureAttack(Unit const* victim, bool skipDistCheck = false) const;
|
||||
void LoadSpellTemplateImmunity();
|
||||
bool IsImmunedToSpell(SpellInfo const* spellInfo) override;
|
||||
bool IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell = nullptr) override;
|
||||
|
||||
[[nodiscard]] bool HasMechanicTemplateImmunity(uint32 mask) const;
|
||||
// redefine Unit::IsImmunedToSpell
|
||||
@@ -155,7 +155,7 @@ public:
|
||||
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 _AddCreatureSpellCooldown(uint32 spell_id, uint16 categoryId, uint32 end_time);
|
||||
@@ -178,7 +178,7 @@ public:
|
||||
void UpdateMaxHealth() override;
|
||||
void UpdateMaxPower(Powers power) 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;
|
||||
[[nodiscard]] int8 GetOriginalEquipmentId() const { return m_originalEquipmentId; }
|
||||
|
||||
@@ -6740,21 +6740,11 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
|
||||
if (proto->ArcaneRes)
|
||||
HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(proto->ArcaneRes), apply);
|
||||
|
||||
WeaponAttackType attType = BASE_ATTACK;
|
||||
|
||||
if (slot == EQUIPMENT_SLOT_RANGED && (
|
||||
proto->InventoryType == INVTYPE_RANGED || proto->InventoryType == INVTYPE_THROWN ||
|
||||
proto->InventoryType == INVTYPE_RANGEDRIGHT))
|
||||
uint8 attType = Player::GetAttackBySlot(slot);
|
||||
if (attType != MAX_ATTACK)
|
||||
{
|
||||
attType = RANGED_ATTACK;
|
||||
}
|
||||
else if (slot == EQUIPMENT_SLOT_OFFHAND)
|
||||
{
|
||||
attType = OFF_ATTACK;
|
||||
}
|
||||
|
||||
if (CanUseAttackType(attType))
|
||||
_ApplyWeaponDamage(slot, proto, ssv, apply);
|
||||
}
|
||||
|
||||
// Druids get feral AP bonus from weapon dps (also use DPS from ScalingStatValue)
|
||||
if (getClass() == CLASS_DRUID)
|
||||
@@ -6797,22 +6787,16 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
|
||||
ssv = ScalingStatValue ? sScalingStatValuesStore.LookupEntry(ssd_level) : nullptr;
|
||||
}
|
||||
|
||||
WeaponAttackType attType = BASE_ATTACK;
|
||||
float damage = 0.0f;
|
||||
|
||||
if (slot == EQUIPMENT_SLOT_RANGED && (
|
||||
proto->InventoryType == INVTYPE_RANGED || proto->InventoryType == INVTYPE_THROWN ||
|
||||
proto->InventoryType == INVTYPE_RANGEDRIGHT))
|
||||
uint8 attType = Player::GetAttackBySlot(slot);
|
||||
if (!IsInFeralForm() && apply && !CanUseAttackType(attType))
|
||||
{
|
||||
attType = RANGED_ATTACK;
|
||||
}
|
||||
else if (slot == EQUIPMENT_SLOT_OFFHAND)
|
||||
{
|
||||
attType = OFF_ATTACK;
|
||||
return;
|
||||
}
|
||||
|
||||
float minDamage = proto->Damage[0].DamageMin;
|
||||
float maxDamage = proto->Damage[0].DamageMax;
|
||||
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||
{
|
||||
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 (ssv)
|
||||
@@ -6826,16 +6810,33 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
|
||||
}
|
||||
}
|
||||
|
||||
if (minDamage > 0)
|
||||
if (apply)
|
||||
{
|
||||
damage = apply ? minDamage : BASE_MINDAMAGE;
|
||||
SetBaseWeaponDamage(attType, MINDAMAGE, damage);
|
||||
if (minDamage > 0.f)
|
||||
{
|
||||
SetBaseWeaponDamage(WeaponAttackType(attType), MINDAMAGE, minDamage, i);
|
||||
}
|
||||
|
||||
if (maxDamage > 0)
|
||||
if (maxDamage > 0.f)
|
||||
{
|
||||
damage = apply ? maxDamage : BASE_MAXDAMAGE;
|
||||
SetBaseWeaponDamage(attType, MAXDAMAGE, damage);
|
||||
SetBaseWeaponDamage(WeaponAttackType(attType), MAXDAMAGE, maxDamage, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
@@ -6852,8 +6853,18 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
|
||||
if (IsInFeralForm())
|
||||
return;
|
||||
|
||||
if (CanModifyStats() && (damage || proto->Delay))
|
||||
UpdateDamagePhysical(attType);
|
||||
if (CanModifyStats() && (GetWeaponDamageRange(WeaponAttackType(attType), MAXDAMAGE) || proto->Delay))
|
||||
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)
|
||||
|
||||
@@ -1905,7 +1905,7 @@ public:
|
||||
void UpdateRating(CombatRating cr);
|
||||
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();
|
||||
inline void RecalculateRating(CombatRating cr) { ApplyRatingMod(cr, 0, true);}
|
||||
@@ -2147,6 +2147,8 @@ public:
|
||||
|
||||
void ResetAllPowers();
|
||||
|
||||
SpellSchoolMask GetMeleeDamageSchoolMask(WeaponAttackType attackType = BASE_ATTACK, uint8 damageIndex = 0) const override;
|
||||
|
||||
void _ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackType, bool apply);
|
||||
void _ApplyWeaponDependentAuraCritMod(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)
|
||||
{
|
||||
float minDamage = 0.0f;
|
||||
float maxDamage = 0.0f;
|
||||
float totalMin = 0.f;
|
||||
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)
|
||||
{
|
||||
case BASE_ATTACK:
|
||||
default:
|
||||
SetStatFloatValue(UNIT_FIELD_MINDAMAGE, minDamage);
|
||||
SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxDamage);
|
||||
SetStatFloatValue(UNIT_FIELD_MINDAMAGE, totalMin);
|
||||
SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, totalMax);
|
||||
break;
|
||||
case OFF_ATTACK:
|
||||
SetStatFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, minDamage);
|
||||
SetStatFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, maxDamage);
|
||||
SetStatFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, totalMin);
|
||||
SetStatFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, totalMax);
|
||||
break;
|
||||
case RANGED_ATTACK:
|
||||
SetStatFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, minDamage);
|
||||
SetStatFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, maxDamage);
|
||||
SetStatFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, totalMin);
|
||||
SetStatFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, totalMax);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -525,8 +531,23 @@ void Player::UpdateShieldBlockValue()
|
||||
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;
|
||||
|
||||
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;
|
||||
float variance = 1.0f;
|
||||
switch (attType)
|
||||
|
||||
@@ -118,9 +118,19 @@ DamageInfo::DamageInfo(Unit* _attacker, Unit* _victim, uint32 _damage, SpellInfo
|
||||
m_block = 0;
|
||||
}
|
||||
|
||||
DamageInfo::DamageInfo(CalcDamageInfo& dmgInfo)
|
||||
: 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(CalcDamageInfo const& dmgInfo) : DamageInfo(DamageInfo(dmgInfo, 0), DamageInfo(dmgInfo, 1))
|
||||
{
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
@@ -268,8 +278,11 @@ Unit::Unit(bool isWorldObject) : WorldObject(isWorldObject),
|
||||
|
||||
for (uint8 i = 0; i < MAX_ATTACK; ++i)
|
||||
{
|
||||
m_weaponDamage[i][MINDAMAGE] = BASE_MINDAMAGE;
|
||||
m_weaponDamage[i][MAXDAMAGE] = BASE_MAXDAMAGE;
|
||||
m_weaponDamage[i][MINDAMAGE][0] = BASE_MINDAMAGE;
|
||||
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)
|
||||
@@ -1437,16 +1450,21 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss,
|
||||
}
|
||||
|
||||
// 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->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->damage = 0;
|
||||
damageInfo->cleanDamage = 0;
|
||||
damageInfo->absorb = 0;
|
||||
damageInfo->resist = 0;
|
||||
damageInfo->blocked_amount = 0;
|
||||
|
||||
damageInfo->TargetState = 0;
|
||||
@@ -1478,8 +1496,25 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
|
||||
return;
|
||||
}
|
||||
|
||||
// Physical Immune check
|
||||
if (damageInfo->target->IsImmunedToDamageOrSchool(SpellSchoolMask(damageInfo->damageSchoolMask)))
|
||||
// School Immune check
|
||||
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->TargetState = VICTIMSTATE_IS_IMMUNE;
|
||||
@@ -1487,23 +1522,46 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
|
||||
damageInfo->procEx |= PROC_EX_IMMUNE;
|
||||
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
|
||||
damage = MeleeDamageBonusDone(damageInfo->target, damage, damageInfo->attackType);
|
||||
damage = damageInfo->target->MeleeDamageBonusTaken(this, damage, damageInfo->attackType);
|
||||
damage = MeleeDamageBonusDone(damageInfo->target, damage, damageInfo->attackType, nullptr, schoolMask);
|
||||
damage = damageInfo->target->MeleeDamageBonusTaken(this, damage, damageInfo->attackType, nullptr, schoolMask);
|
||||
|
||||
// Script Hook For CalculateMeleeDamage -- Allow scripts to change the Damage pre class mitigation calculations
|
||||
sScriptMgr->ModifyMeleeDamage(damageInfo->target, damageInfo->attacker, damage);
|
||||
|
||||
// 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->cleanDamage += damage - damageInfo->damage;
|
||||
damageInfo->damages[i].damage = Unit::CalcArmorReducedDamage(this, damageInfo->target, damage, nullptr, 0, damageInfo->attackType);
|
||||
damageInfo->cleanDamage += damage - damageInfo->damages[i].damage;
|
||||
}
|
||||
else
|
||||
damageInfo->damage = damage;
|
||||
{
|
||||
damageInfo->damages[i].damage = damage;
|
||||
}
|
||||
}
|
||||
|
||||
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->TargetState = VICTIMSTATE_EVADES;
|
||||
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;
|
||||
return;
|
||||
case MELEE_HIT_MISS:
|
||||
damageInfo->HitInfo |= HITINFO_MISS;
|
||||
damageInfo->TargetState = VICTIMSTATE_INTACT;
|
||||
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;
|
||||
break;
|
||||
case MELEE_HIT_NORMAL:
|
||||
@@ -1539,17 +1606,22 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
|
||||
|
||||
damageInfo->procEx |= PROC_EX_CRITICAL_HIT;
|
||||
// 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;
|
||||
// Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
|
||||
if (damageInfo->attackType == RANGED_ATTACK)
|
||||
{
|
||||
mod += damageInfo->target->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
mod += damageInfo->target->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE);
|
||||
|
||||
// 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();
|
||||
@@ -1557,22 +1629,36 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
|
||||
// Increase crit damage from SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
|
||||
mod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask);
|
||||
if (mod != 0)
|
||||
AddPct(damageInfo->damage, mod);
|
||||
{
|
||||
AddPct(damageInfo->damages[i].damage, mod);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MELEE_HIT_PARRY:
|
||||
damageInfo->TargetState = VICTIMSTATE_PARRY;
|
||||
damageInfo->procEx |= PROC_EX_PARRY;
|
||||
damageInfo->cleanDamage += damageInfo->damage;
|
||||
damageInfo->damage = 0;
|
||||
damageInfo->cleanDamage = 0;
|
||||
|
||||
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||
{
|
||||
damageInfo->cleanDamage += damageInfo->damages[i].damage;
|
||||
damageInfo->damages[i].damage = 0;
|
||||
}
|
||||
break;
|
||||
case MELEE_HIT_DODGE:
|
||||
damageInfo->TargetState = VICTIMSTATE_DODGE;
|
||||
damageInfo->procEx |= PROC_EX_DODGE;
|
||||
damageInfo->cleanDamage += damageInfo->damage;
|
||||
damageInfo->damage = 0;
|
||||
damageInfo->cleanDamage = 0;
|
||||
|
||||
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||
{
|
||||
damageInfo->cleanDamage += damageInfo->damages[i].damage;
|
||||
damageInfo->damages[i].damage = 0;
|
||||
}
|
||||
break;
|
||||
case MELEE_HIT_BLOCK:
|
||||
{
|
||||
damageInfo->TargetState = VICTIMSTATE_HIT;
|
||||
damageInfo->HitInfo |= HITINFO_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
|
||||
if (damageInfo->target->isBlockCritical())
|
||||
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;
|
||||
damageInfo->blocked_amount = damageInfo->damage;
|
||||
damageInfo->procEx |= PROC_EX_FULL_BLOCK;
|
||||
if (remainingBlock && remainingBlock >= damageInfo->damages[i].damage)
|
||||
{
|
||||
fullBlockMask |= (1 << i);
|
||||
|
||||
remainingBlock -= damageInfo->damages[i].damage;
|
||||
damageInfo->cleanDamage += damageInfo->damages[i].damage;
|
||||
damageInfo->damages[i].damage = 0;
|
||||
}
|
||||
else
|
||||
damageInfo->procEx |= PROC_EX_NORMAL_HIT;
|
||||
damageInfo->damage -= damageInfo->blocked_amount;
|
||||
damageInfo->cleanDamage += damageInfo->blocked_amount;
|
||||
{
|
||||
damageInfo->cleanDamage += remainingBlock;
|
||||
damageInfo->damages[i].damage -= remainingBlock;
|
||||
remainingBlock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// full block
|
||||
if (fullBlockMask == ((1 << 0) | (1 << 1)))
|
||||
{
|
||||
damageInfo->TargetState = VICTIMSTATE_BLOCKS;
|
||||
damageInfo->blocked_amount -= remainingBlock;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MELEE_HIT_GLANCING:
|
||||
{
|
||||
damageInfo->HitInfo |= HITINFO_GLANCING;
|
||||
@@ -1600,16 +1704,25 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
|
||||
if (leveldif > 3)
|
||||
leveldif = 3;
|
||||
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;
|
||||
}
|
||||
case MELEE_HIT_CRUSHING:
|
||||
damageInfo->HitInfo |= HITINFO_CRUSHING;
|
||||
damageInfo->TargetState = VICTIMSTATE_HIT;
|
||||
damageInfo->procEx |= PROC_EX_NORMAL_HIT;
|
||||
|
||||
// 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;
|
||||
default:
|
||||
break;
|
||||
@@ -1619,43 +1732,70 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
|
||||
if (!(damageInfo->HitInfo & HITINFO_MISS))
|
||||
damageInfo->HitInfo |= HITINFO_AFFECTS_VICTIM;
|
||||
|
||||
// attackType is checked already for BASE_ATTACK or OFF_ATTACK so it can't be RANGED_ATTACK here
|
||||
int32 dmg = damageInfo->damage;
|
||||
uint32 tmpHitInfo[MAX_ITEM_PROTO_DAMAGES] = { };
|
||||
|
||||
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||
{
|
||||
int32 dmg = damageInfo->damages[i].damage;
|
||||
int32 cleanDamage = damageInfo->cleanDamage;
|
||||
// attackType is checked already for BASE_ATTACK or OFF_ATTACK so it can't be RANGED_ATTACK here
|
||||
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);
|
||||
|
||||
resilienceReduction = dmg - resilienceReduction;
|
||||
resilienceReduction = damageInfo->damages[i].damage - resilienceReduction;
|
||||
dmg -= resilienceReduction;
|
||||
cleanDamage += resilienceReduction;
|
||||
}
|
||||
|
||||
damageInfo->damage = std::max(0, dmg);
|
||||
damageInfo->damages[i].damage = std::max(0, dmg);
|
||||
damageInfo->cleanDamage = std::max(0, cleanDamage);
|
||||
|
||||
// Calculate absorb resist
|
||||
if (damageInfo->damage > 0)
|
||||
if (damageInfo->damages[i].damage > 0)
|
||||
{
|
||||
damageInfo->procVictim |= PROC_FLAG_TAKEN_DAMAGE;
|
||||
|
||||
// Calculate absorb & resists
|
||||
|
||||
DamageInfo dmgInfo(*damageInfo);
|
||||
DamageInfo dmgInfo(*damageInfo, i);
|
||||
Unit::CalcAbsorbResist(dmgInfo);
|
||||
damageInfo->absorb = dmgInfo.GetAbsorb();
|
||||
damageInfo->resist = dmgInfo.GetResist();
|
||||
damageInfo->damages[i].absorb = dmgInfo.GetAbsorb();
|
||||
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);
|
||||
damageInfo->procEx |= PROC_EX_ABSORB;
|
||||
tmpHitInfo[i] |= (damageInfo->damages[i].damage - damageInfo->damages[i].absorb == 0 ? HITINFO_FULL_ABSORB : HITINFO_PARTIAL_ABSORB);
|
||||
}
|
||||
|
||||
if (damageInfo->resist)
|
||||
damageInfo->HitInfo |= (damageInfo->damage - damageInfo->resist == 0 ? HITINFO_FULL_RESIST : HITINFO_PARTIAL_RESIST);
|
||||
if (damageInfo->damages[i].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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Hmmmm dont like this emotes client must by self do all animations
|
||||
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
|
||||
CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->absorb, damageInfo->attackType, damageInfo->hitOutCome);
|
||||
Unit::DealDamage(this, victim, damageInfo->damage, &cleanDamage, DIRECT_DAMAGE, SpellSchoolMask(damageInfo->damageSchoolMask), nullptr, durabilityLoss);
|
||||
CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->damages[i].absorb, damageInfo->attackType, damageInfo->hitOutCome);
|
||||
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 (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)
|
||||
&& (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);
|
||||
|
||||
// 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
|
||||
// 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 newdamage = 0;
|
||||
float armor = float(victim->GetArmor());
|
||||
|
||||
// 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)
|
||||
tmpvalue = 0.75f;
|
||||
|
||||
newdamage = uint32(damage - (damage * tmpvalue));
|
||||
|
||||
return (newdamage > 1) ? newdamage : 1;
|
||||
return uint32(std::ceil(std::max(damage * (1.0f - tmpvalue), 0.0f)));
|
||||
}
|
||||
|
||||
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
|
||||
victim = GetMeleeHitRedirectTarget(victim);
|
||||
CalcDamageInfo damageInfo;
|
||||
CalculateMeleeDamage(victim, 0, &damageInfo, attType, sittingVictim);
|
||||
CalculateMeleeDamage(victim, &damageInfo, attType, sittingVictim);
|
||||
|
||||
// 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);
|
||||
|
||||
//TriggerAurasProcOnEvent(damageInfo);
|
||||
@@ -2427,15 +2583,15 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType /*= BASE_A
|
||||
DealMeleeDamage(&damageInfo, true);
|
||||
|
||||
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);
|
||||
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
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
|
||||
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
|
||||
// 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;
|
||||
}
|
||||
|
||||
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 maxDamage = 0.0f;
|
||||
|
||||
if (normalized || !addTotalPct)
|
||||
CalculateMinMaxDamage(attType, normalized, addTotalPct, minDamage, maxDamage);
|
||||
if (normalized || !addTotalPct || itemDamagesMask)
|
||||
{
|
||||
// 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
|
||||
{
|
||||
switch (attType)
|
||||
@@ -2790,14 +2963,15 @@ uint32 Unit::CalculateDamage(WeaponAttackType attType, bool normalized, bool add
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// pussywizard: this check only in "else" section, proper check is also in CalculateMinMaxDamage
|
||||
if (minDamage > maxDamage)
|
||||
minDamage = maxDamage;
|
||||
}
|
||||
|
||||
if (maxDamage == 0.0f)
|
||||
maxDamage = 5.0f;
|
||||
minDamage = std::max(0.f, minDamage);
|
||||
maxDamage = std::max(0.f, maxDamage);
|
||||
|
||||
if (minDamage > maxDamage)
|
||||
{
|
||||
std::swap(minDamage, 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;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
@@ -6078,43 +6342,57 @@ void Unit::SendAttackStateUpdate(CalcDamageInfo* damageInfo)
|
||||
{
|
||||
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
|
||||
uint32 damage = damageInfo->damage;
|
||||
uint32 absorb = damageInfo->absorb;
|
||||
tmpDamage[i] = damageInfo->damages[i].damage;
|
||||
tmpAbsorb[i] = damageInfo->damages[i].absorb;
|
||||
if (damageInfo->target->GetTypeId() == TYPEID_PLAYER && damageInfo->target->ToPlayer()->GetCommandStatus(CHEAT_GOD))
|
||||
{
|
||||
absorb = damage;
|
||||
damage = 0;
|
||||
tmpAbsorb[i] = tmpDamage[i];
|
||||
tmpDamage[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
data << uint32(damageInfo->HitInfo);
|
||||
data << damageInfo->attacker->GetPackGUID();
|
||||
data << damageInfo->target->GetPackGUID();
|
||||
data << uint32(damage); // Full damage
|
||||
int32 overkill = damage - damageInfo->target->GetHealth();
|
||||
data << uint32(tmpDamage[0] + tmpDamage[1]); // Full damage
|
||||
int32 overkill = tmpDamage[0] + tmpDamage[1] - damageInfo->target->GetHealth();
|
||||
data << uint32(overkill < 0 ? 0 : overkill); // Overkill
|
||||
data << uint8(count); // Sub damage count
|
||||
|
||||
for (uint32 i = 0; i < count; ++i)
|
||||
{
|
||||
data << uint32(damageInfo->damageSchoolMask); // School of sub damage
|
||||
data << float(damage); // sub damage
|
||||
data << uint32(damage); // Sub Damage
|
||||
data << uint32(damageInfo->damages[i].damageSchoolMask); // School of sub damage
|
||||
data << float(tmpDamage[i]); // sub damage
|
||||
data << uint32(tmpDamage[i]); // Sub Damage
|
||||
}
|
||||
|
||||
if (damageInfo->HitInfo & (HITINFO_FULL_ABSORB | HITINFO_PARTIAL_ABSORB))
|
||||
{
|
||||
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))
|
||||
{
|
||||
for (uint32 i = 0; i < count; ++i)
|
||||
data << uint32(damageInfo->resist); // Resist
|
||||
{
|
||||
data << uint32(damageInfo->damages[i].resist); // Resist
|
||||
}
|
||||
}
|
||||
|
||||
data << uint8(damageInfo->TargetState);
|
||||
@@ -6153,10 +6431,17 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 /*SwingType
|
||||
dmgInfo.HitInfo = HitInfo;
|
||||
dmgInfo.attacker = this;
|
||||
dmgInfo.target = target;
|
||||
dmgInfo.damage = Damage - AbsorbDamage - Resist - BlockedAmount;
|
||||
dmgInfo.damageSchoolMask = damageSchoolMask;
|
||||
dmgInfo.absorb = AbsorbDamage;
|
||||
dmgInfo.resist = Resist;
|
||||
|
||||
dmgInfo.damages[0].damage = Damage - AbsorbDamage - Resist - BlockedAmount;
|
||||
dmgInfo.damages[0].damageSchoolMask = damageSchoolMask;
|
||||
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.blocked_amount = BlockedAmount;
|
||||
SendAttackStateUpdate(&dmgInfo);
|
||||
@@ -12327,6 +12612,11 @@ int32 Unit::SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask)
|
||||
|
||||
bool Unit::IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const
|
||||
{
|
||||
if (meleeSchoolMask == 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)
|
||||
@@ -12354,6 +12644,11 @@ bool Unit::IsImmunedToDamage(SpellInfo const* spellInfo) const
|
||||
}
|
||||
|
||||
uint32 schoolMask = spellInfo->GetSchoolMask();
|
||||
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)
|
||||
@@ -12363,8 +12658,50 @@ bool Unit::IsImmunedToDamage(SpellInfo const* spellInfo) const
|
||||
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
|
||||
{
|
||||
if (meleeSchoolMask == SPELL_SCHOOL_MASK_NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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)
|
||||
@@ -12380,6 +12717,11 @@ bool Unit::IsImmunedToSchool(SpellInfo const* spellInfo) const
|
||||
return false;
|
||||
|
||||
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 m_immuneToSchool type contain this school type, IMMUNE damage.
|
||||
@@ -12392,8 +12734,43 @@ bool Unit::IsImmunedToSchool(SpellInfo const* spellInfo) const
|
||||
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
|
||||
{
|
||||
if (meleeSchoolMask == SPELL_SCHOOL_MASK_NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsImmunedToDamage(meleeSchoolMask) || IsImmunedToSchool(meleeSchoolMask);
|
||||
}
|
||||
|
||||
@@ -12402,7 +12779,7 @@ bool Unit::IsImmunedToDamageOrSchool(SpellInfo const* spellInfo) const
|
||||
return IsImmunedToDamage(spellInfo) || IsImmunedToSchool(spellInfo);
|
||||
}
|
||||
|
||||
bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo)
|
||||
bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell)
|
||||
{
|
||||
if (!spellInfo)
|
||||
return false;
|
||||
@@ -12466,17 +12843,28 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo)
|
||||
return true;
|
||||
|
||||
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];
|
||||
for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
|
||||
{
|
||||
SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->spellId);
|
||||
if (((itr->type & spellInfo->GetSchoolMask()) == spellInfo->GetSchoolMask())
|
||||
if (((itr->type & spellSchoolMask) == spellSchoolMask)
|
||||
&& (!immuneSpellInfo || immuneSpellInfo->IsPositive()) && !spellInfo->IsPositive()
|
||||
&& !spellInfo->CanPierceImmuneAura(immuneSpellInfo))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -12549,7 +12937,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) cons
|
||||
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)
|
||||
return 0;
|
||||
@@ -12560,7 +12948,7 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
|
||||
if (GetEntry() == 27893)
|
||||
{
|
||||
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
|
||||
float DoneTotalMod = 1.0f;
|
||||
|
||||
// Some spells don't benefit from pct done mods
|
||||
if (spellProto)
|
||||
// mods for SPELL_SCHOOL_MASK_NORMAL are already factored in base melee damage calculation
|
||||
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);
|
||||
for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
|
||||
{
|
||||
if (!spellProto->ValidateAttribute6SpellDamageMods(this, *i, false))
|
||||
continue;
|
||||
|
||||
if (!sScriptMgr->IsNeedModMeleeDamagePercent(this, *i, DoneTotalMod, spellProto))
|
||||
continue;
|
||||
|
||||
if (((*i)->GetMiscValue() & spellProto->GetSchoolMask()) && !((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
|
||||
if (!spellProto || (spellProto->ValidateAttribute6SpellDamageMods(this, *i, false) &&
|
||||
sScriptMgr->IsNeedModMeleeDamagePercent(this, *i, DoneTotalMod, spellProto)))
|
||||
{
|
||||
if (((*i)->GetMiscValue() & damageSchoolMask))
|
||||
{
|
||||
if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
|
||||
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);
|
||||
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));
|
||||
}
|
||||
|
||||
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)
|
||||
return 0;
|
||||
@@ -12762,7 +13149,7 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
|
||||
// ..taken
|
||||
AuraEffectList const& mDamageTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_TAKEN);
|
||||
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();
|
||||
|
||||
if (attType != RANGED_ATTACK)
|
||||
@@ -12773,7 +13160,7 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
|
||||
// Taken total percent damage auras
|
||||
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)
|
||||
if (spellProto)
|
||||
@@ -12839,7 +13226,7 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
|
||||
bool addModifier = false;
|
||||
AuraEffectList const& ResIgnoreAuras = attacker->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
|
||||
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());
|
||||
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())
|
||||
return 0.0f;
|
||||
|
||||
return m_weaponDamage[attType][type];
|
||||
return m_weaponDamage[attType][type][damageIndex];
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
if (Player* player = const_cast<Unit*>(this)->ToPlayer())
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "FollowerRefMgr.h"
|
||||
#include "FollowerReference.h"
|
||||
#include "HostileRefMgr.h"
|
||||
#include "ItemTemplate.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "Object.h"
|
||||
#include "Optional.h"
|
||||
@@ -251,7 +252,9 @@ enum UnitModifierType
|
||||
enum WeaponDamageRange
|
||||
{
|
||||
MINDAMAGE,
|
||||
MAXDAMAGE
|
||||
MAXDAMAGE,
|
||||
|
||||
MAX_WEAPON_DAMAGE_RANGE
|
||||
};
|
||||
|
||||
enum UnitMods
|
||||
@@ -762,9 +765,14 @@ private:
|
||||
uint32 m_resist;
|
||||
uint32 m_block;
|
||||
uint32 m_cleanDamage;
|
||||
|
||||
// amalgamation constructor (used for proc)
|
||||
DamageInfo(DamageInfo const& dmg1, DamageInfo const& dmg2);
|
||||
|
||||
public:
|
||||
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);
|
||||
|
||||
void ModifyDamage(int32 amount);
|
||||
@@ -868,10 +876,15 @@ struct CalcDamageInfo
|
||||
{
|
||||
Unit* attacker; // Attacker
|
||||
Unit* target; // Target for damage
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 damageSchoolMask;
|
||||
uint32 damage;
|
||||
uint32 absorb;
|
||||
uint32 resist;
|
||||
} damages[MAX_ITEM_PROTO_DAMAGES];
|
||||
|
||||
uint32 blocked_amount;
|
||||
uint32 HitInfo;
|
||||
uint32 TargetState;
|
||||
@@ -1331,7 +1344,7 @@ public:
|
||||
bool IsWithinCombatRange(Unit const* obj, float dist2compare) const;
|
||||
bool IsWithinMeleeRange(Unit const* obj, float dist = 0.f) 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;
|
||||
uint32 m_extraAttacks;
|
||||
bool m_canDualWield;
|
||||
@@ -1540,7 +1553,7 @@ public:
|
||||
void HandleEmoteCommand(uint32 emoteId);
|
||||
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 HandleProcExtraAttackFor(Unit* victim, uint32 count);
|
||||
@@ -1570,10 +1583,11 @@ public:
|
||||
|
||||
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;
|
||||
SpellMissInfo MeleeSpellHitResult(Unit* victim, SpellInfo const* spell);
|
||||
SpellMissInfo MagicSpellHitResult(Unit* victim, SpellInfo const* spell);
|
||||
SpellMissInfo SpellHitResult(Unit* victim, SpellInfo const* spell, bool canReflect = false);
|
||||
[[nodiscard]] float MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const;
|
||||
[[nodiscard]] SpellMissInfo MeleeSpellHitResult(Unit* victim, SpellInfo const* spell);
|
||||
[[nodiscard]] SpellMissInfo MagicSpellHitResult(Unit* victim, SpellInfo const* spell);
|
||||
[[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 GetUnitParryChance() const;
|
||||
@@ -2091,10 +2105,10 @@ public:
|
||||
virtual void UpdateAttackPowerAndDamage(bool ranged = false) = 0;
|
||||
virtual void UpdateDamagePhysical(WeaponAttackType attType);
|
||||
float GetTotalAttackPowerValue(WeaponAttackType attType, Unit* pVictim = nullptr) const;
|
||||
[[nodiscard]] float GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange type) const;
|
||||
void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; }
|
||||
virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) = 0;
|
||||
uint32 CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct);
|
||||
[[nodiscard]] float GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange type, uint8 damageIndex = 0) const;
|
||||
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, uint8 damageIndex = 0) = 0;
|
||||
uint32 CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, uint8 itemDamagesMask = 0);
|
||||
float GetAPMultiplier(WeaponAttackType attType, bool normalized);
|
||||
|
||||
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 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 MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, 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, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL);
|
||||
|
||||
bool isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType = BASE_ATTACK);
|
||||
bool isBlockCritical();
|
||||
@@ -2201,12 +2215,14 @@ public:
|
||||
|
||||
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);
|
||||
virtual bool IsImmunedToSpell(SpellInfo const* spellInfo);
|
||||
virtual bool IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell = nullptr);
|
||||
// redefined in Creature
|
||||
[[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;
|
||||
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;
|
||||
bool IsImmunedToDamageOrSchool(SpellInfo const* spellInfo) const;
|
||||
virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const;
|
||||
@@ -2484,7 +2500,7 @@ protected:
|
||||
uint32 m_interruptMask;
|
||||
|
||||
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;
|
||||
VisibleAuraMap m_visibleAuras;
|
||||
|
||||
|
||||
@@ -2428,10 +2428,12 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*=
|
||||
// Calculate hit result
|
||||
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)
|
||||
{
|
||||
targetInfo.missCondition = SPELL_MISS_NONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
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)
|
||||
{
|
||||
// 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
|
||||
targetInfo.reflectResult = SPELL_MISS_PARRY;
|
||||
@@ -2971,8 +2973,10 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
|
||||
return SPELL_MISS_EVADE;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// disable effects to which unit is immune
|
||||
SpellMissInfo returnVal = SPELL_MISS_IMMUNE;
|
||||
|
||||
@@ -589,6 +589,8 @@ public:
|
||||
|
||||
[[nodiscard]] TriggerCastFlags GetTriggeredCastFlags() const { return _triggeredCastFlags; }
|
||||
|
||||
[[nodiscard]] SpellSchoolMask GetSpellSchoolMask() const { return m_spellSchoolMask; }
|
||||
|
||||
protected:
|
||||
bool HasGlobalCooldown() const;
|
||||
void TriggerGlobalCooldown();
|
||||
|
||||
@@ -593,8 +593,14 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
|
||||
if (Player* caster = m_caster->ToPlayer())
|
||||
{
|
||||
// Add Ammo and Weapon damage plus RAP * 0.1
|
||||
float dmg_min = caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE);
|
||||
float dmg_max = caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE);
|
||||
float dmg_min = 0.f;
|
||||
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)
|
||||
{
|
||||
damage += int32(dmg_min);
|
||||
@@ -616,9 +622,17 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
|
||||
// Add main hand dps * effect[2] amount
|
||||
if (Player* player = m_caster->ToPlayer())
|
||||
{
|
||||
float mindamage, maxdamage;
|
||||
player->CalculateMinMaxDamage(BASE_ATTACK, false, false, mindamage, maxdamage);
|
||||
float average = (mindamage + maxdamage) / 2;
|
||||
float minTotal = 0.f;
|
||||
float maxTotal = 0.f;
|
||||
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);
|
||||
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));
|
||||
|
||||
// Add melee damage bonuses (also check for negative)
|
||||
eff_damage = m_caster->MeleeDamageBonusDone(unitTarget, eff_damage, m_attackType, m_spellInfo);
|
||||
eff_damage = unitTarget->MeleeDamageBonusTaken(m_caster, 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, m_spellSchoolMask);
|
||||
|
||||
// Meteor like spells (divided damage to targets)
|
||||
if (m_spellInfo->HasAttribute(SPELL_ATTR0_CU_SHARE_DAMAGE))
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
@@ -131,13 +132,25 @@ struct boss_viscidus : public BossAI
|
||||
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))
|
||||
damage = 0;
|
||||
|
||||
if (!attacker || _phase != PHASE_MELEE)
|
||||
if (!attacker)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_phase != PHASE_MELEE)
|
||||
{
|
||||
if (_phase == PHASE_FROST && effType == DIRECT_DAMAGE && (spellSchoolMask & SPELL_SCHOOL_MASK_FROST) != 0)
|
||||
{
|
||||
++_hitcounter;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (effType == DIRECT_DAMAGE)
|
||||
++_hitcounter;
|
||||
@@ -183,14 +196,23 @@ struct boss_viscidus : public BossAI
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -648,10 +648,13 @@ class spell_dk_dancing_rune_weapon : public AuraScript
|
||||
{
|
||||
target = player->GetMeleeHitRedirectTarget(target);
|
||||
CalcDamageInfo damageInfo;
|
||||
player->CalculateMeleeDamage(target, 0, &damageInfo, eventInfo.GetDamageInfo()->GetAttackType());
|
||||
Unit::DealDamageMods(target, damageInfo.damage, &damageInfo.absorb);
|
||||
player->CalculateMeleeDamage(target, &damageInfo, eventInfo.GetDamageInfo()->GetAttackType());
|
||||
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.damage /= 2.0f;
|
||||
dancingRuneWeapon->SendAttackStateUpdate(&damageInfo);
|
||||
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
|
||||
float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
|
||||
int32 mws = caster->GetAttackTime(BASE_ATTACK);
|
||||
float mwbMin = caster->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE);
|
||||
float mwbMax = caster->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE);
|
||||
float mwbMin = 0.f;
|
||||
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;
|
||||
amount += int32(caster->ApplyEffectModifiers(GetSpellInfo(), aurEff->GetEffIndex(), mwb));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user