Esempio 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();
		}
Esempio 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 delayReduction = ManaDeflector.Handle(attacker, target, ref targetDamage, tAction);

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

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

                // Reduce stun, based on ping
                if (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();
        }
Esempio n. 3
0
        /// <summary>
        ///  Hits targets with thunderbolt.
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="skill"></param>
        /// <param name="stacks"></param>
        /// <param name="damageProp"></param>
        /// <param name="targets"></param>
        private void Thunderbolt(Creature attacker, Skill skill, int stacks, Prop damageProp, List <Creature> targets)
        {
            // Skip if all targets are already dead
            if (targets.All(a => a.IsDead))
            {
                return;
            }

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

            aAction.Set(AttackerOptions.KnockBackHit1 | AttackerOptions.UseEffect);
            aAction.PropId = damageProp.EntityId;

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

            foreach (var target in targets.Where(a => !a.IsDead))
            {
                var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id);
                tAction.Set(TargetOptions.Result | TargetOptions.KnockDown);
                tAction.EffectFlags = EffectFlags.SpecialRangeHit;
                tAction.Delay       = 313;
                tAction.Stun        = (short)ThunderboltTargetStun;

                var damage = this.GetThunderboltDamage(attacker, skill, stacks);

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

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

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

                // Deal damage
                if (damage > 0)
                {
                    target.TakeDamage(tAction.Damage = damage, 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);
                }

                cap.Add(tAction);
            }

            cap.Handle();
        }
Esempio n. 4
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 target)
        {
            attacker.StopMove();
            target.StopMove();

            // Create actions
            var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, target.EntityId);

            aAction.Set(AttackerOptions.Result);

            var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id);

            tAction.Set(TargetOptions.Result);
            tAction.Stun = TargetStun;

            var cap = new CombatActionPack(attacker, skill.Info.Id, aAction, 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
            Defense.Handle(aAction, tAction, ref damage);
            SkillHelper.HandleMagicDefenseProtection(target, ref damage);
            ManaShield.Handle(target, ref damage, tAction);

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

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

            // Knock down on deadly
            if (target.Conditions.Has(ConditionsA.Deadly))
            {
                tAction.Set(TargetOptions.KnockDown);
                tAction.Stun = TargetStun;
            }

            // Reduce stun, based on ping
            if (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
                {
                    var stabilityReduction = 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);
            }

            // 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--;

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

            cap.Handle();
        }
Esempio n. 5
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 target)
        {
            attacker.StopMove();
            target.StopMove();

            // Create actions
            var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, target.EntityId);

            aAction.Set(AttackerOptions.Result);

            var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id);

            tAction.Set(TargetOptions.Result | TargetOptions.KnockDown);
            tAction.Stun = TargetStun;

            var cap = new CombatActionPack(attacker, skill.Info.Id, aAction, 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;
            attacker.Shove(target, KnockbackDistance);
            if (target.IsDead)
            {
                tAction.Set(TargetOptions.FinishingKnockDown);
            }

            // 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, target, ProficiencyGainType.Melee, attacker.RightHand);

            cap.Handle();
        }
Esempio n. 6
0
        /// <summary>
        /// Handles initial bolts.
        /// </summary>
        private void Bolts(Creature attacker, Skill skill, int stacks, Creature mainTarget, List <Creature> targets, int thunderboltDelay)
        {
            // Combat action
            var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, mainTarget.EntityId);

            aAction.Set(AttackerOptions.Result);
            aAction.Stun = (short)thunderboltDelay;

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

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

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

                var damage = this.GetBoltDamage(attacker, skill, stacks);

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

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

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

                // Deal damage
                if (damage > 0)
                {
                    target.TakeDamage(tAction.Damage = damage, 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
                    {
                        var stabilityReduction = StabilityReduction;

                        if (delayReduction > 0)
                        {
                            stabilityReduction = (short)Math.Max(0, stabilityReduction - (stabilityReduction / 100 * delayReduction));
                        }

                        target.Stability -= stabilityReduction;

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

                cap.Add(tAction);

                this.Train(skill, tAction);
            }

            cap.Handle();
        }
Esempio n. 7
0
        /// <summary>
        /// Uses Charging Strike
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="skill"></param>
        /// <param name="packet"></param>
        public void Use(Creature attacker, Skill skill, Packet packet)
        {
            // Get Target
            var targetEntityId = packet.GetLong();

            var target = attacker.Region.GetCreature(targetEntityId);

            var attackerPos = attacker.GetPosition();
            var targetPos   = target.GetPosition();

            // Check target + collisions
            if (target == null || attacker.Region.Collisions.Any(attackerPos, targetPos))
            {
                Send.SkillUseSilentCancel(attacker);
                attacker.Unlock(Locks.All);
                return;
            }

            // Stop movement
            attacker.Lock(Locks.Walk | Locks.Run);
            attacker.StopMove();
            target.StopMove();

            // Effects
            Send.EffectDelayed(attacker, attackerPos.GetDistance(targetPos), Effect.ChargingStrike, (byte)0, targetEntityId);

            // Conditions
            var extra = new MabiDictionary();

            extra.SetBool("CONDITION_FAST_MOVE_NO_LOCK", false);
            attacker.Conditions.Activate(ConditionsC.FastMove, extra);

            Send.ForceRunTo(attacker, targetPos);
            attacker.SetPosition(targetPos.X, targetPos.Y);

            Send.SkillUseEntity(attacker, skill.Info.Id, targetEntityId);

            Send.EffectDelayed(attacker, attackerPos.GetDistance(targetPos), Effect.ChargingStrike, (byte)1, targetEntityId);

            // Counter
            if (Counterattack.Handle(target, attacker))
            {
                attacker.Conditions.Deactivate(ConditionsC.FastMove);
                return;
            }

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

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

            aAction.Set(AttackerOptions.UseEffect);
            aAction.PropId = targetEntityId;

            var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id);

            tAction.Set(TargetOptions.Result);
            tAction.Delay = attackerPos.GetDistance(targetPos);

            cap.Add(aAction, tAction);

            // Damage
            var damage = (attacker.GetRndFighterDamage() * (skill.RankData.Var1 / 100f));

            // Chain Mastery Damage Bonus
            var chainMasterySkill = attacker.Skills.Get(SkillId.ChainMastery);
            var damageBonus       = (chainMasterySkill == null ? 0 : chainMasterySkill.RankData.Var1);

            damage += damage * (damageBonus / 100f);

            // Master Title - Damage +30%
            if (attacker.Titles.SelectedTitle == skill.Data.MasterTitle)
            {
                damage += (damage * 0.3f);
            }

            // Critical Hit
            var critChance = attacker.GetRightCritChance(target.Protection);

            CriticalHit.Handle(attacker, critChance, ref damage, tAction);

            // Handle skills and reductions
            SkillHelper.HandleDefenseProtection(target, ref damage);
            HeavyStander.Handle(attacker, target, ref damage, tAction);
            SkillHelper.HandleConditions(attacker, target, ref damage);
            ManaShield.Handle(target, ref damage, tAction);

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

            // Aggro
            target.Aggro(attacker);

            // Stun Times
            tAction.Stun = TargetStun;
            aAction.Stun = AttackerStun;

            // Death and Knockback
            if (target.IsDead)
            {
                if (target.Is(RaceStands.KnockDownable))
                {
                    tAction.Set(TargetOptions.FinishingKnockDown);
                    attacker.Shove(target, KnockbackDistance);
                }
                else
                {
                    tAction.Set(TargetOptions.Finished | TargetOptions.FinishingHit);
                }
            }
            else             // This skill never knocks back normally
            {
                if (!target.IsKnockedDown)
                {
                    target.Stability -= StabilityReduction;
                }
            }
            cap.Handle();

            attacker.Conditions.Deactivate(ConditionsC.FastMove);
            Send.SkillComplete(attacker, skill.Info.Id);

            // Chain Progress to Stage 2
            attacker.Temp.FighterChainStartTime = DateTime.Now;
            attacker.Temp.FighterChainLevel     = 2;

            attacker.Skills.ActiveSkill = null;

            // Charging strike locks EVERYTHING for some reason...
            attacker.Unlock(Locks.All);
        }
Esempio n. 8
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)
                {
                    CriticalHit.Handle(attacker, 100, ref damage, tAction);
                }

                // Handle skills and reductions
                SkillHelper.HandleMagicDefenseProtection(target, ref damage);
                SkillHelper.HandleConditions(attacker, target, ref damage);
                var delayReduction = ManaDeflector.Handle(attacker, target, ref damage, tAction);
                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, 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);
        }
Esempio n. 9
0
        /// <summary>
        /// Uses the skill
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="skill"></param>
        /// <param name="packet"></param>
        public void UseSkill(Creature attacker, Skill skill, long targetEntityId)
        {
            var target = attacker.Region.GetCreature(targetEntityId);

            var attackerPos = attacker.GetPosition();
            var targetPos   = target.GetPosition();

            // Check target + collisions
            if (target == null || attacker.Region.Collisions.Any(attackerPos, targetPos))
            {
                Send.SkillUseSilentCancel(attacker);
                return;
            }

            // Stop movement
            attacker.StopMove();
            target.StopMove();

            Send.SkillUseEntity(attacker, skill.Info.Id, targetEntityId);
            skill.State = SkillState.Used;

            // Counter
            if (Counterattack.Handle(target, attacker))
            {
                return;
            }

            // Defense/Protection decrease on target
            var debuffChance = (int)skill.RankData.Var6;
            var defDecrease  = (int)skill.RankData.Var3;
            var protDecrease = (int)skill.RankData.Var4;

            var extra = new MabiDictionary();

            extra.SetShort("NEW_DEF", (short)defDecrease);
            extra.SetShort("NEW_PROT", (short)protDecrease);
            extra.SetLong("DDP_CHAR", attacker.EntityId);
            extra.SetShort("DDP_SKILL", (short)skill.Info.Id);

            var rnd = RandomProvider.Get();

            if (rnd.NextDouble() * 100 < debuffChance)
            {
                Send.Effect(target, Effect.SpinningUppercutDebuff, (short)skill.Info.Id, 0, defDecrease, protDecrease);
                target.Conditions.Activate(ConditionsC.DefProtectDebuff, extra);
                attacker.Temp.SpinningUppercutDebuffApplied = true;
            }

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

            var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, targetEntityId, skill.Info.Id);

            aAction.Set(AttackerOptions.Result);

            var tAction = new TargetAction(CombatActionType.TakeHit | CombatActionType.Attacker, target, attacker, skill.Info.Id);

            tAction.Set(TargetOptions.Result | TargetOptions.FighterUnk);

            cap.Add(aAction, tAction);

            // Damage
            var damage = (attacker.GetRndFighterDamage() * (skill.RankData.Var1 / 100f));

            // Chain Mastery Damage Bonus
            var chainMasterySkill = attacker.Skills.Get(SkillId.ChainMastery);
            var damageBonus       = (chainMasterySkill == null ? 0 : chainMasterySkill.RankData.Var1);

            damage += damage * (damageBonus / 100f);

            // Master Title - Damage +20%
            if (attacker.Titles.SelectedTitle == skill.Data.MasterTitle)
            {
                damage += (damage * 0.2f);
            }

            // Critical Hit
            var critChance = attacker.GetRightCritChance(target.Protection);

            CriticalHit.Handle(attacker, critChance, ref damage, tAction);

            // Handle skills and reductions
            SkillHelper.HandleDefenseProtection(target, ref damage);
            HeavyStander.Handle(attacker, target, ref damage, tAction);
            SkillHelper.HandleConditions(attacker, target, ref damage);
            ManaShield.Handle(target, ref damage, tAction);

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

            // Aggro
            target.Aggro(attacker);

            // Stun Times
            tAction.Stun = TargetStun;
            aAction.Stun = AttackerStun;

            // Death and Knockback
            if (target.IsDead)
            {
                if (target.Is(RaceStands.KnockDownable))
                {
                    tAction.Set(TargetOptions.FinishingKnockDown);
                    attacker.Shove(target, KnockbackDistance);
                }
                else
                {
                    tAction.Set(TargetOptions.Finished | TargetOptions.FinishingHit);
                }
            }
            else
            {
                if (!target.IsKnockedDown)
                {
                    target.Stability -= StabilityReduction;
                }

                if (target.IsUnstable && target.Is(RaceStands.KnockDownable))
                {
                    tAction.Set(TargetOptions.KnockDown);
                    attacker.Shove(target, KnockbackDistance);
                }
            }
            cap.Handle();

            // Chain Progress to Stage 3
            attacker.Temp.FighterChainStartTime = DateTime.Now;
            attacker.Temp.FighterChainLevel     = 3;
        }
Esempio n. 10
0
        /// <summary>
        /// Handles drop kick's splash attack
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="skill"></param>
        /// <param name="initTarget"></param>
        /// <param name="skillLength"></param>
        /// <param name="damageBonus"></param>
        public void HandleSplash(Creature attacker, Skill skill, Creature initTarget, float skillLength, float damageBonus, float damageReduction)
        {
            // Variables
            var skillWidth  = skill.RankData.Var3;
            var attackerPos = attacker.GetPosition();

            // Set training variable
            attacker.Temp.DropKickSplashTargetCount = 0;

            // Get splash targets
            var targets = SkillHelper.GetTargetableCreaturesInSkillArea(attacker, (int)skillLength, (int)skillWidth);

            targets.Remove(initTarget);

            // Target Area?
            var targetAreaLoc = new Location(attacker.RegionId, attackerPos);
            var targetAreaId  = targetAreaLoc.ToLocationId();

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

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

            aAction.Set(AttackerOptions.Result);

            cap.Add(aAction);

            // Get critical hit (also for splash attacks)
            var rnd       = RandomProvider.Get();
            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;
                }
            }

            // Target Actions
            foreach (var target in targets)
            {
                attacker.Temp.DropKickSplashTargetCount += 1;

                var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id);
                tAction.Delay = target.GetPosition().GetDistance(attackerPos);
                cap.Add(tAction);

                // Splash Damage
                var damage = (attacker.GetRndFighterDamage() * (skill.RankData.Var5 / 100f));

                // Chain Mastery Damage Bonus
                damage += damage * (damageBonus / 100f);

                // Heavy Armor Damage Reduction
                if (attacker.HasEquipped("/heavyarmor/"))
                {
                    damage -= damage * (damageReduction / 100f);
                }

                // Master Title - Damage +10%
                if (attacker.Titles.SelectedTitle == skill.Data.MasterTitle)
                {
                    damage += (damage * 0.1f);
                }

                // Critical Hit
                if (crit)
                {
                    CriticalHit.Handle(attacker, 100, ref damage, tAction);
                }

                // Handle skills and reductions
                SkillHelper.HandleDefenseProtection(target, ref damage);
                HeavyStander.Handle(attacker, target, ref damage, tAction);
                SkillHelper.HandleConditions(attacker, target, ref damage);
                ManaShield.Handle(target, ref damage, tAction);

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

                // Aggro
                target.Aggro(attacker);

                // Stun
                tAction.Stun = TargetStun;

                // Death and Knockback
                if (target.IsDead)
                {
                    if (target.Is(RaceStands.KnockDownable))
                    {
                        tAction.Set(TargetOptions.FinishingKnockDown);
                        attacker.Shove(target, (int)skillLength);
                    }
                    else
                    {
                        tAction.Set(TargetOptions.Finished | TargetOptions.FinishingHit);
                    }
                }
                else
                {
                    if (!target.IsKnockedDown)
                    {
                        target.Stability -= StabilityReduction;
                    }

                    if (target.Is(RaceStands.KnockDownable))                     // Always knock down
                    {
                        tAction.Set(TargetOptions.KnockDown);
                        attacker.Shove(target, (int)skillLength);
                    }
                }
            }
            cap.Handle();
        }
Esempio n. 11
0
        /// <summary>
        /// Uses the skill
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="skill"></param>
        /// <param name="packet"></param>
        public void UseSkill(Creature attacker, Skill skill, long targetEntityId)
        {
            var target = attacker.Region.GetCreature(targetEntityId);

            var attackerPos = attacker.GetPosition();
            var targetPos   = target.GetPosition();

            // Check target + collisions
            if (target == null || attacker.Region.Collisions.Any(attackerPos, targetPos))
            {
                Send.SkillUseSilentCancel(attacker);
                return;
            }

            // Stop movement
            target.StopMove();

            Send.SkillUseEntity(attacker, skill.Info.Id, targetEntityId);
            skill.State = SkillState.Used;

            // Variables
            var skillLength = skill.RankData.Var4;

            // Effects
            Send.Effect(attacker, Effect.DropKick, (byte)1, targetEntityId);
            Send.EffectDelayed(attacker, 300, Effect.DropKick, (byte)2, targetEntityId, (short)400);

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

            var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, targetEntityId, skill.Info.Id);

            aAction.Set(AttackerOptions.Result);

            var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id);

            tAction.Set(TargetOptions.Result | TargetOptions.FighterUnk);

            cap.Add(aAction, tAction);

            // Damage
            var damage = (attacker.GetRndFighterDamage() * (skill.RankData.Var1 / 100f));

            // Chain Mastery Damage Bonus
            var chainMasterySkill = attacker.Skills.Get(SkillId.ChainMastery);
            var damageBonus       = (chainMasterySkill == null ? 0 : chainMasterySkill.RankData.Var1);

            damage += damage * (damageBonus / 100f);

            // Heavy Armor Damage Reduction
            var damageReduction = (chainMasterySkill == null ? 0 : (100 - chainMasterySkill.RankData.Var3));

            if (attacker.HasEquipped("/heavyarmor/"))
            {
                damage -= damage * (damageReduction / 100f);
            }

            // Master Title - Damage +10%
            if (attacker.Titles.SelectedTitle == skill.Data.MasterTitle)
            {
                damage += (damage * 0.1f);
            }

            // Critical Hit
            var critChance = attacker.GetRightCritChance(target.Protection);

            CriticalHit.Handle(attacker, critChance, ref damage, tAction);

            // Handle skills and reductions
            SkillHelper.HandleDefenseProtection(target, ref damage);
            HeavyStander.Handle(attacker, target, ref damage, tAction);
            SkillHelper.HandleConditions(attacker, target, ref damage);
            ManaShield.Handle(target, ref damage, tAction);

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

            // Aggro
            target.Aggro(attacker);

            // Stun Times
            tAction.Stun = TargetStun;
            aAction.Stun = AttackerStun;

            // Death and Knockback
            if (target.IsDead)
            {
                if (target.Is(RaceStands.KnockDownable))
                {
                    tAction.Set(TargetOptions.FinishingKnockDown);
                    attacker.Shove(target, (int)skillLength);
                }
                else
                {
                    tAction.Set(TargetOptions.Finished | TargetOptions.FinishingHit);
                }
            }
            else
            {
                if (!target.IsKnockedDown)
                {
                    target.Stability -= StabilityReduction;
                }

                if (target.Is(RaceStands.KnockDownable))                 // Always knock down
                {
                    tAction.Set(TargetOptions.KnockDown);
                    attacker.Shove(target, (int)skillLength);
                }
            }
            cap.Handle();

            // Splash Damage
            this.HandleSplash(attacker, skill, target, skillLength, damageBonus, damageReduction);
        }