diff --git a/Source/Game/Entities/Player/Player.Combat.cs b/Source/Game/Entities/Player/Player.Combat.cs index ed7972102..48f1a2af8 100644 --- a/Source/Game/Entities/Player/Player.Combat.cs +++ b/Source/Game/Entities/Player/Player.Combat.cs @@ -89,8 +89,6 @@ namespace Game.Entities SendPacket(packet); } - public override uint GetBlockPercent() { return m_activePlayerData.ShieldBlock; } - bool CanTitanGrip() { return m_canTitanGrip; } float GetRatingMultiplier(CombatRating cr) @@ -344,6 +342,17 @@ namespace Game.Entities UpdateDamagePhysical(attType); } + public override float GetBlockPercent(uint attackerLevel) + { + float blockArmor = (float)m_activePlayerData.ShieldBlock; + float armorConstant = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.ArmorConstant, attackerLevel, -2, 0, Class.None); + + if ((blockArmor + armorConstant) == 0) + return 0; + + return Math.Min(blockArmor / (blockArmor + armorConstant), 0.85f); + } + public void SetCanParry(bool value) { if (m_canParry == value) diff --git a/Source/Game/Entities/Player/Player.Items.cs b/Source/Game/Entities/Player/Player.Items.cs index d4ea8984d..a3b429082 100644 --- a/Source/Game/Entities/Player/Player.Items.cs +++ b/Source/Game/Entities/Player/Player.Items.cs @@ -4239,7 +4239,11 @@ namespace Game.Entities uint armor = proto.GetArmor(itemLevel); if (armor != 0) + { HandleStatFlatModifier(UnitMods.Armor, UnitModifierFlatType.Base, (float)armor, apply); + if (proto.GetClass() == ItemClass.Armor && (ItemSubClassArmor)proto.GetSubClass() == ItemSubClassArmor.Shield) + SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ShieldBlock), apply ? (uint)(armor * 2.5f) : 0); + } WeaponAttackType attType = GetAttackBySlot(slot, proto.GetInventoryType()); if (attType != WeaponAttackType.Max && CanUseAttackType(attType)) diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index b02b51d2a..0813d141d 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -5761,8 +5761,7 @@ namespace Game.Entities SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ParryPercentage), 0.0f); SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BlockPercentage), 0.0f); - // Static 30% damage blocked - SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ShieldBlock), 30u); + SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ShieldBlock), 0u); // Dodge percentage SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.DodgePercentage), 0.0f); diff --git a/Source/Game/Entities/Unit/Unit.Combat.cs b/Source/Game/Entities/Unit/Unit.Combat.cs index 41e8106f5..b84ad0cb1 100644 --- a/Source/Game/Entities/Unit/Unit.Combat.cs +++ b/Source/Game/Entities/Unit/Unit.Combat.cs @@ -1710,7 +1710,7 @@ namespace Game.Entities public void KillSelf(bool durabilityLoss = true) { Kill(this, durabilityLoss); } - public virtual uint GetBlockPercent() { return 30; } + public virtual float GetBlockPercent(uint attackerLevel) { return 30.0f; } void UpdateReactives(uint p_time) { @@ -1981,7 +1981,7 @@ namespace Game.Entities damageInfo.HitInfo |= HitInfo.Block; damageInfo.originalDamage = damageInfo.damage; // 30% damage blocked, double blocked amount if block is critical - damageInfo.blocked_amount = MathFunctions.CalculatePct(damageInfo.damage, damageInfo.target.IsBlockCritical() ? damageInfo.target.GetBlockPercent() * 2 : damageInfo.target.GetBlockPercent()); + damageInfo.blocked_amount = MathFunctions.CalculatePct(damageInfo.damage, damageInfo.target.IsBlockCritical() ? damageInfo.target.GetBlockPercent(GetLevel()) * 2 : damageInfo.target.GetBlockPercent(GetLevel())); damageInfo.damage -= damageInfo.blocked_amount; damageInfo.cleanDamage += damageInfo.blocked_amount; break; @@ -2780,8 +2780,7 @@ namespace Game.Entities uint attackerLevel = attacker.GetLevelForTarget(victim); // Expansion and ContentTuningID necessary? Does Player get a ContentTuningID too ? float armorConstant = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.ArmorConstant, attackerLevel, -2, 0, attacker.GetClass()); - - if (armorConstant == 0) + if ((armor + armorConstant) == 0) return damage; float mitigation = Math.Min(armor / (armor + armorConstant), 0.85f); diff --git a/Source/Game/Entities/Unit/Unit.Spells.cs b/Source/Game/Entities/Unit/Unit.Spells.cs index 69ef6f06b..88bef4ccb 100644 --- a/Source/Game/Entities/Unit/Unit.Spells.cs +++ b/Source/Game/Entities/Unit/Unit.Spells.cs @@ -2418,7 +2418,7 @@ namespace Game.Entities if (blocked) { // double blocked amount if block is critical - uint value = victim.GetBlockPercent(); + float value = victim.GetBlockPercent(GetLevel()); if (victim.IsBlockCritical()) value *= 2; // double blocked percent damageInfo.blocked = (uint)MathFunctions.CalculatePct(damage, value);