[11434] Implemented diminishing returns (DR) for dodge and parry chances.

Also updated base dodge and agility=>dodge conversion values for 3.2 and later

Base stats and percentage based talents/buffs are not affected by DR,
it basically prevents items and stat buffs becoming disproportionally
powerful in terms of survivability as characters approach 100% avoidance.

TODO: implement DR for chance to be missed from defense rating
This commit is contained in:
Lynx3d 2011-05-07 20:11:58 +02:00
parent 8807af4a18
commit 3f531024f7
4 changed files with 109 additions and 43 deletions

View file

@ -5100,35 +5100,37 @@ float Player::GetMeleeCritFromAgility()
return crit*100.0f; return crit*100.0f;
} }
float Player::GetDodgeFromAgility() void Player::GetDodgeFromAgility(float &diminishing, float &nondiminishing)
{ {
// Table for base dodge values // Table for base dodge values
float dodge_base[MAX_CLASSES] = { const float dodge_base[MAX_CLASSES] =
0.0075f, // Warrior {
0.00652f, // Paladin 0.036640f, // Warrior
-0.0545f, // Hunter 0.034943f, // Paladin
-0.0059f, // Rogue -0.040873f, // Hunter
0.03183f, // Priest 0.020957f, // Rogue
0.0114f, // DK 0.034178f, // Priest
0.0167f, // Shaman 0.036640f, // DK
0.034575f, // Mage 0.021080f, // Shaman
0.02011f, // Warlock 0.036587f, // Mage
0.024211f, // Warlock
0.0f, // ?? 0.0f, // ??
-0.0187f // Druid 0.056097f // Druid
}; };
// Crit/agility to dodge/agility coefficient multipliers // Crit/agility to dodge/agility coefficient multipliers; 3.2.0 increased required agility by 15%
float crit_to_dodge[MAX_CLASSES] = { const float crit_to_dodge[MAX_CLASSES] =
1.1f, // Warrior {
1.0f, // Paladin 0.85f/1.15f, // Warrior
1.6f, // Hunter 1.00f/1.15f, // Paladin
2.0f, // Rogue 1.11f/1.15f, // Hunter
1.0f, // Priest 2.00f/1.15f, // Rogue
1.0f, // DK? 1.00f/1.15f, // Priest
1.0f, // Shaman 0.85f/1.15f, // DK
1.0f, // Mage 1.60f/1.15f, // Shaman
1.0f, // Warlock 1.00f/1.15f, // Mage
0.97f/1.15f, // Warlock (?)
0.0f, // ?? 0.0f, // ??
1.7f // Druid 2.00f/1.15f // Druid
}; };
uint32 level = getLevel(); uint32 level = getLevel();
@ -5136,13 +5138,17 @@ float Player::GetDodgeFromAgility()
if (level>GT_MAX_LEVEL) level = GT_MAX_LEVEL; 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); GtChanceToMeleeCritEntry const *dodgeRatio = sGtChanceToMeleeCritStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1);
if (dodgeRatio==NULL || pclass > MAX_CLASSES) if (dodgeRatio==NULL || pclass > MAX_CLASSES)
return 0.0f; return;
float dodge=dodge_base[pclass-1] + GetStat(STAT_AGILITY) * dodgeRatio->ratio * crit_to_dodge[pclass-1]; // TODO: research if talents/effects that increase total agility by x% should increase non-diminishing part
return dodge*100.0f; float base_agility = GetCreateStat(STAT_AGILITY) * m_auraModifiersGroup[UNIT_MOD_STAT_START + STAT_AGILITY][BASE_PCT];
float bonus_agility = GetStat(STAT_AGILITY) - base_agility;
// 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() float Player::GetSpellCritFromIntellect()

View file

@ -1798,7 +1798,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void UpdateDefenseBonusesMod(); void UpdateDefenseBonusesMod();
float GetMeleeCritFromAgility(); float GetMeleeCritFromAgility();
float GetDodgeFromAgility(); void GetDodgeFromAgility(float &diminishing, float &nondiminishing);
float GetSpellCritFromIntellect(); float GetSpellCritFromIntellect();
float OCTRegenHPPerSpirit(); float OCTRegenHPPerSpirit();
float OCTRegenMPPerSpirit(); float OCTRegenMPPerSpirit();
@ -2561,6 +2561,10 @@ class MANGOS_DLL_SPEC Player : public Unit
DeclinedName *m_declinedname; DeclinedName *m_declinedname;
Runes *m_runes; Runes *m_runes;
EquipmentSets m_EquipmentSets; EquipmentSets m_EquipmentSets;
/// class dependent melee diminishing constant for dodge/parry/missed chances
static const float m_diminishing_k[MAX_CLASSES];
private: private:
void _HandleDeadlyPoison(Unit* Target, WeaponAttackType attType, SpellEntry const *spellInfo); void _HandleDeadlyPoison(Unit* Target, WeaponAttackType attType, SpellEntry const *spellInfo);
// internal common parts for CanStore/StoreItem functions // internal common parts for CanStore/StoreItem functions

View file

@ -552,20 +552,55 @@ void Player::UpdateAllCritPercentages()
UpdateCritPercentage(RANGED_ATTACK); UpdateCritPercentage(RANGED_ATTACK);
} }
const float Player::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
};
void Player::UpdateParryPercentage() 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 // No parry
float value = 0.0f; float value = 0.0f;
if (CanParry()) uint32 pclass = getClass()-1;
if (CanParry() && parry_cap[pclass] > 0.0f)
{ {
// Base parry // Base parry
value = 5.0f; float nondiminishing = 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);
// Parry from rating // 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; value = value < 0.0f ? 0.0f : value;
} }
SetStatFloatValue(PLAYER_PARRY_PERCENTAGE, value); SetStatFloatValue(PLAYER_PARRY_PERCENTAGE, value);
@ -573,14 +608,35 @@ void Player::UpdateParryPercentage()
void Player::UpdateDodgePercentage() void Player::UpdateDodgePercentage()
{ {
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;
// Dodge from agility // Dodge from agility
float value = GetDodgeFromAgility(); GetDodgeFromAgility(diminishing, nondiminishing);
// Modify value from defense skill // Modify value from defense skill (only bonus from defense rating diminishes)
value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f; nondiminishing += (GetSkillValue(SKILL_DEFENSE) - GetMaxSkillValueForLevel()) * 0.04f;
diminishing += (int32(GetRatingBonusValue(CR_DEFENSE_SKILL))) * 0.04f;
// Dodge from SPELL_AURA_MOD_DODGE_PERCENT aura // 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 // 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; value = value < 0.0f ? 0.0f : value;
SetStatFloatValue(PLAYER_DODGE_PERCENTAGE, value); SetStatFloatValue(PLAYER_DODGE_PERCENTAGE, value);
} }

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "11433" #define REVISION_NR "11434"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__