public Composite CreateBehavior_KillMantid() { WoWUnit attackTarget = null; WoWUnit IronShredder = null; WaitTimer DeathFromAboveTimer = WaitTimer.TenSeconds; return(new Decorator(r => !Me.IsQuestComplete(QuestId) && Query.IsInVehicle() && (IronShredder = Me.CharmedUnit) != null, new PrioritySelector(ctx => attackTarget = GetAttackTarget(), new Decorator(ctx => attackTarget != null, new PrioritySelector( new ActionSetActivity("Moving to Attack"), new Decorator(ctx => Me.CurrentTargetGuid != attackTarget.Guid, new ActionFail(ctx => attackTarget.Target())), new Decorator(ctx => !Me.IsSafelyFacing(attackTarget) || !IronShredder.IsSafelyFacing(attackTarget), new ActionFail(ctx => attackTarget.Face())), // cast 'Death From Above' ability on targets outside of melee new Decorator( ctx => IronShredder.Location.DistanceSquared(attackTarget.Location) > 10 * 10 && IronShredder.Location.DistanceSquared(attackTarget.Location) < 70 * 70 && DeathFromAboveTimer.IsFinished, new Sequence( new Action(ctx => Lua.DoString("CastPetAction(2)")), new WaitContinue(2, ctx => StyxWoW.Me.CurrentPendingCursorSpell != null, new ActionAlwaysSucceed()), new Action(ctx => SpellManager.ClickRemoteLocation(attackTarget.Location)), new Action(ctx => DeathFromAboveTimer.Reset()))), // cast 'Elecrostatic Distortion' ability on melee range target. new Decorator( ctx => IronShredder.Location.DistanceSquared(attackTarget.Location) <= 25 * 25, new PrioritySelector( new Decorator( ctx => IronShredder.Location.DistanceSquared(attackTarget.Location) <= 25 * 25 && (Me.IsMoving || Me.CharmedUnit.IsMoving), new ActionFail(ctx => WoWMovement.ClickToMove(Me.CharmedUnit.Location))), new Action(ctx => Lua.DoString("CastPetAction(1)")))), new Decorator(ctx => IronShredder.Location.DistanceSquared(attackTarget.Location) > 25 * 25, new Action(ctx => Navigator.MoveTo(attackTarget.Location))))), new Decorator( ctx => attackTarget == null, new PrioritySelector( new Decorator( ctx => IronShredder.Location.DistanceSquared(_waitPoint) > 10 * 10, new PrioritySelector( new Action(ctx => Navigator.MoveTo(_waitPoint)))), new ActionSetActivity("No viable targets, waiting."))), new ActionAlwaysSucceed()))); }
public override void OnStart() { // Let QuestBehaviorBase do basic initializaion of the behavior, deal with bad or deprecated attributes, // capture configuration state, install BT hooks, etc. This will also update the goal text. var isBehaviorShouldRun = OnStart_QuestBehaviorCore(); // If the quest is complete, this behavior is already done... // So we don't want to falsely inform the user of things that will be skipped. if (isBehaviorShouldRun) { int waitDuration = WaitTime + StyxWoW.Random.Next(VariantTime); _timer = new Styx.Common.Helpers.WaitTimer(TimeSpan.FromMilliseconds(waitDuration)); _waitTimeAsString = Utility.PrettyTime(_timer.WaitTime); _timer.Reset(); this.UpdateGoalText(GetQuestId(), "Waiting for " + _waitTimeAsString); } }
public Composite CreateBehavior_KillGnomereganStealthFighter() { WoWUnit attackTarget = null; WoWUnit PrideofKezan = null; WaitTimer WildWeaselRocketsTimer = WaitTimer.FiveSeconds; return(new Decorator(r => !Me.IsQuestComplete(QuestId) && Query.IsInVehicle() && (PrideofKezan = Me.CharmedUnit) != null, new PrioritySelector(ctx => attackTarget = GetAttackTarget(), new Decorator(ctx => attackTarget != null, new PrioritySelector( new ActionSetActivity("Moving to Attack"), new Decorator(ctx => Me.CurrentTargetGuid != attackTarget.Guid, new ActionFail(ctx => attackTarget.Target())), new Decorator(ctx => !Me.IsSafelyFacing(attackTarget) || !PrideofKezan.IsSafelyFacing(attackTarget), new ActionFail(ctx => attackTarget.Face())), // cast 'Wild Weasel Rockets' ability new Decorator( ctx => PrideofKezan.Location.DistanceSqr(attackTarget.Location) < 25 * 25 && WildWeaselRocketsTimer.IsFinished, new Sequence( new Action(ctx => Lua.DoString("CastPetAction(2)")), new Action(ctx => WildWeaselRocketsTimer.Reset()))), // cast 'Machine Gun' ability new Decorator( ctx => PrideofKezan.Location.DistanceSqr(attackTarget.Location) <= 25 * 25, new Sequence( new Action(ctx => Lua.DoString("CastPetAction(1)")))), new Decorator(ctx => PrideofKezan.Location.DistanceSqr(attackTarget.Location) > 25 * 25, new Action(ctx => WoWMovement.ClickToMove(attackTarget.Location))))), new Decorator( ctx => attackTarget == null, new PrioritySelector( new Decorator( ctx => PrideofKezan.Location.DistanceSqr(_waitPoint) > 10 * 10, new Sequence( new Action(ctx => WoWMovement.ClickToMove(_waitPoint)))), new ActionSetActivity("No viable targets, waiting."))), new ActionAlwaysSucceed()))); }
/// <summary>Waits until a result is available for a spell cast and then retrurn it.</summary> /// <param name="maxTimeoutMs">The maximum timeout in milliseconds.</param> public async Task <SpellCastResult> GetResult(int maxTimeoutMs = 15000) { var timer = new WaitTimer(TimeSpan.FromMilliseconds(StyxWoW.WoWClient.Latency * 2 + 50)); timer.Reset(); var startedCast = false; Func <bool> beganCast = () => { startedCast = startedCast || StyxWoW.Me.IsCasting; return(startedCast); }; await Coroutine.Wait(maxTimeoutMs, () => HasResult || timer.IsFinished && !beganCast()); if (!HasResult && timer.IsFinished && !beganCast()) { return(SpellCastResult.NoCastStarted); } return(Result); }
public Composite CreateBehavior_KillMantid() { WoWUnit attackTarget = null; WoWUnit yeti = null; WaitTimer leapSmashTimer = WaitTimer.TenSeconds; return(new Decorator(r => !Me.IsQuestComplete(QuestId) && Query.IsInVehicle() && (yeti = Me.CharmedUnit) != null, new PrioritySelector(ctx => attackTarget = GetAttackTarget(), new Decorator(ctx => attackTarget != null, new PrioritySelector( new ActionFail(ctx => _stuckTimer.Reset()), new ActionSetActivity("Moving to Attack"), new Decorator(ctx => Me.CurrentTargetGuid != attackTarget.Guid, new ActionFail(ctx => attackTarget.Target())), new Decorator(ctx => !Me.IsSafelyFacing(attackTarget) || !yeti.IsSafelyFacing(attackTarget), new ActionFail(ctx => attackTarget.Face())), // cast 'Hozen Snack' ability to heal up. new Decorator(ctx => yeti.HealthPercent <= 70, new ActionFail(ctx => Lua.DoString("CastPetAction(4)"))), // cast 'Leap Smash' ability on targets outside of melee new Decorator( ctx => yeti.Location.DistanceSqr(attackTarget.Location) > 30 * 30 && yeti.Location.DistanceSqr(attackTarget.Location) < 90 * 90 && leapSmashTimer.IsFinished, new Sequence( new Action(ctx => Lua.DoString("CastPetAction(1)")), new WaitContinue(2, ctx => StyxWoW.Me.CurrentPendingCursorSpell != null, new ActionAlwaysSucceed()), new Action(ctx => SpellManager.ClickRemoteLocation(attackTarget.Location)), new Action(ctx => leapSmashTimer.Reset()))), // cast 'Headbutt' ability on melee range target. new Decorator( ctx => yeti.Location.DistanceSqr(attackTarget.Location) <= 25 * 25, new PrioritySelector( new Decorator( ctx => yeti.Location.DistanceSqr(attackTarget.Location) <= 25 * 25 && (Me.IsMoving || Me.CharmedUnit.IsMoving), new ActionFail(ctx => WoWMovement.ClickToMove(Me.CharmedUnit.Location))), new Action(ctx => Lua.DoString("CastPetAction(2)")))), new Decorator(ctx => yeti.Location.DistanceSqr(attackTarget.Location) > 25 * 25, new Action(ctx => Navigator.MoveTo(attackTarget.Location))))), new Decorator( ctx => attackTarget == null, new PrioritySelector( new Decorator( ctx => yeti.Location.DistanceSqr(_waitPoint) > 10 * 10, new PrioritySelector( // can't set path precision so I'll just handle it directly... // the yeti takes wide turns so needs a higher path precision than normal new Decorator( ctx => { var nav = Navigator.NavigationProvider as MeshNavigator; if (nav == null) { return false; } if (nav.CurrentMovePath == null || nav.CurrentMovePath.Index >= nav.CurrentMovePath.Path.Points.Length) { return false; } WoWPoint point = nav.CurrentMovePath.Path.Points[nav.CurrentMovePath.Index]; return point.DistanceSqr(yeti.Location) < 6 * 6; }, new Action(ctx => ((MeshNavigator)Navigator.NavigationProvider).CurrentMovePath.Index++)), CreateBehavior_Antistuck(), new Action(ctx => Navigator.MoveTo(_waitPoint)))), new ActionSetActivity("No viable targets, waiting."))), new ActionAlwaysSucceed()))); }
private async Task TargetLogic(WoWUnit target) { if (!Query.IsViable(target)) { return; } var targetDistSqr = target.Location.DistanceSquared(Vehicle.Location); if (PickUpPassengerButton == 0) { TreeRoot.StatusText = string.Format("Blowing stuff up. {0} mins before resummon is required", _flightTimer.TimeLeft.TotalMinutes); if (HealButton > 0 && targetDistSqr < 60 * 60 && (Vehicle.HealthPercent <= HealPercent || Vehicle.ManaPercent <= HealPercent) && UseVehicleButton(HealButton)) { QBCLog.Info("Used heal button {0} on NPC:{1}", HealButton, target.SafeName); return; } // return when a button is used. foreach (var button in Buttons) { if (UseVehicleButton(button)) { return; } } return; } TreeRoot.StatusText = string.Format("Rescuing {0}", target.SafeName); var pickTimer = new WaitTimer(TimeSpan.FromSeconds(20)); pickTimer.Reset(); while (target.IsValid && target.IsAlive && !UnitIsRidingMyVehicle(target) && Query.IsInVehicle() && !pickTimer.IsFinished) { Vector3 clickLocation = target.Location.RayCast(target.Rotation, 6); clickLocation.Z += 3; if (Vehicle.Location.DistanceSquared(clickLocation) > 3 * 3) { Stopwatch timer = Stopwatch.StartNew(); do { Flightor.MoveTo(clickLocation); await Coroutine.Yield(); } while (timer.ElapsedMilliseconds < 1000 && Vehicle.Location.DistanceSquared(clickLocation) > 3 * 3); } else { if (Vehicle.IsMoving) { await CommonCoroutines.StopMoving(string.Format("Picking up {0}", target.SafeName)); } UseVehicleButton(PickUpPassengerButton); if (await Coroutine.Wait(4000, () => UnitIsRidingMyVehicle(target))) { QBCLog.Info("Successfully picked up passenger {0}", target.SafeName); return; } QBCLog.Info("Failed to picked up passenger {0}", target.SafeName); await Coroutine.Yield(); } } }