Aura.Channel.Skills.Combat.CombatMastery.Use C# (CSharp) Метод

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

Handles attack.
public Use ( Creature attacker, Skill skill, long targetEntityId ) : CombatSkillResult
attacker Aura.Channel.World.Entities.Creature The creature attacking.
skill Skill The skill being used.
targetEntityId long The entity id of the target.
Результат CombatSkillResult
		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);

					// Conditions
					SkillHelper.HandleConditions(attacker, 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;
						}

						// Reduce attacker's knockback stun in new combat, to allow
						// movement after sooner.
						// It's unknown when exactly this was added, but older EU logs
						// don't have this packet, so we'll assume it was part of the the
						// new combat, which's purpose was to be faster.
						// Sending the packet appears to reset the movement lock, and
						// officials seem to send this about 1s after the attack, for
						// an effective 1s movement lock after an attack.
						// If it's send for non-knockback hits, it can add a delay,
						// maybe increasing the time of the lock, like for dual-wielding.
						if (AuraData.FeaturesDb.IsEnabled("CombatSystemRenewal"))
						{
							if (tAction.IsKnockBack)
							{
								Task.Delay(1000).ContinueWith(_ =>
									Send.CharacterLockUpdate(attacker, 18, 1500));
							}
						}
					}
				}

				// Handle
				cap.Handle();
			}

			return CombatSkillResult.Okay;
		}

Usage Example

Пример #1
0
        /// <summary>
        /// Handles skill usage.
        /// </summary>
        /// <param name="creature"></param>
        /// <param name="skill"></param>
        /// <param name="packet"></param>
        public void Use(Creature creature, Skill skill, Packet packet)
        {
            var targetEntityId = packet.GetLong();

            // Similar to WM there is a case where these aren't sent.
            // Apparently this can happen if you activate the skill while
            // targetting an enemy.
            var unk1 = (packet.Peek() != PacketElementType.None ? packet.GetInt() : 0);
            var unk2 = (packet.Peek() != PacketElementType.None ? packet.GetInt() : 0);

            if (_cm == null)
            {
                _cm = ChannelServer.Instance.SkillManager.GetHandler <CombatMastery>(SkillId.CombatMastery);
            }

            // TODO: Check duration

            var attackResult = false;

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

            if (target != null && !creature.IsStunned && creature.CanTarget(target))
            {
                var pos       = creature.GetPosition();
                var targetPos = target.GetPosition();
                var inRange   = pos.InRange(targetPos, creature.AttackRangeFor(target));

                if (!inRange)
                {
                    var telePos = pos.GetRelative(targetPos, -creature.AttackRangeFor(target) + 100);

                    // Check teleport distance
                    if (pos.GetDistance(telePos) > skill.RankData.Var3 + 100)
                    {
                        Send.Notice(creature, "Out of range");
                    }
                    else
                    {
                        Send.Effect(creature, Effect.SilentMoveTeleport, targetEntityId, (byte)0);

                        creature.SetPosition(telePos.X, telePos.Y);
                        Send.SkillTeleport(creature, telePos.X, telePos.Y);

                        inRange = true;
                    }
                }

                if (inRange)
                {
                    attackResult = (_cm.Use(creature, skill, targetEntityId) == CombatSkillResult.Okay);
                }
            }

            Send.CombatAttackR(creature, attackResult);

            Send.SkillUse(creature, skill.Info.Id, targetEntityId, unk1, unk2);
        }
All Usage Examples Of Aura.Channel.Skills.Combat.CombatMastery::Use