aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Player/Player.cpp5
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp6
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp152
-rw-r--r--src/server/game/Entities/Unit/Unit.h11
-rw-r--r--src/server/scripts/World/npcs_special.cpp1
5 files changed, 86 insertions, 89 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 83218f40951..e244db0940f 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -5318,12 +5318,13 @@ float Player::GetRatingBonusValue(CombatRating cr) const
float Player::GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const
{
+ float baseExpertise = 7.5f;
switch (attType)
{
case BASE_ATTACK:
- return GetUInt32Value(PLAYER_EXPERTISE) / 4.0f;
+ return baseExpertise + GetUInt32Value(PLAYER_EXPERTISE) / 4.0f;
case OFF_ATTACK:
- return GetUInt32Value(PLAYER_OFFHAND_EXPERTISE) / 4.0f;
+ return baseExpertise + GetUInt32Value(PLAYER_OFFHAND_EXPERTISE) / 4.0f;
default:
break;
}
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index f85860dfde3..1451b018a39 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -681,19 +681,19 @@ void Player::UpdateArmorPenetration(int32 amount)
void Player::UpdateMeleeHitChances()
{
- m_modMeleeHitChance = (float)GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE);
+ m_modMeleeHitChance = 7.5f + (float)GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE);
m_modMeleeHitChance += GetRatingBonusValue(CR_HIT_MELEE);
}
void Player::UpdateRangedHitChances()
{
- m_modRangedHitChance = (float)GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE);
+ m_modRangedHitChance = 7.5f + (float)GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE);
m_modRangedHitChance += GetRatingBonusValue(CR_HIT_RANGED);
}
void Player::UpdateSpellHitChances()
{
- m_modSpellHitChance = (float)GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE);
+ m_modSpellHitChance = 15.0f + (float)GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE);
m_modSpellHitChance += GetRatingBonusValue(CR_HIT_SPELL);
}
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index c15fe26f60e..803ffc06114 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -263,9 +263,18 @@ Unit::Unit(bool isWorldObject) :
m_createStats[i] = 0.0f;
m_attacking = NULL;
- m_modMeleeHitChance = 0.0f;
- m_modRangedHitChance = 0.0f;
- m_modSpellHitChance = 0.0f;
+ if (GetTypeId() == TYPEID_PLAYER)
+ {
+ m_modMeleeHitChance = 7.5f;
+ m_modRangedHitChance = 7.5f;
+ m_modSpellHitChance = 15.0f;
+ }
+ else
+ {
+ m_modMeleeHitChance = 0.0f;
+ m_modRangedHitChance = 0.0f;
+ m_modSpellHitChance = 0.0f;
+ }
m_baseSpellCritChance = 5;
m_CombatTimer = 0;
@@ -1055,7 +1064,6 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
{
damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT;
damage = SpellCriticalDamageBonus(spellInfo, damage, victim);
-
}
ApplyResilience(victim, &damage);
@@ -1912,42 +1920,29 @@ void Unit::HandleProcExtraAttackFor(Unit* victim)
}
}
-MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit* victim, WeaponAttackType attType) const
+MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(Unit const* victim, WeaponAttackType attType) const
{
- // This is only wrapper
+ if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode())
+ return MELEE_HIT_EVADE;
// Miss chance based on melee
//float miss_chance = MeleeMissChanceCalc(victim, attType);
- float miss_chance = MeleeSpellMissChance(victim, attType, 0);
+ int32 miss_chance = int32(MeleeSpellMissChance(victim, attType, 0) * 100);
// Critical hit chance
- float crit_chance = GetUnitCriticalChance(attType, victim);
+ int32 crit_chance = int32(GetUnitCriticalChance(attType, victim) * 100);
// stunned target cannot dodge and this is check in GetUnitDodgeChance() (returned 0 in this case)
- float dodge_chance = victim->GetUnitDodgeChance();
- float block_chance = victim->GetUnitBlockChance();
- float parry_chance = victim->GetUnitParryChance();
+ int32 dodge_chance = int32(victim->GetUnitDodgeChanceAgainst(this) * 100);
+ int32 block_chance = int32(victim->GetUnitBlockChanceAgainst(this) * 100);
+ int32 parry_chance = int32(victim->GetUnitParryChanceAgainst(this) * 100);
- // 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);
-
- return RollMeleeOutcomeAgainst(victim, attType, int32(crit_chance*100), int32(miss_chance*100), int32(dodge_chance*100), int32(parry_chance*100), int32(block_chance*100));
-}
-
-MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance) const
-{
- if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode())
- return MELEE_HIT_EVADE;
-
- int32 attackerMaxSkillValueForLevel = GetMaxSkillValueForLevel(victim);
- int32 victimMaxSkillValueForLevel = victim->GetMaxSkillValueForLevel(this);
-
- // bonus from skills is 0.04%
- int32 skillBonus = 4 * (attackerMaxSkillValueForLevel - victimMaxSkillValueForLevel);
int32 sum = 0, tmp = 0;
int32 roll = urand (0, 10000);
- TC_LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: skill bonus of %d for attacker", skillBonus);
+ int32 attackerLevel = getLevelForTarget(victim);
+ int32 victimLevel = getLevelForTarget(this);
+
TC_LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: rolled %d, miss %d, dodge %d, parry %d, block %d, crit %d",
roll, miss_chance, dodge_chance, parry_chance, block_chance, crit_chance);
@@ -1982,15 +1977,14 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackT
dodge_chance -= GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE) * 25;
// Modify dodge chance by attacker SPELL_AURA_MOD_COMBAT_RESULT_CHANCE
- dodge_chance+= GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_COMBAT_RESULT_CHANCE, VICTIMSTATE_DODGE) * 100;
- dodge_chance = int32 (float (dodge_chance) * GetTotalAuraMultiplier(SPELL_AURA_MOD_ENEMY_DODGE));
+ dodge_chance += GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_COMBAT_RESULT_CHANCE, VICTIMSTATE_DODGE) * 100;
+ dodge_chance = int32(float(dodge_chance) * GetTotalAuraMultiplier(SPELL_AURA_MOD_ENEMY_DODGE));
tmp = dodge_chance;
if ((tmp > 0) // check if unit _can_ dodge
- && ((tmp -= skillBonus) > 0)
&& roll < (sum += tmp))
{
- TC_LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: DODGE <%d, %d)", sum-tmp, sum);
+ TC_LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: DODGE <%d, %d)", sum - tmp, sum);
return MELEE_HIT_DODGE;
}
}
@@ -2012,7 +2006,6 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackT
{
int32 tmp2 = int32(parry_chance);
if (tmp2 > 0 // check if unit _can_ parry
- && (tmp2 -= skillBonus) > 0
&& roll < (sum += tmp2))
{
TC_LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: PARRY <%d, %d)", sum-tmp2, sum);
@@ -2024,7 +2017,6 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackT
{
tmp = block_chance;
if (tmp > 0 // check if unit _can_ block
- && (tmp -= skillBonus) > 0
&& roll < (sum += tmp))
{
TC_LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: BLOCK <%d, %d)", sum-tmp, sum);
@@ -2049,13 +2041,10 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackT
if (attType != RANGED_ATTACK &&
(GetTypeId() == TYPEID_PLAYER || IsPet()) &&
victim->GetTypeId() != TYPEID_PLAYER && !victim->IsPet() &&
- getLevel() < victim->getLevelForTarget(this))
+ attackerLevel + 3 < victimLevel)
{
// cap possible value (with bonuses > max skill)
- int32 skill = attackerMaxSkillValueForLevel;
-
- tmp = (10 + (victimMaxSkillValueForLevel - skill)) * 100;
- tmp = tmp > 4000 ? 4000 : tmp;
+ tmp = (10 + 10 * (victimLevel - attackerLevel)) * 100;
if (roll < (sum += tmp))
{
TC_LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: GLANCING <%d, %d)", sum-4000, sum);
@@ -2064,24 +2053,17 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackT
}
// mobs can score crushing blows if they're 4 or more levels above victim
- if (getLevelForTarget(victim) >= victim->getLevelForTarget(this) + 4 &&
+ if (attackerLevel >= victimLevel + 4 &&
// can be from by creature (if can) or from controlled player that considered as creature
!IsControlledByPlayer() &&
!(GetTypeId() == TYPEID_UNIT && ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_CRUSH))
{
- // when their weapon skill is 15 or more above victim's defense skill
- tmp = victimMaxSkillValueForLevel;
- // tmp = mob's level * 5 - player's current defense skill
- tmp = attackerMaxSkillValueForLevel - tmp;
- if (tmp >= 15)
+ // add 2% chance per level, min. is 15%
+ tmp = attackerLevel - victimLevel * 1000 - 1500;
+ if (roll < (sum += tmp))
{
- // add 2% chance per lacking skill point, min. is 15%
- tmp = tmp * 200 - 1500;
- if (roll < (sum += tmp))
- {
- TC_LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: CRUSHING <%d, %d)", sum-tmp, sum);
- return MELEE_HIT_CRUSHING;
- }
+ TC_LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: CRUSHING <%d, %d)", sum-tmp, sum);
+ return MELEE_HIT_CRUSHING;
}
}
@@ -2176,7 +2158,7 @@ bool Unit::isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttac
victim->ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_BLOCK)
return false;
- if (roll_chance_f(victim->GetUnitBlockChance()))
+ if (roll_chance_f(victim->GetUnitBlockChanceAgainst(this)))
return true;
}
return false;
@@ -2353,7 +2335,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
if (canDodge)
{
// Roll dodge
- int32 dodgeChance = int32(victim->GetUnitDodgeChance() * 100.0f);
+ int32 dodgeChance = int32(victim->GetUnitDodgeChanceAgainst(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));
@@ -2372,7 +2354,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
if (canParry)
{
// Roll parry
- int32 parryChance = int32(victim->GetUnitParryChance() * 100.0f);
+ int32 parryChance = int32(victim->GetUnitParryChanceAgainst(this) * 100.0f);
// Reduce parry chance by attacker expertise rating
if (GetTypeId() == TYPEID_PLAYER)
parryChance -= int32(ToPlayer()->GetExpertiseDodgeOrParryReduction(attType) * 100.0f);
@@ -2388,7 +2370,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
if (canBlock)
{
- int32 blockChance = int32(victim->GetUnitBlockChance() * 100.0f);
+ int32 blockChance = int32(victim->GetUnitBlockChanceAgainst(this) * 100.0f);
if (blockChance < 0)
blockChance = 0;
tmp += blockChance;
@@ -2414,11 +2396,27 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo
if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsTrigger())
thisLevel = std::max<int32>(thisLevel, spellInfo->SpellLevel);
int32 leveldif = int32(victim->getLevelForTarget(this)) - thisLevel;
+ int32 levelBasedHitDiff = leveldif;
// Base hit chance from attacker and victim levels
int32 modHitChance = 100;
- if (leveldif > 3)
- modHitChance -= (leveldif - 3) * lchance;
+ if (levelBasedHitDiff >= 0)
+ {
+ if (victim->GetTypeId() != TYPEID_PLAYER)
+ {
+ modHitChance = 94 - 3 * std::min(levelBasedHitDiff, 3);
+ levelBasedHitDiff -= 3;
+ }
+ else
+ {
+ modHitChance = 96 - std::min(levelBasedHitDiff, 2);
+ levelBasedHitDiff -= 2;
+ }
+ if (levelBasedHitDiff > 0)
+ modHitChance -= lchance * std::min(levelBasedHitDiff, 7);
+ }
+ else
+ modHitChance = 97 - levelBasedHitDiff;
// Spellmod from SPELLMOD_RESIST_MISS_CHANCE
if (Player* modOwner = GetSpellModOwner())
@@ -2523,12 +2521,7 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spellInfo, boo
return SPELL_MISS_NONE;
}
-uint32 Unit::GetUnitMeleeSkill(Unit const* target) const
-{
- return (target ? getLevelForTarget(target) : getLevel()) * 5;
-}
-
-float Unit::GetUnitDodgeChance() const
+float Unit::GetUnitDodgeChanceAgainst(Unit const* attacker) const
{
if (IsNonMeleeSpellCast(false) || HasUnitState(UNIT_STATE_CONTROLLED))
return 0.0f;
@@ -2541,14 +2534,16 @@ float Unit::GetUnitDodgeChance() const
return 0.0f;
else
{
- float dodge = 5.0f;
- dodge += GetTotalAuraModifier(SPELL_AURA_MOD_DODGE_PERCENT);
+ float dodge = 3.0f + GetTotalAuraModifier(SPELL_AURA_MOD_DODGE_PERCENT);
+ int32 levelDiff = getLevelForTarget(attacker) - attacker->getLevelForTarget(this);
+ if (levelDiff > 0)
+ dodge += 1.5f * levelDiff;
return dodge > 0.0f ? dodge : 0.0f;
}
}
}
-float Unit::GetUnitParryChance() const
+float Unit::GetUnitParryChanceAgainst(Unit const* attacker) const
{
if (IsNonMeleeSpellCast(false) || HasUnitState(UNIT_STATE_CONTROLLED))
return 0.0f;
@@ -2569,11 +2564,11 @@ float Unit::GetUnitParryChance() const
}
else if (GetTypeId() == TYPEID_UNIT)
{
- if (GetCreatureType() == CREATURE_TYPE_HUMANOID)
- {
- chance = 5.0f;
- chance += GetTotalAuraModifier(SPELL_AURA_MOD_PARRY_PERCENT);
- }
+ chance = 6.0f;
+ int32 levelDiff = getLevelForTarget(attacker) - attacker->getLevelForTarget(this);
+ if (levelDiff > 0)
+ chance += 1.5f * levelDiff;
+ chance += GetTotalAuraModifier(SPELL_AURA_MOD_PARRY_PERCENT);
}
return chance > 0.0f ? chance : 0.0f;
@@ -2591,7 +2586,7 @@ float Unit::GetUnitMissChance(WeaponAttackType attType) const
return miss_chance;
}
-float Unit::GetUnitBlockChance() const
+float Unit::GetUnitBlockChanceAgainst(Unit const* attacker) const
{
if (IsNonMeleeSpellCast(false) || HasUnitState(UNIT_STATE_CONTROLLED))
return 0.0f;
@@ -2601,7 +2596,7 @@ float Unit::GetUnitBlockChance() const
if (player->CanBlock())
{
Item* tmpitem = player->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
- if (tmpitem && !tmpitem->IsBroken())
+ if (tmpitem && !tmpitem->IsBroken() && tmpitem->GetTemplate()->GetInventoryType() == INVTYPE_SHIELD)
return GetFloatValue(PLAYER_BLOCK_PERCENTAGE);
}
// is player but has no block ability or no not broken shield equipped
@@ -2613,7 +2608,10 @@ float Unit::GetUnitBlockChance() const
return 0.0f;
else
{
- float block = 5.0f;
+ float block = 3.0f;
+ int32 levelDiff = getLevelForTarget(attacker) - attacker->getLevelForTarget(this);
+ if (levelDiff > 0)
+ block += 1.5f * levelDiff;
block += GetTotalAuraModifier(SPELL_AURA_MOD_BLOCK_PERCENT);
return block > 0.0f ? block : 0.0f;
}
@@ -14557,8 +14555,8 @@ float Unit::MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, u
// Limit miss chance from 0 to 60%
if (missChance < 0.0f)
return 0.0f;
- if (missChance > 60.0f)
- return 60.0f;
+ if (missChance > 77.0f)
+ return 77.0f;
return missChance;
}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 5124513e8ad..88b1dde518c 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1535,9 +1535,9 @@ class 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 GetUnitBlockChance() const;
+ float GetUnitDodgeChanceAgainst(Unit const* attacker) const;
+ float GetUnitParryChanceAgainst(Unit const* attacker) const;
+ float GetUnitBlockChanceAgainst(Unit const* attacker) const;
float GetUnitMissChance(WeaponAttackType attType) const;
float GetUnitCriticalChance(WeaponAttackType attackType, const Unit* victim) const;
int32 GetMechanicResistChance(SpellInfo const* spellInfo) const;
@@ -1545,13 +1545,10 @@ class Unit : public WorldObject
virtual uint32 GetBlockPercent() const { return 30; }
- uint32 GetUnitMeleeSkill(Unit const* target = NULL) const;
-
float GetWeaponProcChance() const;
float GetPPMProcChance(uint32 WeaponSpeed, float PPM, const SpellInfo* spellProto) const;
- MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackType attType) const;
- MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance) const;
+ MeleeHitOutcome RollMeleeOutcomeAgainst(Unit const* victim, WeaponAttackType attType) const;
bool IsVendor() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_VENDOR); }
bool IsTrainer() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TRAINER); }
diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp
index e72e094ea06..964e69874c3 100644
--- a/src/server/scripts/World/npcs_special.cpp
+++ b/src/server/scripts/World/npcs_special.cpp
@@ -1422,6 +1422,7 @@ public:
void Reset() override
{
+ // TODO: solve this in a different way! setting them as stunned prevents dummies from parrying
me->SetControlled(true, UNIT_STATE_STUNNED);//disable rotate
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);//imune to knock aways like blast wave