Exemplo n.º 1
0
        /// <summary>
        /// Handles explosion.
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="skill"></param>
        /// <param name="fireballProp"></param>
        private void Impact(Creature attacker, Skill skill, Prop fireballProp)
        {
            var regionId       = attacker.RegionId;
            var propPos        = fireballProp.GetPosition();
            var targetLocation = new Location(regionId, propPos);
            var targets        = attacker.GetTargetableCreaturesAround(propPos, ExplosionRadius);

            var aAction = new AttackerAction(CombatActionType.SpecialHit, attacker, targetLocation.ToLocationId(), skill.Info.Id);

            aAction.Set(AttackerOptions.UseEffect);
            aAction.PropId = fireballProp.EntityId;

            var cap = new CombatActionPack(attacker, skill.Info.Id, aAction);

            foreach (var target in targets)
            {
                target.StopMove();

                var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id);
                tAction.Set(TargetOptions.Result | TargetOptions.KnockDown);
                tAction.Stun        = TargetStun;
                tAction.Delay       = 200;
                tAction.EffectFlags = EffectFlags.SpecialRangeHit;

                cap.Add(tAction);

                // Damage
                var damage = this.GetDamage(attacker, skill);

                // Elements
                damage *= this.GetElementalDamageMultiplier(attacker, target);

                // Critical Hit
                var critChance = attacker.GetTotalCritChance(target.Protection, true);
                CriticalHit.Handle(attacker, critChance, ref damage, tAction);

                // Reduce damage
                SkillHelper.HandleMagicDefenseProtection(target, ref damage);
                SkillHelper.HandleConditions(attacker, target, ref damage);
                ManaShield.Handle(target, ref damage, tAction);
                ManaDeflector.Handle(attacker, target, ref damage, tAction);

                // Deal damage
                if (damage > 0)
                {
                    target.TakeDamage(tAction.Damage = damage, attacker);
                }
                target.Aggro(attacker);

                // Knockback
                target.Stability = Creature.MinStability;
                target.GetShoved(fireballProp, KnockbackDistance);
                if (target.IsDead)
                {
                    tAction.Set(TargetOptions.FinishingKnockDown);
                }

                this.Train(skill, tAction);
            }

            cap.Handle();
        }
Exemplo n.º 2
0
        /// <summary>
        /// Bolt specific use code.
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="skill"></param>
        /// <param name="target"></param>
        protected override void UseSkillOnTarget(Creature attacker, Skill skill, Creature mainTarget)
        {
            // Create actions
            var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, mainTarget.EntityId);

            aAction.Set(AttackerOptions.Result);

            var cap = new CombatActionPack(attacker, skill.Info.Id, aAction);

            // Get targets
            // Add the main target as first target, so it gets the first hit,
            // and the full damage.
            var targets = new List <Creature>();

            targets.Add(mainTarget);

            var inSplashRange = attacker.GetTargetableCreaturesAround(mainTarget.GetPosition(), SplashRange);

            targets.AddRange(inSplashRange.Where(a => a != mainTarget));

            // Damage
            var damage = this.GetDamage(attacker, skill);

            var max = Math.Min(targets.Count, skill.Stacks);

            for (int i = 0; i < max; ++i)
            {
                var target       = targets[i];
                var targetDamage = damage;

                target.StopMove();

                var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id);
                tAction.Set(TargetOptions.Result);
                tAction.Stun = TargetStun;

                // Full damage for the first target, -10% for every subsequent one.
                targetDamage -= (targetDamage * 0.1f) * i;

                // Critical Hit
                var critChance = attacker.GetTotalCritChance(target.Protection, true);
                CriticalHit.Handle(attacker, critChance, ref damage, tAction);

                // Reduce damage
                Defense.Handle(aAction, tAction, ref targetDamage);
                SkillHelper.HandleMagicDefenseProtection(target, ref targetDamage);
                SkillHelper.HandleConditions(attacker, target, ref damage);
                ManaShield.Handle(target, ref targetDamage, tAction);

                // Mana Deflector
                var mdResult       = ManaDeflector.Handle(attacker, target, ref targetDamage, tAction);
                var delayReduction = mdResult.DelayReduction;
                var pinged         = mdResult.Pinged;

                // Deal damage
                if (targetDamage > 0)
                {
                    target.TakeDamage(tAction.Damage = targetDamage, attacker);
                }

                if (target == mainTarget)
                {
                    target.Aggro(attacker);
                }

                // Reduce stun, based on ping
                if (pinged && delayReduction > 0)
                {
                    tAction.Stun = (short)Math.Max(0, tAction.Stun - (tAction.Stun / 100 * delayReduction));
                }

                // Death/Knockback
                if (target.IsDead)
                {
                    tAction.Set(TargetOptions.FinishingKnockDown);
                }
                else
                {
                    // If knocked down, instant recovery,
                    // if repeat hit, knock down,
                    // otherwise potential knock back.
                    if (target.IsKnockedDown)
                    {
                        tAction.Stun = 0;
                    }
                    else if (target.Stability < MinStability)
                    {
                        tAction.Set(TargetOptions.KnockDown);
                    }
                    else
                    {
                        // If number of stacks is greater than the number of
                        // targets hit, the targets are knocked back, which is
                        // done by reducing the stability to min here.
                        // Targets with high enough Mana Deflector might
                        // negate this knock back, by reducing the stability
                        // reduction to 0.
                        var stabilityReduction = (skill.Stacks > targets.Count ? OverchargeStabilityReduction : StabilityReduction);

                        // Reduce reduction, based on ping
                        // While the Wiki says that "the Knockdown Gauge [does not]
                        // build up", tests show that it does. However, it's
                        // reduced, assumedly based on the MD rank.
                        if (delayReduction > 0)
                        {
                            stabilityReduction = (short)Math.Max(0, stabilityReduction - (stabilityReduction / 100 * delayReduction));
                        }

                        target.Stability -= stabilityReduction;

                        if (target.IsUnstable)
                        {
                            tAction.Set(TargetOptions.KnockBack);
                        }
                    }
                }

                if (tAction.IsKnockBack)
                {
                    attacker.Shove(target, KnockbackDistance);
                }

                cap.Add(tAction);
            }

            // Override stun set by defense
            aAction.Stun = AttackerStun;

            Send.Effect(attacker, Effect.UseMagic, EffectSkillName);
            Send.SkillUseStun(attacker, skill.Info.Id, aAction.Stun, 1);

            skill.Stacks = 0;

            // Update current weapon
            SkillHelper.UpdateWeapon(attacker, targets.FirstOrDefault(), ProficiencyGainType.Melee, attacker.RightHand);

            cap.Handle();
        }
Exemplo n.º 3
0
        /// <summary>
        /// Uses LightningRod
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="skill"></param>
        /// <param name="packet"></param>
        public void Use(Creature attacker, Skill skill, Packet packet)
        {
            // Set full charge variable
            attacker.Temp.LightningRodFullCharge = (DateTime.Now >= attacker.Temp.LightningRodPrepareTime.AddMilliseconds(skill.RankData.Var3));

            // Get direction for target Area
            var direction = Mabi.MabiMath.ByteToRadian(attacker.Direction);

            var attackerPos = attacker.GetPosition();

            // Calculate polygon points
            var r     = MabiMath.ByteToRadian(attacker.Direction);
            var poe   = attackerPos.GetRelative(r, 800);
            var pivot = new Point(poe.X, poe.Y);
            var p1    = new Point(pivot.X - SkillLength / 2, pivot.Y - SkillWidth / 2);
            var p2    = new Point(pivot.X - SkillLength / 2, pivot.Y + SkillWidth / 2);
            var p3    = new Point(pivot.X + SkillLength / 2, pivot.Y + SkillWidth / 2);
            var p4    = new Point(pivot.X + SkillLength / 2, pivot.Y - SkillWidth / 2);

            p1 = this.RotatePoint(p1, pivot, r);
            p2 = this.RotatePoint(p2, pivot, r);
            p3 = this.RotatePoint(p3, pivot, r);
            p4 = this.RotatePoint(p4, pivot, r);

            // TargetProp
            var lProp = new Prop(280, attacker.RegionId, poe.X, poe.Y, MabiMath.ByteToRadian(attacker.Direction), 1f, 0f, "single");

            attacker.Region.AddProp(lProp);

            // Prepare Combat Actions
            var cap = new CombatActionPack(attacker, skill.Info.Id);

            var targetAreaId = new Location(attacker.RegionId, poe).ToLocationId();

            var aAction = new AttackerAction(CombatActionType.SpecialHit, attacker, targetAreaId);

            aAction.Set(AttackerOptions.KnockBackHit1 | AttackerOptions.UseEffect);
            aAction.PropId = lProp.EntityId;
            cap.Add(aAction);

            // Get targets in Polygon - includes collission check
            var targets = attacker.Region.GetCreaturesInPolygon(p1, p2, p3, p4).Where(x => attacker.CanTarget(x) && !attacker.Region.Collisions.Any(attacker.GetPosition(), x.GetPosition())).ToList();

            var rnd = RandomProvider.Get();

            // Check crit
            var crit      = false;
            var critSkill = attacker.Skills.Get(SkillId.CriticalHit);

            if (critSkill != null && critSkill.Info.Rank > SkillRank.Novice)
            {
                var critChance = Math2.Clamp(0, 30, attacker.GetTotalCritChance(0));
                if (rnd.NextDouble() * 100 < critChance)
                {
                    crit = true;
                }
            }

            foreach (var target in targets)
            {
                var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, SkillId.CombatMastery);
                tAction.Set(TargetOptions.None);
                tAction.AttackerSkillId = skill.Info.Id;
                cap.Add(tAction);

                var damage = attacker.GetRndMagicDamage(skill, skill.RankData.Var1, skill.RankData.Var2);

                // Add damage if the skill is fully charged
                var dmgMultiplier = skill.RankData.Var4 / 100f;
                if (attacker.Temp.LightningRodFullCharge)
                {
                    damage += (damage * dmgMultiplier);
                }

                // Critical Hit
                if (crit)
                {
                    var bonus = critSkill.RankData.Var1 / 100f;
                    damage = damage + (damage * bonus);

                    tAction.Set(TargetOptions.Critical);
                }

                // MDef and MProt
                SkillHelper.HandleMagicDefenseProtection(target, ref damage);

                // Conditions
                SkillHelper.HandleConditions(attacker, target, ref damage);

                // Mana Deflector
                var delayReduction = ManaDeflector.Handle(attacker, target, ref damage, tAction);

                // Mana Shield
                ManaShield.Handle(target, ref damage, tAction);

                // Apply Damage
                target.TakeDamage(tAction.Damage = damage, attacker);

                // Stun Time
                tAction.Stun = TargetStun;

                // Death or Knockback
                if (target.IsDead)
                {
                    tAction.Set(TargetOptions.FinishingKnockDown);
                    attacker.Shove(target, KnockbackDistance);
                }
                else
                {
                    // Always knock down
                    if (target.Is(RaceStands.KnockDownable))
                    {
                        tAction.Set(TargetOptions.KnockDown);
                        attacker.Shove(target, KnockbackDistance);
                    }
                }
            }

            // Update current weapon
            SkillHelper.UpdateWeapon(attacker, targets.FirstOrDefault(), ProficiencyGainType.Melee, attacker.RightHand);

            cap.Handle();

            Send.Effect(attacker, Effect.LightningRod, (int)LightningRodEffect.Attack, poe.X, poe.Y);

            Send.SkillUse(attacker, skill.Info.Id, targetAreaId, 0, 1);
            skill.Train(1);             // Use the Skill

            attacker.Region.RemoveProp(lProp);
        }