public override void Initialize() { Priority = SkillPriority.Medium; PreCast = new SkillPreCast((SkillPrecastFlags.CheckRecastTimer | SkillPrecastFlags.CheckCanCast | SkillPrecastFlags.CheckPlayerIncapacitated)); FcriteriaCombat = (u) => ( FunkyGame.Targeting.Cache.Environment.iElitesWithinRange[(int)RangeIntervals.Range_20] > 1 || (u.IsBoss && u.RadiusDistance <= 20) || (FunkyGame.Targeting.Cache.Environment.iAnythingWithinRange[(int)RangeIntervals.Range_20] > 2 && !FunkyGame.Targeting.Cache.Environment.bAnyBossesInRange && (FunkyGame.Targeting.Cache.Environment.iElitesWithinRange[(int)RangeIntervals.Range_50] == 0 || Hotbar.HasPower(SNOPower.Barbarian_SeismicSlam))) || FunkyGame.Hero.dCurrentHealthPct <= 0.75 ); }
public override void Initialize() { Priority = SkillPriority.High; Cost = 20; Range = 35; PreCast = new SkillPreCast((SkillPrecastFlags.CheckPlayerIncapacitated | SkillPrecastFlags.CheckCanCast)); FcriteriaBuff = () => !Hotbar.HasBuff(SNOPower.Barbarian_BattleRage); FcriteriaCombat = (u) => !Hotbar.HasBuff(SNOPower.Barbarian_BattleRage) || //Only if we cannot spam sprint.. (!Hotbar.HasPower(SNOPower.Barbarian_Sprint) && ((FunkyBaseExtension.Settings.Barbarian.bFuryDumpWrath && FunkyGame.Hero.dCurrentEnergyPct >= 0.98 && Hotbar.HasBuff(SNOPower.Barbarian_WrathOfTheBerserker) && FunkyGame.Hero.dCurrentHealthPct > 0.50d) || (FunkyBaseExtension.Settings.Barbarian.bFuryDumpAlways && FunkyGame.Hero.dCurrentEnergyPct >= 0.98 && FunkyGame.Hero.dCurrentHealthPct > 0.50d))); }
public override void Initialize() { Priority = SkillPriority.Medium; Cost = 10; Range = 15; PreCast = new SkillPreCast((SkillPrecastFlags.CheckEnergy | SkillPrecastFlags.CheckPlayerIncapacitated)); ClusterConditions.Add(new SkillClusterConditions(10d, 30f, 2, true)); SingleUnitCondition.Add(new UnitTargetConditions(TargetProperties.None, maxdistance: 20, MinimumHealthPercent: 0.95d, falseConditionalFlags: TargetProperties.Normal)); FcriteriaCombat = (u) => !FunkyGame.Hero.Class.bWaitingForSpecial && (!FunkyBaseExtension.Settings.Barbarian.bSelectiveWhirlwind || FunkyGame.Targeting.Cache.Environment.bAnyNonWWIgnoreMobsInRange || !CacheIDLookup.hashActorSNOWhirlwindIgnore.Contains(u.SNOID)) && // If they have battle-rage, make sure it's up (!Hotbar.HasPower(SNOPower.Barbarian_BattleRage) || (Hotbar.HasPower(SNOPower.Barbarian_BattleRage) && Hotbar.HasBuff(SNOPower.Barbarian_BattleRage))); }
public override void Initialize() { WaitVars = new WaitLoops(1, 1, true); Cost = 30; Range = 10; Priority = SkillPriority.Medium; PreCast = new SkillPreCast((SkillPrecastFlags.CheckEnergy | SkillPrecastFlags.CheckCanCast | SkillPrecastFlags.CheckRecastTimer | SkillPrecastFlags.CheckPlayerIncapacitated)); ClusterConditions.Add(new SkillClusterConditions(4d, 18f, 3, true)); SingleUnitCondition.Add(new UnitTargetConditions(TargetProperties.None, maxdistance: 10, falseConditionalFlags: TargetProperties.Normal)); FcriteriaCombat = (u) => (!Hotbar.HasPower(SNOPower.Monk_SweepingWind) || (Hotbar.HasPower(SNOPower.Monk_SweepingWind) && Hotbar.HasBuff(SNOPower.Monk_SweepingWind))) && (!FunkyGame.Hero.Class.bWaitingForSpecial || FunkyGame.Hero.dCurrentEnergy >= FunkyGame.Hero.Class.iWaitingReservedAmount); }
///<summary> ///Sets criteria based on object given. ///</summary> internal virtual Skill AbilitySelector(CacheUnit obj, bool IgnoreOutOfRange = false) { //Reset default attack can use CanUseDefaultAttack = !Hotbar.HasPower(DefaultAttack.Power) ? false : true; //Reset waiting for special! bWaitingForSpecial = false; ConditionCriteraTypes criterias = ConditionCriteraTypes.All; //Although the unit is a cluster exception.. we should verify it is not a clustered object. if (obj.IsClusterException && obj.BeingIgnoredDueToClusterLogic) { criterias = ConditionCriteraTypes.SingleTarget; } return(AbilitySelector(criterias, IgnoreOutOfRange, obj)); }
public override void Initialize() { Cooldown = 1000; WaitVars = new WaitLoops(2, 2, true); Cost = 50; Priority = SkillPriority.High; PreCast = new SkillPreCast((SkillPrecastFlags.CheckEnergy | SkillPrecastFlags.CheckCanCast | SkillPrecastFlags.CheckRecastTimer | SkillPrecastFlags.CheckPlayerIncapacitated)); //UnitsWithinRangeConditions = new Tuple<RangeIntervals, int>(RangeIntervals.Range_25, 7); //ElitesWithinRangeConditions = new Tuple<RangeIntervals, int>(RangeIntervals.Range_25, 3); SingleUnitCondition.Add(new UnitTargetConditions(TargetProperties.Boss, 23, 7, 0.95d)); SingleUnitCondition.Add(new UnitTargetConditions(TargetProperties.None, 23, 7, 0.95d, TargetProperties.Normal | TargetProperties.Boss)); ClusterConditions.Add(new SkillClusterConditions(10d, 24f, 4, false, 0, ClusterProperties.Large, 10f, false)); FcriteriaCombat = (u) => { if (LastConditionPassed == ConditionCriteraTypes.SingleTarget) { return(true); //special and fast.. } //Use every 5.5s when 7+ units are within 25f. if (LastConditionPassed == ConditionCriteraTypes.UnitsInRange && LastUsedMilliseconds > 5500 && !FunkyGame.Hero.Class.bWaitingForSpecial) { return(true); } if (!Hotbar.HasPower(SNOPower.Monk_ExplodingPalm) || !u.SkillsUsedOnObject.ContainsKey(SNOPower.Monk_ExplodingPalm)) { return(true); //Non Exploding Palm Check } if (DateTime.Now.Subtract(u.SkillsUsedOnObject[SNOPower.Monk_ExplodingPalm]).TotalSeconds < 9 && u.CurrentHealthPct < 0.10d) { return(true); } return(false); }; }
public override void Initialize() { WaitVars = new WaitLoops(0, 0, true); Cost = 35; Range = 28; IsDestructiblePower = true; Priority = SkillPriority.Medium; PreCast = new SkillPreCast((SkillPrecastFlags.CheckPlayerIncapacitated | SkillPrecastFlags.CheckEnergy | SkillPrecastFlags.CheckCanCast)); FcriteriaCombat = (u) => (!HasSignatureAbility() || Hotbar.GetBuffStacks(SNOPower.Wizard_EnergyTwister) < 1) && (FunkyGame.Targeting.Cache.Environment.iElitesWithinRange[(int)RangeIntervals.Range_30] >= 1 || FunkyGame.Targeting.Cache.Environment.iAnythingWithinRange[(int)RangeIntervals.Range_25] >= 1 || u.TargetInfo.RadiusDistance <= 12f) && (!Hotbar.HasPower(SNOPower.Wizard_Electrocute) || !u.IsFast) && (FunkyGame.Hero.dCurrentEnergy >= 35); }
public override void Initialize() { Priority = SkillPriority.Medium; Cost = 20; PreCast = new SkillPreCast((SkillPrecastFlags.CheckEnergy | SkillPrecastFlags.CheckCanCast | SkillPrecastFlags.CheckPlayerIncapacitated)); FcriteriaBuff = () => FunkyBaseExtension.Settings.General.OutOfCombatMovement && !Hotbar.HasBuff(Power); FcriteriaCombat = (u) => (!Hotbar.HasBuff(SNOPower.Barbarian_Sprint) && FunkyBaseExtension.Settings.General.OutOfCombatMovement) || (((FunkyBaseExtension.Settings.Barbarian.bFuryDumpWrath && FunkyGame.Hero.dCurrentEnergyPct >= 0.95 && Hotbar.HasBuff(SNOPower.Barbarian_WrathOfTheBerserker)) || (FunkyBaseExtension.Settings.Barbarian.bFuryDumpAlways && FunkyGame.Hero.dCurrentEnergyPct >= 0.95) || ((FunkyGame.Hero.Class.Abilities[SNOPower.Barbarian_Sprint].AbilityUseTimer() && !Hotbar.HasBuff(SNOPower.Barbarian_Sprint)) && // Always keep up if we are whirlwinding, or if the target is a goblin (Hotbar.HasPower(SNOPower.Barbarian_Whirlwind) || u.IsTreasureGoblin))) && (!Hotbar.HasPower(SNOPower.Barbarian_BattleRage) || (Hotbar.HasPower(SNOPower.Barbarian_BattleRage) && Hotbar.HasBuff(SNOPower.Barbarian_BattleRage)))); }
public override void Initialize() { base.Test = (ref CacheObject obj) => { if (obj == null) { // See if we should wait for milliseconds for possible loot drops before continuing run if (DateTime.Now.Subtract(FunkyGame.Targeting.Cache.lastHadUnitInSights).TotalMilliseconds <= FunkyBaseExtension.Settings.General.AfterCombatDelay && DateTime.Now.Subtract(FunkyGame.Targeting.Cache.lastHadEliteUnitInSights).TotalMilliseconds <= 10000 || //Cut the delay time in half for non-elite monsters! DateTime.Now.Subtract(FunkyGame.Targeting.Cache.lastHadUnitInSights).TotalMilliseconds <= FunkyBaseExtension.Settings.General.AfterCombatDelay) { obj = new CacheObject(FunkyGame.Hero.Position, TargetType.NoMovement, 20000, "WaitForLootDrops", 2f, -1); return(true); } //Herbfunks wait after loot containers are opened. 3s for rare chests, half the settings delay for everything else. if ((DateTime.Now.Subtract(FunkyGame.Targeting.Cache.lastHadRareChestAsTarget).TotalMilliseconds <= 3750) || (DateTime.Now.Subtract(FunkyGame.Targeting.Cache.lastHadContainerAsTarget).TotalMilliseconds <= (FunkyBaseExtension.Settings.General.AfterCombatDelay * 1.25))) { obj = new CacheObject(FunkyGame.Hero.Position, TargetType.NoMovement, 20000, "ContainerLootDropsWait", 2f, -1); return(true); } if (DateTime.Now.Subtract(FunkyGame.Targeting.Cache.lastSeenCursedShrine).TotalMilliseconds <= (1000)) { if (FunkyGame.AdventureMode && SettingAdventureMode.AdventureModeSettingsTag.AllowCombatModifications && FunkyGame.Bounty.CurrentBountyCacheEntry != null && FunkyGame.Bounty.CurrentBountyCacheEntry.Type == BountyTypes.CursedEvent) { Logger.DBLog.Info("[Funky] Cursed Object Found During Cursed Bounty -- Enabling LOS movement for all Units!"); SettingLOSMovement.LOSSettingsTag.MiniumRangeObjects = 10; SettingLOSMovement.LOSSettingsTag.MaximumRange = 125; FunkyGame.Game.AllowAnyUnitForLOSMovement = true; SettingCluster.ClusterSettingsTag = SettingCluster.DisabledClustering; } obj = new CacheObject(FunkyGame.Hero.Position, TargetType.NoMovement, 20000, "CursedShrineWait", 2f, -1); return(true); } if (DateTime.Now.Subtract(FunkyGame.Targeting.Cache.lastHadSwitchAsTarget).TotalMilliseconds <= (4000)) { obj = new CacheObject(FunkyGame.Hero.Position, TargetType.NoMovement, 20000, "SwitchWait", 2f, -1); return(true); } // Finally, a special check for waiting for wrath of the berserker cooldown before engaging Azmodan if (Hotbar.HasPower(SNOPower.Barbarian_WrathOfTheBerserker) && FunkyBaseExtension.Settings.Barbarian.bWaitForWrath && !FunkyGame.Hero.Class.Abilities[SNOPower.Barbarian_WrathOfTheBerserker].AbilityUseTimer() && FunkyGame.Hero.CurrentWorldDynamicID == 121214 && (Vector3.Distance(FunkyGame.Hero.Position, new Vector3(711.25f, 716.25f, 80.13903f)) <= 40f || Vector3.Distance(FunkyGame.Hero.Position, new Vector3(546.8467f, 551.7733f, 1.576313f)) <= 40f)) { Logger.DBLog.InfoFormat("[Funky] Waiting for Wrath Of The Berserker cooldown before continuing to Azmodan."); obj = new CacheObject(FunkyGame.Hero.Position, TargetType.NoMovement, 20000, "GilesWaitForWrath", 0f, -1); InactivityDetector.Reset(); return(true); } // And a special check for wizard archon if (Hotbar.HasPower(SNOPower.Wizard_Archon) && !FunkyGame.Hero.Class.Abilities[SNOPower.Wizard_Archon].AbilityUseTimer() && FunkyBaseExtension.Settings.Wizard.bWaitForArchon && ZetaDia.CurrentWorldId == 121214 && (Vector3.Distance(FunkyGame.Hero.Position, new Vector3(711.25f, 716.25f, 80.13903f)) <= 40f || Vector3.Distance(FunkyGame.Hero.Position, new Vector3(546.8467f, 551.7733f, 1.576313f)) <= 40f)) { Logger.DBLog.InfoFormat("[Funky] Waiting for Wizard Archon cooldown before continuing to Azmodan."); obj = new CacheObject(FunkyGame.Hero.Position, TargetType.NoMovement, 20000, "GilesWaitForArchon", 0f, -1); InactivityDetector.Reset(); return(true); } // And a very sexy special check for WD BigBadVoodoo if (Hotbar.HasPower(SNOPower.Witchdoctor_BigBadVoodoo) && !PowerManager.CanCast(SNOPower.Witchdoctor_BigBadVoodoo) && ZetaDia.CurrentWorldId == 121214 && (Vector3.Distance(FunkyGame.Hero.Position, new Vector3(711.25f, 716.25f, 80.13903f)) <= 40f || Vector3.Distance(FunkyGame.Hero.Position, new Vector3(546.8467f, 551.7733f, 1.576313f)) <= 40f)) { Logger.DBLog.InfoFormat("[Funky] Waiting for WD BigBadVoodoo cooldown before continuing to Azmodan."); obj = new CacheObject(FunkyGame.Hero.Position, TargetType.NoMovement, 20000, "GilesWaitForVoodooo", 0f, -1); InactivityDetector.Reset(); return(true); } //Currently preforming an interactive profile behavior (check if in town and not vendoring) if (FunkyGame.Game.InteractableCachedObject != null && (!FunkyGame.Hero.bIsInTown || !BrainBehavior.IsVendoring)) { if (FunkyGame.Game.InteractableCachedObject.Position.Distance(FunkyGame.Hero.Position) > 50f) { //if (FunkyGame.Targeting.Cache.LastCachedTarget.Position != Bot.Game.Profile.InteractableCachedObject.Position) // Navigator.Clear(); //Generate the path here so we can start moving.. Navigation.Navigation.NP.MoveTo(FunkyGame.Game.InteractableCachedObject.Position, "ReturnToOOCLoc", true); //Setup a temp target that the handler will use obj = new CacheObject(FunkyGame.Game.InteractableCachedObject.Position, TargetType.LineOfSight, 1d, "ReturnToOOCLoc", 10f, FunkyGame.Game.InteractableCachedObject.RAGUID); return(true); } } //Check if we engaged in combat.. bool EngagedInCombat = false; float distanceFromStart = 0f; if (!FunkyGame.Targeting.Cache.LastCachedTarget.Equals(ObjectCache.FakeCacheObject) && !FunkyGame.Targeting.Cache.Backtracking && FunkyGame.Targeting.Cache.StartingLocation != Vector3.Zero) { EngagedInCombat = true; distanceFromStart = FunkyGame.Hero.Position.Distance(FunkyGame.Targeting.Cache.StartingLocation); //lets see how far we are from our starting location. if (distanceFromStart > 20f && !Navigation.Navigation.CanRayCast(FunkyGame.Hero.Position, PlayerMover.vLastMoveTo, UseSearchGridProvider: true)) { Logger.Write(LogLevel.Movement, "Updating Navigator in Target Refresh"); SkipAheadCache.ClearCache(); Navigator.Clear(); //Navigator.MoveTo(Funky.PlayerMover.vLastMoveTo, "original destination", true); } } //Check if our current path intersects avoidances. (When not in town, and not currently inside avoidance) if (!FunkyGame.Hero.bIsInTown && (FunkyBaseExtension.Settings.Avoidance.AttemptAvoidanceMovements) && //|| FunkyGame.Hero.CriticalAvoidance) Navigation.Navigation.NP.CurrentPath.Count > 0 && FunkyGame.Targeting.Cache.Environment.TriggeringAvoidances.Count == 0) { if (ObjectCache.Obstacles.TestVectorAgainstAvoidanceZones(FunkyGame.Hero.Position, Navigation.Navigation.NP.CurrentPath.Current)) { obj = new CacheObject(FunkyGame.Hero.Position, TargetType.NoMovement, 20000, "AvoidanceIntersection", 2.5f, -1); return(true); } } //Backtracking Check.. if (EngagedInCombat && FunkyBaseExtension.Settings.Backtracking.EnableBacktracking && distanceFromStart >= FunkyBaseExtension.Settings.Backtracking.MinimumDistanceFromStart) { FunkyGame.Targeting.Cache.Backtracking = true; obj = new CacheObject(FunkyGame.Targeting.Cache.StartingLocation, TargetType.Backtrack, 20000, "Backtracking", 2.5f); return(true); } } return(obj != null); }; }
///<summary> ///Tests the given avoidance type to see if it should be ignored either due to a buff or if health is greater than the avoidance HP. ///</summary> internal static bool IgnoreAvoidance(AvoidanceType thisAvoidance) { //Pylon Shield? if (Hotbar.HasBuff(SNOPower.Pages_Buff_Invulnerable)) { return(true); } //Countess Julias Cameo (Arcane Immunity) if (Equipment.ImmuneToArcane && thisAvoidance == AvoidanceType.ArcaneSentry) { return(true); } //Maras Kaleidoscope (Poison Immunity) if (Equipment.ImmuneToPoison && (thisAvoidance == AvoidanceType.PlagueCloud || thisAvoidance == AvoidanceType.PlagueHand || thisAvoidance == AvoidanceType.PoisonGas)) { return(true); } //Talisman of Aranoch if (Equipment.ImmuneToCold && (thisAvoidance == AvoidanceType.FrozenPulse || thisAvoidance == AvoidanceType.MalthaelDeathFog)) { return(true); } //Special Blackthorne's Set Bonus Check! if (Equipment.ImmuneToDescratorMoltenPlaguedAvoidances) { switch (thisAvoidance) { case AvoidanceType.Dececrator: case AvoidanceType.MoltenCore: case AvoidanceType.MoltenTrail: case AvoidanceType.PlagueCloud: case AvoidanceType.PlagueHand: return(true); } } double dThisHealthAvoid = FunkyBaseExtension.Settings.Avoidance.Avoidances[(int)thisAvoidance].Health; //if (!FunkyGame.Hero.CriticalAvoidance) //{ //Not Critical Avoidance, should we be in total ignorance because of a buff? // Monks with Serenity up ignore all AOE's if (FunkyGame.CurrentActorClass == ActorClass.Monk) { // Monks with serenity are immune if (Hotbar.HasPower(SNOPower.Monk_Serenity) && Hotbar.HasBuff(SNOPower.Monk_Serenity)) { return(true); } //Epiphany ignore frozen. if (Hotbar.HasPower(SNOPower.X1_Monk_Epiphany) && Hotbar.HasBuff(SNOPower.X1_Monk_Epiphany) && thisAvoidance == AvoidanceType.Frozen) { return(true); } } //Crusader Akarats Champion -- Ignore Frozen! if (FunkyGame.CurrentActorClass == ActorClass.Crusader && Hotbar.HasPower(SNOPower.X1_Crusader_AkaratsChampion) && Hotbar.HasBuff(SNOPower.X1_Crusader_AkaratsChampion) && thisAvoidance == AvoidanceType.Frozen) { return(true); } if (FunkyGame.CurrentActorClass == ActorClass.Barbarian && Hotbar.HasPower(SNOPower.Barbarian_WrathOfTheBerserker) && Hotbar.HasBuff(SNOPower.Barbarian_WrathOfTheBerserker)) { switch (thisAvoidance) { case AvoidanceType.Frozen: case AvoidanceType.ArcaneSentry: case AvoidanceType.Dececrator: case AvoidanceType.PlagueCloud: return(true); } } //} //Only procedee if health percent is necessary for avoidance! return(dThisHealthAvoid < FunkyGame.Hero.dCurrentHealthPct); }
public override RunStatus Tick(object context) { if (!Hotbar.HasPower(Power)) { return(RunStatus.Failure); } if (ContextChangeHandler != null && context == null) { CombatTargeting.Instance.Pulse(); context = ContextChangeHandler(null); } if (context == null) { return(RunStatus.Failure); } bool minReqs = ExtraCondition == null || ExtraCondition(context); if (!minReqs) { return(RunStatus.Failure); } if (!_isSpamming) { using (new PerformanceLogger(BelphegorSettings.Instance.Debug.IsDebugCanCastLogging, "CanCast")) { bool canCast = PowerManager.CanCast(Power); if (!canCast) { return(RunStatus.Failure); } } } Vector3 clickPosition = PositionRetriever != null?PositionRetriever(context) : Vector3.Zero; int worldId = DynamicWorldIdRetriever != null?DynamicWorldIdRetriever(context) : 0; int acdGuid = TargetGuidRetriever != null?TargetGuidRetriever(context) : -1; bool keepSpamming = KeepSpamming != null && KeepSpamming(context); bool castSucceeded = ZetaDia.Me.UsePower(Power, clickPosition, worldId, acdGuid); if (!castSucceeded) { return(RunStatus.Failure); } if (BelphegorSettings.Instance.Debug.IsDebugCastLoggingActive && !keepSpamming) { CastLogSw.Stop(); string castOn = acdGuid == -1 ? "at location " + clickPosition : "on Unit " + acdGuid.ToString(CultureInfo.InvariantCulture); Log.InfoFormat("Using Power: {0} {1}, delay from last cast is {2}ms", Power.ToString(), castOn, CastLogSw.ElapsedMilliseconds); CastLogSw.Restart(); } if (!_isSpamming && SucceedRunner != null) { SucceedRunner(context); } if (keepSpamming) { _isSpamming = true; if (BelphegorSettings.Instance.Debug.IsDebugCastLoggingActive) { CastLogSw.Stop(); string castOn = acdGuid == -1 ? "at location " + clickPosition : "on Unit " + acdGuid.ToString(CultureInfo.InvariantCulture); Log.InfoFormat("Using Power: Is Spamming {0} {1}, delay from last cast is {2}ms", Power.ToString(), castOn, CastLogSw.ElapsedMilliseconds); CastLogSw.Restart(); } return(RunStatus.Running); } _isSpamming = false; return(RunStatus.Success); }
internal virtual void RecreateAbilities() { ContainsAnyPrimarySkill = false; ContainsNonRangedCombatSkill = false; Abilities = new Dictionary <SNOPower, Skill>(); var uninitalizedSkills = new Dictionary <SNOPower, Skill>(); //Create the abilities foreach (var item in Hotbar.HotbarSkills) { Skill newAbility = FunkyGame.Hero.Class.CreateAbility(item.Power); if (newAbility.IsPrimarySkill) { ContainsAnyPrimarySkill = true; } //combat ability set property if (ObjectCache.CheckFlag((SkillExecutionFlags.ClusterLocation | SkillExecutionFlags.ClusterTarget | SkillExecutionFlags.ClusterTargetNearest | SkillExecutionFlags.Location | SkillExecutionFlags.Target), newAbility.ExecutionType)) { newAbility.IsCombat = true; } if (!ContainsNonRangedCombatSkill && !newAbility.IsRanged && !newAbility.IsProjectile && ObjectCache.CheckFlag((SkillExecutionFlags.Target | SkillExecutionFlags.ClusterTarget), newAbility.ExecutionType)) { ContainsNonRangedCombatSkill = true; } uninitalizedSkills.Add(item.Power, newAbility); Logger.DBLog.DebugFormat("[Funky] Added Skill {0} using RuneIndex {1}", newAbility.Power, newAbility.RuneIndex); } foreach (var item in uninitalizedSkills) { Skill skill = item.Value; skill.Initialize(); if (skill.IsPrimarySkill) { ContainsAnyPrimarySkill = true; } Skill.CreateSkillLogicConditions(ref skill); skill.SuccessfullyUsed += AbilitySuccessfullyUsed; Abilities.Add(item.Key, skill); Logger.DBLog.DebugFormat("[Funky] Skill {0} has been initalized", item.Key); } //Sort Abilities SortedAbilities = Abilities.Values.OrderByDescending(a => a.Priority).ThenBy(a => a.Range).ToList(); //No default rage generation Ability.. then we add the Instant Melee Ability. if (!ContainsAnyPrimarySkill) { Skill defaultAbility = FunkyGame.Hero.Class.DefaultAttack; defaultAbility.Initialize(); Skill.CreateSkillLogicConditions(ref defaultAbility); Abilities.Add(defaultAbility.Power, defaultAbility); //Hotbar.RuneIndexCache.Add(defaultAbility.Power, -1); Logger.DBLog.DebugFormat("[Funky] Added Skill {0}", defaultAbility.Power); //No Primary Skill.. Check if Default Attack can be used! if (!FunkyBaseExtension.Settings.Combat.AllowDefaultAttackAlways) { Logger.DBLog.Warn("**** Warning ****"); Logger.DBLog.Warn("No Primary Skill Found and Allow Default Attack Always Is Disabled!"); Logger.DBLog.Warn("This may cause idles to occur.. Enable AllowDefaultAttackAlways setting found under Combat Tab."); Logger.DBLog.Warn("**** Warning ****"); } } LastUsedAbilities = new Skill[Abilities.Count]; int indexCount = 0; foreach (var ability in Abilities.Values) { LastUsedAbilities[indexCount] = ability; indexCount++; } // if (AC == ActorClass.Monk && Hotbar.HasPower(SNOPower.Monk_ExplodingPalm)) { UsesDOTDPSAbility = true; } if (AC == ActorClass.Witchdoctor && (Hotbar.HasPower(SNOPower.Witchdoctor_Haunt) || Hotbar.HasPower(SNOPower.Witchdoctor_Locust_Swarm))) { UsesDOTDPSAbility = true; } if (AC == ActorClass.Barbarian && Hotbar.HasPower(SNOPower.Barbarian_Rend)) { UsesDOTDPSAbility = true; } LastUsedAbility = LastUsedAbilities[0]; PowerPrime = DefaultAttack; }
public override void Initialize() { if (Equipment.CheckLegendaryItemCount(LegendaryItemTypes.Quetzalcoatl)) { recastTime = 5; } bool hotbarContainsLoctusSwarm = Hotbar.HasPower(SNOPower.Witchdoctor_Locust_Swarm); //since we can only track one DOTDPS, we track locus swarm and cast this if (hotbarContainsLoctusSwarm) { SingleUnitCondition.Add(new UnitTargetConditions(TargetProperties.None, maxdistance: 45)); SingleUnitCondition.Add(new UnitTargetConditions(TargetProperties.None, maxdistance: -1, MinimumHealthPercent: 0.95d, falseConditionalFlags: TargetProperties.Normal)); } else { SingleUnitCondition.Add(new UnitTargetConditions(TargetProperties.None, maxdistance: 45, falseConditionalFlags: TargetProperties.DOTDPS)); SingleUnitCondition.Add(new UnitTargetConditions(TargetProperties.None, maxdistance: -1, MinimumHealthPercent: 0.95d, falseConditionalFlags: TargetProperties.Normal | TargetProperties.DOTDPS)); } WaitVars = new WaitLoops(0, 0, false); Cost = 50; Range = 45; Priority = SkillPriority.High; ShouldTrack = true; if (!FunkyGame.Hero.Class.ContainsAnyPrimarySkill) { SingleUnitCondition.Add(new UnitTargetConditions(TargetProperties.None)); IsPrimarySkill = true; Priority = SkillPriority.Low; } var precastflags = SkillPrecastFlags.CheckPlayerIncapacitated | SkillPrecastFlags.CheckCanCast; if (hotbarContainsLoctusSwarm) { precastflags |= SkillPrecastFlags.CheckRecastTimer; } PreCast = new SkillPreCast(precastflags); //PreCast.Criteria += (s) => !Hotbar.HasDebuff(SNOPower.Succubus_BloodStar); FcriteriaCombat = (u) => { if (u.SkillsUsedOnObject.ContainsKey(Power)) { //If we have Creeping Death, then we ignore any units that we already cast upon. if (Hotbar.PassivePowers.Contains(SNOPower.Witchdoctor_Passive_CreepingDeath)) { return(false); } return(DateTime.Now.Subtract(u.SkillsUsedOnObject[Power]).TotalSeconds > recastTime); } return(true); }; }
public override void Initialize() { WaitVars = new WaitLoops(0, 1, true); Cost = 10; if (RuneIndex != 4) { IsDestructiblePower = true; Range = 50; Priority = SkillPriority.Medium; PreCast = new SkillPreCast((SkillPrecastFlags.CheckPlayerIncapacitated | SkillPrecastFlags.CheckEnergy)); ClusterConditions.Add(new SkillClusterConditions(4d, 40, 2, true)); SingleUnitCondition.Add(new UnitTargetConditions(TargetProperties.None, maxdistance: 50, MinimumHealthPercent: 0.95d, falseConditionalFlags: TargetProperties.Normal)); FcriteriaCombat = (u) => !FunkyGame.Hero.Class.bWaitingForSpecial && ((!Hotbar.HasPower(SNOPower.DemonHunter_ClusterArrow)) || LastUsedMilliseconds >= 110000); } else { //Shuriken Cloud _executiontype = SkillExecutionFlags.Buff; PreCast = new SkillPreCast(SkillPrecastFlags.CheckCanCast); Priority = SkillPriority.High; IsBuff = true; FcriteriaBuff = () => !Hotbar.HasBuff(SNOPower.DemonHunter_Chakram); FcriteriaCombat = (u) => !Hotbar.HasBuff(SNOPower.DemonHunter_Chakram); } }
public override void Initialize() { if (RuneIndex == 2) { recastTime = 15; } if (Equipment.CheckLegendaryItemCount(LegendaryItemTypes.Quetzalcoatl)) { recastTime = recastTime / 2; } bool hotbarContainsDOT = Hotbar.HasPower(SNOPower.Witchdoctor_Haunt) || (Hotbar.HasPower(SNOPower.Witchdoctor_Piranhas)); Range = 14; Cost = 196; var precastflags = SkillPrecastFlags.CheckPlayerIncapacitated | SkillPrecastFlags.CheckCanCast; if (!hotbarContainsDOT) { ClusterConditions.Add(new SkillClusterConditions(5d, 35, 4, true, 0.25d)); SingleUnitCondition.Add(new UnitTargetConditions(TargetProperties.None, maxdistance: 20, MinimumHealthPercent: 0.99d, falseConditionalFlags: TargetProperties.DOTDPS)); //Any non-normal unit (Any Range!) SingleUnitCondition.Add(new UnitTargetConditions(TargetProperties.None, maxdistance: -1, MinimumHealthPercent: 0.99d, falseConditionalFlags: TargetProperties.Normal | TargetProperties.DOTDPS)); } else { ClusterConditions.Add(new SkillClusterConditions(5d, 35, 4, true)); SingleUnitCondition.Add(new UnitTargetConditions(TargetProperties.None, maxdistance: 20, MinimumHealthPercent: 0.99d, falseConditionalFlags: TargetProperties.Weak)); //Any non-normal unit (Any Range!) SingleUnitCondition.Add(new UnitTargetConditions(TargetProperties.None, maxdistance: -1, MinimumHealthPercent: 0.99d, falseConditionalFlags: TargetProperties.Normal)); precastflags |= SkillPrecastFlags.CheckRecastTimer; } WaitVars = new WaitLoops(1, 1, true); Priority = SkillPriority.High; PreCast = new SkillPreCast(precastflags); ShouldTrack = true; PreCast.Criteria += (s) => !Hotbar.HasDebuff(SNOPower.Succubus_BloodStar); FcriteriaCombat = (u) => { if (u.SkillsUsedOnObject.ContainsKey(Power)) { //If we have Creeping Death, then we ignore any units that we already cast upon. if (Hotbar.PassivePowers.Contains(SNOPower.Witchdoctor_Passive_CreepingDeath)) { return(false); } //Runeindex 2 has duration of 16s instead of 7s return(DateTime.Now.Subtract(u.SkillsUsedOnObject[Power]).TotalSeconds > (RuneIndex == 2?15:7)); } return(true); }; }
internal RunStatus TargetMoveTo(CacheObject obj) { #region DebugInfo if (FunkyBaseExtension.Settings.Debugging.DebugStatusBar) { string Action = "[Move-"; switch (obj.targetType.Value) { case TargetType.Avoidance: Action += "Avoid] "; break; case TargetType.Fleeing: Action += "Flee] "; break; case TargetType.Backtrack: Action += "BackTrack] "; break; case TargetType.LineOfSight: Action += "LOS] "; break; case TargetType.Unit: if (FunkyGame.Navigation.groupRunningBehavior && FunkyGame.Navigation.groupingCurrentUnit != null && FunkyGame.Navigation.groupingCurrentUnit == obj) { Action += "Grouping] "; } else { Action += "Combat] "; } break; case TargetType.Item: case TargetType.Gold: case TargetType.Globe: Action += "Pickup] "; break; case TargetType.Interactable: Action += "Interact] "; break; case TargetType.Container: Action += "Open] "; break; case TargetType.Destructible: case TargetType.Barricade: Action += "Destroy] "; break; case TargetType.Shrine: Action += "Click] "; break; } FunkyGame.sStatusText = Action + " "; FunkyGame.sStatusText += "Target=" + FunkyGame.Targeting.Cache.CurrentTarget.InternalName + " C-Dist=" + Math.Round(FunkyGame.Targeting.Cache.CurrentTarget.CentreDistance, 2) + ". " + "R-Dist=" + Math.Round(FunkyGame.Targeting.Cache.CurrentTarget.RadiusDistance, 2) + ". "; if (FunkyGame.Targeting.Cache.CurrentTarget.targetType.Value == TargetType.Unit && FunkyGame.Hero.Class.PowerPrime.Power != SNOPower.None) { FunkyGame.sStatusText += "Power=" + FunkyGame.Hero.Class.PowerPrime.Power + " (range " + FunkyGame.Hero.Class.PowerPrime.MinimumRange + ") "; } FunkyGame.sStatusText += "Weight=" + FunkyGame.Targeting.Cache.CurrentTarget.Weight; BotMain.StatusText = FunkyGame.sStatusText; FunkyGame.bResetStatusText = true; } #endregion // Are we currently incapacitated? If so then wait... if (FunkyGame.Hero.bIsIncapacitated || FunkyGame.Hero.bIsRooted) { return(RunStatus.Running); } //Ignore skip ahead cache for LOS movements.. if (FunkyBaseExtension.Settings.Debugging.SkipAhead && obj.targetType.Value != TargetType.LineOfSight) { SkipAheadCache.RecordSkipAheadCachePoint(); } // Some stuff to avoid spamming usepower EVERY loop, and also to detect stucks/staying in one place for too long bool bForceNewMovement = false; //Herbfunk: Added this to prevent stucks attempting to move to a target blocked. (Case: 3 champs behind a wall, within range but could not engage due to being on the other side.) #region Non Movement Counter Reached if (NonMovementCounter > FunkyBaseExtension.Settings.Plugin.MovementNonMovementCount) { Logger.Write(LogLevel.Movement, "non movement counter reached {0}", NonMovementCounter); if (obj.Actortype.HasValue && obj.Actortype.Value.HasFlag(ActorType.Item)) { if (NonMovementCounter > 250) { //Are we stuck? if (!Navigation.Navigation.MGP.CanStandAt(FunkyGame.Hero.Position)) { Logger.DBLog.InfoFormat("Character is stuck inside non-standable location.. attempting townportal cast.."); ZetaDia.Me.UseTownPortal(); NonMovementCounter = 0; return(RunStatus.Running); } } //Check if we can walk to this location from current location.. if (!Navigation.Navigation.CanRayCast(FunkyGame.Hero.Position, CurrentTargetLocation, UseSearchGridProvider: true)) { obj.RequiresLOSCheck = true; obj.BlacklistLoops = 50; Logger.Write(LogLevel.Movement, "Ignoring Item {0} -- due to RayCast Failure!", obj.InternalName); FunkyGame.Targeting.Cache.bForceTargetUpdate = true; return(RunStatus.Running); } } else if (ObjectCache.CheckFlag(obj.targetType.Value, TargetType.LineOfSight | TargetType.Backtrack)) { Logger.Write(LogLevel.LineOfSight, "Line of Sight Movement Stalled!"); //FunkyGame.Navigation.LOSmovementObject = null; Navigation.Navigation.NP.Clear(); FunkyGame.Targeting.Cache.bForceTargetUpdate = true; NonMovementCounter = 0; // Reset the emergency loop counter and return success return(RunStatus.Running); } else { Logger.Write(LogLevel.Movement, "Ignoring obj {0} ", obj.InternalName + " _ SNO:" + obj.SNOID); obj.BlacklistLoops = 50; obj.RequiresLOSCheck = true; FunkyGame.Targeting.Cache.bForceTargetUpdate = true; NonMovementCounter = 0; // Reset the emergency loop counter and return success return(RunStatus.Running); } } #endregion //Do a priority check for nearby obstacle objects. FunkyGame.Navigation.ObstaclePrioritizeCheck(15f); #region Evaluate Last Action // Position didn't change last update.. check if we are stuck! if (DateTime.Now.Subtract(lastPositionChange).TotalMilliseconds > 150 && (!FunkyGame.Hero.IsMoving || FunkyGame.Hero.currentMovementState == MovementState.WalkingInPlace || FunkyGame.Hero.currentMovementState.Equals(MovementState.None))) { bForceNewMovement = true; if (DateTime.Now.Subtract(LastMovementDuringCombat).TotalMilliseconds >= 250) { LastMovementDuringCombat = DateTime.Now; BlockedMovementCounter++; // Tell target finder to prioritize close-combat targets incase we were bodyblocked #region TargetingPriortize switch (BlockedMovementCounter) { case 2: case 3: if (FunkyGame.Navigation.groupRunningBehavior) { Logger.Write(LogLevel.Movement, "Grouping Behavior stopped due to blocking counter"); FunkyGame.Navigation.GroupingFinishBehavior(); FunkyGame.Navigation.groupingSuspendedDate = DateTime.Now.AddMilliseconds(4000); FunkyGame.Targeting.Cache.bForceTargetUpdate = true; return(RunStatus.Running); } if (!ObjectCache.CheckFlag(obj.targetType.Value, TargetType.AvoidanceMovements)) { //Finally try raycasting to see if navigation is possible.. if (obj.Actortype.HasValue && (obj.Actortype.Value == ActorType.Gizmo || obj.Actortype.Value == ActorType.Monster)) { Vector3 hitTest; // No raycast available, try and force-ignore this for a little while, and blacklist for a few seconds if (Navigator.Raycast(FunkyGame.Hero.Position, obj.Position, out hitTest)) { if (hitTest != Vector3.Zero) { obj.RequiresLOSCheck = true; obj.BlacklistLoops = 10; Logger.Write(LogLevel.Movement, "Ignoring object " + obj.InternalName + " due to not moving and raycast failure!", true); FunkyGame.Targeting.Cache.bForceTargetUpdate = true; return(RunStatus.Running); } } } else if (obj.targetType.Value == TargetType.Item) { obj.BlacklistLoops = 10; FunkyGame.Targeting.Cache.bForceTargetUpdate = true; } } else { if (!Navigation.Navigation.CanRayCast(FunkyGame.Hero.Position, CurrentTargetLocation, NavCellFlags.AllowWalk)) { Logger.Write(LogLevel.Movement, "Cannot continue with avoidance movement due to raycast failure!"); BlockedMovementCounter = 0; FunkyGame.Navigation.CurrentGPArea.BlacklistLastSafespot(); FunkyGame.Navigation.vlastSafeSpot = Vector3.Zero; FunkyGame.Targeting.Cache.bForceTargetUpdate = true; return(RunStatus.Running); } } break; } #endregion return(RunStatus.Running); } } else { // Movement has been made, so count the time last moved! LastMovementDuringCombat = DateTime.Now; } #endregion // See if we want to ACTUALLY move, or are just waiting for the last move command... if (!bForceNewMovement && IsAlreadyMoving && CurrentTargetLocation == LastTargetLocation && DateTime.Now.Subtract(LastMovementCommand).TotalMilliseconds <= 100) { return(RunStatus.Running); } // If we're doing avoidance, globes or backtracking, try to use special abilities to move quicker #region SpecialMovementChecks if (ObjectCache.CheckFlag(obj.targetType.Value, FunkyBaseExtension.Settings.Combat.CombatMovementTargetTypes)) { Skill MovementPower; Vector3 MovementVector = FunkyGame.Hero.Class.FindCombatMovementPower(out MovementPower, obj.Position); if (MovementVector != Vector3.Zero) { ZetaDia.Me.UsePower(MovementPower.Power, MovementVector, FunkyGame.Hero.CurrentWorldDynamicID, -1); MovementPower.OnSuccessfullyUsed(); // Store the current destination for comparison incase of changes next loop LastTargetLocation = CurrentTargetLocation; // Reset total body-block count, since we should have moved //if (DateTime.Now.Subtract(FunkyGame.Targeting.Cache.Environment.lastForcedKeepCloseRange).TotalMilliseconds>=2000) BlockedMovementCounter = 0; FunkyGame.Hero.Class.PowerPrime.WaitLoopsBefore = 5; return(RunStatus.Running); } //Special Whirlwind Code if (FunkyGame.Hero.Class.AC == ActorClass.Barbarian && Hotbar.HasPower(SNOPower.Barbarian_Whirlwind)) { // Whirlwind against everything within range (except backtrack points) if (FunkyGame.Hero.dCurrentEnergy >= 10 && FunkyGame.Targeting.Cache.Environment.iAnythingWithinRange[(int)RangeIntervals.Range_20] >= 1 && obj.DistanceFromTarget <= 12f && (!Hotbar.HasPower(SNOPower.Barbarian_Sprint) || Hotbar.HasBuff(SNOPower.Barbarian_Sprint)) && (ObjectCache.CheckFlag(obj.targetType.Value, TargetType.AvoidanceMovements | TargetType.Gold | TargetType.Globe) == false) && (obj.targetType.Value != TargetType.Unit || (obj.targetType.Value == TargetType.Unit && !obj.IsTreasureGoblin && (!FunkyBaseExtension.Settings.Barbarian.bSelectiveWhirlwind || FunkyGame.Targeting.Cache.Environment.bAnyNonWWIgnoreMobsInRange || !CacheIDLookup.hashActorSNOWhirlwindIgnore.Contains(obj.SNOID))))) { // Special code to prevent whirlwind double-spam, this helps save fury bool bUseThisLoop = SNOPower.Barbarian_Whirlwind != FunkyGame.Hero.Class.LastUsedAbility.Power; if (!bUseThisLoop) { if (FunkyGame.Hero.Class.Abilities[SNOPower.Barbarian_Whirlwind].LastUsedMilliseconds >= 200) { bUseThisLoop = true; } } if (bUseThisLoop) { ZetaDia.Me.UsePower(SNOPower.Barbarian_Whirlwind, CurrentTargetLocation, FunkyGame.Hero.CurrentWorldDynamicID); FunkyGame.Hero.Class.Abilities[SNOPower.Barbarian_Whirlwind].OnSuccessfullyUsed(); } // Store the current destination for comparison incase of changes next loop LastTargetLocation = CurrentTargetLocation; BlockedMovementCounter = 0; return(RunStatus.Running); } } } #endregion //Special Movement Check for Steed Charge and Spirit Walk if (FunkyGame.Hero.Class.LastUsedAbility.IsSpecialMovementSkill && FunkyGame.Hero.Class.HasSpecialMovementBuff() && ObjectCache.CheckFlag(obj.targetType.Value, TargetType.Unit)) { //Logger.DBLog.DebugFormat("Preforming ZigZag for special movement skill activation!"); FunkyGame.Navigation.vPositionLastZigZagCheck = FunkyGame.Hero.Position; if (FunkyGame.Hero.Class.ShouldGenerateNewZigZagPath()) { FunkyGame.Hero.Class.GenerateNewZigZagPath(); } CurrentTargetLocation = FunkyGame.Navigation.vSideToSideTarget; } // Now for the actual movement request stuff IsAlreadyMoving = true; UseTargetMovement(obj, bForceNewMovement); // Store the current destination for comparison incase of changes next loop LastMovementAttempted = DateTime.Now; LastTargetLocation = CurrentTargetLocation; //Check if we moved at least 5f.. if (LastPlayerLocation.Distance(FunkyGame.Hero.Position) <= 5f) { NonMovementCounter++; } else { NonMovementCounter = 0; BlockedMovementCounter = 0; } //store player location LastPlayerLocation = FunkyGame.Hero.Position; return(RunStatus.Running); }
private bool HasSignatureAbility() { return(Hotbar.HasPower(SNOPower.Wizard_MagicMissile) || Hotbar.HasPower(SNOPower.Wizard_ShockPulse) || Hotbar.HasPower(SNOPower.Wizard_SpectralBlade) || Hotbar.HasPower(SNOPower.Wizard_Electrocute)); }