Core/Unit: cleanup and minor fixes of miss and resist calculations
Port From (https://github.com/TrinityCore/TrinityCore/commit/1960a95425c63f3b45409bcc1ee544472be598a3)
This commit is contained in:
@@ -716,32 +716,28 @@ namespace Game.Entities
|
|||||||
//calculate miss chance
|
//calculate miss chance
|
||||||
float missChance = victim.GetUnitMissChance(attType);
|
float missChance = victim.GetUnitMissChance(attType);
|
||||||
|
|
||||||
|
// melee attacks while dual wielding have +19% chance to miss
|
||||||
if (spellId == 0 && HaveOffhandWeapon() && !IsInFeralForm())
|
if (spellId == 0 && HaveOffhandWeapon() && !IsInFeralForm())
|
||||||
missChance += 19;
|
missChance += 19.0f;
|
||||||
|
|
||||||
// Calculate hit chance
|
|
||||||
float hitChance = 100.0f;
|
|
||||||
|
|
||||||
// Spellmod from SPELLMOD_RESIST_MISS_CHANCE
|
// Spellmod from SPELLMOD_RESIST_MISS_CHANCE
|
||||||
|
float resistMissChance = 100.0f;
|
||||||
if (spellId != 0)
|
if (spellId != 0)
|
||||||
{
|
{
|
||||||
Player modOwner = GetSpellModOwner();
|
Player modOwner = GetSpellModOwner();
|
||||||
if (modOwner != null)
|
if (modOwner != null)
|
||||||
modOwner.ApplySpellMod(spellId, SpellModOp.ResistMissChance, ref hitChance);
|
modOwner.ApplySpellMod(spellId, SpellModOp.ResistMissChance, ref resistMissChance);
|
||||||
}
|
}
|
||||||
|
|
||||||
missChance += hitChance - 100.0f;
|
missChance += resistMissChance - 100.0f;
|
||||||
|
|
||||||
if (attType == WeaponAttackType.RangedAttack)
|
if (attType == WeaponAttackType.RangedAttack)
|
||||||
missChance -= ModRangedHitChance;
|
missChance -= ModRangedHitChance;
|
||||||
else
|
else
|
||||||
missChance -= ModMeleeHitChance;
|
missChance -= ModMeleeHitChance;
|
||||||
|
|
||||||
// Limit miss chance from 0 to 77%
|
// Limit miss chance from 0 to 60%
|
||||||
if (missChance < 0.0f)
|
MathFunctions.RoundToInterval(ref missChance, 0.0f, 60.0f);
|
||||||
return 0.0f;
|
|
||||||
if (missChance > 77.0f)
|
|
||||||
return 77.0f;
|
|
||||||
return missChance;
|
return missChance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -870,7 +866,7 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
float GetUnitMissChance(WeaponAttackType attType)
|
float GetUnitMissChance(WeaponAttackType attType)
|
||||||
{
|
{
|
||||||
float miss_chance = 5.00f;
|
float miss_chance = 5.0f;
|
||||||
|
|
||||||
if (attType == WeaponAttackType.RangedAttack)
|
if (attType == WeaponAttackType.RangedAttack)
|
||||||
miss_chance -= GetTotalAuraModifier(AuraType.ModAttackerRangedHitChance);
|
miss_chance -= GetTotalAuraModifier(AuraType.ModAttackerRangedHitChance);
|
||||||
@@ -1255,7 +1251,7 @@ namespace Game.Entities
|
|||||||
UpdateSpellDamageAndHealingBonus();
|
UpdateSpellDamageAndHealingBonus();
|
||||||
|
|
||||||
if (pet != null && pet.IsPetGhoul()) // At melee attack power change for DK pet
|
if (pet != null && pet.IsPetGhoul()) // At melee attack power change for DK pet
|
||||||
pet.UpdateAttackPowerAndDamage();
|
pet.UpdateAttackPowerAndDamage();
|
||||||
|
|
||||||
if (guardian != null && guardian.IsSpiritWolf()) // At melee attack power change for Shaman feral spirit
|
if (guardian != null && guardian.IsSpiritWolf()) // At melee attack power change for Shaman feral spirit
|
||||||
guardian.UpdateAttackPowerAndDamage();
|
guardian.UpdateAttackPowerAndDamage();
|
||||||
@@ -1498,24 +1494,63 @@ namespace Game.Entities
|
|||||||
// Store Rating Value
|
// Store Rating Value
|
||||||
SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.CombatRatings, (int)CombatRating.ArmorPenetration), (uint)amount);
|
SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.CombatRatings, (int)CombatRating.ArmorPenetration), (uint)amount);
|
||||||
}
|
}
|
||||||
public void UpdateParryPercentage()
|
|
||||||
|
float CalculateDiminishingReturns(float[] capArray, Class playerClass, float nonDiminishValue, float diminishValue)
|
||||||
{
|
{
|
||||||
float[] parry_cap =
|
float[] m_diminishing_k =
|
||||||
{
|
{
|
||||||
65.631440f, // Warrior
|
0.9560f, // Warrior
|
||||||
65.631440f, // Paladin
|
0.9560f, // Paladin
|
||||||
145.560408f, // Hunter
|
0.9880f, // Hunter
|
||||||
145.560408f, // Rogue
|
0.9880f, // Rogue
|
||||||
0.0f, // Priest
|
0.9830f, // Priest
|
||||||
65.631440f, // DK
|
0.9560f, // DK
|
||||||
145.560408f, // Shaman
|
0.9880f, // Shaman
|
||||||
0.0f, // Mage
|
0.9830f, // Mage
|
||||||
0.0f, // Warlock
|
0.9830f, // Warlock
|
||||||
90.6425f, // Monk
|
0.9830f, // Monk
|
||||||
0.0f, // Druid
|
0.9720f, // Druid
|
||||||
65.631440f // Demon Hunter
|
0.9830f // Demon Hunter
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 1 1 k cx
|
||||||
|
// --- = --- + --- <=> x' = --------
|
||||||
|
// x' c x x + ck
|
||||||
|
|
||||||
|
// where:
|
||||||
|
// k is m_diminishing_k for that class
|
||||||
|
// c is capArray for that class
|
||||||
|
// x is chance before DR (diminishValue)
|
||||||
|
// x' is chance after DR (our result)
|
||||||
|
|
||||||
|
uint classIdx = (byte)playerClass - 1u;
|
||||||
|
|
||||||
|
float k = m_diminishing_k[classIdx];
|
||||||
|
float c = capArray[classIdx];
|
||||||
|
|
||||||
|
float result = c * diminishValue / (diminishValue + c * k);
|
||||||
|
result += nonDiminishValue;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float[] parry_cap =
|
||||||
|
{
|
||||||
|
65.631440f, // Warrior
|
||||||
|
65.631440f, // Paladin
|
||||||
|
145.560408f, // Hunter
|
||||||
|
145.560408f, // Rogue
|
||||||
|
0.0f, // Priest
|
||||||
|
65.631440f, // DK
|
||||||
|
145.560408f, // Shaman
|
||||||
|
0.0f, // Mage
|
||||||
|
0.0f, // Warlock
|
||||||
|
90.6425f, // Monk
|
||||||
|
0.0f, // Druid
|
||||||
|
65.631440f // Demon Hunter
|
||||||
|
};
|
||||||
|
|
||||||
|
public void UpdateParryPercentage()
|
||||||
|
{
|
||||||
// No parry
|
// No parry
|
||||||
float value = 0.0f;
|
float value = 0.0f;
|
||||||
int pclass = (int)GetClass() - 1;
|
int pclass = (int)GetClass() - 1;
|
||||||
@@ -1526,8 +1561,9 @@ namespace Game.Entities
|
|||||||
float diminishing = GetRatingBonusValue(CombatRating.Parry);
|
float diminishing = GetRatingBonusValue(CombatRating.Parry);
|
||||||
// Parry from SPELL_AURA_MOD_PARRY_PERCENT aura
|
// Parry from SPELL_AURA_MOD_PARRY_PERCENT aura
|
||||||
nondiminishing += GetTotalAuraModifier(AuraType.ModParryPercent);
|
nondiminishing += GetTotalAuraModifier(AuraType.ModParryPercent);
|
||||||
|
|
||||||
// apply diminishing formula to diminishing parry chance
|
// apply diminishing formula to diminishing parry chance
|
||||||
value = nondiminishing + diminishing * parry_cap[pclass] / (diminishing + parry_cap[pclass] * m_diminishing_k[pclass]);
|
value = CalculateDiminishingReturns(parry_cap, GetClass(), nondiminishing, diminishing);
|
||||||
|
|
||||||
if (WorldConfig.GetBoolValue(WorldCfg.StatsLimitsEnable))
|
if (WorldConfig.GetBoolValue(WorldCfg.StatsLimitsEnable))
|
||||||
value = value > WorldConfig.GetFloatValue(WorldCfg.StatsLimitsParry) ? WorldConfig.GetFloatValue(WorldCfg.StatsLimitsParry) : value;
|
value = value > WorldConfig.GetFloatValue(WorldCfg.StatsLimitsParry) ? WorldConfig.GetFloatValue(WorldCfg.StatsLimitsParry) : value;
|
||||||
@@ -1535,24 +1571,24 @@ namespace Game.Entities
|
|||||||
SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ParryPercentage), value);
|
SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ParryPercentage), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float[] dodge_cap =
|
||||||
|
{
|
||||||
|
65.631440f, // Warrior
|
||||||
|
65.631440f, // Paladin
|
||||||
|
145.560408f, // Hunter
|
||||||
|
145.560408f, // Rogue
|
||||||
|
150.375940f, // Priest
|
||||||
|
65.631440f, // DK
|
||||||
|
145.560408f, // Shaman
|
||||||
|
150.375940f, // Mage
|
||||||
|
150.375940f, // Warlock
|
||||||
|
145.560408f, // Monk
|
||||||
|
116.890707f, // Druid
|
||||||
|
145.560408f // Demon Hunter
|
||||||
|
};
|
||||||
|
|
||||||
public void UpdateDodgePercentage()
|
public void UpdateDodgePercentage()
|
||||||
{
|
{
|
||||||
float[] dodge_cap =
|
|
||||||
{
|
|
||||||
65.631440f, // Warrior
|
|
||||||
65.631440f, // Paladin
|
|
||||||
145.560408f, // Hunter
|
|
||||||
145.560408f, // Rogue
|
|
||||||
150.375940f, // Priest
|
|
||||||
65.631440f, // DK
|
|
||||||
145.560408f, // Shaman
|
|
||||||
150.375940f, // Mage
|
|
||||||
150.375940f, // Warlock
|
|
||||||
145.560408f, // Monk
|
|
||||||
116.890707f, // Druid
|
|
||||||
145.560408f // Demon Hunter
|
|
||||||
};
|
|
||||||
|
|
||||||
float diminishing = 0.0f, nondiminishing = 0.0f;
|
float diminishing = 0.0f, nondiminishing = 0.0f;
|
||||||
GetDodgeFromAgility(diminishing, nondiminishing);
|
GetDodgeFromAgility(diminishing, nondiminishing);
|
||||||
// Dodge from SPELL_AURA_MOD_DODGE_PERCENT aura
|
// Dodge from SPELL_AURA_MOD_DODGE_PERCENT aura
|
||||||
@@ -1560,14 +1596,14 @@ namespace Game.Entities
|
|||||||
// Dodge from rating
|
// Dodge from rating
|
||||||
diminishing += GetRatingBonusValue(CombatRating.Dodge);
|
diminishing += GetRatingBonusValue(CombatRating.Dodge);
|
||||||
// apply diminishing formula to diminishing dodge chance
|
// apply diminishing formula to diminishing dodge chance
|
||||||
int pclass = (int)GetClass() - 1;
|
float value = CalculateDiminishingReturns(dodge_cap, GetClass(), nondiminishing, diminishing);
|
||||||
float value = nondiminishing + (diminishing * dodge_cap[pclass] / (diminishing + dodge_cap[pclass] * m_diminishing_k[pclass]));
|
|
||||||
|
|
||||||
if (WorldConfig.GetBoolValue(WorldCfg.StatsLimitsEnable))
|
if (WorldConfig.GetBoolValue(WorldCfg.StatsLimitsEnable))
|
||||||
value = value > WorldConfig.GetFloatValue(WorldCfg.StatsLimitsDodge) ? WorldConfig.GetFloatValue(WorldCfg.StatsLimitsDodge) : value;
|
value = value > WorldConfig.GetFloatValue(WorldCfg.StatsLimitsDodge) ? WorldConfig.GetFloatValue(WorldCfg.StatsLimitsDodge) : value;
|
||||||
|
|
||||||
SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.DodgePercentage), value);
|
SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.DodgePercentage), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateBlockPercentage()
|
public void UpdateBlockPercentage()
|
||||||
{
|
{
|
||||||
// No block
|
// No block
|
||||||
@@ -1844,22 +1880,6 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
return apply;
|
return apply;
|
||||||
}
|
}
|
||||||
|
|
||||||
float[] m_diminishing_k =
|
|
||||||
{
|
|
||||||
0.9560f, // Warrior
|
|
||||||
0.9560f, // Paladin
|
|
||||||
0.9880f, // Hunter
|
|
||||||
0.9880f, // Rogue
|
|
||||||
0.9830f, // Priest
|
|
||||||
0.9560f, // DK
|
|
||||||
0.9880f, // Shaman
|
|
||||||
0.9830f, // Mage
|
|
||||||
0.9830f, // Warlock
|
|
||||||
0.9830f, // Monk
|
|
||||||
0.9720f, // Druid
|
|
||||||
0.9830f // Demon Hunter
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class Creature
|
public partial class Creature
|
||||||
|
|||||||
@@ -841,26 +841,22 @@ namespace Game.Entities
|
|||||||
!IsTypeId(TypeId.Player) && !ToCreature().IsControlledByPlayer() && !victim.HasInArc(MathFunctions.PI, this)
|
!IsTypeId(TypeId.Player) && !ToCreature().IsControlledByPlayer() && !victim.HasInArc(MathFunctions.PI, this)
|
||||||
&& (victim.IsTypeId(TypeId.Player) || !victim.ToCreature().IsWorldBoss()) && !victim.IsVehicle())
|
&& (victim.IsTypeId(TypeId.Player) || !victim.ToCreature().IsWorldBoss()) && !victim.IsVehicle())
|
||||||
{
|
{
|
||||||
// -probability is between 0% and 40%
|
|
||||||
// 20% base chance
|
// 20% base chance
|
||||||
float Probability = 20.0f;
|
float chance = 20.0f;
|
||||||
|
|
||||||
// there is a newbie protection, at level 10 just 7% base chance; assuming linear function
|
// there is a newbie protection, at level 10 just 7% base chance; assuming linear function
|
||||||
if (victim.GetLevel() < 30)
|
if (victim.GetLevel() < 30)
|
||||||
Probability = 0.65f * victim.GetLevelForTarget(this) + 0.5f;
|
chance = 0.65f * victim.GetLevelForTarget(this) + 0.5f;
|
||||||
|
|
||||||
uint VictimDefense = victim.GetMaxSkillValueForLevel(this);
|
uint victimDefense = victim.GetMaxSkillValueForLevel(this);
|
||||||
uint AttackerMeleeSkill = GetMaxSkillValueForLevel();
|
uint attackerMeleeSkill = GetMaxSkillValueForLevel();
|
||||||
|
|
||||||
Probability *= (AttackerMeleeSkill / (float)VictimDefense * 0.16f);
|
chance *= attackerMeleeSkill / (float)victimDefense * 0.16f;
|
||||||
|
|
||||||
if (Probability < 0)
|
// -probability is between 0% and 40%
|
||||||
Probability = 0;
|
MathFunctions.RoundToInterval(ref chance, 0.0f, 40.0f);
|
||||||
|
|
||||||
if (Probability > 40.0f)
|
if (RandomHelper.randChance(chance))
|
||||||
Probability = 40.0f;
|
|
||||||
|
|
||||||
if (RandomHelper.randChance(Probability))
|
|
||||||
CastSpell(victim, 1604, true);
|
CastSpell(victim, 1604, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2356,31 +2352,30 @@ namespace Game.Entities
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
float averageResist = GetEffectiveResistChance(this, schoolMask, victim, spellInfo);
|
float averageResist = CalculateAverageResistReduction(schoolMask, victim, spellInfo);
|
||||||
|
|
||||||
float[] discreteResistProbability = new float[11];
|
float[] discreteResistProbability = new float[11];
|
||||||
for (uint i = 0; i < 11; ++i)
|
|
||||||
{
|
|
||||||
discreteResistProbability[i] = 0.5f - 2.5f * Math.Abs(0.1f * i - averageResist);
|
|
||||||
if (discreteResistProbability[i] < 0.0f)
|
|
||||||
discreteResistProbability[i] = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (averageResist <= 0.1f)
|
if (averageResist <= 0.1f)
|
||||||
{
|
{
|
||||||
discreteResistProbability[0] = 1.0f - 7.5f * averageResist;
|
discreteResistProbability[0] = 1.0f - 7.5f * averageResist;
|
||||||
discreteResistProbability[1] = 5.0f * averageResist;
|
discreteResistProbability[1] = 5.0f * averageResist;
|
||||||
discreteResistProbability[2] = 2.5f * averageResist;
|
discreteResistProbability[2] = 2.5f * averageResist;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (uint i = 0; i < 11; ++i)
|
||||||
|
discreteResistProbability[i] = Math.Max(0.5f - 2.5f * Math.Abs(0.1f * i - averageResist), 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float roll = (float)RandomHelper.NextDouble();
|
||||||
|
float probabilitySum = 0.0f;
|
||||||
|
|
||||||
uint resistance = 0;
|
uint resistance = 0;
|
||||||
float r = (float)RandomHelper.NextDouble();
|
for (; resistance < 11; ++resistance)
|
||||||
float probabilitySum = discreteResistProbability[0];
|
if (roll < (probabilitySum += discreteResistProbability[resistance]))
|
||||||
|
break;
|
||||||
|
|
||||||
while (r >= probabilitySum && resistance < 10)
|
float damageResisted = damage * resistance / 10f;
|
||||||
probabilitySum += discreteResistProbability[++resistance];
|
|
||||||
|
|
||||||
float damageResisted = damage * resistance / 10;
|
|
||||||
if (damageResisted > 0.0f) // if any damage was resisted
|
if (damageResisted > 0.0f) // if any damage was resisted
|
||||||
{
|
{
|
||||||
int ignoredResistance = 0;
|
int ignoredResistance = 0;
|
||||||
@@ -2394,31 +2389,31 @@ namespace Game.Entities
|
|||||||
if (spellInfo != null && spellInfo.HasAttribute(SpellCustomAttributes.SchoolmaskNormalWithMagic))
|
if (spellInfo != null && spellInfo.HasAttribute(SpellCustomAttributes.SchoolmaskNormalWithMagic))
|
||||||
{
|
{
|
||||||
uint damageAfterArmor = CalcArmorReducedDamage(attacker, victim, damage, spellInfo, WeaponAttackType.BaseAttack);
|
uint damageAfterArmor = CalcArmorReducedDamage(attacker, victim, damage, spellInfo, WeaponAttackType.BaseAttack);
|
||||||
uint armorReduction = damage - damageAfterArmor;
|
float armorReduction = damage - damageAfterArmor;
|
||||||
if (armorReduction < damageResisted) // pick the lower one, the weakest resistance counts
|
|
||||||
damageResisted = armorReduction;
|
// pick the lower one, the weakest resistance counts
|
||||||
|
damageResisted = Math.Min(damageResisted, armorReduction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
damageResisted = Math.Max(damageResisted, 0.0f);
|
||||||
return (uint)damageResisted;
|
return (uint)damageResisted;
|
||||||
}
|
}
|
||||||
|
|
||||||
float GetEffectiveResistChance(Unit owner, SpellSchoolMask schoolMask, Unit victim, SpellInfo spellInfo)
|
float CalculateAverageResistReduction(SpellSchoolMask schoolMask, Unit victim, SpellInfo spellInfo)
|
||||||
{
|
{
|
||||||
float victimResistance = (float)victim.GetResistance(schoolMask);
|
float victimResistance = (float)victim.GetResistance(schoolMask);
|
||||||
if (owner)
|
|
||||||
|
// pets inherit 100% of masters penetration
|
||||||
|
// excluding traps
|
||||||
|
Player player = GetSpellModOwner();
|
||||||
|
if (player != null && GetEntry() != SharedConst.WorldTrigger)
|
||||||
{
|
{
|
||||||
// pets inherit 100% of masters penetration
|
victimResistance += (float)player.GetTotalAuraModifierByMiscMask(AuraType.ModTargetResistance, (int)schoolMask);
|
||||||
// excluding traps
|
victimResistance -= (float)player.GetSpellPenetrationItemMod();
|
||||||
Player player = owner.GetSpellModOwner();
|
|
||||||
if (player != null && owner.GetEntry() != SharedConst.WorldTrigger)
|
|
||||||
{
|
|
||||||
victimResistance += (float)player.GetTotalAuraModifierByMiscMask(AuraType.ModTargetResistance, (int)schoolMask);
|
|
||||||
victimResistance -= (float)player.GetSpellPenetrationItemMod();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
victimResistance += (float)owner.GetTotalAuraModifierByMiscMask(AuraType.ModTargetResistance, (int)schoolMask);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
victimResistance += (float)GetTotalAuraModifierByMiscMask(AuraType.ModTargetResistance, (int)schoolMask);
|
||||||
|
|
||||||
// holy resistance exists in pve and comes from level difference, ignore template values
|
// holy resistance exists in pve and comes from level difference, ignore template values
|
||||||
if (schoolMask.HasAnyFlag(SpellSchoolMask.Holy))
|
if (schoolMask.HasAnyFlag(SpellSchoolMask.Holy))
|
||||||
@@ -2429,8 +2424,10 @@ namespace Game.Entities
|
|||||||
victimResistance = 0.0f;
|
victimResistance = 0.0f;
|
||||||
|
|
||||||
victimResistance = Math.Max(victimResistance, 0.0f);
|
victimResistance = Math.Max(victimResistance, 0.0f);
|
||||||
if (owner)
|
|
||||||
victimResistance += Math.Max(((float)victim.GetLevelForTarget(owner) - (float)owner.GetLevelForTarget(victim)) * 5.0f, 0.0f);
|
// level-based resistance does not apply to binary spells, and cannot be overcome by spell penetration
|
||||||
|
if (!spellInfo.HasAttribute(SpellCustomAttributes.BinarySpell))
|
||||||
|
victimResistance += Math.Max((victim.GetLevelForTarget(this) - GetLevelForTarget(victim)) * 5.0f, 0.0f);
|
||||||
|
|
||||||
uint bossLevel = 83;
|
uint bossLevel = 83;
|
||||||
float bossResistanceConstant = 510.0f;
|
float bossResistanceConstant = 510.0f;
|
||||||
|
|||||||
@@ -934,7 +934,6 @@ namespace Game.Entities
|
|||||||
return SpellMissInfo.None;
|
return SpellMissInfo.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @todo need use unit spell resistances in calculations
|
|
||||||
SpellMissInfo MagicSpellHitResult(Unit victim, SpellInfo spell)
|
SpellMissInfo MagicSpellHitResult(Unit victim, SpellInfo spell)
|
||||||
{
|
{
|
||||||
// Can`t miss on dead target (on skinning for example)
|
// Can`t miss on dead target (on skinning for example)
|
||||||
@@ -991,7 +990,7 @@ namespace Game.Entities
|
|||||||
int tmp = 10000 - HitChance;
|
int tmp = 10000 - HitChance;
|
||||||
|
|
||||||
int rand = RandomHelper.IRand(0, 9999);
|
int rand = RandomHelper.IRand(0, 9999);
|
||||||
if (rand < tmp)
|
if (tmp > 0 && rand < tmp)
|
||||||
return SpellMissInfo.Miss;
|
return SpellMissInfo.Miss;
|
||||||
|
|
||||||
// Spells with SPELL_ATTR3_IGNORE_HIT_RESULT will additionally fully ignore
|
// Spells with SPELL_ATTR3_IGNORE_HIT_RESULT will additionally fully ignore
|
||||||
@@ -1001,18 +1000,16 @@ namespace Game.Entities
|
|||||||
|
|
||||||
// Chance resist mechanic (select max value from every mechanic spell effect)
|
// Chance resist mechanic (select max value from every mechanic spell effect)
|
||||||
int resist_chance = victim.GetMechanicResistChance(spell) * 100;
|
int resist_chance = victim.GetMechanicResistChance(spell) * 100;
|
||||||
tmp += resist_chance;
|
|
||||||
|
|
||||||
// Roll chance
|
// Roll chance
|
||||||
if (rand < tmp)
|
if (resist_chance > 0 && rand < (tmp += resist_chance))
|
||||||
return SpellMissInfo.Resist;
|
return SpellMissInfo.Resist;
|
||||||
|
|
||||||
// cast by caster in front of victim
|
// cast by caster in front of victim
|
||||||
if (!victim.HasUnitState(UnitState.Controlled) && (victim.HasInArc(MathFunctions.PI, this) || victim.HasAuraType(AuraType.IgnoreHitDirection)))
|
if (!victim.HasUnitState(UnitState.Controlled) && (victim.HasInArc(MathFunctions.PI, this) || victim.HasAuraType(AuraType.IgnoreHitDirection)))
|
||||||
{
|
{
|
||||||
int deflect_chance = victim.GetTotalAuraModifier(AuraType.DeflectSpells) * 100;
|
int deflect_chance = victim.GetTotalAuraModifier(AuraType.DeflectSpells) * 100;
|
||||||
tmp += deflect_chance;
|
if (deflect_chance > 0 && rand < (tmp += deflect_chance))
|
||||||
if (rand < tmp)
|
|
||||||
return SpellMissInfo.Deflect;
|
return SpellMissInfo.Deflect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user