Core/Units: updated Melee, Spell, Parry and Dodge chance calculations to a blizzlike behaivior

This commit is contained in:
Ovahlord
2018-10-07 14:38:36 +02:00
parent 6b95898a2a
commit 4ade341b63
2 changed files with 94 additions and 42 deletions

View File

@@ -100,6 +100,41 @@ float playerBaseMoveSpeed[MAX_MOVE_TYPE] =
3.14f // MOVE_PITCH_RATE
};
// Data taken from PaperDollFrame.lua 4.3.4
#define MAX_LEVEL_DIFFERENCE 4
float MissChancePhysical[MAX_LEVEL_DIFFERENCE] =
{
5.0f,
5.5f,
6.0f,
8.0f
};
float MissChanceSpell[MAX_LEVEL_DIFFERENCE] =
{
4.0f,
5.0f,
6.0f,
17.0f
};
float EnemyDodgeChance[MAX_LEVEL_DIFFERENCE] =
{
5.0f,
5.5f,
6.0f,
6.5f
};
float EnemyParryChance[MAX_LEVEL_DIFFERENCE] =
{
5.0f,
5.5f,
6.0f,
14.0f
};
DamageInfo::DamageInfo(Unit* attacker, Unit* victim, uint32 damage, SpellInfo const* spellInfo, SpellSchoolMask schoolMask, DamageEffectType damageType, WeaponAttackType attackType)
: m_attacker(attacker), m_victim(victim), m_damage(damage), m_spellInfo(spellInfo), m_schoolMask(schoolMask), m_damageType(damageType), m_attackType(attackType),
m_absorb(0), m_resist(0), m_block(0), m_hitMask(0)
@@ -2161,9 +2196,9 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit* victim, WeaponAttackTy
float crit_chance = GetUnitCriticalChance(attType, victim);
// stunned target cannot dodge and this is check in GetUnitDodgeChance() (returned 0 in this case)
float dodge_chance = victim->GetUnitDodgeChance();
float dodge_chance = victim->GetUnitDodgeChance(this);
float block_chance = victim->GetUnitBlockChance();
float parry_chance = victim->GetUnitParryChance();
float parry_chance = victim->GetUnitParryChance(this);
// Useful if want to specify crit & miss chances for melee, else it could be removed
TC_LOG_DEBUG("entities.unit", "MELEE OUTCOME: miss %f crit %f dodge %f parry %f block %f", miss_chance, crit_chance, dodge_chance, parry_chance, block_chance);
@@ -2561,7 +2596,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
if (canDodge)
{
// Roll dodge
int32 dodgeChance = int32(victim->GetUnitDodgeChance() * 100.0f);
int32 dodgeChance = int32(victim->GetUnitDodgeChance(this) * 100.0f);
// Reduce enemy dodge chance by SPELL_AURA_MOD_COMBAT_RESULT_CHANCE
dodgeChance += GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_COMBAT_RESULT_CHANCE, VICTIMSTATE_DODGE) * 100;
dodgeChance = int32(float(dodgeChance) * GetTotalAuraMultiplier(SPELL_AURA_MOD_ENEMY_DODGE));
@@ -2580,7 +2615,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
if (canParry)
{
// Roll parry
int32 parryChance = int32(victim->GetUnitParryChance() * 100.0f);
int32 parryChance = int32(victim->GetUnitParryChance(this) * 100.0f);
// Reduce parry chance by attacker expertise rating
if (GetTypeId() == TYPEID_PLAYER)
parryChance -= int32(ToPlayer()->GetExpertiseDodgeOrParryReduction(attType) * 100.0f);
@@ -2616,19 +2651,27 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo
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);
int32 thisLevel = getLevel();
if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsTrigger())
thisLevel = std::max<int32>(thisLevel, spellInfo->SpellLevel);
int32 leveldif = int32(victim->getLevelForTarget(this)) - thisLevel;
// Base hit chance from attacker and victim levels
int32 modHitChance;
if (leveldif < 3)
modHitChance = 96 - leveldif;
else
modHitChance = 94 - (leveldif - 2) * lchance;
float modHitChance = 100.0f;
uint8 lchance = victim->GetTypeId() == TYPEID_PLAYER ? 7 : 11;
int8 levelDifference = victim->getLevel() - thisLevel;
if (levelDifference >= 0 && levelDifference <= 3)
modHitChance -= MissChanceSpell[levelDifference];
else if (levelDifference < 0)
{
modHitChance -= MissChanceSpell[0];
modHitChance += 1.0f * levelDifference;
}
else if (levelDifference > 3)
modHitChance -= MissChanceSpell[3] + lchance * (levelDifference - 3);
// Normalize chance
modHitChance = std::max(0.0f, modHitChance);
// Spellmod from SPELLMOD_RESIST_MISS_CHANCE
if (Player* modOwner = GetSpellModOwner())
@@ -2641,33 +2684,22 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo
modHitChance += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE, schoolMask);
}
int32 HitChance = modHitChance * 100;
float HitChance = modHitChance + m_modSpellHitChance;
// Increase hit chance from attacker SPELL_AURA_MOD_SPELL_HIT_CHANCE and attacker ratings
HitChance += int32(m_modSpellHitChance * 100.0f);
RoundToInterval(HitChance, 100, 10000);
int32 tmp = 10000 - HitChance;
int32 rand = irand(0, 10000);
if (rand < tmp)
if (!roll_chance_f(HitChance))
return SPELL_MISS_MISS;
// Chance resist mechanic (select max value from every mechanic spell effect)
int32 resist_chance = victim->GetMechanicResistChance(spellInfo) * 100;
tmp += resist_chance;
// Roll chance
if (rand < tmp)
int32 resist_chance = victim->GetMechanicResistChance(spellInfo);
if (roll_chance_i(resist_chance))
return SPELL_MISS_RESIST;
// cast by caster in front of victim
if (victim->HasInArc(float(M_PI), this) || victim->HasAuraType(SPELL_AURA_IGNORE_HIT_DIRECTION))
{
int32 deflect_chance = victim->GetTotalAuraModifier(SPELL_AURA_DEFLECT_SPELLS) * 100;
tmp += deflect_chance;
if (rand < tmp)
int32 deflect_chance = victim->GetTotalAuraModifier(SPELL_AURA_DEFLECT_SPELLS);
if (roll_chance_i(deflect_chance))
return SPELL_MISS_DEFLECT;
}
@@ -2739,7 +2771,7 @@ uint32 Unit::GetUnitMeleeSkill(Unit const* target) const
return (target ? getLevelForTarget(target) : getLevel()) * 5;
}
float Unit::GetUnitDodgeChance() const
float Unit::GetUnitDodgeChance(Unit const* attacker) const
{
if (IsNonMeleeSpellCast(false) || HasUnitState(UNIT_STATE_CONTROLLED))
return 0.0f;
@@ -2752,14 +2784,20 @@ float Unit::GetUnitDodgeChance() const
return 0.0f;
else
{
float dodge = 5.0f;
float dodge = 0.0f;
int8 levelDifference = getLevel() - attacker->getLevel();
if (levelDifference >= 0 && levelDifference <= 3)
dodge += EnemyDodgeChance[levelDifference];
else if (levelDifference > 3)
dodge += EnemyDodgeChance[3];
dodge += GetTotalAuraModifier(SPELL_AURA_MOD_DODGE_PERCENT);
return dodge > 0.0f ? dodge : 0.0f;
return dodge;
}
}
}
float Unit::GetUnitParryChance() const
float Unit::GetUnitParryChance(Unit const* attacker) const
{
if (IsNonMeleeSpellCast(false) || HasUnitState(UNIT_STATE_CONTROLLED))
return 0.0f;
@@ -2782,7 +2820,13 @@ float Unit::GetUnitParryChance() const
{
if (GetCreatureType() == CREATURE_TYPE_HUMANOID)
{
chance = 5.0f;
float chance = 0.0f;
int8 levelDifference = getLevel() - attacker->getLevel();
if (levelDifference >= 0 && levelDifference <= 3)
chance += EnemyParryChance[levelDifference];
else if (levelDifference > 3)
chance += EnemyParryChance[3];
chance += GetTotalAuraModifier(SPELL_AURA_MOD_PARRY_PERCENT);
}
}
@@ -2790,9 +2834,17 @@ float Unit::GetUnitParryChance() const
return chance > 0.0f ? chance : 0.0f;
}
float Unit::GetUnitMissChance(WeaponAttackType attType) const
float Unit::GetUnitMissChance(WeaponAttackType attType, Unit const* attacker) const
{
float miss_chance = 5.00f;
float miss_chance = 0.0f;
int8 levelDifference = getLevel() - attacker->getLevel();
if (levelDifference >= 0 && levelDifference <= 3)
miss_chance += MissChancePhysical[levelDifference];
else if (levelDifference > 3)
miss_chance += MissChancePhysical[3] + 2.0f * (levelDifference - 3);
// Normalize chance
miss_chance = std::min(100.0f, miss_chance);
if (attType == RANGED_ATTACK)
miss_chance -= GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE);
@@ -12635,10 +12687,10 @@ void Unit::ApplyResilience(Unit const* victim, int32* damage) const
// Melee based spells can be miss, parry or dodge on this step
// Crit or block - determined on damage calculation phase! (and can be both in some time)
float Unit::MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, uint32 spellId) const
float Unit::MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, uint32 spellId) const
{
//calculate miss chance
float missChance = victim->GetUnitMissChance(attType);
float missChance = victim->GetUnitMissChance(attType, this);
if (!spellId && haveOffhandWeapon())
missChance += 19;

View File

@@ -1189,10 +1189,10 @@ class TC_GAME_API Unit : public WorldObject
SpellMissInfo MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo);
SpellMissInfo SpellHitResult(Unit* victim, SpellInfo const* spellInfo, bool canReflect = false);
float GetUnitDodgeChance() const;
float GetUnitParryChance() const;
float GetUnitDodgeChance(Unit const* attacker) const;
float GetUnitParryChance(Unit const* attacker) const;
float GetUnitBlockChance() const;
float GetUnitMissChance(WeaponAttackType attType) const;
float GetUnitMissChance(WeaponAttackType attType, Unit const* victim) const;
float GetUnitCriticalChance(WeaponAttackType attackType, const Unit* victim) const;
int32 GetMechanicResistChance(SpellInfo const* spellInfo) const;
bool CanUseAttackType(uint8 attacktype) const;