aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp65
-rwxr-xr-xsrc/server/game/Entities/Player/Player.h3
-rwxr-xr-xsrc/server/game/Entities/Unit/StatSystem.cpp107
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp68
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.h1
5 files changed, 169 insertions, 75 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 01903e81e76..89516bf45c9 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -5755,35 +5755,37 @@ float Player::GetMeleeCritFromAgility()
return crit*100.0f;
}
-float Player::GetDodgeFromAgility()
+void Player::GetDodgeFromAgility(float &diminishing, float &nondiminishing)
{
// Table for base dodge values
- float dodge_base[MAX_CLASSES] = {
- 0.0075f, // Warrior
- 0.00652f, // Paladin
- -0.0545f, // Hunter
- -0.0059f, // Rogue
- 0.03183f, // Priest
- 0.0114f, // DK
- 0.0167f, // Shaman
- 0.034575f, // Mage
- 0.02011f, // Warlock
+ const float dodge_base[MAX_CLASSES] =
+ {
+ 0.036640f, // Warrior
+ 0.034943f, // Paladi
+ -0.040873f, // Hunter
+ 0.020957f, // Rogue
+ 0.034178f, // Priest
+ 0.036640f, // DK
+ 0.021080f, // Shaman
+ 0.036587f, // Mage
+ 0.024211f, // Warlock
0.0f, // ??
- -0.0187f // Druid
+ 0.056097f // Druid
};
- // Crit/agility to dodge/agility coefficient multipliers
- float crit_to_dodge[MAX_CLASSES] = {
- 1.1f, // Warrior
- 1.0f, // Paladin
- 1.6f, // Hunter
- 2.0f, // Rogue
- 1.0f, // Priest
- 1.0f, // DK?
- 1.0f, // Shaman
- 1.0f, // Mage
- 1.0f, // Warlock
- 0.0f, // ??
- 1.7f // Druid
+ // Crit/agility to dodge/agility coefficient multipliers; 3.2.0 increased required agility by 15%
+ const float crit_to_dodge[MAX_CLASSES] =
+ {
+ 0.85f/1.15f, // Warrior
+ 1.00f/1.15f, // Paladin
+ 1.11f/1.15f, // Hunter
+ 2.00f/1.15f, // Rogue
+ 1.00f/1.15f, // Priest
+ 0.85f/1.15f, // DK
+ 1.60f/1.15f, // Shaman
+ 1.00f/1.15f, // Mage
+ 0.97f/1.15f, // Warlock (?)
+ 0.0f, // ??
+ 2.00f/1.15f // Druid
};
uint8 level = getLevel();
@@ -5792,13 +5794,18 @@ float Player::GetDodgeFromAgility()
if (level > GT_MAX_LEVEL)
level = GT_MAX_LEVEL;
- // Dodge per agility for most classes equal crit per agility (but for some classes need apply some multiplier)
+ // Dodge per agility is proportional to crit per agility, which is available from DBC files
GtChanceToMeleeCritEntry const *dodgeRatio = sGtChanceToMeleeCritStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1);
if (dodgeRatio == NULL || pclass > MAX_CLASSES)
- return 0.0f;
+ return;
+
+ // TODO: research if talents/effects that increase total agility by x% should increase non-diminishing part
+ float base_agility = GetCreateStat(STAT_AGILITY) * m_auraModifiersGroup[UNIT_MOD_STAT_START + STAT_AGILITY][BASE_PCT];
+ float bonus_agility = GetStat(STAT_AGILITY) - base_agility;
- float dodge=dodge_base[pclass-1] + GetStat(STAT_AGILITY) * dodgeRatio->ratio * crit_to_dodge[pclass-1];
- return dodge*100.0f;
+ // calculate diminishing (green in char screen) and non-diminishing (white) contribution
+ diminishing = 100.0f * bonus_agility * dodgeRatio->ratio * crit_to_dodge[pclass-1];
+ nondiminishing = 100.0f * (dodge_base[pclass-1] + base_agility * dodgeRatio->ratio * crit_to_dodge[pclass-1]);
}
float Player::GetSpellCritFromIntellect()
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 452f263d478..5ec32002854 100755
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1875,7 +1875,8 @@ class Player : public Unit, public GridObject<Player>
void UpdateDefenseBonusesMod();
inline void RecalculateRating(CombatRating cr) { ApplyRatingMod(cr, 0, true);}
float GetMeleeCritFromAgility();
- float GetDodgeFromAgility();
+ void GetDodgeFromAgility(float &diminishing, float &nondiminishing);
+ float GetMissPercentageFromDefence() const;
float GetSpellCritFromIntellect();
float OCTRegenHPPerSpirit();
float OCTRegenMPPerSpirit();
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index 8da3f35082b..f39f2765067 100755
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -624,20 +624,79 @@ void Player::UpdateAllCritPercentages()
UpdateCritPercentage(RANGED_ATTACK);
}
+const float m_diminishing_k[MAX_CLASSES] =
+{
+ 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.0f, // ??
+ 0.9720f // Druid
+};
+
+float Player::GetMissPercentageFromDefence() const
+{
+ const float miss_cap[MAX_CLASSES] =
+ {
+ 16.00f, // Warrior //correct
+ 16.00f, // Paladin //correct
+ 16.00f, // Hunter //?
+ 16.00f, // Rogue //?
+ 16.00f, // Priest //?
+ 16.00f, // DK //correct
+ 16.00f, // Shaman //?
+ 16.00f, // Mage //?
+ 16.00f, // Warlock //?
+ 0.0f, // ??
+ 16.00f // Druid //?
+ };
+ float diminishing = 0.0f, nondiminishing = 0.0f;
+ // Modify value from defense skill (only bonus from defense rating diminishes)
+ nondiminishing += (GetSkillValue(SKILL_DEFENSE) - GetMaxSkillValueForLevel()) * 0.04f;
+ diminishing += (int32(GetRatingBonusValue(CR_DEFENSE_SKILL))) * 0.04f;
+
+ // apply diminishing formula to diminishing miss chance
+ uint32 pclass = getClass()-1;
+ return nondiminishing + (diminishing * miss_cap[pclass] / (diminishing + miss_cap[pclass] * m_diminishing_k[pclass]));
+}
+
void Player::UpdateParryPercentage()
{
+ const float parry_cap[MAX_CLASSES] =
+ {
+ 47.003525f, // Warrior
+ 47.003525f, // Paladin
+ 145.560408f, // Hunter
+ 145.560408f, // Rogue
+ 0.0f, // Priest
+ 47.003525f, // DK
+ 145.560408f, // Shaman
+ 0.0f, // Mage
+ 0.0f, // Warlock
+ 0.0f, // ??
+ 0.0f // Druid
+ };
+
// No parry
float value = 0.0f;
- if (CanParry())
+ uint32 pclass = getClass()-1;
+ if (CanParry() && parry_cap[pclass] > 0.0f)
{
- // Base parry
- value = 5.0f;
- // Modify value from defense skill
- value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f;
- // Parry from SPELL_AURA_MOD_PARRY_PERCENT aura
- value += GetTotalAuraModifier(SPELL_AURA_MOD_PARRY_PERCENT);
+ float nondiminishing = 5.0f;
// Parry from rating
- value += GetRatingBonusValue(CR_PARRY);
+ float diminishing = GetRatingBonusValue(CR_PARRY);
+ // Modify value from defense skill (only bonus from defense rating diminishes)
+ nondiminishing += (GetSkillValue(SKILL_DEFENSE) - GetMaxSkillValueForLevel()) * 0.04f;
+ diminishing += (int32(GetRatingBonusValue(CR_DEFENSE_SKILL))) * 0.04f;
+ // Parry from SPELL_AURA_MOD_PARRY_PERCENT aura
+ nondiminishing += GetTotalAuraModifier(SPELL_AURA_MOD_PARRY_PERCENT);
+ // apply diminishing formula to diminishing parry chance
+ value = nondiminishing + diminishing * parry_cap[pclass] / (diminishing + parry_cap[pclass] * m_diminishing_k[pclass]);
value = value < 0.0f ? 0.0f : value;
}
SetStatFloatValue(PLAYER_PARRY_PERCENTAGE, value);
@@ -645,14 +704,34 @@ void Player::UpdateParryPercentage()
void Player::UpdateDodgePercentage()
{
- // Dodge from agility
- float value = GetDodgeFromAgility();
- // Modify value from defense skill
- value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f;
+ const float dodge_cap[MAX_CLASSES] =
+ {
+ 88.129021f, // Warrior
+ 88.129021f, // Paladin
+ 145.560408f, // Hunter
+ 145.560408f, // Rogue
+ 150.375940f, // Priest
+ 88.129021f, // DK
+ 145.560408f, // Shaman
+ 150.375940f, // Mage
+ 150.375940f, // Warlock
+ 0.0f, // ??
+ 116.890707f // Druid
+ };
+
+ float diminishing = 0.0f, nondiminishing = 0.0f;
+ GetDodgeFromAgility(diminishing, nondiminishing);
+ // Modify value from defense skill (only bonus from defense rating diminishes)
+ nondiminishing += (GetSkillValue(SKILL_DEFENSE) - GetMaxSkillValueForLevel()) * 0.04f;
+ diminishing += (int32(GetRatingBonusValue(CR_DEFENSE_SKILL))) * 0.04f;
// Dodge from SPELL_AURA_MOD_DODGE_PERCENT aura
- value += GetTotalAuraModifier(SPELL_AURA_MOD_DODGE_PERCENT);
+ nondiminishing += GetTotalAuraModifier(SPELL_AURA_MOD_DODGE_PERCENT);
// Dodge from rating
- value += GetRatingBonusValue(CR_DODGE);
+ diminishing += GetRatingBonusValue(CR_DODGE);
+ // apply diminishing formula to diminishing dodge chance
+ uint32 pclass = getClass()-1;
+ float value = nondiminishing + (diminishing * dodge_cap[pclass] / (diminishing + dodge_cap[pclass] * m_diminishing_k[pclass]));
+
value = value < 0.0f ? 0.0f : value;
SetStatFloatValue(PLAYER_DODGE_PERCENTAGE, value);
}
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 407f7253e3f..691a04cf668 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -2011,7 +2011,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit* victim, WeaponAttackTy
// Miss chance based on melee
//float miss_chance = MeleeMissChanceCalc(victim, attType);
- float miss_chance = MeleeSpellMissChance(victim, attType, int32(GetWeaponSkillValue(attType, victim)) - int32(victim->GetDefenseSkillValue(this)), 0);
+ float miss_chance = MeleeSpellMissChance(victim, attType, int32(GetWeaponSkillValue(attType, victim)) - int32(GetMaxSkillValueForLevel(this)), 0);
// Critical hit chance
float crit_chance = GetUnitCriticalChance(attType, victim);
@@ -2340,11 +2340,10 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell)
attackerWeaponSkill = int32(GetWeaponSkillValue(attType, victim));
int32 skillDiff = attackerWeaponSkill - int32(victim->GetMaxSkillValueForLevel(this));
- int32 fullSkillDiff = attackerWeaponSkill - int32(victim->GetDefenseSkillValue(this));
uint32 roll = urand (0, 10000);
- uint32 missChance = uint32(MeleeSpellMissChance(victim, attType, fullSkillDiff, spell->Id) * 100.0f);
+ uint32 missChance = uint32(MeleeSpellMissChance(victim, attType, skillDiff, spell->Id) * 100.0f);
// Roll miss
uint32 tmp = missChance;
if (roll < tmp)
@@ -2720,6 +2719,21 @@ float Unit::GetUnitParryChance() const
return chance > 0.0f ? chance : 0.0f;
}
+float Unit::GetUnitMissChance(WeaponAttackType attType) const
+{
+ float miss_chance = 5.00f;
+
+ if (Player const* player = ToPlayer())
+ miss_chance += player->GetMissPercentageFromDefence();
+
+ if (attType == RANGED_ATTACK)
+ miss_chance -= GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE);
+ else
+ miss_chance -= GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE);
+
+ return miss_chance;
+}
+
float Unit::GetUnitBlockChance() const
{
if (IsNonMeleeSpellCasted(false) || HasUnitState(UNIT_STAT_CONTROLLED))
@@ -16388,51 +16402,43 @@ void Unit::ApplyResilience(Unit const* victim, float* crit, int32* damage, bool
// Crit or block - determined on damage calculation phase! (and can be both in some time)
float Unit::MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const
{
- // Calculate hit chance (more correct for chance mod)
- int32 HitChance;
+ //calculate miss chance
+ float missChance = victim->GetUnitMissChance(attType);
- // PvP - PvE melee chances
- if (spellId || attType == RANGED_ATTACK || !haveOffhandWeapon())
- HitChance = 95;
- else
- HitChance = 76;
+ if (!spellId && haveOffhandWeapon())
+ missChance += 19;
- // Hit chance depends from victim auras
- if (attType == RANGED_ATTACK)
- HitChance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE);
+ // bonus from skills is 0.04%
+ //miss_chance -= skillDiff * 0.04f;
+ int32 diff = -skillDiff;
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ missChance += diff > 0 ? diff * 0.04f : diff * 0.02f;
else
- HitChance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE);
+ missChance += diff > 10 ? 1 + (diff - 10) * 0.4f : diff * 0.1f;
+
+ // Calculate hit chance
+ float hitChance = 100.0f;
// Spellmod from SPELLMOD_RESIST_MISS_CHANCE
if (spellId)
{
if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellId, SPELLMOD_RESIST_MISS_CHANCE, HitChance);
+ modOwner->ApplySpellMod(spellId, SPELLMOD_RESIST_MISS_CHANCE, hitChance);
}
- // Miss = 100 - hit
- float miss_chance = 100.0f - HitChance;
+ missChance += hitChance - 100.0f;
- // Bonuses from attacker aura and ratings
if (attType == RANGED_ATTACK)
- miss_chance -= m_modRangedHitChance;
- else
- miss_chance -= m_modMeleeHitChance;
-
- // bonus from skills is 0.04%
- //miss_chance -= skillDiff * 0.04f;
- int32 diff = -skillDiff;
- if (victim->GetTypeId() == TYPEID_PLAYER)
- miss_chance += diff > 0 ? diff * 0.04f : diff * 0.02f;
+ missChance -= m_modRangedHitChance;
else
- miss_chance += diff > 10 ? 2 + (diff - 10) * 0.4f : diff * 0.1f;
+ missChance -= m_modMeleeHitChance;
// Limit miss chance from 0 to 60%
- if (miss_chance < 0.0f)
+ if (missChance < 0.0f)
return 0.0f;
- if (miss_chance > 60.0f)
+ if (missChance > 60.0f)
return 60.0f;
- return miss_chance;
+ return missChance;
}
void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index fb41914d6f7..815892ed3b0 100755
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1479,6 +1479,7 @@ class Unit : public WorldObject
float GetUnitDodgeChance() const;
float GetUnitParryChance() const;
float GetUnitBlockChance() const;
+ float GetUnitMissChance(WeaponAttackType attType) const;
float GetUnitCriticalChance(WeaponAttackType attackType, const Unit *pVictim) const;
int32 GetMechanicResistChance(const SpellInfo *spell);
bool CanUseAttackType(uint8 attacktype) const