// Computes accuracy. public void AccuracyRating(AttributeSet attrs) { Accuracy = attrs["+# Accuracy Rating"][0]; // Local weapon accuracy bonus. if (Local.ContainsKey("+# to Accuracy Rating")) { Accuracy += Local["+# to Accuracy Rating"][0]; } float incAcc = 0; // Local weapon accuracy bonus. if (Local.ContainsKey("#% increased Accuracy Rating")) { incAcc += Local["#% increased Accuracy Rating"][0]; } // Gems & global bonuses. if (attrs.ContainsKey("+# to Accuracy Rating")) { Accuracy += attrs["+# to Accuracy Rating"][0]; } if (attrs.ContainsKey("#% increased Accuracy Rating")) { incAcc += attrs["#% increased Accuracy Rating"][0]; } if (attrs.ContainsKey("#% reduced Accuracy Rating")) { incAcc += attrs["#% reduced Accuracy Rating"][0]; } foreach (var attr in attrs.Matches(ReIncreasedAccuracyRatingWithWeaponType)) { Match m = ReIncreasedAccuracyRatingWithWeaponType.Match(attr.Key); WeaponType weaponType; if (WithWeaponType.TryGetValue(m.Groups[2].Value, out weaponType) && Nature.Is(weaponType)) { incAcc += m.Groups[1].Value == "increased" ? attr.Value[0] : -attr.Value[0]; } } if (Compute.IsDualWielding && attrs.ContainsKey("#% increased Accuracy Rating while Dual Wielding")) { incAcc += attrs["#% increased Accuracy Rating while Dual Wielding"][0]; } if (incAcc != 0) { Accuracy = IncreaseValueByPercentage(Accuracy, incAcc); } }
// Computes critical strike chance and multiplier. public void CriticalStrike(AttributeSet attrs) { // Critical chance. if (Compute.ResoluteTechnique) { CriticalChance = 0; } else { if (CriticalChance > 0) { float incCC = 0; if (attrs.ContainsKey("#% increased Critical Strike Chance")) { incCC += attrs["#% increased Critical Strike Chance"][0]; } if (attrs.ContainsKey("#% increased Global Critical Strike Chance")) { incCC += attrs["#% increased Global Critical Strike Chance"][0]; } if (Compute.IsWieldingStaff && attrs.ContainsKey("#% increased Global Critical Strike Chance while wielding a Staff")) { incCC += attrs["#% increased Global Critical Strike Chance while wielding a Staff"][0]; } if (Nature.Is(DamageSource.Spell)) { if (attrs.ContainsKey("#% increased Critical Strike Chance for Spells")) { incCC += attrs["#% increased Critical Strike Chance for Spells"][0]; } if (attrs.ContainsKey("#% increased Global Critical Strike Chance for Spells")) { incCC += attrs["#% increased Global Critical Strike Chance for Spells"][0]; } } else // Attack { foreach (var attr in attrs.Matches(ReIncreasedCriticalChanceWithWeaponType)) { Match m = ReIncreasedCriticalChanceWithWeaponType.Match(attr.Key); if (WithWeaponType.ContainsKey(m.Groups[2].Value) && Nature.Is(WithWeaponType[m.Groups[2].Value])) { incCC += m.Groups[1].Value == "increased" ? attr.Value[0] : -attr.Value[0]; } } if (Compute.IsDualWielding && attrs.ContainsKey("#% increased Weapon Critical Strike Chance while Dual Wielding")) { incCC += attrs["#% increased Weapon Critical Strike Chance while Dual Wielding"][0]; } } // Form specific. foreach (var attr in attrs.Matches(ReIncreasedCriticalChanceForm)) { Match m = ReIncreasedCriticalChanceForm.Match(attr.Key); if (DamageNature.Forms.ContainsKey(m.Groups[2].Value) && Nature.Is(DamageNature.Forms[m.Groups[2].Value])) { incCC += m.Groups[1].Value == "increased" ? attr.Value[0] : -attr.Value[0]; } } if (incCC > 0) { CriticalChance = IncreaseValueByPercentage(CriticalChance, incCC); } // Critical chance can not be less than 5% nor more than 95%. // @see http://pathofexile.gamepedia.com/Critical_Strike if (CriticalChance < 5) { CriticalChance = 5; } else if (CriticalChance > 95) { CriticalChance = 95; } float incCM = 0; if (attrs.ContainsKey("+#% to Critical Strike Multiplier")) { incCM += attrs["+#% to Critical Strike Multiplier"][0]; } if (attrs.ContainsKey("+#% to Global Critical Strike Multiplier")) { incCM += attrs["+#% to Global Critical Strike Multiplier"][0]; } if (Compute.IsWieldingStaff && attrs.ContainsKey("+#% to Global Critical Strike Multiplier while wielding a Staff")) { incCM += attrs["+#% to Global Critical Strike Multiplier while wielding a Staff"][0]; } if (Nature.Is(DamageSource.Spell)) { if (attrs.ContainsKey("+#% to Critical Strike Multiplier for Spells")) { incCM += attrs["+#% to Critical Strike Multiplier for Spells"][0]; } if (attrs.ContainsKey("+#% to Global Critical Strike Multiplier for Spells")) { incCM += attrs["+#% to Global Critical Strike Multiplier for Spells"][0]; } } else // Attack { foreach (var attr in attrs.Matches(ReIncreasedCriticalMultiplierWithWeaponType)) { Match m = ReIncreasedCriticalMultiplierWithWeaponType.Match(attr.Key); if (WithWeaponType.ContainsKey(m.Groups[2].Value) && Nature.Is(WithWeaponType[m.Groups[2].Value])) { incCM += m.Groups[1].Value == "+" ? attr.Value[0] : -attr.Value[0]; } } if (Compute.IsDualWielding && attrs.ContainsKey("+#% to Weapon Critical Strike Multiplier while Dual Wielding")) { incCM += attrs["+#% to Weapon Critical Strike Multiplier while Dual Wielding"][0]; } } // Form specific. foreach (var attr in attrs.Matches(ReIncreasedCriticalMultiplierForm)) { Match m = ReIncreasedCriticalMultiplierForm.Match(attr.Key); if (DamageNature.Forms.ContainsKey(m.Groups[2].Value) && Nature.Is(DamageNature.Forms[m.Groups[2].Value])) { incCM += m.Groups[1].Value == "+" ? attr.Value[0] : -attr.Value[0]; } } CriticalMultiplier += incCM; if (attrs.ContainsKey("No Critical Strike Multiplier")) { CriticalMultiplier = 100; } } } }
// Computes attacks or casts per second. public void AttackSpeed(AttackSkill skill, AttributeSet attrs) { if (Nature.Is(DamageSource.Attack)) { // If gem has own Attacks per Second, use it instead of weapon one. if (skill.Local.ContainsKey("Attacks per Second: #")) { APS = skill.Local["Attacks per Second: #"][0]; // Apply local increased attack speed of weapon. if (Local.ContainsKey("#% increased Attack Speed")) { APS = IncreaseValueByPercentage(APS, Local["#% increased Attack Speed"][0]); } } float incAS = 0; if (attrs.ContainsKey("#% increased Attack Speed")) { incAS += attrs["#% increased Attack Speed"][0]; } if (attrs.ContainsKey("#% reduced Attack Speed")) { incAS -= attrs["#% reduced Attack Speed"][0]; } if (attrs.ContainsKey("#% increased Attack and Cast Speed")) { incAS += attrs["#% increased Attack and Cast Speed"][0]; } if (attrs.ContainsKey("#% reduced Attack and Cast Speed")) { incAS -= attrs["#% reduced Attack and Cast Speed"][0]; } foreach (var attr in attrs.MatchesAny(new Regex[] { ReIncreasedAttackSpeedWithWeaponHandOrType, ReIncreasedAttackSpeedType })) { Match m = ReIncreasedAttackSpeedWithWeaponHandOrType.Match(attr.Key); if (m.Success) { if (WithWeaponHand.ContainsKey(m.Groups[2].Value) && Nature.Is(WithWeaponHand[m.Groups[2].Value])) { incAS += m.Groups[1].Value == "increased" ? attr.Value[0] : -attr.Value[0]; } else if (WithWeaponType.ContainsKey(m.Groups[2].Value) && Nature.Is(WithWeaponType[m.Groups[2].Value])) { incAS += m.Groups[1].Value == "increased" ? attr.Value[0] : -attr.Value[0]; } } else { m = ReIncreasedAttackSpeedType.Match(attr.Key); if (m.Success) { // XXX: Not sure there are any mods with WeaponType here (Melee string in mod is DamageForm now, maybe Unarmed should be form as well). if (Weapon.Types.ContainsKey(m.Groups[2].Value) && Nature.Is(Weapon.Types[m.Groups[2].Value])) { incAS += m.Groups[1].Value == "increased" ? attr.Value[0] : -attr.Value[0]; } else if (DamageNature.Forms.ContainsKey(m.Groups[2].Value) && Nature.Is(DamageNature.Forms[m.Groups[2].Value])) { incAS += m.Groups[1].Value == "increased" ? attr.Value[0] : -attr.Value[0]; } } } } if (Compute.IsDualWielding && attrs.ContainsKey("#% increased Attack Speed while Dual Wielding")) { incAS += attrs["#% increased Attack Speed while Dual Wielding"][0]; } if (Compute.OffHand.IsShield() && attrs.ContainsKey("#% increased Attack Speed while holding a Shield")) { incAS += attrs["#% increased Attack Speed while holding a Shield"][0]; } if (incAS != 0) { APS = IncreaseValueByPercentage(APS, incAS); } float moreAS = 1; if (attrs.ContainsKey("#% more Attack Speed")) { moreAS *= 1 + attrs["#% more Attack Speed"][0] / 100; } if (attrs.ContainsKey("#% less Attack Speed")) { moreAS *= 1 - attrs["#% less Attack Speed"][0] / 100; } foreach (var attr in attrs.Matches(ReMoreAttackSpeedType)) { Match m = ReMoreAttackSpeedType.Match(attr.Key); if (m.Success) { // XXX: Not sure there are any mods with WeaponType here (Melee string in mod is DamageForm now, maybe Unarmed should be form as well). if (Weapon.Types.ContainsKey(m.Groups[2].Value) && Nature.Is(Weapon.Types[m.Groups[2].Value]) || DamageNature.Forms.ContainsKey(m.Groups[2].Value) && Nature.Is(DamageNature.Forms[m.Groups[2].Value])) { moreAS *= m.Groups[1].Value == "more" ? 1 + attr.Value[0] / 100 : 1 - attr.Value[0] / 100; } } } APS = APS * moreAS; APS = RoundHalfDownEvenValue(APS, 2); } else // Spell (use Cast Time directly). { float incCS = 0; if (attrs.ContainsKey("#% increased Cast Speed")) { incCS += attrs["#% increased Cast Speed"][0]; } if (attrs.ContainsKey("#% reduced Cast Speed")) { incCS -= attrs["#% reduced Cast Speed"][0]; } if (attrs.ContainsKey("#% increased Attack and Cast Speed")) { incCS += attrs["#% increased Attack and Cast Speed"][0]; } if (attrs.ContainsKey("#% reduced Attack and Cast Speed")) { incCS -= attrs["#% reduced Attack and Cast Speed"][0]; } if (Compute.IsDualWielding && attrs.ContainsKey("#% increased Cast Speed while Dual Wielding")) { incCS += attrs["#% increased Cast Speed while Dual Wielding"][0]; } if (incCS != 0) { CastTime = RoundValue(CastTime / ((100 + incCS) / 100), 3); } float moreCS = 0; if (attrs.ContainsKey("#% more Cast Speed")) { moreCS += attrs["#% more Cast Speed"][0]; } if (attrs.ContainsKey("#% less Cast Speed")) { moreCS -= attrs["#% less Cast Speed"][0]; } if (moreCS != 0) { CastTime = FloorValue(CastTime / ((100 + moreCS) / 100), 3); } APS = RoundValue(1 / CastTime, 2); } }
// Creates modifier. public static Increased Create(KeyValuePair <string, List <float> > attr) { Match m = ReIncreasedType.Match(attr.Key); var value = attr.Value[0]; Func <float, string, float> incRedFunc = (v, increasedOrReduced) => increasedOrReduced == "increased" ? v : -v; if (m.Success) { return(new Increased(m.Groups[2].Value, incRedFunc(value, m.Groups[1].Value))); } else { m = ReIncreasedWithSource.Match(attr.Key); if (m.Success) { return(new Increased(m.Groups[3].Value == "Spells" ? DamageSource.Spell : DamageSource.Attack, m.Groups[2].Value, incRedFunc(value, m.Groups[1].Value))); } else { m = ReIncreasedTypeWithWeaponTypeOrHand.Match(attr.Key); if (m.Success) { if (WithWeaponHand.ContainsKey(m.Groups[3].Value)) { return new Increased(m.Groups[2].Value, incRedFunc(value, m.Groups[1].Value)) { WeaponHand = WithWeaponHand[m.Groups[3].Value] } } ; else if (WithWeaponType.ContainsKey(m.Groups[3].Value)) { return new Increased(m.Groups[2].Value, incRedFunc(value, m.Groups[1].Value)) { WeaponType = WithWeaponType[m.Groups[3].Value] } } ; } else { m = ReIncreasedAll.Match(attr.Key); if (m.Success) { return(new Increased(incRedFunc(value, m.Groups[1].Value))); } else { m = ReIncreasedAllWithWeaponType.Match(attr.Key); if (m.Success && WithWeaponType.ContainsKey(m.Groups[2].Value)) { return new Increased(incRedFunc(value, m.Groups[1].Value)) { WeaponType = WithWeaponType[m.Groups[2].Value] } } ; } } } } return(null); } }