/// <summary>
 /// TrinityNode wraps a TrinityObject to add a canvas plot location.
 /// </summary>
 public RadarObject(TrinityObject obj, CanvasData canvasData)
 {
     Actor = obj;
     obj.PropertyChanged += ItemOnPropertyChanged;
     Morph.CanvasData = canvasData;
     Update();
 }
        /// <summary>
        /// Weighting for Health Wells
        /// </summary>
        public static IEnumerable<Weight> GetWeight(TrinityObject cacheObject)
        {
            var weightFactors = new List<Weight>();
            var gizmo = cacheObject as TrinityGizmo;
            if (gizmo == null)
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.TypeMismatch));
                return weightFactors;
            }

            if (!CacheManager.EliteRareUniqueBoss.Any())
            {
                if (!Trinity.Settings.WorldObject.UseShrine)
                {
                    weightFactors.Add(new Weight(1, WeightMethod.Set, WeightReason.DisabledInSettings));
                    return weightFactors;
                }

                weightFactors.TryAddWeight(cacheObject, WeightReason.MonsterInLoS);
                weightFactors.TryAddWeight(cacheObject, WeightReason.AvoidanceInLoS);

                if (cacheObject.IsBlocking)
                {
                    weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.NavBlocking));
                    return weightFactors;
                }
            }

            // As a percentage of health with typical maximum weight
            cacheObject.Weight = WeightManager.MaxWeight * (1 - CacheManager.Me.CurrentHealthPct);

            return weightFactors;
        }
Example #3
0
        /// <summary>
        /// Weighting for Hotspots
        /// </summary>
        public static IEnumerable<Weight> GetWeight(TrinityObject cacheObject)
        {
            var weightFactors = new List<Weight>();

            //// If there's monsters in our face, ignore
            //if (CombatContext.PrioritizeCloseRangeUnits)
            //{
            //    weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.MonstersNearPlayer));
            //    return weightFactors;
            //}

            //// if we started cache refresh with a target already
            //if (Trinity.LastTargetRactorGUID != -1)
            //{
            //    weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.HasTarget));
            //    return weightFactors;
            //}

            //// If it's very close, ignore
            //if (cacheObject.Distance <= V.F("Cache.HotSpot.MinDistance"))
            //{
            //    weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.AlreadyCloseEnough));
            //    return weightFactors;
            //}

            //// Avoidance near position
            //if (!CacheData.TimeBoundAvoidance.Any(aoe => aoe.Position.Distance2D(cacheObject.Position) <= aoe.Radius))
            //{
            //    float maxDist = V.F("Cache.HotSpot.MaxDistance");
            //    weightFactors.Add(new Weight((maxDist - cacheObject.Distance) / maxDist * 50000d, WeightMethod.Set, WeightReason.AvoidanceAtPosition));
            //}

            return weightFactors;
        }
Example #4
0
        /// <summary>
        /// Weighting for Shrines
        /// </summary>
        public static IEnumerable<Weight> GetPreWeightChecks(TrinityObject cacheObject)
        {
            var weightFactors = new List<Weight>();

            if (cacheObject.IsOwnedByPlayer)
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.OwnedByPlayer));

            return weightFactors;
        }
        /// <summary>
        /// This is separated from GetMovementSpeed() to prevent parrallel tasks failing on changed collection.
        /// </summary>
        /// <param name="o"></param>
        public void RecordMovement(TrinityObject o)
        {
            if (o.ActorType != ActorType.Monster && o.ActorType != ActorType.Projectile && o.ActorType != ActorType.Player)
            {
                if (o.AvoidanceType != AvoidanceType.Arcane)
                    return;
            }

            if (!_speedSensors.Any() || o.AvoidanceType == AvoidanceType.Arcane)
            {
                // For things that don't move, like units standing in town we can't calculate which way they're facing.
                _startHeadingRadians = o.Object.Movement.Rotation;                
            }

            if (DateTime.UtcNow.Subtract(_lastRecordedPositionTime).TotalMilliseconds >= (int)UpdateSpeed.Ultra)
            {
                if (!_speedSensors.Any())
                {                    
                    _speedSensors.Add(new SpeedSensor
                    {
                        Location = o.Position,
                        TimeSinceLastMove = new TimeSpan(0),
                        Distance = 0f,
                        WorldID = CacheManager.WorldDynamicId
                    });
                    _lastRecordedPositionTime = DateTime.UtcNow;
                }
                else
                {
                    var lastSensor = _speedSensors.Last();
                    var distanceTravelled = Vector3.Distance(o.Position, lastSensor.Location);
                    if (distanceTravelled > 1f)
                    {
                        _speedSensors.Add(new SpeedSensor
                        {
                            Location = o.Position,
                            TimeSinceLastMove = new TimeSpan(DateTime.UtcNow.Subtract(lastSensor.TimeSinceLastMove).Ticks),
                            Distance = distanceTravelled,
                            WorldID = CacheManager.WorldDynamicId
                        });

                        _lastRecordedPositionTime = DateTime.UtcNow;
                        HasMoved = true;
                    }
                }
            }

            // Check if we have enough recorded positions, remove one if so
            while (_speedSensors.Count > MaxSpeedSensors - 1)
            {
                _speedSensors.RemoveAt(0);
            }            
        }
        /// <summary>
        /// Weighting for Barricades
        /// </summary>
        public static IEnumerable<Weight> GetBarricadeWeight(TrinityObject cacheObject)
        {
            var weightFactors = new List<Weight>();

            // rrrix added this as a single "weight" source based on the DestructableRange.
            // Calculate the weight based on distance, where a distance = 1 is 5000, 90 = 0
            weightFactors.Add(new Weight((90f - cacheObject.RadiusDistance) / 90f * 5000f, WeightMethod.Set, WeightReason.Start));

            weightFactors.TryAddWeight(cacheObject, WeightReason.PreviousTarget);
            weightFactors.TryAddWeight(cacheObject, WeightReason.CloseProximity, 30000);

            return weightFactors;
        }
        /// <summary>
        /// Weighting for Gold
        /// </summary>
        public static IEnumerable<Weight> GetGoldWeight(TrinityObject cacheObject)
        {
            var weightFactors = new List<Weight>();
            var item = cacheObject as TrinityItem;
            if (item == null)
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.TypeMismatch));
                return weightFactors;
            }

            if (!Trinity.Settings.Loot.Pickup.PickupGold)
            {
                 weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.DisabledInSettings));
                return weightFactors;
            }

            if (item.Gold < Trinity.Settings.Loot.Pickup.MinimumGoldStack)
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.MinGoldStack, item.Gold, Trinity.Settings.Loot.Pickup.MinimumGoldStack));
                return weightFactors;
            }

            if (weightFactors.TryAddWeight(cacheObject, WeightReason.DisableForQuest))
                return weightFactors;

            if (Trinity.Settings.Loot.Pickup.IgnoreGoldNearElites && CacheManager.Units.Any(m => m.IsBossOrEliteRareUnique))
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.BossOrEliteNearby));
                return weightFactors;
            }

            if (Trinity.Settings.Loot.Pickup.IgnoreGoldInAoE && CacheManager.Avoidances.Any(aoe => item.Position.Distance2D(aoe.Position) <= aoe.Radius))
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.InAOE));
            }

            weightFactors.Add(new Weight(Math.Max((175 - item.Distance) / 175 * WeightManager.MaxWeight, 100d), WeightMethod.Set, WeightReason.Start));

            weightFactors.TryAddWeight(cacheObject, WeightReason.PreviousTarget, 800);
            weightFactors.TryAddWeight(cacheObject, WeightReason.NoCombatLooting);
            weightFactors.TryAddWeight(cacheObject, WeightReason.MonsterInLoS);
            weightFactors.TryAddWeight(cacheObject, WeightReason.AvoidanceInLoS);

            return weightFactors;
        }
        /// <summary>
        /// Weighting for Interactables
        /// </summary>
        public static IEnumerable<Weight> GetWeight(TrinityObject cacheObject)
        {
            var weightFactors = new List<Weight>();

            // Campaign A5 Quest "Lost Treasure of the Nephalem" - have to interact with nephalem switches first... 
            // Quest: x1_Adria, Id: 257120, Step: 108 - disable all looting, pickup, and objects
            if (CacheManager.Me.WorldType != Act.OpenWorld && CacheManager.Me.CurrentQuestSNO == 257120 && CacheManager.Me.CurrentQuestStep == 108)
            {
                weightFactors.Add(new Weight(WeightManager.MaxWeight / 3, WeightMethod.Set, WeightReason.PrioritizeForQuest));
                return weightFactors;
            }

            // Need to Prioritize, forget it!
            if (CombatContext.PrioritizeCloseRangeUnits)
                return weightFactors;

            // nearby monsters attacking us - don't try to use headtone
            if (cacheObject.Object is DiaGizmo && cacheObject.GizmoType == GizmoType.Headstone &&
                CacheManager.Units.Any(u => u.RadiusDistance < 25f))
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.MonstersNearPlayer));
                return weightFactors;
            }

            if (DataDictionary.HighPriorityInteractables.Contains(cacheObject.ActorSNO) && cacheObject.RadiusDistance <= 30f)
            {
                weightFactors.Add(new Weight(WeightManager.MaxWeight, WeightMethod.Set, WeightReason.HighPriorityInteractable));
                return weightFactors;
            }

            // Weight Interactable Specials
            weightFactors.Add(new Weight((300d - cacheObject.Distance) / 300d * 1000d, WeightMethod.Set, WeightReason.Start));

            weightFactors.TryAddWeight(cacheObject, WeightReason.CloseProximity);

            var unit = cacheObject as TrinityUnit;
            if (unit != null && unit.IsQuestMonster)
                weightFactors.Add(new Weight(3000, WeightMethod.Add, WeightReason.QuestObjective));

            weightFactors.TryAddWeight(cacheObject, WeightReason.PreviousTarget);
            weightFactors.TryAddWeight(cacheObject, WeightReason.MonsterInLoS);
            weightFactors.TryAddWeight(cacheObject, WeightReason.AvoidanceInLoS);

            return weightFactors;
        }
Example #9
0
        /// <summary>
        /// Weighting for Doors
        /// </summary>
        public static IEnumerable<Weight> GetWeight(TrinityObject cacheObject)
        {
            var weightFactors = new List<Weight>();
            var gizmo = cacheObject as TrinityGizmo;
            if (gizmo == null)
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.TypeMismatch));
                return weightFactors;
            }

            if (weightFactors.TryAddWeight(cacheObject, WeightReason.MonsterInLoS))
                return weightFactors;

            weightFactors.TryAddWeight(cacheObject, WeightReason.UnitsBehind, 15000);
            weightFactors.TryAddWeight(cacheObject, WeightReason.PreviousTarget);
            weightFactors.TryAddWeight(cacheObject, WeightReason.CloseProximity, WeightManager.MaxWeight);

            return weightFactors;
        }
Example #10
0
        /// <summary>
        /// Weighting for Shrines
        /// </summary>
        public static IEnumerable<Weight> GetWeight(TrinityObject cacheObject)
        {
            var weightFactors = new List<Weight>();
            var gizmo = cacheObject as TrinityGizmo;
            if (gizmo == null)
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.TypeMismatch));
                return weightFactors;
            }

            if (cacheObject.TrinityType == TrinityObjectType.CursedShrine)
            {
                weightFactors.Add(new Weight(5000, WeightMethod.Add, WeightReason.Event));
                return weightFactors;
            }

            if (weightFactors.TryAddWeight(cacheObject, WeightReason.DisableForQuest))
                return weightFactors;

            var maxRange = CacheManager.Me.IsInRift ? 300f : 75f;
            var maxWeight = CacheManager.Me.IsInRift ? WeightManager.MaxWeight * 0.75d : 100d;
            var priorityShrines = Trinity.Settings.WorldObject.HiPriorityShrines;
            var startingWeight = priorityShrines ? WeightManager.MaxWeight * 0.75 : Math.Max(((maxRange - cacheObject.RadiusDistance) / maxRange * 15000d), 100d);

            weightFactors.Add(new Weight(startingWeight, WeightMethod.Set, WeightReason.Start));

            // Very close shrines get a weight increase
            if (cacheObject.Distance <= 30f)
                weightFactors.Add(new Weight(10000, WeightMethod.Add, WeightReason.CloseProximity));

            // Disable safety checks for Rift Pylons
            if (!CacheManager.Me.IsInRift)
            {
                weightFactors.TryAddWeight(cacheObject, WeightReason.PreviousTarget);
                weightFactors.TryAddWeight(cacheObject, WeightReason.MonsterInLoS);
                weightFactors.TryAddWeight(cacheObject, WeightReason.AvoidanceInLoS);
                weightFactors.TryAddWeight(cacheObject, WeightReason.DangerClose);
            }

            return weightFactors;
        }
Example #11
0
        /// <summary>
        /// Weighting for Containers
        /// </summary>
        public static IEnumerable<Weight> GetWeight(TrinityObject cacheObject)
        {
            var weightFactors = new List<Weight>();

            if (cacheObject == null)
                return weightFactors.Return(WeightReason.NullObject);

            if (cacheObject.ActorType == ActorType.Gizmo && cacheObject.DiaGizmo == null)
                return weightFactors.Return(WeightReason.TypeMismatch);

            if (weightFactors.TryAddWeight(cacheObject, WeightReason.CloseRangePriority))
                return weightFactors;

            if (weightFactors.TryAddWeight(cacheObject, WeightReason.NavBlocking))
                return weightFactors;

            // Dont open any containers while damage buff is active
            if (Legendary.HarringtonWaistguard.IsBuffActive)
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.HarringtonBuff));
                return weightFactors;
            }

            // Weight Containers
            float maxOpenRange = cacheObject.InternalName.ToLower().Contains("chest_rare") ? 250 : Trinity.Settings.WorldObject.ContainerOpenRange;
            weightFactors.Add(new Weight((maxOpenRange - cacheObject.Distance) / maxOpenRange * 100d, WeightMethod.Set, WeightReason.Start));

            weightFactors.TryAddWeight(cacheObject, WeightReason.CloseProximity, 600);

            // Open container for the damage buff
            if (Legendary.HarringtonWaistguard.IsEquipped && !Legendary.HarringtonWaistguard.IsBuffActive &&
                ZetaDia.Me.IsInCombat && cacheObject.Distance < 80f || CombatContext.ShouldPrioritizeContainers)
                weightFactors.Add(new Weight(20000, WeightMethod.Add, WeightReason.Start));

            weightFactors.TryAddWeight(cacheObject, WeightReason.PreviousTarget);
            weightFactors.TryAddWeight(cacheObject, WeightReason.MonsterInLoS, 0.5, WeightMethod.Multiply);
            weightFactors.TryAddWeight(cacheObject, WeightReason.AvoidanceInLoS);

            return weightFactors;
        }
        /// <summary>
        /// Weighting for Destructibles
        /// </summary>
        public static IEnumerable<Weight> GetDestructibleWeight(TrinityObject cacheObject)
        {
            var weightFactors = new List<Weight>();

            if (DataDictionary.ForceDestructibles.Contains(cacheObject.ActorSNO))
            {
                weightFactors.Add(new Weight(100, WeightMethod.Add, WeightReason.SettingForceDestructibles));
                return weightFactors;
            }

            // Not Stuck, skip!
            if (Trinity.Settings.WorldObject.DestructibleOption == DestructibleIgnoreOption.OnlyIfStuck && cacheObject.RadiusDistance > 0 &&
                (DateTime.UtcNow.Subtract(PlayerMover.LastGeneratedStuckPosition).TotalSeconds > 3))
            {
                return weightFactors;
            }

            // rrrix added this as a single "weight" source based on the DestructableRange.
            // Calculate the weight based on distance, where a distance = 1 is 5000, 90 = 0
            weightFactors.Add(new Weight((90f - cacheObject.RadiusDistance) / 90f * 1000f, WeightMethod.Set, WeightReason.Start));

            weightFactors.TryAddWeight(cacheObject, WeightReason.PreviousTarget);
            weightFactors.TryAddWeight(cacheObject, WeightReason.CloseProximity, 1500);
            weightFactors.TryAddWeight(cacheObject, WeightReason.MonsterInLoS, 0.5, WeightMethod.Multiply);
            weightFactors.TryAddWeight(cacheObject, WeightReason.AvoidanceInLoS);

            // Are we prioritizing close-range stuff atm? If so limit it at a value 3k lower than monster close-range priority
            if (CombatContext.PrioritizeCloseRangeUnits)
                weightFactors.Add(new Weight((15f - cacheObject.Distance) / 15f * 19200d, WeightMethod.Set, WeightReason.CloseRangePriority));

            weightFactors.TryAddWeight(cacheObject, WeightReason.TouchProximity, 40000);

            // Fix for WhimsyShire Pinata
            if (DataDictionary.ResplendentChestIds.Contains(cacheObject.ActorSNO))
                weightFactors.Add(new Weight(100 + cacheObject.RadiusDistance, WeightMethod.Set, WeightReason.DestructableChest));

            return weightFactors;
        }
Example #13
0
 public static TimeSpan GetAvoidanceSpawnerDuration(TrinityObject trinityObject)
 {
     TimeSpan aoeExpiration;
     return DataDictionary.AvoidanceSpawnerDuration.TryGetValue(trinityObject.ActorSNO, out aoeExpiration) ? aoeExpiration : TimeSpan.Zero;
 }
Example #14
0
        /// <summary>
        /// The radius distance, checking for overrides in DataDictionary.
        /// </summary>
        public static float GetRadiusDistance(TrinityObject o)
        {
            float customRadiusDistance;
            if (o.TrinityType == TrinityObjectType.Destructible && DataDictionary.DestructableObjectRadius.TryGetValue(o.ActorSNO, out customRadiusDistance))
                return customRadiusDistance;

            return Math.Max(o.Distance - o.Radius - CacheManager.Me.Radius, 0f);
        }
Example #15
0
        /// <summary>
        /// Weighting for Progression Globes (grift thingies)
        /// </summary>
        public static IEnumerable<Weight> GetProgressionGlobeWeight(TrinityObject cacheObject)
        {
            var weightFactors = new List<Weight>();
            var item = cacheObject as TrinityItem;
            if (item == null)
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.TypeMismatch));
                return weightFactors;
            }

            if (!TownRun.IsTryingToTownPortal())
            {
                weightFactors.Add(new Weight((90f - cacheObject.RadiusDistance) / 90f * WeightManager.MaxWeight, WeightMethod.Set, WeightReason.Start));
            }

            weightFactors.TryAddWeight(cacheObject, WeightReason.CloseProximity);
            weightFactors.TryAddWeight(cacheObject, WeightReason.MonsterInLoS);
            weightFactors.TryAddWeight(cacheObject, WeightReason.AvoidanceInLoS);

            return weightFactors;
        }
        /// <summary>
        /// Weighting for Items
        /// </summary>
        public static IEnumerable<Weight> GetItemWeight(TrinityObject cacheObject)
        {
            var weightFactors = new List<Weight>();
            var item = cacheObject as TrinityItem;
            if (item == null)
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.TypeMismatch));
                return weightFactors;
            }

            if (weightFactors.TryAddWeight(item, WeightReason.DisableForQuest))
                return weightFactors;

            if (CacheManager.Me.InTieredLootRun && CacheManager.Units.Any(m => m.IsBoss))
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.BossNearby));
                return weightFactors;
            }

            // Default Weight
            weightFactors.Add(new Weight(Math.Max((175 - item.Distance) / 175 * WeightManager.MaxWeight, 100d), WeightMethod.Set, WeightReason.Start));

            // Don't pickup items if we're doing a TownRun
            if (TrinityItemManager.FindValidBackpackLocation(item.IsTwoSquareItem) == new Vector2(-1, -1))
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.TownRun));
                return weightFactors;
            }

            // Give legendaries max weight, always
            if (item.ItemQuality >= ItemQuality.Legendary)
            {
                weightFactors.Add(new Weight(WeightManager.MaxWeight, WeightMethod.Set, WeightReason.IsLegendary));
                return weightFactors;
            }

            // ignore non-legendaries and gold near elites if we're ignoring elites; not sure how we should safely determine this distance
            if (item.ItemQuality < ItemQuality.Legendary && CombatBase.IgnoringElites && CacheManager.Units.Any(u => u.IsUnit && u.IsEliteRareUnique &&
                    u.Position.Distance2D(item.Position) <= V.F("Weight.Items.IgnoreNonLegendaryNearEliteDistance")))
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.IgnoreElites));
                return weightFactors;
            }

            // Ignore Legendaries in AoE
            if (Trinity.Settings.Loot.Pickup.IgnoreLegendaryInAoE && item.ItemQuality >= ItemQuality.Legendary &&
                CacheManager.Avoidances.Any(aoe => cacheObject.Position.Distance2D(aoe.Position) <= aoe.Radius))
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.InAOE));
                return weightFactors;
            }

            // Ignore Non-Legendaries in AoE
            if (Trinity.Settings.Loot.Pickup.IgnoreNonLegendaryInAoE && item.ItemQuality < ItemQuality.Legendary &&
                CacheManager.Avoidances.Any(aoe => cacheObject.Position.Distance2D(aoe.Position) <= aoe.Radius))
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.InAOE));
                return weightFactors;
            }

            // Ignore Legendaries near Elites
            if (Trinity.Settings.Loot.Pickup.IgnoreLegendaryNearElites && item.ItemQuality >= ItemQuality.Legendary &&
                CacheManager.Units.Any(u => u.IsEliteRareUnique && u.Position.Distance2D(cacheObject.Position) <= V.F("Weight.Items.IgnoreLegendaryNearEliteDistance")))
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.IgnoreNearElites));
                return weightFactors;
            }
            // Ignore Non-Legendaries near Elites
            if (Trinity.Settings.Loot.Pickup.IgnoreNonLegendaryNearElites && item.ItemQuality < ItemQuality.Legendary &&
                CacheManager.Units.Any(u => u.IsEliteRareUnique && u.Position.Distance2D(cacheObject.Position) <= V.F("Weight.Items.IgnoreNonLegendaryNearEliteDistance")))
            {
                weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.IgnoreNearElites));
                return weightFactors;
            }

            weightFactors.TryAddWeight(item, WeightReason.CloseProximity);
            weightFactors.TryAddWeight(item, WeightReason.PreviousTarget, 800);

            if (CacheManager.Me.ActorClass == ActorClass.Monk && Trinity.Hotbar.Contains(SNOPower.Monk_TempestRush) && Trinity.TimeSinceUse(SNOPower.Monk_TempestRush) < 1000 && item.ItemQuality < ItemQuality.Legendary)
            {
                weightFactors.Add(new Weight(500, WeightMethod.Set, WeightReason.MonkTR));
            }

            if (item.ItemQuality < ItemQuality.Legendary)
            {
                weightFactors.TryAddWeight(item, WeightReason.AvoidanceInLoS);
                weightFactors.TryAddWeight(item, WeightReason.MonsterInLoS);
                weightFactors.TryAddWeight(item, WeightReason.NoCombatLooting);
            }

            return weightFactors;
        }
Example #17
0
        /// <summary>
        /// Weighting for Health Globes
        /// </summary>
        public static IEnumerable<Weight> GetHealthGlobeWeight(TrinityObject cacheObject)
        {
            var weightFactors = new List<Weight>();
            //var item = cacheObject as TrinityItem;
            //if (item == null)
            //{
            //    weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.InvalidType));
            //    return weightFactors;
            //}

            //var highPrioritySetting = Trinity.Settings.Combat.Misc.HiPriorityHG;

            //// Can't be reached.
            //if (cacheObject.IsBlocking)
            //{
            //    weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.NavBlocking));
            //    return weightFactors;
            //}

            //if (!Trinity.Settings.Combat.Misc.CollectHealthGlobe)
            //{
            //    weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.DisabledInSettings));
            //}

            //// WD's logic with Gruesome Feast passive,
            //// mostly for intelligence stacks, 10% per globe
            //// 1200 by default
            //bool wdGruesomeFeast =
            //    CacheManager.Me.ActorClass == ActorClass.Witchdoctor &&
            //    CacheManager.Me.CurrentPrimaryResource <= V.F("WitchDoctor.ManaForHealthGlobes") &&
            //    CacheData.Hotbar.PassiveSkills.Contains(SNOPower.Witchdoctor_Passive_GruesomeFeast);

            //if (wdGruesomeFeast)
            //    weightFactors.Add(new Weight(10000, WeightMethod.Add, WeightReason.GruesomeFeast));


            //// DH's logic with Blood Vengeance passive
            //// gain amount - 30 hatred per globe
            //// 100 by default
            //bool dhBloodVengeance =
            //    CacheManager.Me.ActorClass == ActorClass.DemonHunter &&
            //    CacheManager.Me.CurrentPrimaryResource <= V.F("DemonHunter.HatredForHealthGlobes") &&
            //    CacheData.Hotbar.PassiveSkills.Contains(SNOPower.DemonHunter_Passive_Vengeance);

            //if (dhBloodVengeance)
            //    weightFactors.Add(new Weight(10000, WeightMethod.Add, WeightReason.BloodVengeance));

            //// Health is High - Non-Emergency
            //if (!dhBloodVengeance && !wdGruesomeFeast && (CacheManager.Me.CurrentHealthPct > CombatBase.EmergencyHealthGlobeLimit))
            //{
            //    // If we're giving high priority to health globes, give it higher weight and check for resource level
            //    if (Trinity.Settings.Combat.Misc.HiPriorityHG)
            //    {
            //        weightFactors.Add(new Weight(0.9 * WeightManager.MaxWeight, WeightMethod.Set, WeightReason.HighPrioritySetting));
            //    }

            //    // Added weight for lowest health of party member
            //    var minPartyHealth = (CacheManager.Players.Any(p => !p.IsMe)) ? CacheManager.Players.Where(p => !p.IsMe).Min(p => p.HitpointsCurrentPct) : 1d;
            //    if (minPartyHealth > 0d && minPartyHealth < V.D("Weight.Globe.MinPartyHealthPct"))
            //        weightFactors.Add(new Weight((1d - minPartyHealth) * 5000d, WeightMethod.Add, WeightReason.LowHealthPartyMember));
            //}
            //else
            //{
            //    // Ok we have globes enabled, and our health is low
            //    if (highPrioritySetting)
            //    {
            //        weightFactors.Add(new Weight(WeightManager.MaxWeight, WeightMethod.Set, WeightReason.HighPrioritySetting));
            //    }
            //    else
            //    {
            //        weightFactors.Add(new Weight((90f - cacheObject.RadiusDistance) / 90f * 17000d, WeightMethod.Set, WeightReason.HealthEmergency));
            //    }

            //    // Point-blank items get a weight increase
            //    weightFactors.TryAddWeight(cacheObject, WeightReason.CloseProximity, 3000);

            //    // Close items get a weight increase
            //    if (cacheObject.Distance <= 60f)
            //        weightFactors.Add(new Weight(1500, WeightMethod.Add, WeightReason.MediumProximity));

            //    // Primary resource is low and we're wearing Reapers Wraps
            //    if (CacheManager.Me.IsInCombat && CacheManager.Me.PrimaryResourcePct < 0.3 && Legendary.ReapersWraps.IsEquipped && (CacheManager.Monsters.Count(u => u.Distance <= 40f) >= 5 || CacheManager.Monsters.Any(u => u.IsElite && u.Distance <= 40f)))
            //        weightFactors.Add(new Weight(3000, WeightMethod.Add, WeightReason.ReapersWraps));

            //    // Was already a target and is still viable, give it some free extra weight, to help stop flip-flopping between two targets
            //    if (cacheObject.RActorGuid == Trinity.LastTargetRactorGUID && cacheObject.Distance <= 25f)
            //        weightFactors.Add(new Weight(800, WeightMethod.Add, WeightReason.PreviousTarget));
            //}

            //if (!highPrioritySetting)
            //{
            //    // If there's a monster in the path-line to the item, reduce the weight by 15% for each
            //    foreach (var obstacle in CacheManager.Units.Where(cp => MathUtil.IntersectsPath(cp.Position, cp.Radius, CacheManager.Me.Position, cacheObject.Position)))
            //    {
            //        if (Trinity.Settings.Combat.Misc.HiPriorityHG)
            //            weightFactors.Add(new Weight(0.85, WeightMethod.Multiply, WeightReason.MonsterInLoS));
            //    }

            //    // See if there's any AOE avoidance in that spot, if so reduce the weight by 10%
            //    if (cacheObject.Distance > 10f)
            //        weightFactors.Add(new Weight(0.90, WeightMethod.Multiply, WeightReason.AvoidanceAtPosition));
            //}

            //// Do not collect health globes if we are kiting and health globe is too close to monster or avoidance
            //if (CombatBase.KiteDistance > 0)
            //{
            //    weightFactors.TryAddWeight(cacheObject, WeightReason.MonsterInLoS);
            //    weightFactors.TryAddWeight(cacheObject, WeightReason.AvoidanceInLoS);
            //}

            return weightFactors;
        }
Example #18
0
        /// <summary>
        /// Utility for common weight factors
        /// </summary>
        public static bool TryAddWeight(this List<Weight> weightFactors, TrinityObject cacheObject, WeightReason reason, double value = -1, WeightMethod method = WeightMethod.None)
        {
            var isMethod = method != WeightMethod.None;
            var isValue = value > 0;

            switch (reason)
            {
                case WeightReason.PreviousTarget:

                    if (cacheObject.IsLastTarget && cacheObject.Distance <= 25f)
                    {
                        weightFactors.Add(new Weight(isValue ? value : 400, isMethod ? method : WeightMethod.Add, WeightReason.PreviousTarget));
                        return true;
                    }
                    break;

                case WeightReason.AvoidanceInLoS:

                    if (CacheManager.Avoidances.Any(a => MathUtil.IntersectsPath(a.Position, a.Radius + 5f, CacheManager.Me.Position, cacheObject.Position)))
                    {
                        weightFactors.Add(new Weight(isValue ? value : 0, isMethod ? method : WeightMethod.Set, WeightReason.AvoidanceInLoS));
                        return true;
                    }
                    break;

                case WeightReason.MonsterInLoS:

                    if (CacheManager.Units.Any(u => MathUtil.TrinityIntersectsPath(CacheManager.Me.Position, u.Position, cacheObject.Position, u.Distance, cacheObject.Distance)))
                    {
                        weightFactors.Add(new Weight(isValue ? value : 0, isMethod ? method : WeightMethod.Set, WeightReason.MonsterInLoS));
                        return true;
                    }
                    break;

                case WeightReason.DangerClose:

                    if (CacheManager.Monsters.Any(u => u.Distance <= 15f) && !CacheManager.Me.IsInRift || CombatContext.PrioritizeCloseRangeUnits)
                    {
                        weightFactors.Add(new Weight(isValue ? value : 0, isMethod ? method : WeightMethod.Set, WeightReason.DangerClose));
                        return true;
                    }
                    break;

                case WeightReason.TouchProximity:

                    if (cacheObject.RadiusDistance <= 4f)
                    {
                        weightFactors.Add(new Weight(isValue ? value : 5000, isMethod ? method : WeightMethod.Add, WeightReason.TouchProximity));                    
                        return true;
                    }
                    break;

                case WeightReason.CloseProximity:

                    if (cacheObject.RadiusDistance <= 12f)
                    {
                        weightFactors.Add(new Weight(isValue ? value : 1000, isMethod ? method : WeightMethod.Add, WeightReason.CloseProximity));
                        return true;
                    }
                    break;

                case WeightReason.UnitsBehind:

                    if (CacheManager.Units.Any(u => u.IsUnit && u.HitpointsCurrentPct > 0 && u.Distance > cacheObject.Distance && MathUtil.IntersectsPath(cacheObject.Position, cacheObject.Radius, CacheManager.Me.Position, u.Position)))
                    {
                        weightFactors.Add(new Weight(isValue ? value : 250, isMethod ? method : WeightMethod.Add, WeightReason.UnitsBehind));
                        return true;
                    }
                    break;

                case WeightReason.DisableForQuest:

                    // Campaign A5 Quest "Lost Treasure of the Nephalem" - have to interact with nephalem switches first... 
                    // Quest: x1_Adria, Id: 257120, Step: 108 - disable all looting, pickup, and objects
                    if (CacheManager.Me.WorldType != Act.OpenWorld && CacheManager.Me.CurrentQuestSNO == 257120 && CacheManager.Me.CurrentQuestStep == 108)
                    {
                        weightFactors.Add(new Weight(isValue ? value : 0, isMethod ? method : WeightMethod.Set, WeightReason.DisableForQuest));
                        return true;
                    }
                    break;

                case WeightReason.CloseRangePriority:

                    if (CombatContext.PrioritizeCloseRangeUnits)
                    {
                        weightFactors.Add(new Weight(isValue ? value : 0, isMethod ? method : WeightMethod.Set, WeightReason.CloseRangePriority));
                        return true;
                    }
                    break;

                case WeightReason.NavBlocking:

                    if (cacheObject.IsBlocking)
                    {
                        weightFactors.Add(new Weight(isValue ? value : 0, isMethod ? method : WeightMethod.Set, WeightReason.NavBlocking));
                        return true;
                    }
                    break;

                case WeightReason.BossOrEliteNearby:

                    if (CacheManager.Units.Any(m => m.IsBossOrEliteRareUnique))
                    {
                        weightFactors.Add(new Weight(isValue ? value : 0, isMethod ? method : WeightMethod.Set, WeightReason.BossOrEliteNearby));
                        return true;
                    }
                    break;


                case WeightReason.NoCombatLooting:

                    if (!CharacterSettings.Instance.CombatLooting && CombatBase.IsInCombat && CacheManager.Monsters.Any(u => u.Distance <= CombatContext.KillRadius))
                    {
                        weightFactors.Add(new Weight(isValue ? value : 0, isMethod ? method : WeightMethod.Set, WeightReason.NoCombatLooting));
                        return true;
                    }
                    break;

            }

            if (isValue && isMethod)
            {
                weightFactors.Add(new Weight(value, method, reason));
                return true;
            }

            return false;
        }
Example #19
0
 /// <summary>
 /// Faster distance call than ACD.Distance due to being 2d and calling cached player position.
 /// </summary>
 internal static float GetDistance(TrinityObject o)
 {
     var pos = o.Position;
     return pos == Vector3.Zero ? 0f : pos.Distance2D(CacheManager.Me.Position);
 }
        /// <summary>
        /// Weighting for Units
        /// </summary>
        public static IEnumerable<Weight> GetWeight(TrinityObject cacheObject)
        {
            using (new PerformanceLogger(string.Format("UnitWeighting for {0}", cacheObject.InternalName)))
            {
                
                var weightFactors = GetBaseWeight();
                var unit = cacheObject as TrinityUnit;            
            
                /*
                 * Ignore rules 
                 * 
                 * */

                if (unit == null)
                    return weightFactors.Return(WeightReason.TypeMismatch);

                if (unit.IsSummonedByPlayer)
                    return weightFactors.Return(WeightReason.IsSummoned);

                if (!unit.IsHostile)
                    return weightFactors.Return(WeightReason.NotHostile);

                if (unit.IsDead)
                    return weightFactors.Return(WeightReason.DeadUnit);

                if (unit.HasShieldingAffix && unit.IsInvulnerable)
                    return weightFactors.Return(WeightReason.NotAttackable);

                if(unit.IsBoss && CombatContext.ShouldIgnoreBosses)
                    return weightFactors.Return(WeightReason.IgnoreBosses);

                if (unit.IsEliteRareUnique && CombatContext.ShouldIgnoreElites)
                    return weightFactors.Return(WeightReason.IgnoreElites);
            
                if (unit.IsTrash && CombatContext.ShouldIgnoreTrashMobs)
                    return weightFactors.Return(WeightReason.IgnoreTrash);

                if (!unit.IsBoss && !unit.IsGoblin)
                {
                    if (Trinity.Settings.Combat.Misc.IgnoreTrashBelowHealth > 0 && unit.CurrentHealthPct < Trinity.Settings.Combat.Misc.IgnoreTrashBelowHealth)
                        return weightFactors.Return(WeightReason.IgnoreHealth);

                    if (Trinity.Settings.Combat.Misc.IgnoreTrashBelowHealthDoT > 0 && unit.HasDotDps && unit.CurrentHealthPct < Trinity.Settings.Combat.Misc.IgnoreTrashBelowHealthDoT)
                        return weightFactors.Return(WeightReason.IgnoreHealthDot);
                }

                if (Trinity.Settings.Combat.Misc.GoblinPriority == GoblinPriority.Ignore && unit.IsGoblin)
                    return weightFactors.Return(WeightReason.GoblinIgnore);

                /*
                 * Force Kill Rules
                 * 
                 * */

                if (Trinity.Settings.Combat.Misc.GoblinPriority == GoblinPriority.Kamikaze && unit.IsGoblin)
                    return weightFactors.Return(WeightReason.GoblinKamikaze, WeightManager.MaxWeight);

                /*
                 * Unit Weighting
                 * 
                 * */

                weightFactors.Add(new Weight(5000, WeightMethod.Set, WeightReason.Start));

                if(unit.IsBoss)
                    weightFactors.Add(new Weight(30000, WeightMethod.Add, WeightReason.IsBoss));

                if(unit.IsEliteRareUnique)
                    weightFactors.Add(new Weight(15000, WeightMethod.Add, WeightReason.IsElite));

                // Distance - Negative weight for units beyond kill radius, positive weight to those closer
                weightFactors.Add(new Weight((CombatContext.KillRadius - unit.Distance/2) * 100, WeightMethod.Add, WeightReason.Distance));

                if (Trinity.Settings.Combat.Misc.ForceKillSummoners && unit.IsSummoner)
                    weightFactors.Add(new Weight(1000, WeightMethod.Add, WeightReason.Summoner));

                if (Trinity.Settings.Combat.Misc.ForceKillSummoners && unit.IsSummoned)
                    weightFactors.Add(new Weight(0, WeightMethod.Add, WeightReason.IsSummoned));

                // Clustering - Add weight to groups of units.
                //weightFactors.Add(new Weight((unit.UnitsNearby * unit.UnitsNearby) * 10, WeightMethod.Add, WeightReason.Cluster));

                // Avoidance - Reduce weight if melee and targets standing in avoidance
                if (CacheManager.Me.IsMelee && unit.IsStandingInAvoidance)
                    weightFactors.Add(new Weight(0.5, WeightMethod.Multiply, WeightReason.InAvoidance));

                // Goblin Priority
                if (Trinity.Settings.Combat.Misc.GoblinPriority == GoblinPriority.Prioritize && unit.IsGoblin)
                    weightFactors.Add(new Weight(10000, WeightMethod.Add, WeightReason.GoblinPriority));





                //if (unit.IsTownVendor || !unit.IsAttackable)
                //{
                //    weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.NotAttackable));
                //    return weightFactors;
                //}

                //// Not attackable, could be shielded, make super low priority
                //if (unit.HasShieldingAffix && unit.IsInvulnerable)
                //{
                //    // Only 100 weight helps prevent it being prioritized over an unshielded
                //    weightFactors.Add(new Weight(100, WeightMethod.Set, WeightReason.NotAttackable));
                //    return weightFactors;
                //}

                //// Ignore Dead monsters :)
                //if (unit.IsDead)
                //{
                //    weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.DeadUnit));
                //    return weightFactors;
                //}

                //bool isInHotSpot = GroupHotSpots.CacheObjectIsInHotSpot(unit.Position);

                //// Ignore Trash Situations
                //if (unit.IsTrash)
                //{
                //    int nearbyMonsterCount = unit.UnitsNearby;
                //    bool elitesInRangeOfUnit = !CombatBase.IgnoringElites && CacheManager.Monsters.Any(u => u.IsElite && u.Distance < 15f);
                //    bool shouldIgnoreTrashMob = CombatContext.ShouldIgnoreTrashMobs && nearbyMonsterCount < Trinity.Settings.Combat.Misc.TrashPackSize && !elitesInRangeOfUnit;
                //    bool ignoreSummoner = unit.IsSummoner && !Trinity.Settings.Combat.Misc.ForceKillSummoners || unit.IsBlocking;

                //    // Ignore trash mobs < 15% health or 50% health with a DoT
                //    if (unit.IsTrash && shouldIgnoreTrashMob &&
                //        (unit.HitpointsCurrentPct < Trinity.Settings.Combat.Misc.IgnoreTrashBelowHealth ||
                //            unit.HitpointsCurrentPct < Trinity.Settings.Combat.Misc.IgnoreTrashBelowHealthDoT && unit.HasDotDps) &&
                //            !unit.IsQuestMonster && !unit.IsMinimapActive)
                //    {
                //        weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.IgnoreHealthDot));
                //        return weightFactors;
                //    }

                //    // Ignore Solitary Trash mobs (no elites present)
                //    // Except if has been primary target or if already low on health (<= 20%)
                //    if ((shouldIgnoreTrashMob && !isInHotSpot &&
                //            !unit.IsQuestMonster && !unit.IsMinimapActive && !ignoreSummoner &&
                //            !unit.IsBountyObjective) || CombatContext.IsHealthGlobeEmergency || CombatContext.ShouldPrioritizeContainers
                //            || CombatContext.ShouldPrioritizeShrines || CombatContext.ShouldKamakaziGoblins)
                //    {
                //        weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.IgnoreOrphanTrash));
                //        return weightFactors;
                //    }
                //}

                //// Ignore Elite Situations
                //if (unit.IsEliteRareUnique)
                //{
                //    // Ignore elite option, except if trying to town portal
                //    if ((!unit.IsBoss || CombatContext.ShouldIgnoreBosses) && !unit.IsBountyObjective &&
                //        CombatContext.ShouldIgnoreElites && unit.IsEliteRareUnique && !isInHotSpot &&
                //        !(unit.HitpointsCurrentPct <= ((float)Trinity.Settings.Combat.Misc.ForceKillElitesHealth / 100))
                //        || CombatContext.IsHealthGlobeEmergency || CombatContext.ShouldPrioritizeShrines || CombatContext.ShouldPrioritizeContainers || CombatContext.ShouldKamakaziGoblins)
                //    {
                //        weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.IgnoreElites));
                //        return weightFactors;
                //    }
                //}

                //// Monster is not within kill range
                //if (!unit.IsBoss && !unit.IsTreasureGoblin && Trinity.LastTargetRactorGUID != unit.RActorGuid &&
                //    unit.RadiusDistance > unit.KillRange && !unit.IsQuestMonster && !unit.IsBountyObjective)
                //{
                //    weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.NotInKillRange));
                //    return weightFactors;
                //}

                //// Ignore event monsters that are too far from event
                //if (CombatContext.InActiveEvent)
                //{
                //    var eventObject = CacheManager.Objects.FirstOrDefault(o => o.IsEventObject);
                //    if (eventObject != null)
                //    {
                //        var eventObjectPosition = eventObject.Position;
                //        if (!unit.IsQuestMonster && unit.Position.Distance2DSqr(eventObjectPosition) > 75 * 75)
                //        {
                //            weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.TooFarFromEvent));
                //            return weightFactors;
                //        }
                //    }
                //}

                //// Force a close range target because we seem to be stuck *OR* if not ranged and currently rooted
                //if (CombatContext.PrioritizeCloseRangeUnits)
                //{
                //    double rangePercent = (20d - unit.RadiusDistance) / 20d;
                //    weightFactors.Add(new Weight(Math.Max(rangePercent * WeightManager.MaxWeight, 200d), WeightMethod.Set, WeightReason.GoblinKamikaze));

                //    // Goblin priority KAMIKAZEEEEEEEE
                //    if (unit.IsTreasureGoblin && Trinity.Settings.Combat.Misc.GoblinPriority == GoblinPriority.Kamikaze)
                //        weightFactors.Add(new Weight(0, WeightMethod.Set, WeightReason.GoblinKamikaze));

                //    return weightFactors;
                //}

                //// Starting weight of 500 for Trash
                //if (unit.IsTrash)
                //{
                //    var startingWeight = Math.Max((unit.KillRange - unit.RadiusDistance) / unit.KillRange * 100d, 2d);
                //    weightFactors.Add(new Weight(startingWeight, WeightMethod.Set, WeightReason.StartingWeight));
                //}

                //// Elite Weight based on kill range and max possible weight
                //if (unit.IsBossOrEliteRareUnique)
                //{
                //    var startingWeight = unit.Weight = Math.Max((unit.KillRange - unit.RadiusDistance) / unit.KillRange * WeightManager.MaxWeight, 2000d);
                //    weightFactors.Add(new Weight(startingWeight, WeightMethod.Set, WeightReason.IsBossEliteRareUnique));
                //}

                //// Bounty Objectives goooo
                //if (unit.IsBountyObjective && !unit.IsBlocking)
                //{
                //    weightFactors.Add(new Weight(15000d, WeightMethod.Add, WeightReason.BountyObjective));
                //}

                //// set a minimum 100 just to make sure it's not 0
                //if (CombatContext.IsKillBounty || CombatContext.InActiveEvent)
                //    weightFactors.Add(new Weight(100, WeightMethod.Add, WeightReason.InActiveEvent));

                //// Elites with Archon get super weight
                //if (!CombatBase.IgnoringElites && CacheManager.Me.ActorClass == ActorClass.Wizard && Trinity.GetHasBuff(SNOPower.Wizard_Archon) && unit.IsBossOrEliteRareUnique)
                //    weightFactors.Add(new Weight(10000d, WeightMethod.Add, WeightReason.ArchonElite));

                //// Monsters near other players given higher weight
                //if (CacheManager.Players.Count > 1)
                //{
                //    var group = 0d;
                //    foreach (var player in CacheManager.Players.Where(p => !p.IsMe))
                //    {
                //        group += Math.Max(((55f - unit.Position.Distance2D(player.Position)) / 55f * 500d), 2d);
                //    }
                //    weightFactors.Add(new Weight(group, WeightMethod.Add, WeightReason.ElitesNearPlayers));
                //}

                //// Is standing in HotSpot - focus fire!
                //if (isInHotSpot)
                //    weightFactors.Add(new Weight(10000, WeightMethod.Add, WeightReason.InHotSpot));

                //// Give extra weight to ranged enemies
                //if ((CacheManager.Me.ActorClass == ActorClass.Barbarian || CacheManager.Me.ActorClass == ActorClass.Monk) &&
                //    (unit.MonsterSize == MonsterSize.Ranged || DataDictionary.RangedMonsterIds.Contains(unit.ActorSNO)))
                //{
                //    weightFactors.Add(new Weight(1100d, WeightMethod.Add, WeightReason.RangedUnit));
                //}

                //// Lower health gives higher weight - health is worth up to 1000ish extra weight
                //if (unit.IsTrash && unit.HitpointsCurrentPct < 0.20 && unit.IsAlive)
                //    weightFactors.Add(new Weight(Math.Max((1 - unit.HitpointsCurrentPct) / 100 * 1000d, 100d), WeightMethod.Add, WeightReason.LowHPTrash));

                //// Elites on low health get extra priority - up to 2500ish
                //if (unit.IsEliteRareUnique && unit.HitpointsCurrentPct < 0.25 && unit.HitpointsCurrentPct > 0.01)
                //    weightFactors.Add(new Weight(Math.Max((1 - unit.HitpointsCurrentPct) / 100 * 2500d, 100d), WeightMethod.Add, WeightReason.LowHPElite));

                //// Bonuses to priority type monsters from the dictionary/hashlist set at the top of the code
                //int extraPriority;
                //if (DataDictionary.MonsterCustomWeights.TryGetValue(unit.ActorSNO, out extraPriority))
                //{
                //    // adding a constant multiple of 3 to all weights here (e.g. 999 becomes 1998)
                //    weightFactors.Add(new Weight(extraPriority * 2d, WeightMethod.Add, WeightReason.XtraPriority));
                //}

                //// Extra weight for summoners
                //if (!unit.IsBoss && unit.IsSummoner)
                //    weightFactors.Add(new Weight(2500, WeightMethod.Add, WeightReason.Summoner));

                //// Was already a target and is still viable, give it some free extra weight, to help stop flip-flopping between two targets
                //if (unit.IsLastTarget && unit.Distance <= 25f)
                //    weightFactors.Add(new Weight(1000d, WeightMethod.Add, WeightReason.PreviousTarget));

                //// Close range get higher weights the more of them there are, to prevent body-blocking
                //if (!unit.IsBoss && unit.RadiusDistance <= 10f)
                //    weightFactors.Add(new Weight(3000d * unit.Radius, WeightMethod.Add, WeightReason.CloseProximity));

                //// Special additional weight for corrupt growths in act 4 ONLY if they are at close range (not a standard priority thing)
                //if ((unit.ActorSNO == 210120 || unit.ActorSNO == 210268) && unit.Distance <= 25f)
                //    weightFactors.Add(new Weight(5000d * unit.Radius, WeightMethod.Add, WeightReason.CorruptGrowth));

                //// If standing Molten, Arcane, or Poison Tree near unit, reduce weight
                //if (CombatBase.KiteDistance <= 0 && CacheManager.Avoidances.Any(aoe =>
                //        (aoe.AvoidanceType == AvoidanceType.Arcane ||
                //         aoe.AvoidanceType == AvoidanceType.MoltenCore ||
                //            //aoe.AvoidanceType == AvoidanceType.MoltenTrail ||
                //         aoe.AvoidanceType == AvoidanceType.PoisonTree) &&
                //        unit.Position.Distance2D(aoe.Position) <= aoe.Radius))
                //{
                //    weightFactors.Add(new Weight(1, WeightMethod.Set, WeightReason.InSpecialAoE));
                //}

                //// If any AoE between us and target, reduce weight, for melee only
                //if (!Trinity.Settings.Combat.Misc.KillMonstersInAoE &&
                //    CombatBase.KiteDistance <= 0 && unit.RadiusDistance > 3f &&
                //    CacheManager.Avoidances.Any(aoe => aoe.AvoidanceType != AvoidanceType.PlagueCloud &&
                //    MathUtil.IntersectsPath(aoe.Position, aoe.Radius, CacheManager.Me.Position, unit.Position)))
                //{
                //    weightFactors.Add(new Weight(1, WeightMethod.Set, WeightReason.AoEPathLine));
                //}
                //// See if there's any AOE avoidance in that spot, if so reduce the weight to 1, for melee only
                //if (!Trinity.Settings.Combat.Misc.KillMonstersInAoE &&
                //    CombatBase.KiteDistance <= 0 && unit.RadiusDistance > 3f &&
                //    CacheData.TimeBoundAvoidance.Any(aoe => aoe.AvoidanceType != AvoidanceType.PlagueCloud &&
                //    unit.Position.Distance2D(aoe.Position) <= aoe.Radius))
                //{
                //    weightFactors.Add(new Weight(1, WeightMethod.Set, WeightReason.InAoE));
                //}

                //// Deal with treasure goblins - note, of priority is set to "0", then the is-a-goblin flag isn't even set for use here - the monster is ignored
                //// Goblins on low health get extra priority - up to 2000ish
                //if (Trinity.Settings.Combat.Misc.GoblinPriority >= GoblinPriority.Prioritize && unit.IsTreasureGoblin && unit.HitpointsCurrentPct <= 0.98)
                //    weightFactors.Add(new Weight(Math.Max(((1 - unit.HitpointsCurrentPct) / 100) * 2000d, 100d), WeightMethod.Add, WeightReason.LowHPGoblin));

                //// If this is a goblin and there's no doors or barricades blocking our path to it.
                //if (unit.IsTreasureGoblin && !CacheManager.Objects.Any(obj => (obj.TrinityType == TrinityObjectType.Door || obj.TrinityType == TrinityObjectType.Barricade) && !MathUtil.IntersectsPath(obj.Position, obj.Radius, CacheManager.Me.Position, unit.Position)))
                //{
                //    // Logging goblin sightings
                //    if (Trinity.lastGoblinTime == DateTime.MinValue)
                //    {
                //        Trinity.TotalNumberGoblins++;
                //        Trinity.LastGoblinTime = DateTime.UtcNow;
                //        Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Goblin #{0} in sight. Distance={1:0}", Trinity.TotalNumberGoblins, unit.Distance);
                //    }
                //    else
                //    {
                //        if (DateTime.UtcNow.Subtract(Trinity.LastGoblinTime).TotalMilliseconds > 30000)
                //            Trinity.LastGoblinTime = DateTime.MinValue;
                //    }

                //    // Ignore goblins in AOE
                //    if (CacheManager.Avoidances.Any(aoe => unit.Position.Distance2D(aoe.Position) <= aoe.Radius) && Trinity.Settings.Combat.Misc.GoblinPriority != GoblinPriority.Kamikaze)
                //    {
                //        weightFactors.Add(new Weight(1, WeightMethod.Set, WeightReason.InAoE));
                //        return weightFactors;
                //    }

                //    // Original Trinity stuff for priority handling now
                //    switch (Trinity.Settings.Combat.Misc.GoblinPriority)
                //    {
                //        case GoblinPriority.Normal:
                //            weightFactors.Add(new Weight(751, WeightMethod.Add, WeightReason.GoblinNormal));
                //            break;

                //        case GoblinPriority.Prioritize:
                //            // Super-high priority option below... 
                //            var gobWeight = Math.Max((unit.KillRange - unit.RadiusDistance) / unit.KillRange * WeightManager.MaxWeight, 1000d);
                //            weightFactors.Add(new Weight(gobWeight, WeightMethod.Add, WeightReason.GoblinPriority));
                //            break;
                //        case GoblinPriority.Kamikaze:
                //            // KAMIKAZE SUICIDAL TREASURE GOBLIN RAPE AHOY!
                //            weightFactors.Add(new Weight(WeightManager.MaxWeight, WeightMethod.Add, WeightReason.GoblinKamikaze));
                //            break;
                //    }
                //}

                return weightFactors;
            }
        }
Example #21
0
 /// <summary>
 /// The monster type, checking for overrides in DataDictionary.
 /// </summary>
 internal static MonsterType GetMonsterType(TrinityObject o)
 {
     MonsterType monsterTypeOverride;
     return DataDictionary.MonsterTypeOverrides.TryGetValue(o.ActorSNO, out monsterTypeOverride) ? monsterTypeOverride : o.ActorMeta.MonsterType;
 }
Example #22
0
        public static float GetAvoidanceRadius(TrinityObject trinityObject)
        {
            float customRadius;

            if (!DataDictionary.DefaultAvoidanceCustomRadius.TryGetValue(trinityObject.ActorSNO, out customRadius))
            {
                DataDictionary.DefaultAvoidanceAnimationCustomRadius.TryGetValue((int) trinityObject.CurrentAnimation, out customRadius);
            }

            if (DataDictionary.AvoidanceTypeSNO.ContainsKey(trinityObject.ActorSNO))
                return GetAvoidanceRadius(DataDictionary.AvoidanceTypeSNO[trinityObject.ActorSNO], customRadius);

            return customRadius;
        }
        public double GetMovementSpeed(TrinityObject o)
        {
            if (_speedSensors.Any(s => s != null && s.WorldID != CacheManager.WorldDynamicId))
            {
                _speedSensors.Clear();
                _movementSpeed = 1d;
            }

            else if (o.IsMe && DateTime.UtcNow.Subtract(SpellHistory.GetSpellLastused()).TotalMilliseconds <= 1000)
            {
                _movementSpeed = 1d;                
            }

            // Minimum of 2 records to calculate speed
            else if (!_speedSensors.Any() || _speedSensors.Count <= 1)
                _movementSpeed = 0d;                

            // If we haven't "moved" in over a second, then we're standing still
            else if (DateTime.UtcNow.Subtract(_lastRecordedPositionTime).TotalMilliseconds > 1000)
                _movementSpeed = 0d;

            else
            {
                _averageRecordingTimeHours = _speedSensors.Average(s => s.TimeSinceLastMove.TotalHours);
                _averageDistance = _speedSensors.Average(s => Vector3.Distance(s.Location, o.Position));
                _averageMovementSpeed =  _averageDistance * 1000000;
                _movementSpeed =  _averageMovementSpeed / _averageRecordingTimeHours;
            }

            return _movementSpeed;
        }
Example #24
0
        /// <summary>
        /// Calculate a weight for a TrinityObject
        /// </summary>
        public static double CalculateWeight(TrinityObject trinityObject, out List<Weight> outFactors, out double weightTime)
        {
            var timer = Stopwatch.StartNew();

            var weightFactors = new List<Weight>();

            weightFactors.AddRange(WeightingBase.GetPreWeightChecks(trinityObject));

            if (!weightFactors.Any())
            {                
                switch (trinityObject.TrinityType)
                {
                    case TrinityObjectType.Unit:
                        weightFactors.AddRange(UnitWeighting.GetWeight(trinityObject));
                        break;

                    //case TrinityObjectType.HotSpot:
                    //    weightFactors.AddRange(HotSpotWeighting.GetWeight(trinityObject));
                    //    break;

                    //case TrinityObjectType.Item:
                    //    weightFactors.AddRange(ItemWeighting.GetItemWeight(trinityObject));
                    //    break;

                    case TrinityObjectType.Gold:
                        weightFactors.AddRange(ItemWeighting.GetGoldWeight(trinityObject));
                        break;

                    //case TrinityObjectType.PowerGlobe:
                    //    weightFactors.AddRange(GlobeWeighting.GetPowerGlobeWeight(trinityObject));
                    //    break;

                    //case TrinityObjectType.HealthGlobe:
                    //    weightFactors.AddRange(GlobeWeighting.GetHealthGlobeWeight(trinityObject));
                    //    break;

                    //case TrinityObjectType.ProgressionGlobe:
                    //    weightFactors.AddRange(GlobeWeighting.GetProgressionGlobeWeight(trinityObject));
                    //    break;

                    //case TrinityObjectType.HealthWell:
                    //    weightFactors.AddRange(HealthWellWeighting.GetWeight(trinityObject));
                    //    break;

                    //case TrinityObjectType.CursedShrine:
                    //case TrinityObjectType.Shrine:
                    //    weightFactors.AddRange(ShrineWeighting.GetWeight(trinityObject));
                    //    break;

                    //case TrinityObjectType.Door:
                    //    weightFactors.AddRange(DoorWeighting.GetWeight(trinityObject));
                    //    break;

                    //case TrinityObjectType.Barricade:
                    //    weightFactors.AddRange(ObstacleWeighting.GetBarricadeWeight(trinityObject));
                    //    break;

                    //case TrinityObjectType.Destructible:
                    //    weightFactors.AddRange(ObstacleWeighting.GetDestructibleWeight(trinityObject));
                    //    break;

                    //case TrinityObjectType.Interactable:
                    //    weightFactors.AddRange(InteractableWeighting.GetWeight(trinityObject));
                    //    break;

                    //case TrinityObjectType.Container:
                    //    weightFactors.AddRange(ContainerWeighting.GetWeight(trinityObject));
                    //    break;
                }

            }

            var finalWeight = CombineWeights(weightFactors);

            outFactors = weightFactors;

            timer.Stop();

            weightTime = timer.Elapsed.TotalMilliseconds;

            return finalWeight;
        }
Example #25
0
        /// <summary>
        /// The friendly name (the name you see in the Diablo interface)
        /// </summary>
        internal static string GetName(TrinityObject o)
        {
            if (o.ActorType == ActorType.Item && o.DiaItem != null)
                return o.DiaItem.Name;

            return o.InternalName;
        }
Example #26
0
        /// <summary>
        /// The type of player-summoned actor this is.
        /// </summary>
        internal static TrinityPetType GetSummonType(TrinityObject o)
        {
            if (DataDictionary.MysticAllyIds.Contains(o.ActorSNO))
                return TrinityPetType.MysticAlly;

            if (DataDictionary.DemonHunterPetIds.Contains(o.ActorSNO))
                return TrinityPetType.Companion;

            if (DataDictionary.DemonHunterSentryIds.Contains(o.ActorSNO))
                return TrinityPetType.Sentry;

            if (DataDictionary.WizardHydraIds.Contains(o.ActorSNO))
                return TrinityPetType.Hydra;

            if (DataDictionary.GargantuanIds.Contains(o.ActorSNO))
                return TrinityPetType.Gargantuan;

            if (DataDictionary.ZombieDogIds.Contains(o.ActorSNO))
                return TrinityPetType.ZombieDog;

            return TrinityPetType.Unknown;
        }
Example #27
0
        /// <summary>
        /// Faster distance call than ACD.Distance due to being 2d and calling cached player position.
        /// </summary>
        internal static Vector3 GetPosition(TrinityObject o)
        {
            // Position/Distance only works for Ground Items if called on DiaItem
            if(o.ActorType == ActorType.Item)
                return o.GetDiaItemProperty(x => x.Position);

            return o.GetSourceProperty(x => x.Position);
        }
Example #28
0
        /// <summary>
        /// The radius, checking for overrides in DataDictionary.
        /// </summary>
        internal static float GetRadius(TrinityObject o)
        {
            float radius;
            if (o.IsNavigationObstacle && DataDictionary.CustomObjectRadius.TryGetValue(o.ActorSNO, out radius))
                return radius;

            return (float)o.ActorMeta.Radius;
        }