diff options
Diffstat (limited to 'src')
| -rwxr-xr-x | src/server/game/Entities/Player/Player.cpp | 65 | ||||
| -rwxr-xr-x | src/server/game/Entities/Player/Player.h | 3 | ||||
| -rwxr-xr-x | src/server/game/Entities/Unit/StatSystem.cpp | 107 | ||||
| -rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 68 | ||||
| -rwxr-xr-x | src/server/game/Entities/Unit/Unit.h | 1 |
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 |
