protected bool CanRun(KeyAction item) { if (!string.IsNullOrEmpty(item.CastIfAddsVisible)) { var needAdds = bool.Parse(item.CastIfAddsVisible); if (needAdds != npcNameFinder.PotentialAddsExist) { item.LogInformation($"Only cast if adds exist = {item.CastIfAddsVisible} and it is {npcNameFinder.PotentialAddsExist} - Targets:{npcNameFinder.TargetCount} - Adds:{npcNameFinder.AddCount}"); return(false); } else { item.LogInformation($"Only cast if adds exist = {item.CastIfAddsVisible} and it is {npcNameFinder.PotentialAddsExist} - Targets:{npcNameFinder.TargetCount} - Adds:{npcNameFinder.AddCount}"); } } if (item.School != SchoolMask.None) { if (classConfig.ImmunityBlacklist.TryGetValue(playerReader.TargetId, out var list)) { if (list.Contains(item.School)) { return(false); } } } return(item.CanRun()); }
private async Task <bool> WaitForGCD(KeyAction item, bool beforeHasTarget) { if (item.WaitForGCD) { (bool gcd, double gcdElapsedMs) = await wait.InterruptTask(GCD, () => addonReader.UsableAction.Is(item) || beforeHasTarget != playerReader.HasTarget); if (!gcd) { item.LogInformation($" ... gcd interrupted {gcdElapsedMs}ms"); if (beforeHasTarget != playerReader.HasTarget) { item.LogInformation($" ... lost target!"); return(false); } } else { item.LogInformation($" ... gcd fully waited {gcdElapsedMs}ms"); } } return(true); }
private async Task <bool> CastInstant(KeyAction item) { if (item.StopBeforeCast) { await stopMoving.Stop(); await wait.Update(1); } playerReader.CastEvent.ForceUpdate(0); int beforeCastEventValue = playerReader.CastEvent.Value; int beforeSpellId = playerReader.CastSpellId.Value; bool beforeUsable = addonReader.UsableAction.Is(item); await PressKeyAction(item); bool inputNotHappened; double inputElapsedMs; if (item.AfterCastWaitNextSwing) { (inputNotHappened, inputElapsedMs) = await wait.InterruptTask(MaxSwingTimeMs, interrupt : () => !addonReader.CurrentAction.Is(item), repeat : async() => { if (classConfig.Approach.GetCooldownRemaining() == 0) { await input.TapApproachKey(""); } }); } else { (inputNotHappened, inputElapsedMs) = await wait.InterruptTask(MaxWaitCastTimeMs, interrupt : () => (beforeSpellId != playerReader.CastSpellId.Value && beforeCastEventValue != playerReader.CastEvent.Value) || beforeUsable != addonReader.UsableAction.Is(item) ); } if (!inputNotHappened) { item.LogInformation($" ... instant input {inputElapsedMs}ms"); } else { item.LogInformation($" ... instant input not registered! {inputElapsedMs}ms"); return(false); } item.LogInformation($" ... usable: {beforeUsable}->{addonReader.UsableAction.Is(item)} -- ({(UI_ERROR)beforeCastEventValue}->{(UI_ERROR)playerReader.CastEvent.Value})"); if (!CastSuccessfull((UI_ERROR)playerReader.CastEvent.Value)) { await ReactToLastCastingEvent(item, $"{item.Name}-{GetType().Name}: CastInstant"); return(false); } return(true); }
protected bool CanRun(KeyAction item) { if (!string.IsNullOrEmpty(item.CastIfAddsVisible)) { var needAdds = bool.Parse(item.CastIfAddsVisible); if (needAdds != npcNameFinder.PotentialAddsExist) { item.LogInformation($"Only cast if adds exist = {item.CastIfAddsVisible} and it is {npcNameFinder.PotentialAddsExist}"); return(false); } } return(item.CanRun()); }
protected async Task <bool> SwitchToCorrectStanceForm(Form beforeForm, KeyAction item) { if (string.IsNullOrEmpty(item.Form)) { return(true); } if (playerReader.Form == item.FormEnum) { return(true); } var formKeyAction = classConfig.Form .Where(s => s.FormEnum == item.FormEnum) .FirstOrDefault(); if (formKeyAction == null) { logger.LogWarning($"Unable to find key in Form to transform into {item.FormEnum}"); return(false); } await input.KeyPress(formKeyAction.ConsoleKey, formKeyAction.PressDuration); (bool notChanged, double elapsedMs) = await wait.InterruptTask(SpellQueueTimeMs, () => beforeForm != playerReader.Form); item.LogInformation($" ... form changed: {!notChanged} | Delay: {elapsedMs}ms"); if (playerReader.Form == Form.None) { item.LogInformation($" ... wait for GCD after form change {beforeForm}->{playerReader.Form}!"); await WaitForGCD(item, playerReader.HasTarget); } return(playerReader.Form == item.FormEnum); }
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, GoapGoal source, 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 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) { item.LogInformation($" ... delay after cast {item.DelayAfterCast}"); await Task.Delay(item.DelayAfterCast); } else { await Task.Delay(300); 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 Task.Delay(300); 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 Task.Delay(100); 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 { await Task.Delay(item.DelayAfterCast); } } if (source.GetType() == typeof(PullTargetGoal) && this.playerReader.PlayerBitValues.PlayerInCombat && !this.playerReader.PlayerBitValues.TargetOfTargetIsPlayer && this.playerReader.IsCasting && this.playerReader.TargetHealthPercentage > 99 ) { if (!this.playerReader.TargetIsFrostbitten) { await this.wowProcess.KeyPress(ConsoleKey.UpArrow, 200, "Stop cast as picked up an add, my mob is not targetting me."); await wowProcess.KeyPress(ConsoleKey.F3, 400); // clear target break; } } await Task.Delay(100); } } if (item.StepBackAfterCast > 0) { await this.wowProcess.KeyPress(ConsoleKey.DownArrow, item.StepBackAfterCast * 1000, "Step back hero"); } 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); }
private async Task <bool> CastCastbar(KeyAction item) { if (playerReader.Bits.IsFalling) { (bool notfalling, double fallingElapsedMs) = await wait.InterruptTask(MaxAirTimeMs, () => !playerReader.Bits.IsFalling); if (!notfalling) { item.LogInformation($" ... castbar waited for landing {fallingElapsedMs}ms"); } } await stopMoving.Stop(); await wait.Update(1); bool beforeHasTarget = playerReader.HasTarget; bool beforeUsable = addonReader.UsableAction.Is(item); int beforeCastEventValue = playerReader.CastEvent.Value; int beforeSpellId = playerReader.CastSpellId.Value; int beforeCastCount = playerReader.CastCount; await PressKeyAction(item); (bool input, double inputElapsedMs) = await wait.InterruptTask(MaxWaitCastTimeMs, interrupt : () => beforeCastEventValue != playerReader.CastEvent.Value || beforeSpellId != playerReader.CastSpellId.Value || beforeCastCount != playerReader.CastCount ); if (!input) { item.LogInformation($" ... castbar input {inputElapsedMs}ms"); } else { item.LogInformation($" ... castbar input not registered! {inputElapsedMs}ms"); return(false); } item.LogInformation($" ... casting: {playerReader.IsCasting} -- count:{playerReader.CastCount} -- usable: {beforeUsable}->{addonReader.UsableAction.Is(item)} -- {(UI_ERROR)beforeCastEventValue}->{(UI_ERROR)playerReader.CastEvent.Value}"); if (!CastSuccessfull((UI_ERROR)playerReader.CastEvent.Value)) { await ReactToLastCastingEvent(item, $"{item.Name}-{GetType().Name}: CastCastbar"); return(false); } if (playerReader.IsCasting) { item.LogInformation(" ... waiting for visible cast bar to end or target loss."); await wait.InterruptTask(MaxCastTimeMs, () => !playerReader.IsCasting || beforeHasTarget != playerReader.HasTarget); } else if ((UI_ERROR)playerReader.CastEvent.Value == UI_ERROR.CAST_START) { beforeCastEventValue = playerReader.CastEvent.Value; item.LogInformation(" ... waiting for hidden cast bar to end or target loss."); await wait.InterruptTask(MaxCastTimeMs, () => beforeCastEventValue != playerReader.CastEvent.Value || beforeHasTarget != playerReader.HasTarget); } return(true); }