Aura.Channel.World.Entities.Creature.GetTargetableCreaturesAround C# (CSharp) Метод

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

Returns targetable creatures in given range around position. Optionally factors in attack range.
public GetTargetableCreaturesAround ( Position position, int range, TargetableOptions options = TargetableOptions.None ) : ICollection
position Position Reference position.
range int Radius around position.
options TargetableOptions Options to change the result.
Результат ICollection
		public ICollection<Creature> GetTargetableCreaturesAround(Position position, int range, TargetableOptions options = TargetableOptions.None)
		{
			var targetable = this.Region.GetCreatures(target =>
			{
				var targetPos = target.GetPosition();
				var radius = range;
				if ((options & TargetableOptions.AddAttackRange) != 0)
				{
					// This is unofficial, the target's "hitbox" should be
					// factored in, but the total attack range is too much.
					// Using 50% for now until we know more.
					radius += this.AttackRangeFor(target) / 2;
				}

				return target != this // Exclude creature
					&& this.CanTarget(target) // Check targetability
					&& ((!this.Has(CreatureStates.Npc) || !target.Has(CreatureStates.Npc)) || this.Target == target) // Allow NPC on NPC only if it's the creature's target
					&& targetPos.InRange(position, radius) // Check range
					&& (((options & TargetableOptions.IgnoreWalls) != 0) || !this.Region.Collisions.Any(position, targetPos)) // Check collisions between positions
					&& !target.Conditions.Has(ConditionsA.Invisible); // Check visiblility (GM)
			});

			return targetable;
		}

Usage Example

Пример #1
0
		/// <summary>
		/// Bolt specific use code.
		/// </summary>
		/// <param name="attacker"></param>
		/// <param name="skill"></param>
		/// <param name="target"></param>
		protected override void UseSkillOnTarget(Creature attacker, Skill skill, Creature mainTarget)
		{
			// Create actions
			var aAction = new AttackerAction(CombatActionType.RangeHit, attacker, mainTarget.EntityId);
			aAction.Set(AttackerOptions.Result);

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

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

			var inSplashRange = attacker.GetTargetableCreaturesAround(mainTarget.GetPosition(), SplashRange);
			targets.AddRange(inSplashRange.Where(a => a != mainTarget));

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

			var max = Math.Min(targets.Count, skill.Stacks);
			for (int i = 0; i < max; ++i)
			{
				var target = targets[i];
				var targetDamage = damage;

				target.StopMove();

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

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

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

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

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

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

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

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

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

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

						target.Stability -= stabilityReduction;

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

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

				cap.Add(tAction);
			}

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

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

			skill.Stacks = 0;

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

			cap.Handle();
		}