Пример #1
0
        // Computes offensive attacks.
        public List <ListGroup> Offense()
        {
            List <ListGroup> groups = new List <ListGroup>();

            foreach (Item item in Items)
            {
                if (item.Gems == null)
                {
                    continue;
                }
                foreach (Item gem in item.Gems)
                {
                    if (AttackSkill.IsAttackSkill(gem))
                    {
                        // Skip gems linked to totems and Cast on gems for now.
                        if (item.GetLinkedGems(gem).Find(g => g.Name.Contains("Totem")) != null)
                        {
                            continue;
                        }

                        AttackSkill attack = AttackSkill.Create(gem, this);

                        attack.Link(item.GetLinkedGems(gem), item);
                        attack.Apply(item);

                        groups.Add(attack.ToListGroup());
                    }
                }
            }

            return(groups);
        }
Пример #2
0
        public AttackSource(string name, AttackSkill skill, Weapon weapon, Computation compute)
        {
            Name    = name;
            Compute = compute;

            if (weapon == null) // Spells get damage from gem local attributes.
            {
                Nature = new DamageNature(skill.Nature);

                foreach (var attr in skill.Local)
                {
                    Damage damage = Damage.Create(skill.Nature, attr.Key, attr.Value);
                    if (damage != null)
                    {
                        Deals.Add(damage);
                    }
                }

                if (skill.Gem.Properties.TryGetValue("Cast Time: # sec", 0, out CastTime))
                {
                    APS = 1 / CastTime;
                }
                else
                {
                    APS = CastTime = 1; // Spell without Cast Time has cast time of 1 second.
                }
                if (!skill.Gem.Properties.TryGetValue("Critical Strike Chance: #%", 0, out CriticalChance))
                {
                    CriticalChance = 0;     // Spell without Critical Strike Chance has none.
                }
                Local = new AttributeSet(); // No local weapon attributes.
            }
            else
            {
                if ((skill.Nature.WeaponType & weapon.Nature.WeaponType) == 0) // Skill can't be used.
                                                                               // Override weapon type and form of skill with actual weapon (client shows damage of unuseable skills as well).
                {
                    Nature = new DamageNature(skill.Nature)
                    {
                        Form = weapon.Nature.Form, WeaponHand = weapon.Hand, WeaponType = weapon.Nature.WeaponType
                    }
                }
                ;
                else // Narrow down weapon type and form of skill gem to actual weapon (e.g. Frenzy).
                {
                    Nature = new DamageNature(skill.Nature)
                    {
                        Form       = skill.Nature.ChooseWeaponForm(weapon.Nature), // XXX: Choose between melee or projectile form according to weapon.
                        WeaponHand = weapon.Hand,
                        WeaponType = skill.Nature.WeaponType & weapon.Nature.WeaponType
                    }
                };

                // XXX: If source has no form, but skill has form defined, then force form of skill.
                // This happens in form transition from melee to projectile with skills like Spectral Throw.
                if (Nature.Form == DamageForm.Any && skill.Nature.Form != DamageForm.Any)
                {
                    Nature.Form = skill.Nature.Form;
                }

                foreach (Damage damage in weapon.Deals)
                {
                    Deals.Add(new Damage(damage)
                    {
                        Form = Nature.Form, Source = Nature.Source, WeaponHand = Nature.WeaponHand, WeaponType = Nature.WeaponType
                    });
                }

                foreach (Damage.Added added in weapon.Added)
                {
                    if (weapon.Is(added.Hand)) // Added damage may require specific hand.
                    {
                        added.Apply(this, 100);
                    }
                }

                APS = weapon.Attributes["Attacks per Second: #"][0];

                if (weapon.Attributes.ContainsKey("Critical Strike Chance: #%"))
                {
                    CriticalChance = weapon.Attributes["Critical Strike Chance: #%"][0];
                }
                else
                {
                    CriticalChance = 0; // Weapon without Critical Strike Chance has none.
                }
                Local = weapon.Attributes;
            }
        }
Пример #3
0
        // 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);
            }
        }