private DataDrivenMechanicCollection CreateCollection() => new DataDrivenMechanicCollection(ModifierBuilder, BuilderFactories) { // speed { PercentMore, Stat.MovementSpeed, ActionSpeedValueForPercentMore }, { PercentMore, Stat.CastRate, ActionSpeedValueForPercentMore, Not(Or(With(Keyword.Totem), With(Keyword.Trap), With(Keyword.Mine))) }, { PercentMore, Stat.Totem.Speed, ActionSpeedValueForPercentMore }, { PercentMore, Stat.Trap.Speed, ActionSpeedValueForPercentMore }, { PercentMore, Stat.Mine.Speed, ActionSpeedValueForPercentMore }, { BaseSet, Stat.Totem.Speed, Stat.Totem.BaseTime.Value.Invert }, { BaseSet, Stat.Trap.Speed, Stat.Trap.BaseTime.Value.Invert }, { BaseSet, Stat.Mine.Speed, Stat.Mine.BaseTime.Value.Invert }, // resistances { BaseAdd, dt => DamageTypeBuilders.From(dt).Resistance, dt => DamageTypeBuilders.From(dt).Exposure.Value }, // ailments { TotalOverride, MetaStats.AilmentDealtDamageType(Common.Builders.Effects.Ailment.Ignite), (int)DamageType.Fire }, { TotalOverride, MetaStats.AilmentDealtDamageType(Common.Builders.Effects.Ailment.Bleed), (int)DamageType.Physical }, { TotalOverride, MetaStats.AilmentDealtDamageType(Common.Builders.Effects.Ailment.Poison), (int)DamageType.Chaos }, { TotalOverride, Ailment.Chill.On(Self), 1, Ailment.Freeze.IsOn(Self) }, { PercentIncrease, Ailment.Shock.AddStat(Damage.Taken), Ailment.IncreasedDamageTakenFromShocks.Value }, { BaseSet, Ailment.IncreasedDamageTakenFromShocks.Maximum, 50 }, { TotalOverride, Ailment.IncreasedDamageTakenFromShocks.Minimum, 1 }, { PercentReduce, Ailment.Chill.AddStat(Stat.ActionSpeed), Ailment.ReducedActionSpeedFromChill.Value }, { BaseSet, Ailment.ReducedActionSpeedFromChill.Maximum, 30 }, { TotalOverride, Ailment.ReducedActionSpeedFromChill.Minimum, 1 }, { BaseSet, a => Ailment.From(a).TickRateModifier, a => ValueFactory.Create(1) }, { PercentMore, a => Ailment.From(a).Duration, a => 100 / Ailment.From(a).TickRateModifier.Value }, // stun (see https://pathofexile.gamepedia.com/Stun) { TotalOverride, MetaStats.EffectiveStunThreshold, Effect.Stun.Threshold, EffectiveStunThresholdValue }, // other { PercentMore, Stat.Radius, Stat.AreaOfEffect.Value.Select(Math.Sqrt, v => $"Sqrt({v})") }, { PercentMore, Stat.Cooldown, 100 - 100 * Stat.CooldownRecoverySpeed.Value.Invert }, };
private DataDrivenMechanicCollection CreateCollection() => new DataDrivenMechanicCollection(ModifierBuilder, BuilderFactories) { // resistances/damage reduction { BaseSet, dt => DamageTypeBuilders.From(dt).ResistanceAgainstHits, dt => DamageTypeBuilders.From(dt).Resistance.Value }, { BaseSet, dt => DamageTypeBuilders.From(dt).ResistanceAgainstDoTs, dt => DamageTypeBuilders.From(dt).Resistance.Value }, // damage reduction { BaseSet, dt => DamageTypeBuilders.From(dt).DamageReductionIncludingArmour, dt => DamageTypeBuilders.From(dt).DamageReduction.Value }, { BaseAdd, Physical.DamageReductionIncludingArmour, PhysicalDamageReductionFromArmour(Armour, Physical.Damage.WithSkills.With(AttackDamageHand.MainHand).For(Enemy).Value) }, // damage mitigation (resistance, damage reduction, damage taken) { TotalOverride, MetaStats.MitigationAgainstHits, dt => 1 - DamageTakenMultiplier( DamageTypeBuilders.From(dt).ResistanceAgainstHits, DamageTypeBuilders.From(dt).DamageReductionIncludingArmour, DamageTaken(dt).WithSkills(DamageSource.Secondary)) }, { TotalOverride, MetaStats.MitigationAgainstDoTs, dt => 1 - DamageTakenMultiplier( DamageTypeBuilders.From(dt).ResistanceAgainstDoTs, DamageTypeBuilders.From(dt).DamageReduction, DamageTaken(dt).WithSkills(DamageSource.OverTime)) }, // chance to evade { BaseSet, Evasion.Chance, 100 - ChanceToHitValue(Stat.Accuracy.With(AttackDamageHand.MainHand).For(Enemy), Evasion, Buff.Blind.IsOn(Enemy)) }, // chance to avoid { TotalOverride, MetaStats.ChanceToAvoidMeleeAttacks, 100 - 100 * (FailureProbability(Evasion.ChanceAgainstMeleeAttacks) * FailureProbability(Stat.Dodge.AttackChance) * FailureProbability(Block.AttackChance)) }, { TotalOverride, MetaStats.ChanceToAvoidProjectileAttacks, 100 - 100 * (FailureProbability(Evasion.ChanceAgainstProjectileAttacks) * FailureProbability(Stat.Dodge.AttackChance) * FailureProbability(Block.AttackChance)) }, { TotalOverride, MetaStats.ChanceToAvoidSpells, 100 - 100 * (FailureProbability(Stat.Dodge.SpellChance) * FailureProbability(Block.SpellChance)) }, // pools { BaseAdd, p => Stat.Pool.From(p).Regen, p => MetaStats.RegenTargetPoolValue(p) * Stat.Pool.From(p).Regen.Percent.Value.AsPercentage }, { TotalOverride, MetaStats.EffectiveRegen, p => p.Regen.Value * p.RecoveryRate.Value }, { TotalOverride, MetaStats.EffectiveDegeneration, p => Enums.GetValues <DamageType>().Except(DamageType.RandomElement) .Select(dt => MetaStats.EffectiveDegeneration(p, dt).Value) .Aggregate((v1, v2) => v1 + v2) }, { TotalOverride, MetaStats.NetRegen, p => MetaStats.EffectiveRegen(p).Value - MetaStats.EffectiveDegeneration(p).Value }, { TotalOverride, MetaStats.EffectiveRecharge, p => p.Recharge.Value * p.RecoveryRate.Value }, { TotalOverride, MetaStats.RechargeStartDelay, p => 2 / p.Recharge.Start.Value }, { TotalOverride, MetaStats.EffectiveDegeneration, (p, dt) => p.Degeneration(DamageTypeBuilders.From(dt)).Value *MetaStats.MitigationAgainstDoTs(dt).Value }, // ailments { PercentMore, a => Ailment.From(a).Duration, a => 100 / Effect.ExpirationModifier.For(Enemy).Value - 100 }, // stun (see https://pathofexile.gamepedia.com/Stun) { TotalOverride, MetaStats.StunAvoidanceWhileCasting, 1 - (1 - Effect.Stun.Avoidance.Value) * (1 - Effect.Stun.ChanceToAvoidInterruptionWhileCasting.Value) }, };