public async Task <bool> CastIfReady(KeyAction item, int sleepBeforeCast = 0) { if (!CanRun(item)) { return(false); } if (item.ConsoleKey == 0) { return(false); } if (!await SwitchToCorrectShapeShiftForm(item)) { return(false); } if (this.playerReader.IsShooting) { await input.TapInteractKey("Stop casting shoot"); await Task.Delay(1500); // wait for shooting to end } if (sleepBeforeCast > 0) { item.LogInformation($" Wait before {sleepBeforeCast}."); await Task.Delay(sleepBeforeCast); } await PressKey(item.ConsoleKey, item.Name, item.PressDuration); item.SetClicked(); if (!item.HasCastBar) { var result = await WaitInterrupt(item.DelayAfterCast, () => playerReader.PlayerBitValues.TargetIsDead || playerReader.TargetHealthPercentage < 5); item.LogInformation($" ... no castbar delay after cast {result.Item2}ms"); await InteractOnUIError(); } else { await playerReader.WaitForNUpdate(1); if (!this.playerReader.IsCasting && this.playerReader.HasTarget) { await this.InteractOnUIError(); item.LogInformation($"Not casting, pressing it again"); await PressKey(item.ConsoleKey, item.Name, item.PressDuration); await playerReader.WaitForNUpdate(1); if (!this.playerReader.IsCasting && this.playerReader.HasTarget) { item.LogInformation($"Still not casting !"); await this.InteractOnUIError(); return(false); } } item.LogInformation(" waiting for cast bar to end."); for (int i = 0; i < 15000; i += 100) { if (!this.playerReader.IsCasting) { await playerReader.WaitForNUpdate(1); break; } // wait after cast if the delay is different to the default value if (item.DelayAfterCast != new KeyAction().DelayAfterCast) { item.LogInformation($" ... delay after cast {item.DelayAfterCast}"); if (item.DelayUntilCombat) // stop waiting if the mob is targetting me { var sw = new Stopwatch(); sw.Start(); while (sw.ElapsedMilliseconds < item.DelayAfterCast) { await Task.Delay(10); if (this.playerReader.PlayerBitValues.TargetOfTargetIsPlayer) { break; } } } else { var result = await WaitInterrupt(item.DelayAfterCast, () => playerReader.PlayerBitValues.TargetIsDead || playerReader.TargetHealthPercentage < 5); item.LogInformation($" ... castbar delay after cast {result.Item2}ms"); } } await playerReader.WaitForNUpdate(1); } } if (item.StepBackAfterCast > 0) { await this.input.KeyPress(ConsoleKey.DownArrow, item.StepBackAfterCast, $"Step back for {item.StepBackAfterCast}ms"); } item.ConsumeCharge(); return(true); }
public async Task <bool> CastIfReady(KeyAction item, int sleepBeforeCast = 0) { if (!CanRun(item)) { return(false); } if (item.ConsoleKey == 0) { return(false); } if (item.Name == classConfig.Approach.Name || item.Name == classConfig.AutoAttack.Name || item.Name == classConfig.Interact.Name) { await PressKeyAction(item); return(true); } bool beforeUsable = addonReader.UsableAction.Is(item); var beforeForm = playerReader.Form; if (!await SwitchToCorrectStanceForm(beforeForm, item)) { return(false); } if (beforeForm != playerReader.Form && !beforeUsable && !addonReader.UsableAction.Is(item)) { item.LogInformation(" ... after Form switch still not usable!"); return(false); } if (playerReader.Bits.IsAutoRepeatSpellOn_Shoot) { await input.TapStopAttack("Stop AutoRepeat Shoot"); await input.TapStopAttack("Stop AutoRepeat Shoot"); await wait.Update(1); (bool interrupted, double elapsedMs) = await wait.InterruptTask(GCD, () => addonReader.UsableAction.Is(item)); if (!interrupted) { item.LogInformation($" ... waited to end Shoot {elapsedMs}ms"); } } if (sleepBeforeCast > 0) { if (item.StopBeforeCast || item.HasCastBar) { await stopMoving.Stop(); await wait.Update(1); await stopMoving.Stop(); await wait.Update(1); } item.LogInformation($" Wait {sleepBeforeCast}ms before press."); await Task.Delay(sleepBeforeCast); } bool beforeHasTarget = playerReader.HasTarget; int auraHash = playerReader.AuraCount.Hash; if (!await WaitForGCD(item, beforeHasTarget)) { return(false); } if (!item.HasCastBar) { if (!await CastInstant(item)) { // try again after reacted to UI_ERROR if (!await CastInstant(item)) { return(false); } } } else { if (!await CastCastbar(item)) { // try again after reacted to UI_ERROR if (!await CastCastbar(item)) { return(false); } } } if (item.AfterCastWaitBuff) { (bool notappeared, double elapsedMs) = await wait.InterruptTask(MaxWaitBuffTimeMs, () => auraHash != playerReader.AuraCount.Hash); item.LogInformation($" ... AfterCastWaitBuff: Buff: {!notappeared} | pb: {playerReader.AuraCount.PlayerBuff} | pd: {playerReader.AuraCount.PlayerDebuff} | tb: {playerReader.AuraCount.TargetBuff} | td: {playerReader.AuraCount.TargetDebuff} | Delay: {elapsedMs}ms"); } if (item.DelayAfterCast != defaultKeyAction.DelayAfterCast) { if (item.DelayUntilCombat) // stop waiting if the mob is targetting me { item.LogInformation($" ... DelayUntilCombat ... delay after cast {item.DelayAfterCast}ms"); var sw = new Stopwatch(); sw.Start(); while (sw.ElapsedMilliseconds < item.DelayAfterCast) { await wait.Update(1); if (playerReader.Bits.TargetOfTargetIsPlayer) { break; } } } else if (item.DelayAfterCast > 0) { item.LogInformation($" ... delay after cast {item.DelayAfterCast}ms"); var result = await wait.InterruptTask(item.DelayAfterCast, () => beforeHasTarget != playerReader.HasTarget); if (!result.Item1) { item.LogInformation($" .... delay after cast interrupted, target changed {result.Item2}ms"); } else { item.LogInformation($" .... delay after cast not interrupted {result.Item2}ms"); } } } else { if (item.RequirementObjects.Any()) { (bool firstReq, double firstReqElapsedMs) = await wait.InterruptTask(SpellQueueTimeMs, () => !item.CanRun() ); item.LogInformation($" ... instant interrupt: {!firstReq} | CanRun:{item.CanRun()} | Delay: {firstReqElapsedMs}ms"); } } if (item.StepBackAfterCast > 0) { input.SetKeyState(ConsoleKey.DownArrow, true, false, $"Step back for {item.StepBackAfterCast}ms"); (bool notStepback, double stepbackElapsedMs) = await wait.InterruptTask(item.StepBackAfterCast, () => beforeHasTarget != playerReader.HasTarget); if (!notStepback) { item.LogInformation($" .... interrupted stepback | lost target? {beforeHasTarget != playerReader.HasTarget} | {stepbackElapsedMs}ms"); } input.SetKeyState(ConsoleKey.DownArrow, false, false); } if (item.AfterCastWaitNextSwing) { await wait.Update(1); } item.ConsumeCharge(); return(true); }