private static bool RefreshAvoidance(bool AddToCache) { AddToCache = true; try { CurrentCacheObject.Animation = CurrentCacheObject.Object.CommonData.CurrentAnimation; } catch (Exception ex) { Logger.LogDebug(LogCategory.CacheManagement, "Error reading CurrentAnimation for AoE sno:{0} raGuid:{1} name:{2} ex:{3}", CurrentCacheObject.ActorSNO, CurrentCacheObject.RActorGuid, CurrentCacheObject.InternalName, ex.Message); } float customRadius; if (DataDictionary.DefaultAvoidanceCustomRadius.TryGetValue(CurrentCacheObject.ActorSNO, out customRadius)) { CurrentCacheObject.Radius = customRadius; } double minAvoidanceHealth = GetAvoidanceHealth(CurrentCacheObject.ActorSNO); double minAvoidanceRadius = GetAvoidanceRadius(CurrentCacheObject.ActorSNO, CurrentCacheObject.Radius); // Are we allowed to path around avoidance? if (Settings.Combat.Misc.AvoidanceNavigation) { MainGridProvider.AddCellWeightingObstacle(CurrentCacheObject.ActorSNO, (float)minAvoidanceRadius); } AvoidanceType avoidanceType = AvoidanceManager.GetAvoidanceType(CurrentCacheObject.ActorSNO); // Beast Charge should set aoe position as players current position! if (avoidanceType == AvoidanceType.BeastCharge) { CurrentCacheObject.Position = Trinity.Player.Position; } // Monks with Serenity up ignore all AOE's if (Player.ActorClass == ActorClass.Monk && Hotbar.Contains(SNOPower.Monk_Serenity) && GetHasBuff(SNOPower.Monk_Serenity)) { // Monks with serenity are immune minAvoidanceHealth *= V.F("Monk.Avoidance.Serenity"); Logger.Log(TrinityLogLevel.Debug, LogCategory.Avoidance, "Ignoring avoidance as a Monk with Serenity"); } // Witch doctors with spirit walk available and not currently Spirit Walking will subtly ignore ice balls, arcane, desecrator & plague cloud if (Player.ActorClass == ActorClass.Witchdoctor && Hotbar.Contains(SNOPower.Witchdoctor_SpiritWalk) && GetHasBuff(SNOPower.Witchdoctor_SpiritWalk)) { if (avoidanceType == AvoidanceType.IceBall || avoidanceType == AvoidanceType.Arcane || avoidanceType == AvoidanceType.Desecrator || avoidanceType == AvoidanceType.PlagueCloud) { // Ignore ICE/Arcane/Desc/PlagueCloud altogether with spirit walk up or available minAvoidanceHealth *= V.F("WitchDoctor.Avoidance.SpiritWalk"); Logger.Log(TrinityLogLevel.Debug, LogCategory.Avoidance, "Ignoring avoidance as a WitchDoctor with Spirit Walk"); } } // Remove ice balls if the barbarian has wrath of the berserker up, and reduce health from most other SNO avoidances if (Player.ActorClass == ActorClass.Barbarian && Settings.Combat.Barbarian.IgnoreAvoidanceInWOTB && Hotbar.Contains(SNOPower.Barbarian_WrathOfTheBerserker) && GetHasBuff(SNOPower.Barbarian_WrathOfTheBerserker)) { switch (avoidanceType) { case AvoidanceType.IceBall: minAvoidanceHealth *= V.F("Barbarian.Avoidance.WOTB.IceBall"); break; case AvoidanceType.Arcane: minAvoidanceHealth *= V.F("Barbarian.Avoidance.WOTB.Arcane"); break; case AvoidanceType.Desecrator: minAvoidanceHealth *= V.F("Barbarian.Avoidance.WOTB.Desecrator"); break; case AvoidanceType.Belial: minAvoidanceHealth = V.F("Barbarian.Avoidance.WOTB.Belial"); break; case AvoidanceType.PoisonTree: minAvoidanceHealth = V.F("Barbarian.Avoidance.WOTB.PoisonTree"); break; case AvoidanceType.BeastCharge: minAvoidanceHealth = V.F("Barbarian.Avoidance.WOTB.BeastCharge"); break; default: minAvoidanceHealth *= V.F("Barbarian.Avoidance.WOTB.Other"); break; } } if (minAvoidanceHealth == 0) { AddToCache = false; Logger.Log(TrinityLogLevel.Verbose, LogCategory.Avoidance, "Ignoring Avoidance! Name={0} SNO={1} radius={2:0} health={3:0.00} dist={4:0}", CurrentCacheObject.InternalName, CurrentCacheObject.ActorSNO, minAvoidanceRadius, minAvoidanceHealth, CurrentCacheObject.Distance); return(AddToCache); } // Add it to the list of known avoidance objects, *IF* our health is lower than this avoidance health limit if (minAvoidanceHealth >= Player.CurrentHealthPct) { float avoidanceRadius = (float)GetAvoidanceRadius(CurrentCacheObject.ActorSNO, CurrentCacheObject.Radius); TimeSpan aoeExpiration; DataDictionary.AvoidanceSpawnerDuration.TryGetValue(CurrentCacheObject.ActorSNO, out aoeExpiration); CacheData.TimeBoundAvoidance.Add(new CacheObstacleObject(CurrentCacheObject.Position, avoidanceRadius, CurrentCacheObject.ActorSNO, CurrentCacheObject.InternalName) { Expires = DateTime.UtcNow.Add(aoeExpiration), ObjectType = GObjectType.Avoidance, Rotation = CurrentCacheObject.Rotation }); // Is this one under our feet? If so flag it up so we can find an avoidance spot if (CurrentCacheObject.Distance <= minAvoidanceRadius) { _standingInAvoidance = true; // Note if this is a travelling projectile or not so we can constantly update our safe points if (DataDictionary.AvoidanceProjectiles.Contains(CurrentCacheObject.ActorSNO)) { _isAvoidingProjectiles = true; Logger.Log(TrinityLogLevel.Verbose, LogCategory.Avoidance, "Is standing in avoidance for projectile Name={0} SNO={1} radius={2:0} health={3:0.00} dist={4:0}", CurrentCacheObject.InternalName, CurrentCacheObject.ActorSNO, minAvoidanceRadius, minAvoidanceHealth, CurrentCacheObject.Distance); } else { Logger.Log(TrinityLogLevel.Verbose, LogCategory.Avoidance, "Is standing in avoidance Name={0} SNO={1} radius={2:0} health={3:0.00} dist={4:0}", CurrentCacheObject.InternalName, CurrentCacheObject.ActorSNO, minAvoidanceRadius, minAvoidanceHealth, CurrentCacheObject.Distance); } } } return(AddToCache); }
private static bool RefreshAvoidance() { try { CurrentCacheObject.Animation = c_diaObject.CommonData.CurrentAnimation; } catch (Exception ex) { Logger.LogDebug(LogCategory.CacheManagement, "Error reading CurrentAnimation for AoE sno:{0} raGuid:{1} name:{2} ex:{3}", CurrentCacheObject.ActorSNO, CurrentCacheObject.RActorGuid, CurrentCacheObject.InternalName, ex.Message); } float customRadius; if (DataDictionary.DefaultAvoidanceCustomRadius.TryGetValue(CurrentCacheObject.ActorSNO, out customRadius) || DataDictionary.DefaultAvoidanceAnimationCustomRadius.TryGetValue((int)CurrentCacheObject.Animation, out customRadius)) { CurrentCacheObject.Radius = customRadius; } double minAvoidanceHealth = GetAvoidanceHealth(CurrentCacheObject.ActorSNO); double minAvoidanceRadius = GetAvoidanceRadius(CurrentCacheObject.ActorSNO, CurrentCacheObject.Radius + 5); // Add Navigation cell weights to path around avoidance MainGridProvider.AddCellWeightingObstacle(CurrentCacheObject.ActorSNO, (float)minAvoidanceRadius); AvoidanceType avoidanceType = AvoidanceManager.GetAvoidanceType(CurrentCacheObject.ActorSNO); // Beast Charge should set aoe position as players current position! var avoidAtPlayerPosition = DataDictionary.AvoidAnimationAtPlayer.Contains((int)CurrentCacheObject.Animation); if (avoidAtPlayerPosition) { CurrentCacheObject.Position = Player.Position; } // Monks with Serenity up ignore all AOE's if (Player.ActorClass == ActorClass.Monk && Hotbar.Contains(SNOPower.Monk_Serenity) && GetHasBuff(SNOPower.Monk_Serenity)) { // Monks with serenity are immune minAvoidanceHealth *= V.F("Monk.Avoidance.Serenity"); Logger.Log(TrinityLogLevel.Debug, LogCategory.Avoidance, "Ignoring avoidance as a Monk with Serenity"); } // Witch doctors with spirit walk available and not currently Spirit Walking will subtly ignore ice balls, arcane, desecrator & plague cloud if (Player.ActorClass == ActorClass.Witchdoctor && Hotbar.Contains(SNOPower.Witchdoctor_SpiritWalk) && GetHasBuff(SNOPower.Witchdoctor_SpiritWalk)) { if (avoidanceType == AvoidanceType.IceBall || avoidanceType == AvoidanceType.Arcane || avoidanceType == AvoidanceType.Desecrator || avoidanceType == AvoidanceType.PlagueCloud) { // Ignore ICE/Arcane/Desc/PlagueCloud altogether with spirit walk up or available minAvoidanceHealth *= V.F("WitchDoctor.Avoidance.SpiritWalk"); Logger.Log(TrinityLogLevel.Debug, LogCategory.Avoidance, "Ignoring avoidance as a WitchDoctor with Spirit Walk"); } } // Remove ice balls if the barbarian has wrath of the berserker up, and reduce health from most other SNO avoidances if (Player.ActorClass == ActorClass.Barbarian && Settings.Combat.Barbarian.IgnoreAvoidanceInWOTB && Hotbar.Contains(SNOPower.Barbarian_WrathOfTheBerserker) && GetHasBuff(SNOPower.Barbarian_WrathOfTheBerserker)) { switch (avoidanceType) { case AvoidanceType.IceBall: minAvoidanceHealth *= V.F("Barbarian.Avoidance.WOTB.IceBall"); break; case AvoidanceType.Arcane: minAvoidanceHealth *= V.F("Barbarian.Avoidance.WOTB.Arcane"); break; case AvoidanceType.Desecrator: minAvoidanceHealth *= V.F("Barbarian.Avoidance.WOTB.Desecrator"); break; case AvoidanceType.Belial: minAvoidanceHealth = V.F("Barbarian.Avoidance.WOTB.Belial"); break; case AvoidanceType.PoisonTree: minAvoidanceHealth = V.F("Barbarian.Avoidance.WOTB.PoisonTree"); break; case AvoidanceType.BeastCharge: minAvoidanceHealth = V.F("Barbarian.Avoidance.WOTB.BeastCharge"); break; case AvoidanceType.MoltenCore: minAvoidanceHealth = V.F("Barbarian.Avoidance.WOTB.MoltenCore"); break; default: minAvoidanceHealth *= V.F("Barbarian.Avoidance.WOTB.Other"); break; } } // Item based immunity switch (avoidanceType) { case AvoidanceType.PoisonTree: case AvoidanceType.PlagueCloud: case AvoidanceType.PoisonEnchanted: case AvoidanceType.PlagueHand: if (Legendary.MarasKaleidoscope.IsEquipped) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Avoidance, "Ignoring Avoidance {0} because MarasKaleidoscope is equipped", avoidanceType); minAvoidanceHealth = 0; } break; case AvoidanceType.AzmoFireball: case AvoidanceType.DiabloRingOfFire: case AvoidanceType.DiabloMeteor: case AvoidanceType.ButcherFloorPanel: case AvoidanceType.Mortar: case AvoidanceType.MageFire: case AvoidanceType.MoltenTrail: case AvoidanceType.MoltenBall: case AvoidanceType.ShamanFire: if (Legendary.TheStarOfAzkaranth.IsEquipped) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Avoidance, "Ignoring Avoidance {0} because TheStarofAzkaranth is equipped", avoidanceType); minAvoidanceHealth = 0; } break; case AvoidanceType.FrozenPulse: case AvoidanceType.IceBall: case AvoidanceType.IceTrail: // Ignore if both items are equipped if (Legendary.TalismanOfAranoch.IsEquipped) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Avoidance, "Ignoring Avoidance {0} because TalismanofAranoch is equipped", avoidanceType); minAvoidanceHealth = 0; } break; case AvoidanceType.Orbiter: case AvoidanceType.Thunderstorm: if (Legendary.XephirianAmulet.IsEquipped) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Avoidance, "Ignoring Avoidance {0} because XephirianAmulet is equipped", avoidanceType); minAvoidanceHealth = 0; } break; case AvoidanceType.Arcane: if (Legendary.CountessJuliasCameo.IsEquipped) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Avoidance, "Ignoring Avoidance {0} because CountessJuliasCameo is equipped", avoidanceType); minAvoidanceHealth = 0; } break; } // Set based immunity if (Sets.BlackthornesBattlegear.IsMaxBonusActive) { var blackthornsImmunity = new HashSet <AvoidanceType> { AvoidanceType.Desecrator, AvoidanceType.MoltenBall, AvoidanceType.MoltenCore, AvoidanceType.MoltenTrail, AvoidanceType.PlagueHand }; if (blackthornsImmunity.Contains(avoidanceType)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Avoidance, "Ignoring Avoidance {0} because BlackthornesBattlegear is equipped", avoidanceType); minAvoidanceHealth = 0; } } if (minAvoidanceHealth == 0) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Avoidance, "Ignoring Avoidance! Name={0} SNO={1} radius={2:0} health={3:0.00} dist={4:0}", CurrentCacheObject.InternalName, CurrentCacheObject.ActorSNO, minAvoidanceRadius, minAvoidanceHealth, CurrentCacheObject.Distance); return(false); } //Logger.LogDebug(LogCategory.Avoidance, "{0} Distance={1:0} {2}! {3} ({4})", // (avoidanceType == AvoidanceType.None) ? CurrentCacheObject.Animation.ToString() : avoidanceType.ToString(), // CurrentCacheObject.Distance, // minAvoidanceHealth >= Player.CurrentHealthPct ? "Adding" : "Ignoring", // CurrentCacheObject.InternalName, CurrentCacheObject.ActorSNO); // Add it to the list of known avoidance objects, *IF* our health is lower than this avoidance health limit if (minAvoidanceHealth >= Player.CurrentHealthPct) { float avoidanceRadius = (float)GetAvoidanceRadius(CurrentCacheObject.ActorSNO, CurrentCacheObject.Radius); TimeSpan aoeExpiration; DataDictionary.AvoidanceSpawnerDuration.TryGetValue(CurrentCacheObject.ActorSNO, out aoeExpiration); CacheData.TimeBoundAvoidance.Add(new CacheObstacleObject(CurrentCacheObject.Position, avoidanceRadius, CurrentCacheObject.ActorSNO, CurrentCacheObject.InternalName) { Expires = DateTime.UtcNow.Add(aoeExpiration), ObjectType = TrinityObjectType.Avoidance, Rotation = CurrentCacheObject.Rotation }); // Is this one under our feet? If so flag it up so we can find an avoidance spot if (CurrentCacheObject.Distance <= minAvoidanceRadius) { _currentAvoidance = CurrentCacheObject; _currentAvoidance.AvoidanceRadius = avoidanceRadius; _currentAvoidance.AvoidanceHealth = minAvoidanceHealth; _currentAvoidanceName = CurrentCacheObject.InternalName; _standingInAvoidance = true; // Note if this is a travelling projectile or not so we can constantly update our safe points if (DataDictionary.AvoidanceProjectiles.Contains(CurrentCacheObject.ActorSNO)) { Logger.Log(TrinityLogLevel.Verbose, LogCategory.Avoidance, "Is standing in avoidance for projectile Name={0} SNO={1} radius={2:0} health={3:0.00} dist={4:0}", CurrentCacheObject.InternalName, CurrentCacheObject.ActorSNO, minAvoidanceRadius, minAvoidanceHealth, CurrentCacheObject.Distance); } else { Logger.Log(TrinityLogLevel.Verbose, LogCategory.Avoidance, "Is standing in avoidance Name={0} SNO={1} radius={2:0} health={3:0.00} dist={4:0}", CurrentCacheObject.InternalName, CurrentCacheObject.ActorSNO, minAvoidanceRadius, minAvoidanceHealth, CurrentCacheObject.Distance); } } } return(true); }