CalculateElementalDamageMultiplier() публичный Метод

Calculates the creature's elemental damage modifier, against the target's elements.
public CalculateElementalDamageMultiplier ( Creature target ) : float
target Creature
Результат float
Пример #1
0
		/// <summary>
		/// Returns elemental damage multiplier for this skill.
		/// </summary>
		/// <param name="attacker"></param>
		/// <param name="target"></param>
		/// <returns></returns>
		protected override float GetElementalDamageMultiplier(Creature attacker, Creature target)
		{
			return attacker.CalculateElementalDamageMultiplier(Creature.MaxElementalAffinity, 0, 0, target);
		}
Пример #2
0
		/// <summary>
		/// Uses the skill.
		/// </summary>
		/// <param name="attacker"></param>
		/// <param name="skill"></param>
		/// <param name="targetEntityId"></param>
		/// <returns></returns>
		public CombatSkillResult Use(Creature attacker, Skill skill, long targetEntityId)
		{
			// Get target
			var target = attacker.Region.GetCreature(targetEntityId);
			if (target == null)
				return CombatSkillResult.InvalidTarget;

			// "Cancels" the skill
			// 800 = old load time? == aAction.Stun? Varies? Doesn't seem to be a stun.
			Send.SkillUse(attacker, skill.Info.Id, AttackerStun, 1);

			var chance = attacker.AimMeter.GetAimChance(target);
			var rnd = RandomProvider.Get().NextDouble() * 100;
			var successfulHit = (rnd < chance);

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

			var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, targetEntityId);
			aAction.Set(AttackerOptions.Result);
			aAction.Stun = AttackerStun;
			cap.Add(aAction);

			// Target action if hit
			if (successfulHit)
			{
				target.StopMove();

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

				cap.Add(tAction);

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

				// Elementals
				damage *= attacker.CalculateElementalDamageMultiplier(target);

				// More damage with fire arrow
				if (attacker.Temp.FireArrow)
					damage *= FireBonus;

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

				// Subtract target def/prot
				SkillHelper.HandleDefenseProtection(target, ref damage);

				// Defense
				Defense.Handle(aAction, tAction, ref damage);

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

				// Natural Shield
				var delayReduction = NaturalShield.Handle(attacker, target, ref damage, tAction);

				// Deal with it!
				if (damage > 0)
				{
					target.TakeDamage(tAction.Damage = damage, attacker);
					SkillHelper.HandleInjury(attacker, target, damage);
				}

				// Aggro
				target.Aggro(attacker);

				// Knock down on deadly
				if (target.Conditions.Has(ConditionsA.Deadly))
					tAction.Set(TargetOptions.KnockDown);

				// Death/Knockback
				if (target.IsDead)
					tAction.Set(TargetOptions.FinishingKnockDown);

				// Knock Back
				if (tAction.IsKnockBack)
					attacker.Shove(target, KnockBackDistance);

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

				// TODO: "Weakened" state (G12S2 gfSupportShotRenewal)
			}

			// Reduce arrows
			if (attacker.Magazine != null && !ChannelServer.Instance.Conf.World.InfiniteArrows && !attacker.Magazine.HasTag("/unlimited_arrow/"))
				attacker.Inventory.Decrement(attacker.Magazine);

			cap.Handle();

			// Disable fire arrow effect
			if (attacker.Temp.FireArrow)
				Send.Effect(attacker, Effect.FireArrow, false);

			return CombatSkillResult.Okay;
		}
Пример #3
0
		/// <summary>
		/// Handles using the skill.
		/// </summary>
		/// <param name="attacker"></param>
		/// <param name="skill"></param>
		/// <param name="targetAreaId"></param>
		/// <param name="unkInt1"></param>
		/// <param name="unkInt2"></param>
		public void Use(Creature attacker, Skill skill, long targetAreaId, int unkInt1, int unkInt2)
		{
			var range = this.GetRange(attacker, skill);
			var targets = attacker.GetTargetableCreaturesInRange(range, TargetableOptions.AddAttackRange);
			var rnd = RandomProvider.Get();

			// Create actions
			var cap = new CombatActionPack(attacker, skill.Info.Id);

			var aAction = new AttackerAction(CombatActionType.Attacker, attacker, targetAreaId);
			aAction.Set(AttackerOptions.Result);
			aAction.Stun = AttackerStun;

			cap.Add(aAction);

			foreach (var target in targets)
			{
				// Check if hit
				var hitChance = this.GetHitChance(attacker, target, skill);
				if (rnd.Next(0, 100) > hitChance)
					continue;

				target.StopMove();

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

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

				// Elementals
				damage *= attacker.CalculateElementalDamageMultiplier(target);

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

				// Clean Hit if not critical
				if (!tAction.Has(TargetOptions.Critical))
					tAction.Set(TargetOptions.CleanHit);

				// Take damage if any is left
				if (damage > 0)
				{
					target.TakeDamage(tAction.Damage = damage, attacker);
					SkillHelper.HandleInjury(attacker, target, damage);
				}

				// Finish if dead, knock down if not defended
				if (target.IsDead)
					tAction.Set(TargetOptions.KnockDownFinish);
				else
					tAction.Set(TargetOptions.KnockDown);

				// Anger Management
				if (!target.IsDead)
					target.Aggro(attacker);

				// Stun & knock down
				tAction.Stun = CombatMastery.GetTargetStun(attacker.AverageKnockCount, attacker.AverageAttackSpeed, true);
				target.Stability = Creature.MinStability;

				// Add action
				cap.Add(tAction);
			}

			Send.UseMotion(attacker, 10, 1);

			cap.Handle();

			Send.SkillUse(attacker, skill.Info.Id, targetAreaId, unkInt1, unkInt2);
		}
Пример #4
0
		/// <summary>
		/// Uses the skill.
		/// </summary>
		/// <param name="attacker"></param>
		/// <param name="skill"></param>
		/// <param name="targetEntityId"></param>
		/// <returns></returns>
		public CombatSkillResult Use(Creature attacker, Skill skill, long targetEntityId)
		{
			// Get target
			var target = attacker.Region.GetCreature(targetEntityId);
			if (target == null)
				return CombatSkillResult.InvalidTarget;

			// "Cancels" the skill
			// 800 = old load time? == aAction.Stun? Varies? Doesn't seem to be a stun.
			Send.SkillUse(attacker, skill.Info.Id, AttackerStun, 1);

			var chance = attacker.AimMeter.GetAimChance(target);
			var rnd = RandomProvider.Get().NextDouble() * 100;
			var successfulHit = (rnd < chance);

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

			var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, targetEntityId);
			aAction.Set(AttackerOptions.Result);
			aAction.Stun = AttackerStun;
			cap.Add(aAction);

			// Target action if hit
			if (successfulHit)
			{
				target.StopMove();

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

				cap.Add(tAction);

				// Damage
				// Formula unofficial, but it kinda matches what you would
				// expect from the skill, and what players believed the damage
				// to be, back in G2.
				// bonus = (100 - (6 - stacks) * 5 + rank, +var2 on last shot
				// I'm using rank instead of Var1, which goes from 1-15 in
				// AR2, so AR1 gets a little bonus as well, as AR1's Var1 and
				// 2 are 0.
				// With this formula, the bonus range (1st shot rF vs 5th shot
				// r1) is 76~110% for AR1, and 76~140% for AR2.
				var bonus = 100f - (6 - skill.Stacks) * 5f + (byte)skill.Info.Rank;
				if (skill.Stacks == 1)
					bonus += skill.RankData.Var2;

				var damage = attacker.GetRndRangedDamage() * (bonus / 100f);

				// Elementals
				damage *= attacker.CalculateElementalDamageMultiplier(target);

				// More damage with fire arrow
				if (attacker.Temp.FireArrow)
					damage *= FireBonus;

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

				// Subtract target def/prot
				SkillHelper.HandleDefenseProtection(target, ref damage);

				// Defense
				Defense.Handle(aAction, tAction, ref damage);

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

				// Natural Shield
				var delayReduction = NaturalShield.Handle(attacker, target, ref damage, tAction);

				// Deal with it!
				if (damage > 0)
				{
					target.TakeDamage(tAction.Damage = damage, attacker);
					SkillHelper.HandleInjury(attacker, target, damage);
				}

				// Aggro
				target.Aggro(attacker);

				// Knock down on deadly
				if (target.Conditions.Has(ConditionsA.Deadly))
					tAction.Set(TargetOptions.KnockDown);

				// Death/Knockback
				if (target.IsDead)
				{
					tAction.Set(TargetOptions.FinishingKnockDown);
				}
				else
				{
					// Insta-recover in knock down
					if (target.IsKnockedDown)
					{
						tAction.Stun = 0;
					}
					// Knock down if hit repeatedly
					else if (target.Stability < 30)
					{
						tAction.Set(TargetOptions.KnockDown);
					}
					// Normal stability reduction
					else
					{
						var stabilityReduction = StabilityReduction;

						// Reduce reduction, based on ping
						// According to the Wiki, "the Knockdown Gauge
						// [does not] build up", but it's still possible
						// to knock back with repeated hits. The stability
						// reduction is probably reduced, just like stun.
						if (delayReduction > 0)
							stabilityReduction = (short)Math.Max(0, stabilityReduction - (stabilityReduction / 100 * delayReduction));

						target.Stability -= stabilityReduction;
						if (target.IsUnstable)
						{
							tAction.Set(TargetOptions.KnockBack);
						}
					}
				}

				// Knock Back
				if (tAction.IsKnockBack)
					attacker.Shove(target, KnockBackDistance);

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

			// Skill training
			if (skill.Info.Rank == SkillRank.RF)
				skill.Train(1); // Try attacking with Arrow Revolver.

			// Reduce arrows
			if (attacker.Magazine != null && !ChannelServer.Instance.Conf.World.InfiniteArrows && !attacker.Magazine.HasTag("/unlimited_arrow/"))
				attacker.Inventory.Decrement(attacker.Magazine);

			// Reduce stack
			skill.Stacks--;

			// Handle
			cap.Handle();

			// Disable fire arrow effect
			if (attacker.Temp.FireArrow)
				Send.Effect(attacker, Effect.FireArrow, false);

			return CombatSkillResult.Okay;
		}
Пример #5
0
		/// <summary>
		/// Uses the skill.
		/// </summary>
		/// <param name="attacker"></param>
		/// <param name="skill"></param>
		/// <param name="targetEntityId"></param>
		/// <returns></returns>
		public CombatSkillResult Use(Creature attacker, Skill skill, long targetEntityId)
		{
			// Get target
			var target = attacker.Region.GetCreature(targetEntityId);
			if (target == null)
				return CombatSkillResult.InvalidTarget;

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

			var actionType = (attacker.IsElf ? CombatActionPackType.ChainRangeAttack : CombatActionPackType.NormalAttack);
			var attackerStun = (short)(actionType == CombatActionPackType.ChainRangeAttack ? AttackerStunElf : AttackerStun);

			// "Cancels" the skill
			// 800 = old load time? == aAction.Stun? Varies? Doesn't seem to be a stun.
			Send.SkillUse(attacker, skill.Info.Id, attackerStun, 1);

			var chance = attacker.AimMeter.GetAimChance(target);
			var rnd = RandomProvider.Get().NextDouble() * 100;
			var successfulHit = (rnd < chance);

			var maxHits = (actionType == CombatActionPackType.ChainRangeAttack && successfulHit ? 2 : 1);
			var prevId = 0;

			for (byte i = 1; i <= maxHits; ++i)
			{
				target.StopMove();

				// Actions
				var cap = new CombatActionPack(attacker, skill.Info.Id);
				cap.Hit = i;
				cap.Type = actionType;
				cap.PrevId = prevId;
				prevId = cap.Id;

				var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, targetEntityId);
				aAction.Set(AttackerOptions.Result);
				aAction.Stun = attackerStun;
				cap.Add(aAction);

				// Target action if hit
				if (successfulHit)
				{
					var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id);
					tAction.Set(TargetOptions.Result);
					tAction.Stun = (short)(actionType == CombatActionPackType.ChainRangeAttack ? TargetStunElf : TargetStun);
					if (actionType == CombatActionPackType.ChainRangeAttack)
						tAction.EffectFlags = EffectFlags.Unknown;

					cap.Add(tAction);

					// Damage
					var damage = attacker.GetRndRangedDamage();

					// Elementals
					damage *= attacker.CalculateElementalDamageMultiplier(target);

					// More damage with fire arrow
					// XXX: Does this affect the element?
					if (attacker.Temp.FireArrow)
						damage *= FireBonus;

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

					// Subtract target def/prot
					SkillHelper.HandleDefenseProtection(target, ref damage);

					// Defense
					Defense.Handle(aAction, tAction, ref damage);

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

					// Natural Shield
					var delayReduction = NaturalShield.Handle(attacker, target, ref damage, tAction);

					// Deal with it!
					if (damage > 0)
					{
						target.TakeDamage(tAction.Damage = damage, attacker);
						SkillHelper.HandleInjury(attacker, target, damage);
					}

					// Knock down on deadly
					if (target.Conditions.Has(ConditionsA.Deadly))
					{
						tAction.Set(TargetOptions.KnockDown);
						tAction.Stun = (short)(actionType == CombatActionPackType.ChainRangeAttack ? TargetStunElf : TargetStun);
					}

					// Aggro
					target.Aggro(attacker);

					// Death/Knockback
					if (target.IsDead)
					{
						tAction.Set(TargetOptions.FinishingKnockDown);
						maxHits = 1;
					}
					else
					{
						// Insta-recover in knock down
						// TODO: Tied to stability?
						if (target.IsKnockedDown)
						{
							tAction.Stun = 0;
						}
						// Knock down if hit repeatedly
						else if (target.Stability < 30)
						{
							tAction.Set(TargetOptions.KnockDown);
						}
						// Normal stability reduction
						else
						{
							var stabilityReduction = (actionType == CombatActionPackType.ChainRangeAttack ? StabilityReductionElf : StabilityReduction);

							// Reduce reduction, based on ping
							// According to the Wiki, "the Knockdown Gauge
							// [does not] build up", but it's still possible
							// to knock back with repeated hits. The stability
							// reduction is probably reduced, just like stun.
							if (delayReduction > 0)
								stabilityReduction = (short)Math.Max(0, stabilityReduction - (stabilityReduction / 100 * delayReduction));

							target.Stability -= stabilityReduction;
							if (target.IsUnstable)
							{
								tAction.Set(TargetOptions.KnockBack);
							}
						}
					}

					// Knock Back
					if (tAction.IsKnockBack)
						attacker.Shove(target, KnockBackDistance);

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

				// Skill training
				if (skill.Info.Rank == SkillRank.Novice || skill.Info.Rank == SkillRank.RF)
					skill.Train(1); // Try ranged attack.

				// Reduce arrows
				if (attacker.Magazine != null && !ChannelServer.Instance.Conf.World.InfiniteArrows && !attacker.Magazine.HasTag("/unlimited_arrow/"))
					attacker.Inventory.Decrement(attacker.Magazine);

				cap.Handle();
			}

			// Disable fire arrow effect
			if (attacker.Temp.FireArrow)
				Send.Effect(attacker, Effect.FireArrow, false);

			return CombatSkillResult.Okay;
		}
Пример #6
0
		/// <summary>
		/// Uses WM, attacking targets.
		/// </summary>
		/// <param name="attacker"></param>
		/// <param name="skill"></param>
		/// <param name="targetAreaId"></param>
		/// <param name="unkInt1"></param>
		/// <param name="unkInt2"></param>
		public void Use(Creature attacker, Skill skill, long targetAreaId, int unkInt1, int unkInt2)
		{
			var range = this.GetRange(attacker, skill);
			var targets = attacker.GetTargetableCreaturesInRange(range, TargetableOptions.AddAttackRange);

			// Check targets
			if (targets.Count == 0)
			{
				Send.Notice(attacker, Localization.Get("There isn't a target nearby to use that on."));
				Send.SkillUseSilentCancel(attacker);
				return;
			}

			// Create actions
			var cap = new CombatActionPack(attacker, skill.Info.Id);

			var aAction = new AttackerAction(CombatActionType.SpecialHit, attacker, targetAreaId);
			aAction.Set(AttackerOptions.Result);
			aAction.Stun = CombatMastery.GetAttackerStun(attacker.AverageKnockCount, attacker.AverageAttackSpeed, true);

			cap.Add(aAction);

			var survived = new List<Creature>();
			var rnd = RandomProvider.Get();

			// Check crit
			var crit = false;
			if (attacker.Skills.Has(SkillId.CriticalHit, SkillRank.RF))
				crit = (rnd.Next(100) < attacker.GetTotalCritChance(0));

			// Handle all targets
			foreach (var target in targets)
			{
				target.StopMove();

				var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id);
				tAction.Delay = 300; // Usually 300, sometimes 350?

				// Calculate damage
				var damage = attacker.GetRndTotalDamage();
				damage *= skill.RankData.Var1 / 100f;

				// Elementals
				damage *= attacker.CalculateElementalDamageMultiplier(target);

				// Crit bonus
				if (crit)
					CriticalHit.Handle(attacker, 100, ref damage, tAction);

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

				// Clean Hit if not defended nor critical
				if (tAction.SkillId != SkillId.Defense && !tAction.Has(TargetOptions.Critical))
					tAction.Set(TargetOptions.CleanHit);

				// Take damage if any is left
				if (damage > 0)
					target.TakeDamage(tAction.Damage = damage, attacker);

				// Knock down on deadly
				if (target.Conditions.Has(ConditionsA.Deadly))
				{
					tAction.Set(TargetOptions.KnockDown);
					tAction.Stun = CombatMastery.GetTargetStun(attacker.AverageKnockCount, attacker.AverageAttackSpeed, true);
				}

				// Finish if dead, knock down if not defended
				if (target.IsDead)
					tAction.Set(TargetOptions.KnockDownFinish);
				else if (tAction.SkillId != SkillId.Defense)
					tAction.Set(TargetOptions.KnockDown);

				// Anger Management
				if (!target.IsDead)
					survived.Add(target);

				// Stun and shove if not defended
				if (target.IsDead || tAction.SkillId != SkillId.Defense || target.Conditions.Has(ConditionsA.Deadly))
				{
					tAction.Stun = CombatMastery.GetTargetStun(attacker.AverageKnockCount, attacker.AverageAttackSpeed, true);
					target.Stability = Creature.MinStability;
					attacker.Shove(target, KnockbackDistance);
				}

				// Add action
				cap.Add(tAction);
			}

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

			// Only select a random aggro if there is no aggro yet,
			// WM only aggroes one target at a time.
			if (survived.Count != 0 && attacker.Region.CountAggro(attacker) < 1)
			{
				var aggroTarget = survived.Random();
				aggroTarget.Aggro(attacker);
			}

			// Reduce life in old combat system
			if (!AuraData.FeaturesDb.IsEnabled("CombatSystemRenewal"))
			{
				// Default reduction is 10%, it's reduced to 2% if attacker
				// has less max life than the rate is set to.
				var lifeReducationRate = skill.RankData.Var2;
				if (attacker.LifeMax < lifeReducationRate)
					lifeReducationRate /= 5;

				var amount = attacker.LifeMax / 100f * lifeReducationRate;
				attacker.ModifyLife(-amount);

				// TODO: Invincibility
			}

			// Spin it~
			Send.UseMotion(attacker, 8, 4);

			cap.Handle();

			Send.SkillUse(attacker, skill.Info.Id, targetAreaId, unkInt1, unkInt2);

			skill.Stacks = 0;
		}
Пример #7
0
        /// <summary>
        /// Handles attack.
        /// </summary>
        /// <param name="attacker">The creature attacking.</param>
        /// <param name="skill">The skill being used.</param>
        /// <param name="targetEntityId">The entity id of the target.</param>
        /// <returns></returns>
        public CombatSkillResult Use(Creature attacker, Skill skill, long targetEntityId)
        {
            if (attacker.IsStunned)
                return CombatSkillResult.Okay;

            var mainTarget = attacker.Region.GetCreature(targetEntityId);
            if (mainTarget == null)
                return CombatSkillResult.Okay;

            if (!attacker.GetPosition().InRange(mainTarget.GetPosition(), attacker.AttackRangeFor(mainTarget)))
                return CombatSkillResult.OutOfRange;

            attacker.StopMove();

            // Get targets, incl. splash.
            var targets = new HashSet<Creature>() { mainTarget };
            targets.UnionWith(attacker.GetTargetableCreaturesInCone(mainTarget.GetPosition(), attacker.GetTotalSplashRadius(), attacker.GetTotalSplashAngle()));

            // Counter
            if (Counterattack.Handle(targets, attacker))
                return CombatSkillResult.Okay;

            var rightWeapon = attacker.Inventory.RightHand;
            var leftWeapon = attacker.Inventory.LeftHand;
            var magazine = attacker.Inventory.Magazine;
            var maxHits = (byte)(attacker.IsDualWielding ? 2 : 1);
            int prevId = 0;

            for (byte i = 1; i <= maxHits; ++i)
            {
                var weapon = (i == 1 ? rightWeapon : leftWeapon);
                var weaponIsKnuckle = (weapon != null && weapon.Data.HasTag("/knuckle/"));

                var aAction = new AttackerAction(CombatActionType.Attacker, attacker, targetEntityId);
                aAction.Set(AttackerOptions.Result);

                if (attacker.IsDualWielding)
                {
                    aAction.Set(AttackerOptions.DualWield);
                    aAction.WeaponParameterType = (byte)(i == 1 ? 2 : 1);
                }

                var cap = new CombatActionPack(attacker, skill.Info.Id, aAction);
                cap.Hit = i;
                cap.Type = (attacker.IsDualWielding ? CombatActionPackType.TwinSwordAttack : CombatActionPackType.NormalAttack);
                cap.PrevId = prevId;
                prevId = cap.Id;

                var mainDamage = (i == 1 ? attacker.GetRndRightHandDamage() : attacker.GetRndLeftHandDamage());

                foreach (var target in targets)
                {
                    if (target.IsDead)
                        continue;

                    target.StopMove();

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

                    // Base damage
                    var damage = mainDamage;

                    // Elementals
                    damage *= attacker.CalculateElementalDamageMultiplier(target);

                    // Splash modifier
                    if (target != mainTarget)
                        damage *= attacker.GetSplashDamage(weapon);

                    // Critical Hit
                    var critChance = (i == 1 ? attacker.GetRightCritChance(target.Protection) : attacker.GetLeftCritChance(target.Protection));
                    CriticalHit.Handle(attacker, critChance, ref damage, tAction);

                    // Subtract target def/prot
                    SkillHelper.HandleDefenseProtection(target, ref damage);

                    // Defense
                    Defense.Handle(aAction, tAction, ref damage);

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

                    // Heavy Stander
                    // Can only happen on the first hit
                    var pinged = (cap.Hit == 1 && HeavyStander.Handle(attacker, target, ref damage, tAction));

                    // Deal with it!
                    if (damage > 0)
                    {
                        target.TakeDamage(tAction.Damage = damage, attacker);
                        SkillHelper.HandleInjury(attacker, target, damage);
                    }

                    // Knock down on deadly
                    if (target.Conditions.Has(ConditionsA.Deadly))
                    {
                        tAction.Set(TargetOptions.KnockDown);
                        tAction.Stun = GetTargetStun(attacker, weapon, tAction.IsKnockBack);
                    }

                    // Aggro
                    if (target == mainTarget)
                        target.Aggro(attacker);

                    // Evaluate caused damage
                    if (!target.IsDead)
                    {
                        if (tAction.SkillId != SkillId.Defense)
                        {
                            target.Stability -= this.GetStabilityReduction(attacker, weapon) / maxHits;

                            // React normal for CombatMastery, knock down if
                            // FH and not dual wield, don't knock at all if dual.
                            if (skill.Info.Id != SkillId.FinalHit)
                            {
                                // Originally we thought you knock enemies back, unless it's a critical
                                // hit, but apparently you knock *down* under normal circumstances.
                                // More research to be done.
                                if (target.IsUnstable && target.Is(RaceStands.KnockBackable))
                                    //tAction.Set(tAction.Has(TargetOptions.Critical) ? TargetOptions.KnockDown : TargetOptions.KnockBack);
                                    tAction.Set(TargetOptions.KnockDown);
                            }
                            else if (!attacker.IsDualWielding && !weaponIsKnuckle && target.Is(RaceStands.KnockBackable))
                            {
                                target.Stability = Creature.MinStability;
                                tAction.Set(TargetOptions.KnockDown);
                            }
                        }
                    }
                    else
                    {
                        tAction.Set(TargetOptions.FinishingKnockDown);
                    }

                    // React to knock back
                    if (tAction.IsKnockBack)
                    {
                        attacker.Shove(target, KnockBackDistance);
                        if (target == mainTarget)
                            aAction.Set(AttackerOptions.KnockBackHit2);
                    }

                    // Set stun time if not defended, Defense handles the stun
                    // in case the target used it.
                    if (tAction.SkillId != SkillId.Defense)
                    {
                        if (target == mainTarget)
                            aAction.Stun = GetAttackerStun(attacker, weapon, tAction.IsKnockBack && skill.Info.Id != SkillId.FinalHit);
                        tAction.Stun = GetTargetStun(attacker, weapon, tAction.IsKnockBack);
                    }

                    if (target == mainTarget)
                    {
                        // Set increased stun if target pinged
                        if (pinged)
                            aAction.Stun = GetAttackerStun(attacker, weapon, true);

                        // Second hit doubles stun time for normal hits
                        if (cap.Hit == 2 && !tAction.IsKnockBack && !pinged)
                            aAction.Stun *= 2;

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

                        // Consume stamina for weapon
                        var staminaUsage = (weapon != null ? weapon.Data.StaminaUsage : Creature.BareHandStaminaUsage);
                        if (attacker.Stamina < staminaUsage)
                            Send.Notice(attacker, Localization.Get("Your stamina is too low to fight properly!"));
                        attacker.Stamina -= staminaUsage;

                        // No second hit if defended, pinged, or knocked back
                        if (tAction.IsKnockBack || tAction.SkillId == SkillId.Defense || pinged)
                        {
                            // Set to 1 to prevent second run
                            maxHits = 1;

                            // Remove dual wield option if last hit doesn't come from
                            // the second weapon. If this isn't done, the client shows
                            // the second hit.
                            if (cap.Hit != 2)
                                aAction.Options &= ~AttackerOptions.DualWield;
                        }
                    }
                }

                // Handle
                cap.Handle();
            }

            return CombatSkillResult.Okay;
        }
Пример #8
0
        /// <summary>
        /// Handles skill usage.
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="skill"></param>
        /// <param name="targetEntityId"></param>
        /// <returns></returns>
        public override CombatSkillResult Use(Creature attacker, Skill skill, long targetEntityId)
        {
            // Check target
            var mainTarget = attacker.Region.GetCreature(targetEntityId);
            if (mainTarget == null)
                return CombatSkillResult.InvalidTarget;

            // Check range
            var targetPosition = mainTarget.GetPosition();
            if (!attacker.GetPosition().InRange(targetPosition, attacker.AttackRangeFor(mainTarget)))
                return CombatSkillResult.OutOfRange;

            // Stop movement
            attacker.StopMove();

            // Get targets, incl. splash.
            // Splash happens from r5 onwards, but we'll base it on Var4,
            // which is the splash damage and first != 0 on r5.
            var targets = new HashSet<Creature>() { mainTarget };
            if (skill.RankData.Var4 != 0)
                targets.UnionWith(attacker.GetTargetableCreaturesInCone(mainTarget.GetPosition(), attacker.GetTotalSplashRadius(), attacker.GetTotalSplashAngle()));

            // Counter
            if (Counterattack.Handle(targets, attacker))
                return CombatSkillResult.Okay;

            // Prepare combat actions
            var aAction = new AttackerAction(CombatActionType.HardHit, attacker, targetEntityId);
            aAction.Set(AttackerOptions.Result | AttackerOptions.KnockBackHit2);
            aAction.Stun = StunTime;

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

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

            foreach (var target in targets)
            {
                // Stop movement
                target.StopMove();

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

                cap.Add(tAction);

                // Damage
                var damage = mainDamage;

                // Elementals
                damage *= attacker.CalculateElementalDamageMultiplier(target);

                // Splash modifier
                if (target != mainTarget)
                    damage *= (skill.RankData.Var4 / 100f);

                // Critical Hit
                var critChance = this.GetCritChance(attacker, target, skill);
                CriticalHit.Handle(attacker, critChance, ref damage, tAction);

                // Subtract target def/prot
                SkillHelper.HandleDefenseProtection(target, ref damage);

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

                // Heavy Stander
                HeavyStander.Handle(attacker, target, ref damage, tAction);

                // Apply damage
                if (damage > 0)
                {
                    target.TakeDamage(tAction.Damage = damage, attacker);
                    SkillHelper.HandleInjury(attacker, target, damage);
                }

                // Aggro
                if (target == mainTarget)
                    target.Aggro(attacker);

                if (target.IsDead)
                    tAction.Set(TargetOptions.FinishingHit | TargetOptions.Finished);

                // Set Stun/Knockback
                target.Stun = tAction.Stun = StunTime;
                target.Stability = Creature.MinStability;

                // Set knockbacked position
                attacker.Shove(target, KnockbackDistance);
            }

            // Response
            Send.SkillUseStun(attacker, skill.Info.Id, AfterUseStun, 1);

            // Update both weapons
            SkillHelper.UpdateWeapon(attacker, mainTarget, ProficiencyGainType.Melee, attacker.RightHand, attacker.LeftHand);

            // Action!
            cap.Handle();

            return CombatSkillResult.Okay;
        }
Пример #9
0
		/// <summary>
		/// Uses the skill.
		/// </summary>
		/// <param name="attacker"></param>
		/// <param name="skill"></param>
		/// <param name="targetEntityId"></param>
		/// <returns></returns>
		public CombatSkillResult Use(Creature attacker, Skill skill, long targetEntityId)
		{
			// Get target
			var mainTarget = attacker.Region.GetCreature(targetEntityId);
			if (mainTarget == null)
				return CombatSkillResult.InvalidTarget;

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

			var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, targetEntityId);
			aAction.Set(AttackerOptions.Result);
			aAction.Stun = AttackerStun;
			cap.Add(aAction);

			// Hit by chance
			var chance = attacker.AimMeter.GetAimChance(mainTarget);
			var rnd = RandomProvider.Get();
			if (rnd.NextDouble() * 100 < chance)
			{
				aAction.Set(AttackerOptions.KnockBackHit2);

				// Get targets, incl. splash.
				// Splash happens from r5 onwards, but we'll base it on Var4,
				// which is the splash damage and first != 0 on r5.
				var targets = new HashSet<Creature>() { mainTarget };
				if (skill.RankData.Var4 != 0)
				{
					var targetPosition = mainTarget.GetPosition();
					var direction = attacker.GetPosition().GetDirection(targetPosition);
					targets.UnionWith(attacker.GetTargetableCreaturesInCone(targetPosition, direction, skill.RankData.Var5, skill.RankData.Var6));
				}

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

				foreach (var target in targets)
				{
					var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Info.Id);
					tAction.Set(TargetOptions.Result | TargetOptions.CleanHit);
					tAction.Stun = TargetStun;
					cap.Add(tAction);

					// Damage
					var damage = mainDamage;

					// Elementals
					damage *= attacker.CalculateElementalDamageMultiplier(target);

					// More damage with fire arrow
					// XXX: Does this affect the element?
					if (attacker.Temp.FireArrow)
						damage *= FireBonus;

					// Splash modifier
					if (target != mainTarget)
						damage *= (skill.RankData.Var4 / 100f);

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

					// Subtract target def/prot
					SkillHelper.HandleDefenseProtection(target, ref damage);

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

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

					// Natural Shield
					// Ignore delay reduction, as knock downs shouldn't be shortened
					NaturalShield.Handle(attacker, target, ref damage, tAction);

					// Deal with it!
					if (damage > 0)
					{
						target.TakeDamage(tAction.Damage = damage, attacker);
						SkillHelper.HandleInjury(attacker, target, damage);
					}

					// Knock down
					// If target is using a shield and defense, don't KD.
					var targetLeftHand = target.LeftHand;
					if (tAction.SkillId != SkillId.Defense || targetLeftHand == null || !targetLeftHand.IsShield)
					{
						// TODO: We have to calculate knockback distance right
						attacker.Shove(target, KnockBackDistance);
						tAction.Set(TargetOptions.KnockDownFinish);
					}

					// Aggro
					if (target == mainTarget)
						target.Aggro(attacker);

					if (target.IsDead)
					{
						tAction.Set(TargetOptions.Finished);
						if (target == mainTarget)
							aAction.Set(AttackerOptions.KnockBackHit1);
					}
				}
			}
			else
			{
				aAction.Set(AttackerOptions.Missed);
			}

			// Update current weapon
			SkillHelper.UpdateWeapon(attacker, mainTarget, ProficiencyGainType.Ranged, attacker.RightHand);

			// Reduce arrows
			if (attacker.Magazine != null && !ChannelServer.Instance.Conf.World.InfiniteArrows && !attacker.Magazine.HasTag("/unlimited_arrow/"))
				attacker.Inventory.Decrement(attacker.Magazine);

			// Disable fire arrow effect
			if (attacker.Temp.FireArrow)
				Send.Effect(attacker, Effect.FireArrow, false);

			// "Cancels" the skill
			// 800 = old load time? == aAction.Stun? Varies? Doesn't seem to be a stun.
			Send.SkillUse(attacker, skill.Info.Id, 800, 1);

			cap.Handle();

			return CombatSkillResult.Okay;
		}
Пример #10
0
		/// <summary>
		/// Handles skill usage.
		/// </summary>
		/// <param name="attacker"></param>
		/// <param name="skill"></param>
		/// <param name="targetEntityId"></param>
		/// <returns></returns>
		public override CombatSkillResult Use(Creature attacker, Skill skill, long targetEntityId)
		{
			// Check target
			var target = attacker.Region.GetCreature(targetEntityId);
			if (target == null)
				return CombatSkillResult.InvalidTarget;

			// Check range
			var targetPosition = target.GetPosition();
			if (!attacker.GetPosition().InRange(targetPosition, attacker.AttackRangeFor(target)))
				return CombatSkillResult.OutOfRange;

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

			// Counter
			if (Counterattack.Handle(target, attacker))
				return CombatSkillResult.Okay;

			// Prepare combat actions
			var aAction = new AttackerAction(CombatActionType.HardHit, attacker, targetEntityId);
			aAction.Set(AttackerOptions.Result | AttackerOptions.KnockBackHit2);

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

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

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

			// Elementals
			damage *= attacker.CalculateElementalDamageMultiplier(target);

			// Critical Hit
			var critChance = this.GetCritChance(attacker, target, skill);
			CriticalHit.Handle(attacker, critChance, ref damage, tAction);

			// Subtract target def/prot
			SkillHelper.HandleDefenseProtection(target, ref damage);

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

			// Heavy Stander
			HeavyStander.Handle(attacker, target, ref damage, tAction);

			// Apply damage
			if (damage > 0)
			{
				target.TakeDamage(tAction.Damage = damage, attacker);
				SkillHelper.HandleInjury(attacker, target, damage);
			}

			// Aggro
			target.Aggro(attacker);

			if (target.IsDead)
				tAction.Set(TargetOptions.FinishingHit | TargetOptions.Finished);

			// Set Stun/Knockback
			attacker.Stun = aAction.Stun = StunTime;
			target.Stun = tAction.Stun = StunTime;
			target.Stability = Creature.MinStability;

			// Set knockbacked position
			attacker.Shove(target, KnockbackDistance);

			// Response
			Send.SkillUseStun(attacker, skill.Info.Id, AfterUseStun, 1);

			// Update both weapons
			SkillHelper.UpdateWeapon(attacker, target, attacker.RightHand, attacker.LeftHand);

			// Action!
			cap.Handle();

			return CombatSkillResult.Okay;
		}
Пример #11
0
        /// <summary>
        /// Handles usage of the skill.
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="target"></param>
        public void Use(Creature attacker, Creature target)
        {
            // Updating unlock because of the updating lock for pre-renovation
            // Has to be done here because we can't have an updating unlock
            // after the combat action, it resets the stun.
            if (!AuraData.FeaturesDb.IsEnabled("TalentRenovationCloseCombat"))
                attacker.Unlock(Locks.Move, true);

            var skill = attacker.Skills.Get(SkillId.Counterattack);

            var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, target.EntityId);
            aAction.Options |= AttackerOptions.Result | AttackerOptions.KnockBackHit2;

            var tAction = new TargetAction(CombatActionType.CounteredHit2, target, attacker, skill.Info.Id);
            tAction.Options |= TargetOptions.Result | TargetOptions.Smash;

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

            var damage =
                (attacker.GetRndTotalDamage() * (skill.RankData.Var2 / 100f)) +
                (target.GetRndTotalDamage() * (skill.RankData.Var1 / 100f));

            // Elementals
            damage *= attacker.CalculateElementalDamageMultiplier(target);

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

            // Subtract target def/prot
            SkillHelper.HandleDefenseProtection(target, ref damage, true, true);

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

            // Heavy Stander
            HeavyStander.Handle(attacker, target, ref damage, tAction);

            // Deal with it!
            if (damage > 0)
            {
                target.TakeDamage(tAction.Damage = damage, attacker);
                SkillHelper.HandleInjury(attacker, target, damage);
            }

            target.Aggro(attacker);

            if (target.IsDead)
                tAction.Options |= TargetOptions.FinishingKnockDown;

            aAction.Stun = StunTime;
            tAction.Stun = StunTime;

            target.Stability = Creature.MinStability;
            attacker.Shove(target, KnockbackDistance);

            // Update both weapons
            SkillHelper.UpdateWeapon(attacker, target, ProficiencyGainType.Melee, attacker.RightHand, attacker.LeftHand);

            Send.SkillUseStun(attacker, skill.Info.Id, StunTime, 1);

            this.Training(aAction, tAction);

            cap.Handle();
        }
Пример #12
0
		/// <summary>
		/// Uses the skill.
		/// </summary>
		/// <param name="attacker"></param>
		/// <param name="skill"></param>
		/// <param name="targetEntityId"></param>
		/// <returns></returns>
		public CombatSkillResult Use(Creature attacker, Skill skill, long targetEntityId)
		{
			// Get target
			var target = attacker.Region.GetCreature(targetEntityId);
			if (target == null)
				return CombatSkillResult.InvalidTarget;

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

			var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, targetEntityId);
			aAction.Set(AttackerOptions.Result);
			aAction.Stun = AttackerStun;
			cap.Add(aAction);

			// Hit by chance
			var chance = attacker.AimMeter.GetAimChance(target);
			var rnd = RandomProvider.Get();
			if (rnd.NextDouble() * 100 < chance)
			{
				target.StopMove();

				aAction.Set(AttackerOptions.KnockBackHit2);

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

				// TODO: Splash damage

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

				// Elementals
				damage *= attacker.CalculateElementalDamageMultiplier(target);

				// More damage with fire arrow
				// XXX: Does this affect the element?
				if (attacker.Temp.FireArrow)
					damage *= FireBonus;

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

				// Subtract target def/prot
				SkillHelper.HandleDefenseProtection(target, ref damage);

				// Defense
				Defense.Handle(aAction, tAction, ref damage);

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

				// Natural Shield
				// Ignore delay reduction, as knock downs shouldn't be shortened
				NaturalShield.Handle(attacker, target, ref damage, tAction);

				// Deal with it!
				if (damage > 0)
				{
					target.TakeDamage(tAction.Damage = damage, attacker);
					SkillHelper.HandleInjury(attacker, target, damage);
				}

				// Knock down
				// If target is using a shield and defense, don't KD.
				var targetLeftHand = target.LeftHand;
				if (tAction.SkillId != SkillId.Defense || targetLeftHand == null || !targetLeftHand.IsShield)
				{
					// TODO: We have to calculate knockback distance right
					attacker.Shove(target, KnockBackDistance);
					tAction.Set(TargetOptions.KnockDownFinish);
				}

				// Aggro
				target.Aggro(attacker);

				if (target.IsDead)
				{
					aAction.Set(AttackerOptions.KnockBackHit1);
					tAction.Set(TargetOptions.Finished);
				}
			}
			else
			{
				aAction.Set(AttackerOptions.Missed);
			}

			// Reduce arrows
			if (attacker.Magazine != null && !ChannelServer.Instance.Conf.World.InfiniteArrows && !attacker.Magazine.HasTag("/unlimited_arrow/"))
				attacker.Inventory.Decrement(attacker.Magazine);

			// Disable fire arrow effect
			if (attacker.Temp.FireArrow)
				Send.Effect(attacker, Effect.FireArrow, false);

			// "Cancels" the skill
			// 800 = old load time? == aAction.Stun? Varies? Doesn't seem to be a stun.
			Send.SkillUse(attacker, skill.Info.Id, 800, 1);

			cap.Handle();

			return CombatSkillResult.Okay;
		}