/// <summary>
 /// The number of actors clustered around this unit (TrashPackClusterRadius)
 /// </summary>
 internal static int GetUnitsNearby(TrinityUnit o)
 {
     return (from u in CacheManager.Monsters
             where u.ACDGuid != o.ACDGuid && MathUtil.PositionIsInCircle(u.Position, o.Position, Trinity.Settings.Combat.Misc.TrashPackClusterRadius/2)
             select u).Count();
 }
        /// <summary>
        /// Map affix GameBalanceIds to enum, excluding Bad Axe Data / -1
        /// </summary>
        /// <param name="trinityUnit"></param>
        /// <returns></returns>
        private static HashSet<TrinityMonsterAffix> GetMonsterAffixes(TrinityUnit trinityUnit)
        {
            var affixes = new HashSet<TrinityMonsterAffix>();

            if (!trinityUnit.IsBossOrEliteRareUnique)
                return affixes;
            
            var sourceAffixes = trinityUnit.GetSourceProperty(x => x.Affixes).ToList();
            
            if (!sourceAffixes.Any())
                return affixes;

            foreach (var sourceAffix in sourceAffixes)
            {
                if (sourceAffix != -1)
                    affixes.Add((TrinityMonsterAffix)sourceAffix);
            }

            return affixes;
        }
        /// <summary>
        /// Get attack distance specific to a unit
        /// </summary>
        private static double GetKillRange(TrinityUnit o)
        {
            var killRange = (double)Math.Max(Trinity.Settings.Combat.Misc.EliteRange, Trinity.Settings.Combat.Misc.NonEliteRange);

            // Always within kill range if in the NoCheckKillRange list!
            if (DataDictionary.NoCheckKillRange.Contains(o.ActorSNO))
                return o.RadiusDistance + 100f;

            // Bosses, always kill
            if (o.IsBoss)
                return o.RadiusDistance + 100f;

            // Elitey type mobs and things
            if (o.IsEliteRareUnique)
                killRange = Trinity.Settings.Combat.Misc.EliteRange;

            if (!TownRun.IsTryingToTownPortal())
                return killRange;

            // Safety for TownRuns
            if (killRange <= V.F("Cache.TownPortal.KillRange")) 
                killRange = V.F("Cache.TownPortal.KillRange");

            return killRange;
        }
 /// <summary>
 /// The number of actors between you and this actor
 /// </summary>
 internal static int GetUnitsInFront(TrinityUnit o)
 {
     return (from u in CacheManager.Units
             where u.ACDGuid != o.ACDGuid && o.IsAlive && MathUtil.IntersectsPath(u.Position, u.Radius, CacheManager.Me.Position, o.Position)
         select u).Count();
 }
 /// <summary>
 /// If unit player is standing in avoidance
 /// </summary>
 internal static bool GetIsStandingInAvoidance(TrinityUnit o)
 {
     return CacheManager.Avoidances.Any(a => a.Position.Distance2D(o.Position) <= a.Radius) || CacheData.TimeBoundAvoidance.Any(a => a.Position.Distance2D(o.Position) <= a.Radius);
 }
 /// <summary>
 /// If unit is attackable factoring overrides
 /// </summary>
 internal static bool GetIsAttackable(TrinityUnit o)
 {
     return o.IsHostile && (o.GetUnitProperty(x => x.IsAttackable) || o.InternalName.StartsWith("Diablo_shadowClone"));
 }
 public static void LogComparison(TrinityUnit u)
 {
     Logger.Log("{8} Speed={0}/{1} Rotation={2}/{3} RotationDegrees={4}/{5} Heading={6}/{7}",
         u.Movement.GetMovementSpeed(u), u.DiaUnit.Movement.SpeedXY,
         u.Movement.GetHeadingRadians(), u.DiaUnit.Movement.Rotation,
         u.Movement.GetHeadingDegrees(), u.DiaUnit.Movement.RotationDegrees,
         u.Movement.GetHeading(), MathUtil.GetHeading(u.DiaUnit.Movement.RotationDegrees),
         u.Name);            
 }