aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Object/Object.cpp86
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp7
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h6
-rw-r--r--src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp18
4 files changed, 64 insertions, 53 deletions
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index be19025582d..07b73e66697 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -2366,54 +2366,62 @@ SpellMissInfo WorldObject::MagicSpellHitResult(Unit* victim, SpellInfo const* sp
if (!victim->IsAlive() && victim->GetTypeId() != TYPEID_PLAYER)
return SPELL_MISS_NONE;
- SpellSchoolMask schoolMask = spellInfo->GetSchoolMask();
- // PvP - PvE spell misschances per leveldif > 2
- int32 lchance = victim->GetTypeId() == TYPEID_PLAYER ? 7 : 11;
- int32 thisLevel = GetLevelForTarget(victim);
- if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsTrigger())
- thisLevel = std::max<int32>(thisLevel, spellInfo->SpellLevel);
- int32 leveldif = int32(victim->GetLevelForTarget(this)) - thisLevel;
- int32 levelBasedHitDiff = leveldif;
-
- // Base hit chance from attacker and victim levels
- int32 modHitChance = 100;
- if (levelBasedHitDiff >= 0)
- {
- if (victim->GetTypeId() != TYPEID_PLAYER)
+ float missChance = [&]()
+ {
+ if (spellInfo->HasAttribute(SPELL_ATTR7_NO_ATTACK_MISS))
+ return 0.0f;
+
+ SpellSchoolMask schoolMask = spellInfo->GetSchoolMask();
+ // PvP - PvE spell misschances per leveldif > 2
+ int32 lchance = victim->GetTypeId() == TYPEID_PLAYER ? 7 : 11;
+ int32 thisLevel = GetLevelForTarget(victim);
+ if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsTrigger())
+ thisLevel = std::max<int32>(thisLevel, spellInfo->SpellLevel);
+ int32 leveldif = int32(victim->GetLevelForTarget(this)) - thisLevel;
+ int32 levelBasedHitDiff = leveldif;
+
+ // Base hit chance from attacker and victim levels
+ int32 modHitChance = 100;
+ if (levelBasedHitDiff >= 0)
{
- modHitChance = 94 - 3 * std::min(levelBasedHitDiff, 3);
- levelBasedHitDiff -= 3;
+ if (victim->GetTypeId() != TYPEID_PLAYER)
+ {
+ modHitChance = 94 - 3 * std::min(levelBasedHitDiff, 3);
+ levelBasedHitDiff -= 3;
+ }
+ else
+ {
+ modHitChance = 96 - std::min(levelBasedHitDiff, 2);
+ levelBasedHitDiff -= 2;
+ }
+ if (levelBasedHitDiff > 0)
+ modHitChance -= lchance * std::min(levelBasedHitDiff, 7);
}
else
+ modHitChance = 97 - levelBasedHitDiff;
+
+ // Spellmod from SpellModOp::HitChance
+ if (Player* modOwner = GetSpellModOwner())
+ modOwner->ApplySpellMod(spellInfo, SpellModOp::HitChance, modHitChance);
+
+ // Spells with SPELL_ATTR3_IGNORE_HIT_RESULT will ignore target's avoidance effects
+ if (!spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
{
- modHitChance = 96 - std::min(levelBasedHitDiff, 2);
- levelBasedHitDiff -= 2;
+ // Chance hit from victim SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE auras
+ modHitChance += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE, schoolMask);
}
- if (levelBasedHitDiff > 0)
- modHitChance -= lchance * std::min(levelBasedHitDiff, 7);
- }
- else
- modHitChance = 97 - levelBasedHitDiff;
-
- // Spellmod from SpellModOp::HitChance
- if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellInfo, SpellModOp::HitChance, modHitChance);
- // Spells with SPELL_ATTR3_IGNORE_HIT_RESULT will ignore target's avoidance effects
- if (!spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
- {
- // Chance hit from victim SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE auras
- modHitChance += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE, schoolMask);
- }
+ float HitChance = modHitChance;
+ // Increase hit chance from attacker SPELL_AURA_MOD_SPELL_HIT_CHANCE and attacker ratings
+ if (Unit const* unit = ToUnit())
+ HitChance += unit->m_modSpellHitChance;
- int32 HitChance = modHitChance * 100;
- // Increase hit chance from attacker SPELL_AURA_MOD_SPELL_HIT_CHANCE and attacker ratings
- if (Unit const* unit = ToUnit())
- HitChance += int32(unit->m_modSpellHitChance * 100.0f);
+ RoundToInterval(HitChance, 0.0f, 100.0f);
- RoundToInterval(HitChance, 0, 10000);
+ return 100.0f - HitChance;
+ }();
- int32 tmp = 10000 - HitChance;
+ int32 tmp = int32(missChance * 100.0f);
int32 rand = irand(0, 9999);
if (tmp > 0 && rand < tmp)
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index f9e66caa44d..cfb20a015b8 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -2363,8 +2363,8 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
if (spellInfo->HasAttribute(SPELL_ATTR0_IMPOSSIBLE_DODGE_PARRY_BLOCK))
return SPELL_MISS_NONE;
- bool canDodge = true;
- bool canParry = true;
+ bool canDodge = !spellInfo->HasAttribute(SPELL_ATTR7_NO_ATTACK_DODGE);
+ bool canParry = !spellInfo->HasAttribute(SPELL_ATTR7_NO_ATTACK_PARRY);
bool canBlock = spellInfo->HasAttribute(SPELL_ATTR3_BLOCKABLE_SPELL);
// if victim is casting or cc'd it can't avoid attacks
@@ -11559,6 +11559,9 @@ int32 Unit::CalculateAOEAvoidance(int32 damage, uint32 schoolMask, ObjectGuid co
// Crit or block - determined on damage calculation phase! (and can be both in some time)
float Unit::MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, SpellInfo const* spellInfo) const
{
+ if (spellInfo && spellInfo->HasAttribute(SPELL_ATTR7_NO_ATTACK_MISS))
+ return 0.f;
+
//calculate miss chance
float missChance = victim->GetUnitMissChance();
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 707668233b5..b62dbe68786 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -686,9 +686,9 @@ enum SpellAttr7 : uint32
SPELL_ATTR7_UNK20 = 0x00100000, // TITLE Unknown attribute 20@Attr7 DESCRIPTION Invulnerability related?
SPELL_ATTR7_UNK21 = 0x00200000, // TITLE Unknown attribute 21@Attr7
SPELL_ATTR7_IGNORES_COLD_WEATHER_FLYING_REQUIREMENT = 0x00400000, // TITLE Ignores Cold Weather Flying Requirement
- SPELL_ATTR7_UNK23 = 0x00800000, // TITLE Unknown attribute 23@Attr7
- SPELL_ATTR7_UNK24 = 0x01000000, // TITLE Unknown attribute 24@Attr7
- SPELL_ATTR7_UNK25 = 0x02000000, // TITLE Unknown attribute 25@Attr7
+ SPELL_ATTR7_NO_ATTACK_DODGE = 0x00800000, // TITLE No Attack Dodge
+ SPELL_ATTR7_NO_ATTACK_PARRY = 0x01000000, // TITLE No Attack Parry
+ SPELL_ATTR7_NO_ATTACK_MISS = 0x02000000, // TITLE No Attack Miss
SPELL_ATTR7_UNK26 = 0x04000000, // TITLE Unknown attribute 26@Attr7
SPELL_ATTR7_BYPASS_NO_RESURRECT_AURA = 0x08000000, // TITLE Bypass No Resurrect Aura
SPELL_ATTR7_CONSOLIDATED_RAID_BUFF = 0x10000000, // TITLE Consolidate in raid buff frame (client only)
diff --git a/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp b/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp
index 4f90df03315..ab86d61c4e7 100644
--- a/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp
+++ b/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp
@@ -1173,9 +1173,9 @@ TC_API_EXPORT EnumText EnumUtils<SpellAttr7>::ToString(SpellAttr7 value)
case SPELL_ATTR7_UNK20: return { "SPELL_ATTR7_UNK20", "Unknown attribute 20@Attr7", "Invulnerability related?" };
case SPELL_ATTR7_UNK21: return { "SPELL_ATTR7_UNK21", "Unknown attribute 21@Attr7", "" };
case SPELL_ATTR7_IGNORES_COLD_WEATHER_FLYING_REQUIREMENT: return { "SPELL_ATTR7_IGNORES_COLD_WEATHER_FLYING_REQUIREMENT", "Ignores Cold Weather Flying Requirement", "" };
- case SPELL_ATTR7_UNK23: return { "SPELL_ATTR7_UNK23", "Unknown attribute 23@Attr7", "" };
- case SPELL_ATTR7_UNK24: return { "SPELL_ATTR7_UNK24", "Unknown attribute 24@Attr7", "" };
- case SPELL_ATTR7_UNK25: return { "SPELL_ATTR7_UNK25", "Unknown attribute 25@Attr7", "" };
+ case SPELL_ATTR7_NO_ATTACK_DODGE: return { "SPELL_ATTR7_NO_ATTACK_DODGE", "No Attack Dodge", "" };
+ case SPELL_ATTR7_NO_ATTACK_PARRY: return { "SPELL_ATTR7_NO_ATTACK_PARRY", "No Attack Parry", "" };
+ case SPELL_ATTR7_NO_ATTACK_MISS: return { "SPELL_ATTR7_NO_ATTACK_MISS", "No Attack Miss", "" };
case SPELL_ATTR7_UNK26: return { "SPELL_ATTR7_UNK26", "Unknown attribute 26@Attr7", "" };
case SPELL_ATTR7_BYPASS_NO_RESURRECT_AURA: return { "SPELL_ATTR7_BYPASS_NO_RESURRECT_AURA", "Bypass No Resurrect Aura", "" };
case SPELL_ATTR7_CONSOLIDATED_RAID_BUFF: return { "SPELL_ATTR7_CONSOLIDATED_RAID_BUFF", "Consolidate in raid buff frame (client only)", "" };
@@ -1217,9 +1217,9 @@ TC_API_EXPORT SpellAttr7 EnumUtils<SpellAttr7>::FromIndex(size_t index)
case 20: return SPELL_ATTR7_UNK20;
case 21: return SPELL_ATTR7_UNK21;
case 22: return SPELL_ATTR7_IGNORES_COLD_WEATHER_FLYING_REQUIREMENT;
- case 23: return SPELL_ATTR7_UNK23;
- case 24: return SPELL_ATTR7_UNK24;
- case 25: return SPELL_ATTR7_UNK25;
+ case 23: return SPELL_ATTR7_NO_ATTACK_DODGE;
+ case 24: return SPELL_ATTR7_NO_ATTACK_PARRY;
+ case 25: return SPELL_ATTR7_NO_ATTACK_MISS;
case 26: return SPELL_ATTR7_UNK26;
case 27: return SPELL_ATTR7_BYPASS_NO_RESURRECT_AURA;
case 28: return SPELL_ATTR7_CONSOLIDATED_RAID_BUFF;
@@ -1258,9 +1258,9 @@ TC_API_EXPORT size_t EnumUtils<SpellAttr7>::ToIndex(SpellAttr7 value)
case SPELL_ATTR7_UNK20: return 20;
case SPELL_ATTR7_UNK21: return 21;
case SPELL_ATTR7_IGNORES_COLD_WEATHER_FLYING_REQUIREMENT: return 22;
- case SPELL_ATTR7_UNK23: return 23;
- case SPELL_ATTR7_UNK24: return 24;
- case SPELL_ATTR7_UNK25: return 25;
+ case SPELL_ATTR7_NO_ATTACK_DODGE: return 23;
+ case SPELL_ATTR7_NO_ATTACK_PARRY: return 24;
+ case SPELL_ATTR7_NO_ATTACK_MISS: return 25;
case SPELL_ATTR7_UNK26: return 26;
case SPELL_ATTR7_BYPASS_NO_RESURRECT_AURA: return 27;
case SPELL_ATTR7_CONSOLIDATED_RAID_BUFF: return 28;