protected override IReadOnlyList <MatcherData> CreateCollection() => new ValueConversionMatcherCollection(_modifierBuilder) { // action { "for each enemy you've killed recently", Kill.CountRecently }, { "per enemy killed recently, up to #%", CappedMultiplier(Kill.CountRecently, Value) }, { "per enemy killed by you or your totems recently", Kill.CountRecently + Kill.By(Entity.Totem).CountRecently }, { "for each enemy you or your minions have killed recently, up to #%( per second)?", CappedMultiplier(Kill.CountRecently + Kill.By(Entity.Minion).CountRecently, Value) }, { "for each hit you've blocked recently", Block.CountRecently }, { "for each corpse consumed recently", Action.ConsumeCorpse.CountRecently }, // equipment { "for each magic item( you have)? equipped", Equipment.Count(e => e.Has(FrameType.Magic)) }, // stats { "per # accuracy rating", PerStat(Stat.Accuracy.With(AttackDamageHand.MainHand)) }, { "per #%? ({StatMatchers})(?! leech)", PerStat(stat: Reference.AsStat, divideBy: Value) }, { "per # ({StatMatchers}), up to #%", CappedMultiplier((Reference.AsStat.Value / Values[0]).Floor(), Values[1]) }, { "per # ({StatMatchers}) ceiled", PerStatCeiled(stat: Reference.AsStat, divideBy: Value) }, { "per ({StatMatchers})(?! leech)", PerStat(stat: Reference.AsStat) }, { "per ({StatMatchers}), up to #%", CappedMultiplier(Reference.AsStat.Value, Value) }, { "per # ({StatMatchers}) on helmet", PerStat(Reference.AsStat.ValueFor(NodeType.Base, new ModifierSource.Local.Item(ItemSlot.Helm)), divideBy: Value) }, { "per # ({StatMatchers}) on body armour", PerStat( Reference.AsStat.ValueFor(NodeType.Base, new ModifierSource.Local.Item(ItemSlot.BodyArmour)), divideBy: Value) }, { "per grand spectrum", PerStat(stat: Stat.GrandSpectrumJewelsSocketed) }, { "per level", PerStat(Stat.Level) }, { "per (stage|fuse charge)", PerStat(Stat.SkillStage) }, { "for each (stage|blade)", PerStat(Stat.SkillStage) }, { @"per stage, up to \+#", CappedMultiplier(Stat.SkillStage.Value, Value) }, { "per stage after the first", PerStatAfterFirst(Stat.SkillStage) }, { "per ({ChargeTypeMatchers}) removed", Reference.AsChargeType.Amount.Value - Reference.AsChargeType.Amount.Minimum.Value }, { "when placed, (?<inner>.*) per stage", Stat.BannerStage.Value, Flag.IsBannerPlanted, "${inner}" }, { "per nearby enemy", Enemy.CountNearby }, { "per one hundred nearby enemies", Enemy.CountNearby / 100 }, { @"per nearby enemy, up to \+#%?", CappedMultiplier(Enemy.CountNearby, Value) }, { "per # unreserved maximum mana, up to #%", CappedMultiplier(((Mana.Value - Mana.Reservation.Value) / Values[0]).Floor(), Values[1]) }, { "per # mana spent recently, up to #%", CappedMultiplier(Action.SpendMana(Values[0]).CountRecently, Values[1]) }, { "per # additional melee range", PerStat(Stat.Range.With(AttackDamageHand.MainHand).ValueFor(NodeType.BaseAdd), Value) }, // buffs { "per buff on you", Buffs(targets: Self).Count() }, { "per curse on you", Buffs(targets: Self).With(Keyword.Curse).Count() }, { "per curse on enemy", Buffs(targets: Enemy).With(Keyword.Curse).Count() }, { "for each curse on that enemy,", Buffs(targets: Enemy).With(Keyword.Curse).Count() }, { "for each impale on enemy", Buff.Impale.StackCount.For(Enemy).Value }, // ailments { "for each poison on the enemy", Ailment.Poison.InstancesOn(Enemy).Value }, { "per poison on enemy", Ailment.Poison.InstancesOn(Enemy).Value }, { "per poison on you", Ailment.Poison.InstancesOn(Self).Value }, { "per poison(?= affecting enemies)", Ailment.Poison.InstancesOn(Enemy).Value }, { @"per poison affecting enemy, up to \+#%", CappedMultiplier(Ailment.Poison.InstancesOn(Enemy).Value, Value) }, { "for each poison on the enemy, up to #", CappedMultiplier(Ailment.Poison.InstancesOn(Enemy).Value, Value) }, { "per elemental ailment on the enemy", Ailment.Elemental.Count(b => b.IsOn(Enemy)) }, // skills { "for each zombie you own", Skills.RaiseZombie.Instances.Value }, { "for each raised zombie", Skills.RaiseZombie.Instances.Value }, { "for each summoned golem", Golems.CombinedInstances.Value }, { "per summoned golem", Golems.CombinedInstances.Value }, { "for each golem you have summoned", Golems.CombinedInstances.Value }, { "for each type of golem you have summoned", Golems.CombinedInstances.Value }, { "per minion, up to #%", CappedMultiplier(Skills[Keyword.Minion].CombinedInstances.Value, Value) }, { "for each skill you've used Recently, up to #%", CappedMultiplier(AllSkills.Cast.CountRecently, Value) }, // traps, mines, totems { "for each trap", Traps.CombinedInstances.Value }, { "for each mine", Mines.CombinedInstances.Value }, { "for each trap and mine you have", Traps.CombinedInstances.Value + Mines.CombinedInstances.Value }, { "(per|for each) totem", Totems.CombinedInstances.Value }, { "each mine( from supported skills)? applies (?<inner>.*) to( hits against)? enemies near it, up to( a maximum of)? #%", CappedMultiplier(MineAura(), Value), "${inner}" }, { "each mine (?<inner>.*) to( hits against)? enemies near it, up to( a maximum of)? # to #", CappedMultiplier(MineAura(), ValueFactory.FromMinAndMax(Values[0], Values[1])), "${inner}" }, // jewels { "(per|for every) # ({AttributeStatMatchers}) (allocated|(from|on) allocated passives) in radius", PerStat(PassiveTree.AllocatedInModifierSourceJewelRadius(Reference.AsStat), Value) }, { "(per|for every) # ({AttributeStatMatchers}) (from|on) unallocated passives in radius", PerStat(PassiveTree.UnallocatedInModifierSourceJewelRadius(Reference.AsStat), Value) }, // unique { "for each poison you have inflicted recently", Stat.UniqueAmount("# of Poisons inflicted Recently") }, { "for each remaining chain", AtLeastZero(Projectile.ChainCount.Value - Stat.UniqueAmount("Projectile.ChainedCount")) }, { "per chain", Stat.UniqueAmount("Projectile.ChainedCount") }, { "for each enemy pierced", Stat.UniqueAmount("Projectile.PiercedCount") }, { "for each (of your mines|mine) detonated recently, up to #%( per second)?", CappedMultiplier(Stat.UniqueAmount("# of Mines Detonated Recently"), Value) }, { "for each (of your traps|trap) triggered recently, up to #%( per second)?", CappedMultiplier(Stat.UniqueAmount("# of Traps Triggered Recently"), Value) }, { "for each time you've blocked in the past 10 seconds", Stat.UniqueAmount("# of times blocked in the past 10 seconds") }, { "for each endurance charge lost recently, up to #%", CappedMultiplier(Stat.UniqueAmount("# of Endurance Charges lost recently"), Value) }, { "for each nearby corpse, (?<inner>.*) up to #%? per second", CappedMultiplier(Stat.UniqueAmount("# of nearby Corpses"), Value), "${inner}" }, { "for each prior mine in detonation sequence", CappedMultiplier( Stat.UniqueAmount("# of prior mines in detonation sequence"), Mines.CombinedInstances.Maximum.Value) }, { "for every # prior mines in detonation sequence", CappedMultiplier( (Stat.UniqueAmount("# of prior mines in detonation sequence") / Value).Floor(), Mines.CombinedInstances.Maximum.Value) }, }; // add
private GivenStatCollection CreateCollection() => Expand(new GivenStatCollection(_modifierBuilder, ValueFactory) { // passive points { BaseSet, Stat.PassivePoints.Maximum, Stat.Level.Value - 1 }, { BaseAdd, Stat.PassivePoints.Maximum, 22 }, { BaseSet, Stat.AscendancyPassivePoints.Maximum, 8 }, // pools { BaseSet, Life, CharacterClassBased(_characterBaseStats.Life, "Life") }, { BaseSet, Mana, CharacterClassBased(_characterBaseStats.Mana, "Mana") }, { BaseSet, Mana.Regen.Percent, 1.75 }, // other basic stats { BaseSet, Attribute.Strength, CharacterClassBased(_characterBaseStats.Strength, "Strength") }, { BaseSet, Attribute.Dexterity, CharacterClassBased(_characterBaseStats.Dexterity, "Dexterity") }, { BaseSet, Attribute.Intelligence, CharacterClassBased(_characterBaseStats.Intelligence, "Intelligence") }, { BaseSet, Evasion, 53 }, { BaseSet, Stat.Accuracy, -2 }, // 0 at level 1 with no dexterity { BaseSet, CriticalStrike.Multiplier, 150 }, { BaseAdd, Ground.Consecrated.AddStat(Life.Regen), 6 }, // resistances { BaseSet, AnyDamageType.DamageReduction.Maximum, 90 }, { BaseSet, AnyDamageType.DamageReductionIncludingArmour.Maximum, 90 }, // traps, mines and totems { BaseSet, Traps.CombinedInstances.Maximum, 15 }, { BaseSet, Mines.CombinedInstances.Maximum, 15 }, { BaseSet, Totems.CombinedInstances.Maximum, 1 }, { BaseSet, Stat.Totem.BaseTime, 0.6 }, { BaseSet, Stat.Trap.BaseTime, 0.5 }, { BaseSet, Stat.Mine.BaseTime, 0.3 }, // rage { BaseSet, Charge.Rage.Amount.Maximum, 50 }, { BaseSet, Charge.RageEffect, 1 }, { PercentIncrease, Damage.WithSkills(DamageSource.Attack), Charge.Rage.Amount.Value * Charge.RageEffect.Value }, { PercentIncrease, Stat.CastRate.With(DamageSource.Attack), PerStat(Charge.Rage.Amount, 2) * Charge.RageEffect.Value }, { PercentIncrease, Stat.MovementSpeed, PerStat(Charge.Rage.Amount, 5) * Charge.RageEffect.Value }, { BaseSubtract, Life.Regen.Percent, 0.1 * Charge.Rage.Amount.Value * Charge.RageEffect.Value }, // unarmed { BaseSet, Stat.Range, CharacterClassBased(_characterBaseStats.UnarmedRange, "UnarmedRange"), Not(MainHand.HasItem) }, { BaseSet, CriticalStrike.Chance.With(AttackDamageHand.MainHand), 0, Not(MainHand.HasItem) }, { BaseSet, Stat.BaseCastTime.With(AttackDamageHand.MainHand), CharacterClassBased(_characterBaseStats.UnarmedAttackTime, "UnarmedAttackTime") / 1000, Not(MainHand.HasItem) }, { BaseSet, Physical.Damage.WithSkills.With(AttackDamageHand.MainHand), Stat.CharacterClass.Value.Select( c => UnarmedPhysicalDamage((CharacterClass)(int)c.Single), c => $"{c}.UnarmedPhysicalDamage"), Not(MainHand.HasItem) }, { BaseSet, MainHand.ItemClass, (double)ItemClass.Unarmed, Not(MainHand.HasItem) }, // buff configuration { TotalOverride, Buff.Onslaught.On(Self), 1, Condition.Unique("Onslaught.ExplicitlyActive") }, { TotalOverride, Buff.UnholyMight.On(Self), 1, Condition.Unique("UnholyMight.ExplicitlyActive") }, { TotalOverride, Buff.Fortify.On(Self), 1, Condition.Unique("Fortify.ExplicitlyActive") }, { TotalOverride, Buff.Tailwind.On(Self), 1, Condition.Unique("Tailwind.ExplicitlyActive") }, { TotalOverride, Buff.Infusion.On(Self), 1, Condition.Unique("Infusion.ExplicitlyActive") }, { TotalOverride, Buff.Elusive.On(Self), 1, Condition.Unique("Elusive.ExplicitlyActive") }, { PercentReduce, Buff.Elusive.Effect, 20 * Stat.UniqueAmount("Elusive.SecondsOfDecay", 2.5) }, // character class connections { TotalOverride, PassiveTree.ConnectsToClass(CharacterClass.Scion), 1, Stat.CharacterClass.Value.Eq((int)CharacterClass.Scion) }, { TotalOverride, PassiveTree.ConnectsToClass(CharacterClass.Marauder), 1, Stat.CharacterClass.Value.Eq((int)CharacterClass.Marauder) }, { TotalOverride, PassiveTree.ConnectsToClass(CharacterClass.Ranger), 1, Stat.CharacterClass.Value.Eq((int)CharacterClass.Ranger) }, { TotalOverride, PassiveTree.ConnectsToClass(CharacterClass.Witch), 1, Stat.CharacterClass.Value.Eq((int)CharacterClass.Witch) }, { TotalOverride, PassiveTree.ConnectsToClass(CharacterClass.Duelist), 1, Stat.CharacterClass.Value.Eq((int)CharacterClass.Duelist) }, { TotalOverride, PassiveTree.ConnectsToClass(CharacterClass.Templar), 1, Stat.CharacterClass.Value.Eq((int)CharacterClass.Templar) }, { TotalOverride, PassiveTree.ConnectsToClass(CharacterClass.Shadow), 1, Stat.CharacterClass.Value.Eq((int)CharacterClass.Shadow) }, });
// Start is called before the first frame update public Player() { roundManager = new RoundManager(); ascendancyTree = new AscendancyTree(); passiveTree = new PassiveTree(); }