/// <summary> /// Returns targetable creatures in given range around position. /// Optionally factors in attack range. /// </summary> /// <param name="position">Reference position.</param> /// <param name="range">Radius around position.</param> /// <param name="options">Options to change the result.</param> /// <returns></returns> 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; }
/// <summary> /// Returns targetable creatures in cone, based on the /// given parameters. /// </summary> /// <param name="position">Pointy end of the cone.</param> /// <param name="direction">Cone's direction as radian.</param> /// <param name="radius">Cone's radius.</param> /// <param name="angle">Cone's angle in degree.</param> /// <param name="options">Options to change the result.</param> /// <returns></returns> public ICollection<Creature> GetTargetableCreaturesInCone(Position position, float direction, float radius, float angle, TargetableOptions options = TargetableOptions.None) { if (radius == 0 || angle == 0) return new Creature[0]; angle = MabiMath.DegreeToRadian((int)angle); var targetable = this.Region.GetCreatures(target => { var targetPos = target.GetPosition(); 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.InCone(position, direction, (int)radius, angle) // Check position && (((options & TargetableOptions.IgnoreWalls) != 0) || !this.Region.Collisions.Any(position, targetPos)) // Check collisions between positions && !target.Conditions.Has(ConditionsA.Invisible); // Check visiblility (GM) }); return targetable; }
/// <summary> /// Returns targetable creatures in given range around creature. /// </summary> /// <param name="range">Radius around position.</param> /// <param name="options">Options to change the result.</param> /// <returns></returns> public ICollection<Creature> GetTargetableCreaturesInRange(int range, TargetableOptions options = TargetableOptions.None) { return this.GetTargetableCreaturesAround(this.GetPosition(), range, options); }
/// <summary> /// Returns targetable creatures in cone, based on the /// given parameters, with direction of cone being based on the /// given positions. /// </summary> /// <param name="position">Pointy end of the cone.</param> /// <param name="targetPosition">Target's position, used as reference for the direction of the cone.</param> /// <param name="radius">Cone's radius.</param> /// <param name="angle">Cone's angle in degree.</param> /// <param name="options">Options to change the result.</param> /// <returns></returns> public ICollection<Creature> GetTargetableCreaturesInCone(Position position, Position targetPosition, float radius, float angle, TargetableOptions options = TargetableOptions.None) { var direction = position.GetDirection(targetPosition); return this.GetTargetableCreaturesInCone(position, direction, radius, angle, options); }