private static Composite MovementMoveStop(UnitSelectionDelegate toUnit, double range) { return(new Decorator( ret => THSettings.Instance.AutoMove && !IsOverrideModeOn && toUnit != null && toUnit(ret) != null && toUnit(ret) != Me && toUnit(ret).IsAlive&& Me.IsMoving && !toUnit(ret).IsMoving&& IsEnemy(toUnit(ret)) && toUnit(ret).Distance - toUnit(ret).CombatReach < 3 && toUnit(ret).InLineOfSight, new Action(ret => { //if (DateTime.Now < MovementDelay && !Me.IsBehind(toUnit(ret))) //{ // Logging.Write(LogLevel.Diagnostic, // DateTime.Now.ToString("ss:fff ") + "IsMovingBehind"); // return RunStatus.Failure; //} Navigator.PlayerMover.MoveStop(); //Logging.Write(LogLevel.Diagnostic, // DateTime.Now.ToString("ss:fff ") + "MovementMoveStop"); return RunStatus.Failure; }))); }
/// <summary> /// Creates a behavior to cast a spell by name, with special requirements, on a specific unit. Returns /// RunStatus.Success if successful, RunStatus.Failure otherwise. /// </summary> /// <remarks> /// Created 5/2/2011. /// </remarks> /// <param name = "name">The name.</param> /// <param name="checkMovement"></param> /// <param name = "onUnit">The on unit.</param> /// <param name = "requirements">The requirements.</param> /// <returns>.</returns> public static Composite CastLikeMonk(string name, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements) { return(new PrioritySelector( new Decorator(ret => requirements != null && onUnit != null && requirements(ret) && onUnit(ret) != null && name != null && CanCastLikeMonk(name, onUnit(ret)), new PrioritySelector( new Sequence( // cast the spell new Action(ret => { wasMonkSpellQueued = (Spell.GcdActive || Me.IsCasting || Me.ChanneledSpell != null); Logger.Write(Color.Aquamarine, string.Format("*{0} on {1} at {2:F1} yds at {3:F1}%", name, onUnit(ret).SafeName(), onUnit(ret).Distance, onUnit(ret).HealthPercent)); Spell.CastPrimative(name, onUnit(ret)); }), // if spell was in progress before cast (we queued this one) then wait in progress one to finish new WaitContinue( new TimeSpan(0, 0, 0, 0, (int)SingularRoutine.Latency << 1), ret => !wasMonkSpellQueued || !(Spell.GcdActive || Me.IsCasting || Me.ChanneledSpell != null), new ActionAlwaysSucceed() ), // wait for this cast to appear on the GCD or Spell Casting indicators new WaitContinue( new TimeSpan(0, 0, 0, 0, (int)SingularRoutine.Latency << 1), ret => Spell.GcdActive || Me.IsCasting || Me.ChanneledSpell != null, new ActionAlwaysSucceed() ) ) ) ) )); }
/// <summary> /// Creates a behavior to cast a spell by name, with special requirements, on a specific unit. Returns /// RunStatus.Success if successful, RunStatus.Failure otherwise. /// </summary> /// <remarks> /// Created 5/2/2011. /// </remarks> /// <param name = "name">The name.</param> /// <param name="checkMovement"></param> /// <param name = "onUnit">The on unit.</param> /// <param name = "requirements">The requirements.</param> /// <returns>.</returns> public static Composite CastLikeMonk(string name, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements) { return(new PrioritySelector( new Decorator(ret => requirements != null && onUnit != null && requirements(ret) && onUnit(ret) != null && name != null && CanCastLikeMonk(name, onUnit(ret)), new PrioritySelector( // set context to whether currently busy with GCD or Cast ctx => (bool)(SpellManager.GlobalCooldown || Me.IsCasting || Me.ChanneledSpell != null), new Sequence( // cast the spell new Action(ret => { Logger.Write(Color.Aquamarine, string.Format("*{0} on {1} at {2:F1} yds at {3:F1}%", name, onUnit(ret).SafeName(), onUnit(ret).Distance, onUnit(ret).HealthPercent)); SpellManager.Cast(name, onUnit(ret)); }), // if spell was in progress before cast (we queued this one) then wait in progress one to finish new WaitContinue( new TimeSpan(0, 0, 0, 0, (int)StyxWoW.WoWClient.Latency << 1), ret => !((bool)ret) || !(SpellManager.GlobalCooldown || Me.IsCasting || Me.ChanneledSpell != null), new ActionAlwaysSucceed() ), // wait for this cast to appear on the GCD or Spell Casting indicators new WaitContinue( new TimeSpan(0, 0, 0, 0, (int)StyxWoW.WoWClient.Latency << 1), ret => SpellManager.GlobalCooldown || Me.IsCasting || Me.ChanneledSpell != null, new ActionAlwaysSucceed() ) ) ) ) )); }
/// <summary> /// Cast "Freeze" pet ability on a target. Uses a local store for location to /// avoid target position changing during cast preparation and being out of /// range after range check /// </summary> /// <param name="onUnit">target to cast on</param> /// <returns></returns> public static Composite CastFreeze( UnitSelectionDelegate onUnit, SimpleBooleanDelegate require = null) { if (onUnit == null) return new ActionAlwaysFail(); if (require == null) require = req => true; return new Sequence( ctx => onUnit(ctx), new Decorator( req => req != null && (req as WoWUnit).SpellDistance() < 40 && require(req), new Action( r => { _locFreeze = (r as WoWUnit).Location; if (StyxWoW.Me.Location.Distance(_locFreeze) > 45) _locFreeze = WoWMathHelper.CalculatePointFrom(StyxWoW.Me.Location, _locFreeze, 7f + (r as WoWUnit).CombatReach); if (StyxWoW.Me.Location.Distance(_locFreeze) > 45) return RunStatus.Failure; return RunStatus.Success; }) ), new Throttle( TimeSpan.FromMilliseconds(250), Pet.CastPetActionOnLocation( "Freeze", on => _locFreeze, ret => !Me.CurrentTarget.TreatAsFrozen() ) ) ); }
public static Composite CreateApplyDotsBehaviorNormal(UnitSelectionDelegate onUnit) { System.Diagnostics.Debug.Assert(onUnit != null); return(new PrioritySelector( ctx => onUnit(ctx), new Decorator( req => Unit.ValidUnit((WoWUnit)req), new PrioritySelector( CreateCastSoulSwap(on => (WoWUnit)on), new Decorator( req => GetSoulSwapDotsNeeded((WoWUnit)req) > 0, new PrioritySelector( Spell.Buff("Agony", 3, on => (WoWUnit)on, ret => true), Spell.Buff("Corruption", 3, on => (WoWUnit)on, ret => !Common.HasTalent(WarlockTalents.AbsoluteCorruption)), Spell.Buff("Corruption", ret => Common.HasTalent(WarlockTalents.AbsoluteCorruption)), Spell.Buff("Siphon Life"), Spell.Cast("Unstable Affliction", req => !((WoWUnit)req).HasAura("Unstable Affliction") || (((WoWUnit)req).GetAuraStacks("Unstable Affliciton") <= 2 && Me.GetPowerInfo(WoWPowerType.SoulShards).Current >= 3 && ((WoWUnit)req).TimeToDeath() > 4) ), new Action(r => { Logger.WriteDebug("ApplyDots: no DoTs needed on {0}", ((WoWUnit)r).SafeName()); return RunStatus.Failure; }) ) ) ) ) )); }
public static Composite CreateCastSoulSwap(UnitSelectionDelegate onUnit) { const string SOUL_SWAP = "Soul Swap"; if (!SpellManager.HasSpell(SOUL_SWAP)) { return(new ActionAlwaysFail()); } NeedSoulSwapDelegate needSoulSwap = NeedSoulSwapNormal; return(new Decorator( req => Me.CurrentSoulShards >= 2, new Sequence( ctx => onUnit(ctx), new Decorator( req => needSoulSwap((WoWUnit)req), new ActionAlwaysSucceed() ), Common.CreateCastSoulburn(req => true), new Action(ret => { Logger.Write(LogColor.SpellNonHeal, $"*Soul Swap on {((WoWUnit) ret).SafeName()} @ {((WoWUnit) ret).HealthPercent:F1}% at {((WoWUnit) ret).SpellDistance():F1} yds"); if (!Spell.CastPrimative("Soul Swap", onUnit(ret))) { return RunStatus.Failure; } return RunStatus.Success; }) ) )); }
public static Composite CastElementalBlast(UnitSelectionDelegate onUnit = null, SimpleBooleanDelegate requirements = null, SimpleBooleanDelegate cancel = null) { const string ELEMENTAL_BLAST = "Elemental Blast"; UnitSelectionDelegate ondel = onUnit ?? (o => Me.CurrentTarget); SimpleBooleanDelegate reqdel = requirements ?? (r => true); SimpleBooleanDelegate candel = cancel ?? (c => false); // we do a doublecast check with Me as the target // .. since the buff appears on us -- a different model requiring custom handling below return(new Decorator( req => { if (Spell.DoubleCastContains(Me, ELEMENTAL_BLAST)) { return false; } if (!Me.HasAuraExpired(ELEMENTAL_BLAST, 0, myAura: true)) { return false; } return true; }, new Sequence( Spell.Cast(ELEMENTAL_BLAST, ondel, reqdel, candel), new Action(r => Spell.UpdateDoubleCast(ELEMENTAL_BLAST, Me, 750)) ) )); }
public static Composite StopAndBuff(string name, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements) { return (new Decorator( ret => onUnit(ret) != null && !onUnit(ret).HasAura(name), StopAndCast(name, onUnit, requirements))); }
public Composite MovementMoveBehind(UnitSelectionDelegate toUnit) { return new Decorator( ret => THSettings.Instance.AutoMove && DateTime.Now > DoNotMove && !Me.Mounted && !IsOverrideModeOn && !Me.IsCasting && //!Me.IsChanneling && toUnit != null && toUnit(ret) != null && toUnit(ret) != Me && toUnit(ret).IsAlive && //only MovementMoveBehind if IsWithinMeleeRange GetDistance(toUnit(ret)) <= 5 && !Me.IsBehind(toUnit(ret)) && //!IsTank(Me) && //Only Move again After a certain delay or target move 3 yard from original posision (toUnit(ret).IsPlayer || !toUnit(ret).IsPlayer && toUnit(ret).CurrentTarget != Me && toUnit(ret).Combat), new Action(ret => { WoWPoint pointBehind = toUnit(ret).Location.RayCast( toUnit(ret).Rotation + WoWMathHelper.DegreesToRadians(150), 3f); Navigator.MoveTo(pointBehind); return RunStatus.Failure; })); }
/// <summary> /// Creates a behavior to cast a buff by name, with special requirements, on a specific unit. Returns /// RunStatus.Success if successful, RunStatus.Failure otherwise. /// </summary> /// <remarks> /// Created 5/2/2011. /// </remarks> /// <param name = "spellId">The ID of the buff</param> /// <param name = "onUnit">The on unit</param> /// <param name = "requirements">The requirements.</param> /// <returns></returns> public static Composite Buff(int spellId, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements) { return (new Decorator( ret => onUnit(ret) != null && !onUnit(ret).Auras.Values.Any(a => a.SpellId == spellId), Cast(spellId, onUnit, requirements))); }
public static Composite CreateHunterTrapBehavior(string trapName, bool useLauncher, UnitSelectionDelegate onUnit) { return new PrioritySelector( new Decorator( ret => onUnit != null && onUnit(ret) != null && onUnit(ret).DistanceSqr < 40 * 40 && SpellManager.HasSpell(trapName) && !SpellManager.Spells[trapName].Cooldown, new PrioritySelector( Spell.BuffSelf(trapName, ret => !useLauncher), Spell.BuffSelf("Trap Launcher", ret => useLauncher), new Decorator( ret => StyxWoW.Me.HasAura("Trap Launcher"), new Sequence( new Switch<string>(ctx => trapName, new SwitchArgument<string>("Immolation Trap", new Action(ret => LegacySpellManager.CastSpellById(82945))), new SwitchArgument<string>("Freezing Trap", new Action(ret => LegacySpellManager.CastSpellById(60192))), new SwitchArgument<string>("Explosive Trap", new Action(ret => LegacySpellManager.CastSpellById(82939))), new SwitchArgument<string>("Ice Trap", new Action(ret => LegacySpellManager.CastSpellById(82941))), new SwitchArgument<string>("Snake Trap", new Action(ret => LegacySpellManager.CastSpellById(82948))) ), new ActionSleep(200), new Action(ret => LegacySpellManager.ClickRemoteLocation(onUnit(ret).Location))))))); }
public static Composite CreateRebirthBehavior(UnitSelectionDelegate onUnit) { if (!DruidSettings.UseRebirth) { return(new PrioritySelector()); } if (onUnit == null) { Logger.WriteDebug("CreateRebirthBehavior: error - onUnit == null"); return(new PrioritySelector()); } return(new PrioritySelector( ctx => onUnit(ctx), new Decorator( ret => onUnit(ret) != null && Spell.GetSpellCooldown("Rebirth") == TimeSpan.Zero, new PrioritySelector( Spell.WaitForCast(true), Movement.CreateMoveToRangeAndStopBehavior(ret => (WoWUnit)ret, range => 40f), new Decorator( ret => !Spell.IsGlobalCooldown(), Spell.Cast("Rebirth", ret => (WoWUnit)ret) ) ) ) )); }
private Composite CastLikeMonk(string spell, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements, bool face = false) { return(new Decorator( ret => requirements != null && onUnit != null && requirements(ret) && onUnit(ret) != null && spell != null && CanCastLikeMonk(spell, onUnit(ret)), new Sequence( new Styx.TreeSharp.Action(ctx => { Logging.Write(LogLevel.Normal, MONK_COLOR, "{0} on {1} at {2:F1} yds at {3:F1}%", spell, onUnit(ctx).Name, onUnit(ctx).Distance, onUnit(ctx).HealthPercent); if (face) { onUnit(ctx).Face(); } SpellManager.Cast(spell, onUnit(ctx)); } ), new WaitContinue(TimeSpan.FromMilliseconds((int)StyxWoW.WoWClient.Latency << 1), ctx => !(SpellManager.GlobalCooldown || StyxWoW.Me.IsCasting || StyxWoW.Me.ChanneledSpell != null), new ActionAlwaysSucceed() ), new WaitContinue(TimeSpan.FromMilliseconds((int)StyxWoW.WoWClient.Latency << 1), ctx => SpellManager.GlobalCooldown || StyxWoW.Me.IsCasting || StyxWoW.Me.ChanneledSpell != null, new ActionAlwaysSucceed() ) ) )); }
private static Composite PetBuffUnit(string name, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements, params string[] myMutexBuffs) { return (new Decorator( ret => onUnit(ret) != null && (PartyBuffType.None != (onUnit(ret).GetMissingPartyBuffs() & GetPartyBuffForSpell(name))) && (myMutexBuffs == null || myMutexBuffs.Count() == 0 || !onUnit(ret).GetAllAuras().Any(a => a.CreatorGuid == StyxWoW.Me.Guid && myMutexBuffs.Contains(a.Name))), new Sequence( PetManager.Buff(name, onUnit, requirements, myMutexBuffs), new Wait(1, until => StyxWoW.Me.HasPartyBuff(name), new ActionAlwaysSucceed()), new Action(ret => { System.Diagnostics.Debug.Assert(PartyBuffType.None != GetPartyBuffForSpell(name)); if (PartyBuffType.None != GetPartyBuffForSpell(name)) { ResetReadyToPartyBuffTimer(); } else { Logger.WriteDebug("Programmer Error: should use Spell.Buff(\"{0}\") instead", name); } }) ) )); }
public Composite MovementMoveBehind(UnitSelectionDelegate toUnit) { return (new Decorator( ret => THSettings.Instance.AutoMove && DateTime.Now > DoNotMove && !Me.Mounted && !IsOverrideModeOn && !Me.IsCasting && //!Me.IsChanneling && toUnit != null && toUnit(ret) != null && toUnit(ret) != Me && toUnit(ret).IsAlive&& //only MovementMoveBehind if IsWithinMeleeRange GetDistance(toUnit(ret)) <= 5 && !Me.IsBehind(toUnit(ret)) && //!IsTank(Me) && //Only Move again After a certain delay or target move 3 yard from original posision (toUnit(ret).IsPlayer || !toUnit(ret).IsPlayer&& toUnit(ret).CurrentTarget != Me && toUnit(ret).Combat), new Action(ret => { WoWPoint pointBehind = toUnit(ret).Location.RayCast( toUnit(ret).Rotation + WoWMathHelper.DegreesToRadians(150), 3f); Navigator.MoveTo(pointBehind); return RunStatus.Failure; }))); }
private static Composite ShowHealTarget(UnitSelectionDelegate onUnit) { return (new Sequence( new DecoratorContinue( ret => onUnit(ret) == null && guidLastHealTarget != 0, new Action(ret => { guidLastHealTarget = 0; Logger.WriteDebug(Color.LightGreen, "Heal Target - none", ((WoWUnit)ret).SafeName(), ((WoWUnit)ret).HealthPercent, ((WoWUnit)ret).Distance); return RunStatus.Failure; }) ), new DecoratorContinue( ret => onUnit(ret) != null && guidLastHealTarget != onUnit(ret).Guid, new Action(ret => { guidLastHealTarget = ((WoWUnit)ret).Guid; Logger.WriteDebug(Color.LightGreen, "Heal Target - {0} {1:F1}% @ {2:F1} yds", ((WoWUnit)ret).SafeName(), ((WoWUnit)ret).HealthPercent, ((WoWUnit)ret).Distance); return RunStatus.Failure; })), new Action(ret => { return RunStatus.Failure; }) )); }
//private static string _lastBuffCast = string.Empty; //private static System.Diagnostics.Stopwatch _castTimer = new System.Diagnostics.Stopwatch(); /// <summary> /// Creates a behavior to cast a buff by name, with special requirements, on a specific unit. Returns /// RunStatus.Success if successful, RunStatus.Failure otherwise. /// </summary> /// <remarks> /// Created 5/2/2011. /// </remarks> /// <param name = "name">The name of the buff</param> /// <param name = "myBuff">Check for self debuffs or not</param> /// <param name = "onUnit">The on unit</param> /// <param name = "requirements">The requirements.</param> /// <returns></returns> public static Composite Buff(string name, bool myBuff, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements, params string[] buffNames) { //if (name == _lastBuffCast && _castTimer.IsRunning && _castTimer.ElapsedMilliseconds < 250) //{ // return new Action(ret => RunStatus.Success); //} //if (name == _lastBuffCast && StyxWoW.Me.IsCasting) //{ // _castTimer.Reset(); // _castTimer.Start(); // return new Action(ret => RunStatus.Success); //} return (new Decorator( ret => onUnit(ret) != null && !DoubleCastPreventionDict.ContainsKey(name) && buffNames.All(b => myBuff ? !onUnit(ret).HasMyAura(b) : !onUnit(ret).HasAura(b)), new Sequence( // new Action(ctx => _lastBuffCast = name), Cast(name, onUnit, requirements), new DecoratorContinue( ret => SpellManager.Spells[name].CastTime > 0, new Sequence( new WaitContinue( 1, ret => StyxWoW.Me.IsCasting, new Action(ret => UpdateDoubleCastDict(name)))) )) )); }
public static Composite HoT(string spell, UnitSelectionDelegate onUnit, int hp = 100, Selection <bool> reqs = null) { return(new Decorator( ret => onUnit != null && onUnit(ret) != null && (reqs == null || reqs(ret)) && !onUnit(ret).HasMyBuff(spell) && onUnit(ret).HealthPercent <= hp, Cast(spell, onUnit, reqs))); }
public static Composite CreateMoveToLosBehavior(UnitSelectionDelegate toUnit) { return(new Decorator( ret => !SingularSettings.Instance.DisableAllMovement && toUnit != null && toUnit(ret) != null && toUnit(ret) != StyxWoW.Me && !toUnit(ret).InLineOfSpellSight, new Action(ret => Navigator.MoveTo(toUnit(ret).Location)))); }
private static Composite BuffUnleashLife(UnitSelectionDelegate onUnit) { return(new PrioritySelector( Spell.Cast("Unleash Elements", onUnit, ret => IsImbuedForHealing(Me.Inventory.Equipped.MainHand) && (Me.Combat || onUnit(ret).Combat)), new ActionAlwaysSucceed() )); }
public Composite CreateApproachToCast(string spellName, UnitSelectionDelegate unitSelector) { return (new Decorator( ret => !SingularSettings.Instance.DisableAllMovement && SpellManager.Spells[spellName].MaxRange != 0 && (unitSelector(ret).Distance > SpellManager.Spells[spellName].MaxRange - 2f || !unitSelector(ret).InLineOfSightOCD), new Action(ret => Navigator.MoveTo(unitSelector(ret).Location)))); }
private static Throttle CreateGuardianWildChargeBehavior(UnitSelectionDelegate onUnit = null) { return(new Throttle(7, new Sequence( Spell.CastHack("Wild Charge", onUnit ?? (on => Me.CurrentTarget), ret => MovementManager.IsClassMovementAllowed && Me.Shapeshift == ShapeshiftForm.Bear && (Me.CurrentTarget.Distance + Me.CurrentTarget.CombatReach).Between(10, 25)), new Action(ret => StopMoving.Clear()), new Wait(1, until => !Me.GotTarget() || Me.CurrentTarget.IsWithinMeleeRange, new ActionAlwaysSucceed()) ) )); }
/// <summary> /// Creates a composite to avoid double casting spells on specified unit. Mostly usable for spells like Immolate, Devouring Plague etc. /// </summary> /// <remarks> /// Created 19/12/2011 raphus /// </remarks> /// <param name="unit"> Unit to check </param> /// <param name="spellNames"> Spell names to check </param> /// <returns></returns> public static Composite PreventDoubleCast(UnitSelectionDelegate unit, params string[] spellNames) { return (new PrioritySelector( new Decorator( ret => StyxWoW.Me.IsCasting && spellNames.Contains(StyxWoW.Me.CastingSpell.Name) && unit != null && unit(ret) != null && unit(ret).Auras.Any(a => a.Value.SpellId == StyxWoW.Me.CastingSpellId && a.Value.CreatorGuid == StyxWoW.Me.Guid), new Action(ret => SpellManager.StopCasting())))); }
/// <summary>Creates an interrupt spell cast composite. This will attempt to use racials before any class/spec abilities. It will attempt to stun if possible!</summary> /// <remarks>Created 9/7/2011.</remarks> /// <param name="onUnit">The on unit.</param> /// <returns>.</returns> public static Composite CreateInterruptSpellCast(UnitSelectionDelegate onUnit) { return (new Decorator( // If the target is casting, and can actually be interrupted, AND we've waited out the double-interrupt timer, then find something to interrupt with. ret => onUnit != null && onUnit(ret) != null && onUnit(ret).IsCasting&& onUnit(ret).CanInterruptCurrentSpellCast /* && PreventDoubleInterrupt*/, new PrioritySelector( Spell.Cast("Rebuke", onUnit), Spell.Cast("Avenger's Shield", onUnit), Spell.Cast("Hammer of Justice", onUnit), Spell.Cast("Repentance", onUnit, ret => onUnit(ret).IsPlayer || onUnit(ret).IsDemon || onUnit(ret).IsHumanoid || onUnit(ret).IsDragon || onUnit(ret).IsGiant || onUnit(ret).IsUndead), Spell.Cast("Kick", onUnit), Spell.Cast("Gouge", onUnit, ret => !onUnit(ret).IsBoss() && !onUnit(ret).MeIsSafelyBehind), // Can't gouge bosses. Spell.Cast("Counterspell", onUnit), Spell.Cast("Wind Shear", onUnit), Spell.Cast("Pummel", onUnit), Spell.Cast("Spear Hand Strike", onUnit), // AOE interrupt Spell.Cast("Disrupting Shout", onUnit), // Gag Order only works on non-bosses due to it being a silence, not an interrupt! Spell.Cast("Heroic Throw", onUnit, ret => TalentManager.IsSelected(7) && !onUnit(ret).IsBoss()), Spell.Cast("Silence", onUnit), Spell.Cast("Silencing Shot", onUnit), // Can't stun most bosses. So use it on trash, etc. Spell.Cast("Bash", onUnit, ret => !onUnit(ret).IsBoss()), Spell.Cast("Skull Bash (Cat)", onUnit, ret => StyxWoW.Me.Shapeshift == ShapeshiftForm.Cat), Spell.Cast("Skull Bash (Bear)", onUnit, ret => StyxWoW.Me.Shapeshift == ShapeshiftForm.Bear), Spell.Cast("Mighty Bash", onUnit, ret => !onUnit(ret).IsBoss() && onUnit(ret).IsWithinMeleeRange), Spell.Cast("Solar Beam", onUnit, ret => StyxWoW.Me.Shapeshift == ShapeshiftForm.Moonkin), Spell.Cast("Strangulate", onUnit), Spell.Cast("Mind Freeze", onUnit), // Racials last. Spell.Cast("Arcane Torrent", onUnit), // Don't waste stomp on bosses. They can't be stunned 99% of the time! Spell.Cast("War Stomp", onUnit, ret => !onUnit(ret).IsBoss() && onUnit(ret).Distance < 8), Spell.Cast("Quaking Palm", onUnit) ))); }
private Composite Cast(string spell, SimpleBooleanDelegate requirements, UnitSelectionDelegate unit) { return(new Decorator(ret => requirements != null && requirements(ret) && SpellManager.HasSpell(spell) && SpellManager.CanCast(spell, unit(ret), true, true), new Styx.TreeSharp.Action(ctx => { SpellManager.Cast(spell, unit(ctx)); Logging.Write(LogLevel.Normal, MONK_COLOR, "Casting Spell [{0}].", spell); return RunStatus.Success; }) )); }
private static Composite MovementMoveToMelee(UnitSelectionDelegate toUnit) { return(new Decorator( ret => THSettings.Instance.AutoMove && !Me.Mounted && DateTime.Now > DoNotMove && !IsOverrideModeOn && !Me.IsCasting && !Me.IsChanneling && toUnit != null && toUnit(ret) != null && toUnit(ret) != Me && toUnit(ret).IsAlive&& //(Me.IsFacing(toUnit(ret)) || // Me.Combat) && toUnit(ret).Distance - toUnit(ret).CombatReach > 2 && IsEnemy(toUnit(ret)), new Action(ret => { //WoWMovement.ConstantFace(toUnit(ret).Guid); LastMovementWoWPoint = toUnit(ret).Location; Navigator.MoveTo(LastMovementWoWPoint); //Logging.Write(LogLevel.Diagnostic, // DateTime.Now.ToString("ss:fff ") + "MovementMoveToMelee"); //I'm just a stupid //Logging.Write(LogLevel.Diagnostic, // (LastMovementTime + MovementDelay).ToString("yyyy-mm-dd hh:mm:ss:fff ") + // "LastMovementTime + MovementDelay"); //Logging.Write(LogLevel.Diagnostic, // DateTime.Now.ToString("yyyy-mm-dd hh:mm:ss:fff ") + "DateTime.Now"); //if (DateTime.Now > LastMovementTime + MovementDelay) //{ // Logging.Write("DateTime.Now > LastMovementTime + MovementDelay " + // DateTime.Now.ToString("yyyy-mm-dd hh:mm:ss:fff > ") + // (LastMovementTime + MovementDelay).ToString( // "yyyy-mm-dd hh:mm:ss:fff ")); //} //if (DateTime.Now < LastMovementTime + MovementDelay) //{ // Logging.Write("DateTime.Now < LastMovementTime + MovementDelay " + // DateTime.Now.ToString("yyyy-mm-dd hh:mm:ss:fff < ") + // (LastMovementTime + MovementDelay).ToString( // "yyyy-mm-dd hh:mm:ss:fff ")); //} LastMovementTime = DateTime.Now; return RunStatus.Failure; }))); }
public Composite CreateFaceTargetBehavior(UnitSelectionDelegate toUnit) { return new Decorator( ret => toUnit != null && toUnit(ret) != null && !StyxWoW.Me.IsMoving && !toUnit(ret).IsMe && !StyxWoW.Me.IsSafelyFacing(toUnit(ret), 70f), new Action(ret => { StyxWoW.Me.CurrentTarget.Face(); return RunStatus.Failure; })); }
public static Composite CreateFaceTargetBehavior(UnitSelectionDelegate toUnit, float viewDegrees = 70f) { return(new Decorator( ret => !SingularSettings.Instance.DisableAllMovement && toUnit != null && toUnit(ret) != null && !StyxWoW.Me.IsMoving && !toUnit(ret).IsMe&& !StyxWoW.Me.IsSafelyFacing(toUnit(ret), viewDegrees), new Action(ret => { StyxWoW.Me.CurrentTarget.Face(); return RunStatus.Failure; }))); }
private static Composite CastRegrowth(UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements, SimpleBooleanDelegate cancel) { SimpleBooleanDelegate require = r => (glyphRegrowth || !Spell.DoubleCastContains((WoWUnit)r, "Regrowth")) && requirements(r); return(new Sequence( ctx => onUnit(ctx), Spell.Cast("Regrowth", on => (WoWUnit)on, req => require(req), cancel), new DecoratorContinue( req => !glyphRegrowth, new Action(ret => Spell.UpdateDoubleCast("Regrowth", (WoWUnit)ret)) ) )); }
public static Composite CreateFaceTargetBehavior(UnitSelectionDelegate toUnit, float viewDegrees = 70f) { return new Decorator( ret => !SingularSettings.Instance.DisableAllMovement && toUnit != null && toUnit(ret) != null && !StyxWoW.Me.IsMoving && !toUnit(ret).IsMe && !StyxWoW.Me.IsSafelyFacing(toUnit(ret), viewDegrees ), new Action(ret => { StyxWoW.Me.CurrentTarget.Face(); return RunStatus.Failure; })); }
/// <summary> /// Creates a behavior to cast a spell by ID, with special requirements, on a specific unit. /// Returns RunStatus.Success if successful, RunStatus.Failure otherwise. /// </summary> /// <remarks> /// Created 5/2/2011. /// </remarks> /// <param name = "spellId">Identifier for the spell.</param> /// <param name = "onUnit">The on unit.</param> /// <param name = "requirements">The requirements.</param> /// <returns>.</returns> public static Composite Cast(int spellId, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements) { return(new Decorator( ret => requirements != null && requirements(ret) && onUnit != null && onUnit(ret) != null && SpellManager.CanCast(spellId, onUnit(ret), true), new Action( ret => { Logger.Write("Casting " + spellId + " on " + onUnit(ret).SafeName()); SpellManager.Cast(spellId); }) )); }
public static Composite CreateMoveToUnitBehavior(UnitSelectionDelegate onUnit, float range, float stopAt = float.MinValue) { return(new Decorator( ret => onUnit != null && onUnit(ret) != null && onUnit(ret).Distance > range, new Sequence( new Action(ret => Logging.WriteDiagnostic("MoveToUnit: moving within {0:F1} yds of {1} @ {2:F1} yds", range, onUnit(ret).SafeName(), onUnit(ret).Distance)), //Logger.WriteDebug(Color.White, "MoveToUnit: moving within {0:F1} yds of {1} @ {2:F1} yds", range, onUnit(ret).SafeName(), onUnit(ret).Distance)), new Action(ret => Navigator.MoveTo(onUnit(ret).Location)), new Action(ret => StopMoving.InRangeOfUnit(onUnit(ret), stopAt == float.MinValue ? range : stopAt)), new ActionAlwaysFail() ) )); }
public static Composite Buff(string spell, UnitSelectionDelegate onUnit, SimpleBooleanDelegate require, params string[] buffNames) { return(new Decorator( ret => { if (onUnit == null || require == null) { return false; } _buffUnit = onUnit(ret); if (_buffUnit == null) { return false; } if (spell == null) { return false; } if (Spell.DoubleCastContains(_buffUnit, spell)) { return false; } if (!buffNames.Any()) { return !_buffUnit.HasAura(spell); } bool buffFound; try { buffFound = buffNames.Any(b => _buffUnit.HasAura(b)); } catch { // mark as found buff, so we return false buffFound = true; } return !buffFound; }, new Sequence( // new Action(ctx => _lastBuffCast = name), new Action(r => PetManager.CastPetAction(spell)), new Action(ret => Spell.UpdateDoubleCast(spell, _buffUnit)) ) )); }
public static Composite CreateExecuteOnSuddenDeath(UnitSelectionDelegate onUnit = null, SimpleBooleanDelegate requirements = null) { if (onUnit == null) { onUnit = on => Me.CurrentTarget; } if (requirements == null) { requirements = req => true; } return(Spell.Cast("Execute", onUnit, req => Me.HasAura(SUDDEN_DEATH_PROC) && requirements(req))); }
private static Composite Cast(string spell, UnitSelectionDelegate onUnit, Selection<bool> reqs = null) { return new Decorator( ret => onUnit != null && onUnit(ret) != null && ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.CanCast(spell, onUnit(ret), true), new Sequence( new Action(ret => SpellManager.Cast(spell, onUnit(ret))), new Action( ret => Log.Info(string.Format("[Casting:{0}] [Target:{1}] [Distance:{2:F1}yds]", spell, onUnit(ret).SafeName, onUnit(ret).Distance))) )); }
public static Composite Cast(string spell, UnitSelectionDelegate onUnit, Selection<bool> reqs = null) { return new Decorator( ret => (onUnit != null && onUnit(ret) != null && (reqs == null || reqs(ret)) && AbilityManager.CanCast(spell, onUnit(ret))), new PrioritySelector( new Action(delegate { Logger.Write(">> Casting << " + spell); return RunStatus.Failure; }), new Action(ret => AbilityManager.Cast(spell, onUnit(ret)))) ); }
/// <summary>Creates an interrupt spell cast composite. This will attempt to use racials before any class/spec abilities. It will attempt to stun if possible!</summary> /// <remarks>Created 9/7/2011.</remarks> /// <param name="onUnit">The on unit.</param> /// <returns>.</returns> public static Composite CreateInterruptSpellCast(UnitSelectionDelegate onUnit) { return new Decorator( // If the target is casting, and can actually be interrupted, AND we've waited out the double-interrupt timer, then find something to interrupt with. ret => onUnit != null && onUnit(ret) != null && onUnit(ret).IsCasting && onUnit(ret).CanInterruptCurrentSpellCast /* && PreventDoubleInterrupt*/, new PrioritySelector( Spell.Cast("Rebuke", onUnit), Spell.Cast("Avenger's Shield", onUnit), Spell.Cast("Hammer of Justice", onUnit), Spell.Cast("Repentance", onUnit, ret => onUnit(ret).IsPlayer || onUnit(ret).IsDemon || onUnit(ret).IsHumanoid || onUnit(ret).IsDragon || onUnit(ret).IsGiant || onUnit(ret).IsUndead), Spell.Cast("Kick", onUnit), Spell.Cast("Gouge", onUnit, ret => !onUnit(ret).IsBoss() && !onUnit(ret).MeIsSafelyBehind), // Can't gouge bosses. Spell.Cast("Counterspell", onUnit), Spell.Cast("Wind Shear", onUnit), Spell.Cast("Pummel", onUnit), // Gag Order only works on non-bosses due to it being a silence, not an interrupt! Spell.Cast("Heroic Throw", onUnit, ret => TalentManager.GetCount(3, 7) == 2 && !onUnit(ret).IsBoss()), Spell.Cast("Silence", onUnit), Spell.Cast("Silencing Shot", onUnit), // Can't stun most bosses. So use it on trash, etc. Spell.Cast("Bash", onUnit, ret => !onUnit(ret).IsBoss()), Spell.Cast("Skull Bash (Cat)", onUnit, ret => StyxWoW.Me.Shapeshift == ShapeshiftForm.Cat), Spell.Cast("Skull Bash (Bear)", onUnit, ret => StyxWoW.Me.Shapeshift == ShapeshiftForm.Bear), Spell.Cast("Solar Beam", onUnit, ret => StyxWoW.Me.Shapeshift == ShapeshiftForm.Moonkin), Spell.Cast("Strangulate", onUnit), Spell.Cast("Mind Freeze", onUnit), // Racials last. Spell.Cast("Arcane Torrent", onUnit), // Don't waste stomp on bosses. They can't be stunned 99% of the time! Spell.Cast("War Stomp", onUnit, ret => !onUnit(ret).IsBoss() && onUnit(ret).Distance < 8) )); }
/// <summary> /// Cast "Freeze" pet ability on a target. Uses a local store for location to /// avoid target position changing during cast preparation and being out of /// range after range check /// </summary> /// <param name="onUnit">target to cast on</param> /// <returns></returns> public static Composite CastFreeze( UnitSelectionDelegate onUnit ) { return new Sequence( new Decorator( ret => onUnit != null && onUnit(ret) != null, new Action( ret => _locFreeze = onUnit(ret).Location) ), new Throttle( TimeSpan.FromMilliseconds(250), Pet.CreateCastPetActionOnLocation( "Freeze", on => _locFreeze, ret => Me.Pet.ManaPercent >= 12 && Me.Pet.Location.Distance(_locFreeze) < 45 && !Me.CurrentTarget.IsFrozen() ) ) ); }
private static Composite MovementMoveStop(UnitSelectionDelegate toUnit, double range) { return new Decorator( ret => THSettings.Instance.AutoMove && !IsOverrideModeOn && toUnit != null && toUnit(ret) != null && toUnit(ret) != Me && toUnit(ret).IsAlive && IsMoving(Me) && IsEnemy(toUnit(ret)) && GetDistance(toUnit(ret)) <= range && InLineOfSpellSightCheck(toUnit(ret)), new Action(ret => { Navigator.PlayerMover.MoveStop(); return RunStatus.Failure; })); }
/// <summary> /// Creates a behavior to move within range, within LOS, and keep facing the specified target. /// </summary> /// <remarks> /// Created 3/4/2011. /// </remarks> /// <param name = "maxRange">The maximum range.</param> /// <param name = "coneDegrees">The cone in degrees. (If we're facing +/- this many degrees from the target, we will face the target)</param> /// <param name = "unit">The unit.</param> /// <param name="noMovement"></param> /// <returns>.</returns> protected Composite CreateMoveToAndFace(float maxRange, float coneDegrees, UnitSelectionDelegate unit, bool noMovement) { return new Decorator( ret =>!SingularSettings.Instance.DisableAllMovement&& unit(ret) != null, new PrioritySelector( new Decorator( ret =>(!unit(ret).InLineOfSightOCD || (!noMovement && unit(ret).DistanceSqr > maxRange * maxRange)), new Action(ret => Navigator.MoveTo(unit(ret).Location))), //Returning failure for movestop for smoother movement //Rest should return success ! new Decorator( ret =>Me.IsMoving && unit(ret).DistanceSqr <= maxRange * maxRange, new Action(delegate { Navigator.PlayerMover.MoveStop(); return RunStatus.Failure; })), new Decorator( ret => Me.CurrentTarget != null && Me.CurrentTarget.IsAlive && !Me.IsSafelyFacing(Me.CurrentTarget, coneDegrees), new Action(ret => Me.CurrentTarget.Face())) )); }
/// <summary> /// Creates a behavior to cast a spell by ID, with special requirements, on a specific unit. /// Returns RunStatus.Success if successful, RunStatus.Failure otherwise. /// </summary> /// <remarks> /// Created 5/2/2011. /// </remarks> /// <param name = "spellId">Identifier for the spell.</param> /// <param name = "onUnit">The on unit.</param> /// <param name = "requirements">The requirements.</param> /// <returns>.</returns> public static Composite Cast(int spellId, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements) { return new Decorator(ret => requirements != null && requirements(ret) && onUnit != null && onUnit(ret) != null && SpellManager.CanCast(spellId, onUnit(ret),true), new Action(ret => { Logger.Write(string.Format("Casting {0} on {1}", spellId, onUnit(ret).SafeName())); SpellManager.Cast(spellId); })); }
/// <summary> /// Creates a behavior to cast a spell by ID, on a specific unit. Returns /// RunStatus.Success if successful, RunStatus.Failure otherwise. /// </summary> /// <remarks> /// Created 5/2/2011. /// </remarks> /// <param name = "spellId">Identifier for the spell.</param> /// <param name = "onUnit">The on unit.</param> /// <returns>.</returns> public static Composite Cast(int spellId, UnitSelectionDelegate onUnit) { return Cast(spellId, onUnit, ret => true); }
/// <summary> /// Creates a behavior to cast a buff by name, with special requirements, on a specific unit. Returns /// RunStatus.Success if successful, RunStatus.Failure otherwise. /// </summary> /// <remarks> /// Created 5/2/2011. /// </remarks> /// <param name = "spellId">The ID of the buff</param> /// <param name = "onUnit">The on unit</param> /// <param name = "requirements">The requirements.</param> /// <returns></returns> public static Composite Buff(int spellId, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements) { return new Decorator(ret => onUnit(ret) != null && onUnit(ret).Auras.Values.All(a => a.SpellId != spellId), Cast(spellId, onUnit, requirements)); }
//private static string _lastBuffCast = string.Empty; //private static System.Diagnostics.Stopwatch _castTimer = new System.Diagnostics.Stopwatch(); /// <summary> /// Creates a behavior to cast a buff by name, with special requirements, on a specific unit. Returns /// RunStatus.Success if successful, RunStatus.Failure otherwise. /// </summary> /// <remarks> /// Created 5/2/2011. /// </remarks> /// <param name = "name">The name of the buff</param> /// <param name = "myBuff">Check for self debuffs or not</param> /// <param name = "onUnit">The on unit</param> /// <param name = "requirements">The requirements.</param> /// <returns></returns> public static Composite Buff(string name, bool myBuff, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements, params string[] buffNames) { //if (name == _lastBuffCast && _castTimer.IsRunning && _castTimer.ElapsedMilliseconds < 250) //{ // return new Action(ret => RunStatus.Success); //} //if (name == _lastBuffCast && StyxWoW.Me.IsCasting) //{ // _castTimer.Reset(); // _castTimer.Start(); // return new Action(ret => RunStatus.Success); //} return new Decorator( ret => onUnit(ret) != null && !DoubleCastPreventionDict.ContainsKey(name) && buffNames.All(b => myBuff ? !onUnit(ret).HasMyAura(b) : !onUnit(ret).HasAura(b)), new Sequence( // new Action(ctx => _lastBuffCast = name), Cast(name, onUnit, requirements), new DecoratorContinue(ret => SpellManager.Spells[name].CastTime > 0, new Sequence(new WaitContinue(1, ret => StyxWoW.Me.IsCasting, new Action(ret => UpdateDoubleCastDict(name))))))); }
public static Composite Buff(string name, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements, params string[] buffNames) { return Buff(name, false, onUnit, requirements, buffNames); }
public static Composite Buff(string name, bool myBuff, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements) { return Buff(name, myBuff, onUnit, requirements, name); }
public static Composite CreateWordOfGloryBehavior(UnitSelectionDelegate onUnit ) { if ( HasTalent( PaladinTalents.EternalFlame )) { if (onUnit == null) return new ActionAlwaysFail(); return new PrioritySelector( ctx => onUnit(ctx), Spell.Cast( "Eternal Flame", on => (WoWUnit) on, ret => ret is WoWPlayer && PaladinSettings.KeepEternalFlameUp && Group.Tanks.Contains((WoWPlayer)onUnit(ret)) && !Group.Tanks.Any(t => t.HasMyAura("Eternal Flame"))), Spell.Cast( "Eternal Flame", on => (WoWUnit) on, ret => (Me.CurrentHolyPower >= 3 || Me.GetAuraTimeLeft("Divine Purpose", true).TotalSeconds > 0) && ((WoWUnit)ret).HealthPercent <= SingularSettings.Instance.Paladin().SelfEternalFlameHealth) ); } return new PrioritySelector( new Decorator( req => Me.HealthPercent <= Math.Max( PaladinSettings.SelfWordOfGloryHealth1, Math.Max( PaladinSettings.SelfWordOfGloryHealth2, PaladinSettings.SelfWordOfGloryHealth3)) && Me.ActiveAuras.ContainsKey("Divine Purpose"), Spell.Cast("Word of Glory", onUnit) ), new Decorator( req => Me.CurrentHolyPower >= 1 && Me.HealthPercent <= PaladinSettings.SelfWordOfGloryHealth1, Spell.Cast("Word of Glory", onUnit) ), new Decorator( req => Me.CurrentHolyPower >= 2 && Me.HealthPercent <= PaladinSettings.SelfWordOfGloryHealth2, Spell.Cast("Word of Glory", onUnit) ), new Decorator( req => Me.CurrentHolyPower >= 3 && Me.HealthPercent <= PaladinSettings.SelfWordOfGloryHealth3, Spell.Cast("Word of Glory", onUnit) ) ); }
public static Composite Buff(string name, bool myBuff, UnitSelectionDelegate onUnit) { return Buff(name, myBuff, onUnit, ret => true); }
/// <summary> /// Creates a composite to avoid double casting spells on specified unit. Mostly usable for spells like Immolate, Devouring Plague etc. /// </summary> /// <remarks> /// Created 19/12/2011 raphus /// </remarks> /// <param name="unit"> Unit to check </param> /// <param name="spellNames"> Spell names to check </param> /// <returns></returns> public static Composite PreventDoubleCast(UnitSelectionDelegate unit, params string[] spellNames) { return new PrioritySelector( new Decorator( ret => StyxWoW.Me.IsCasting && spellNames.Contains(StyxWoW.Me.CastingSpell.Name) && unit != null && unit(ret) != null && unit(ret).Auras.Any( a => a.Value.SpellId == StyxWoW.Me.CastingSpellId && a.Value.CreatorGuid == StyxWoW.Me.Guid), new Action(ret => SpellManager.StopCasting()))); }
public static Composite Heal(string name, SimpleBooleanDelegate checkMovement, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements, bool allowLagTollerance = false) { return Heal(name, checkMovement, onUnit, requirements, ret => onUnit(ret).HealthPercent > SingularSettings.Instance.IgnoreHealTargetsAboveHealth, false); }
private static Composite CreateShieldCharge(UnitSelectionDelegate onUnit = null, SimpleBooleanDelegate requirements = null) { if (onUnit == null) onUnit = on => Me.CurrentTarget; if (requirements == null) requirements = req => true; return new Sequence( new Decorator( req => Spell.DoubleCastContains(Me, "Shield Charge") || !HasShieldInOffHand, new ActionAlwaysFail() ), Spell.Cast("Shield Charge", onUnit, req => requirements(req), gcd: HasGcd.No), new Action(ret => Spell.UpdateDoubleCast("Shield Charge", Me)) ); }
private Composite Cast(string spell, SimpleBooleanDelegate requirements, UnitSelectionDelegate unit) { return new Decorator(ret => requirements != null && requirements(ret) && SpellManager.HasSpell(spell) && SpellManager.CanCast(spell, unit(ret), true, true), new Styx.TreeSharp.Action(ctx => { SpellManager.Cast(spell, unit(ctx)); Logging.Write(LogLevel.Normal, MONK_COLOR, "Casting Spell [{0}].", spell); return RunStatus.Success; }) ); }
/// <summary> /// Creates a behavior to cast a heal spell by name, on a specific unit. Heal behaviors will make sure /// we don't double cast. Returns RunStatus.Success if successful, RunStatus.Failure otherwise. /// </summary> /// <remarks> /// Created 5/2/2011. /// </remarks> /// <param name = "name">The name.</param> /// <param name = "onUnit">The on unit.</param> /// <returns>.</returns> public static Composite Heal(string name, UnitSelectionDelegate onUnit) { return Heal(name, ret => true, onUnit, ret => true); }
public static Composite Buff(string name, bool myBuff, UnitSelectionDelegate onUnit, params string[] buffNames) { return Buff(name, myBuff, onUnit, ret => true, buffNames); }
/// <summary> /// Creates a behavior to cast a heal spell by name, on a specific unit. Heal behaviors will make sure /// we don't double cast. Returns RunStatus.Success if successful, RunStatus.Failure otherwise. /// </summary> /// <remarks> /// Created 5/2/2011. /// </remarks> /// <param name = "name">The name.</param> /// <param name = "onUnit">The on unit.</param> /// <param name = "requirements">The requirements.</param> /// <returns>.</returns> public static Composite Heal(string name, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements) { return Heal(name, ret => true, onUnit, requirements); }
private Composite CastLikeMonk(string spell, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements, bool face = false) { return new Decorator( ret => requirements != null && onUnit != null && requirements(ret) && onUnit(ret) != null && spell != null && CanCastLikeMonk(spell, onUnit(ret)), new Sequence( new Styx.TreeSharp.Action(ctx => { Logging.Write(LogLevel.Normal, MONK_COLOR, "{0} on {1} at {2:F1} yds at {3:F1}%", spell, onUnit(ctx).Name, onUnit(ctx).Distance, onUnit(ctx).HealthPercent); if (face) onUnit(ctx).Face(); SpellManager.Cast(spell, onUnit(ctx)); } ), new WaitContinue(TimeSpan.FromMilliseconds((int)StyxWoW.WoWClient.Latency << 1), ctx => !(SpellManager.GlobalCooldown || StyxWoW.Me.IsCasting || StyxWoW.Me.ChanneledSpell != null), new ActionAlwaysSucceed() ), new WaitContinue(TimeSpan.FromMilliseconds((int)StyxWoW.WoWClient.Latency << 1), ctx => SpellManager.GlobalCooldown || StyxWoW.Me.IsCasting || StyxWoW.Me.ChanneledSpell != null, new ActionAlwaysSucceed() ) ) ); }
/// <summary> /// Creates a behavior to cast a heal spell by name, with special requirements, on a specific unit. Heal behaviors will make sure /// we don't double cast. Returns RunStatus.Success if successful, RunStatus.Failure otherwise. /// </summary> /// <remarks> /// Created 5/2/2011. /// </remarks> /// <param name = "name">The name.</param> /// <param name="checkMovement"></param> /// <param name = "onUnit">The on unit.</param> /// <param name = "requirements">The requirements.</param> /// <param name="cancel">The cancel cast in progress delegate</param> /// <param name="allowLagTollerance">allow next spell to queue before this one completes</param> /// <returns>.</returns> public static Composite Heal(string name, SimpleBooleanDelegate checkMovement, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements, SimpleBooleanDelegate cancel, bool allowLagTollerance = false) { return new PrioritySelector( // save context of currently in a GCD or IsCasting before our Cast ctx => (bool)(SpellManager.GlobalCooldown || StyxWoW.Me.IsCasting || StyxWoW.Me.ChanneledSpell != null), new Sequence( Cast(name, checkMovement, onUnit, requirements), // if saved context indicates action was in progress (so we queued this one) then wait briefly for its progress to finish new WaitContinue( new TimeSpan(0, 0, 0, 0, (int) StyxWoW.WoWClient.Latency * 2), ret => !((bool)ret) || !(SpellManager.GlobalCooldown || StyxWoW.Me.IsCasting || StyxWoW.Me.ChanneledSpell != null), new ActionAlwaysSucceed() ), // now for non-instant spell, wait for .IsCasting to be true new WaitContinue(1, ret => { WoWSpell spell; if (SpellManager.Spells.TryGetValue(name, out spell)) { if (spell.CastTime == 0) return true; return StyxWoW.Me.IsCasting; } return true; }, new ActionAlwaysSucceed() ), // finally, wait at this point until heal completes new WaitContinue(10, ret => { // Let channeled heals been cast till end. if (StyxWoW.Me.ChanneledSpell != null) // .ChanneledCastingSpellId != 0) { return false; } // Interrupted or finished casting. Continue (note: following test doesn't deal with latency) if (!StyxWoW.Me.IsCasting) { return true; } // when doing lag tolerance, don't wait for spell to complete before considering finished if (allowLagTollerance) { TimeSpan castTimeLeft = StyxWoW.Me.CurrentCastTimeLeft; if (castTimeLeft != TimeSpan.Zero && castTimeLeft.TotalMilliseconds < (StyxWoW.WoWClient.Latency * 2)) return true; } // 500ms left till cast ends. Shall continue for next spell //if (StyxWoW.Me.CurrentCastTimeLeft.TotalMilliseconds < 500) //{ // return true; //} // temporary hack - checking requirements won't work -- either need global value or cancelDelegate // if ( onUnit(ret).HealthPercent > SingularSettings.Instance.IgnoreHealTargetsAboveHealth) // (!requirements(ret)) if ( cancel(ret) ) { SpellManager.StopCasting(); Logger.Write(System.Drawing.Color.Orange, "/cancel {0} on {1} @ {2:F1}%", name, onUnit(ret).SafeName(), onUnit(ret).HealthPercent); return true; } return false; }, new ActionAlwaysSucceed() ) ) ); }
public static Composite CreateWarlockRessurectBehavior(UnitSelectionDelegate onUnit) { if (!UseSoulstoneForBattleRez()) return new PrioritySelector(); if (onUnit == null) { Logger.WriteDebug("CreateWarlockRessurectBehavior: error - onUnit == null"); return new PrioritySelector(); } return new Decorator( ret => Me.Combat && onUnit(ret) != null && onUnit(ret).IsDead && Spell.CanCastHack( "Soulstone", onUnit(ret)) && !Group.Healers.Any(h => h.IsAlive && !h.Combat && h.SpellDistance() < 40), new Sequence( new Action( r => _targetRez = onUnit(r)), new PrioritySelector( Spell.WaitForCastOrChannel(), Movement.CreateMoveToUnitBehavior(ret => _targetRez, 40f), new Decorator( ret => !Spell.IsGlobalCooldown(), Spell.Cast("Soulstone", mov => true, on => _targetRez, req => true, cancel => ((WoWUnit)cancel).IsAlive) ) ) ) ); }
/// <summary> /// private function to buff individual units. makes assumptions /// that certain states have been checked previously. only the /// group interface to PartyBuffs is exposed since it handles the /// case of LocalPlayer not in a group as well /// </summary> /// <param name="name">spell name</param> /// <param name="onUnit">unit selection delegate</param> /// <param name="requirements">requirements delegate that must be true to cast buff</param> /// <param name="myMutexBuffs">list of buffs your mechanics make mutually exclusive for you to cast. For example, BuffGroup("Blessing of Kings", ret => true, "Blessing of Might") </param> /// <returns></returns> private static Composite BuffUnit(string name, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements, params string[] myMutexBuffs) { return new Decorator( ret => onUnit(ret) != null && (PartyBuffType.None != (onUnit(ret).GetMissingPartyBuffs() & GetPartyBuffForSpell(name))) && (myMutexBuffs == null || myMutexBuffs.Count() == 0 || !onUnit(ret).GetAllAuras().Any(a => a.CreatorGuid == StyxWoW.Me.Guid && myMutexBuffs.Contains(a.Name))), new Sequence( Spell.Buff( name, onUnit, requirements), new Wait( 1, until => StyxWoW.Me.HasPartyBuff(name), new ActionAlwaysSucceed()), new Action(ret => { System.Diagnostics.Debug.Assert( PartyBuffType.None != GetPartyBuffForSpell(name)); if (PartyBuffType.None != GetPartyBuffForSpell(name)) ResetReadyToPartyBuffTimer(); else Logger.WriteDebug("Programmer Error: should use Spell.Buff(\"{0}\") instead", name); }) ) ); }
/// <summary> /// Creates a behavior to cast a buff by name on a specific unit. Returns /// RunStatus.Success if successful, RunStatus.Failure otherwise. /// </summary> /// <remarks> /// Created 5/2/2011. /// </remarks> /// <param name = "name">The name of the buff</param> /// <param name = "onUnit">The on unit</param> /// <returns></returns> public static Composite Buff(string name, UnitSelectionDelegate onUnit) { return Buff(name, false, onUnit, ret => true, name); }