public static void ClickRepeat(Interactor intr, int xCoord, int yCoord, int repeats) { for (int c = 0; c < repeats; c++) { Click(intr, xCoord, yCoord); intr.Wait(25); } }
public static void DoubleClick(Interactor intr, int xCoord, int yCoord) { intr.Log(LogEntryType.Trace, "Double-clicking at ({0},{1}).", xCoord, yCoord); intr.ExecuteStatement("SendEvent { Click " + xCoord + ", " + yCoord + ", 0 }"); intr.Wait(10); intr.ExecuteStatement("SendEvent { Click 2 }"); }
public static void WheelDown(Interactor intr, int repeats) { for (int c = 0; c < repeats; c++) { intr.ExecuteStatement("SendEvent { Click WheelDown }"); intr.Wait(5); } }
private static bool CollectCompleted(Interactor intr) { var resultAvailable = Screen.ImageSearch(intr, "ProfessionsCollectResult"); if (resultAvailable.Found) { Mouse.Click(intr, resultAvailable.Point, 15, 5); intr.Wait(900); Mouse.ClickImage(intr, "ProfessionsTakeRewardsButton", 21, 5); intr.Wait(1500); return(true); } else { return(false); } }
public static bool ActivateClient(Interactor intr) { //intr.ExecuteStatement("ActivateNeverwinter()"); Screen.WindowActivate(intr, States.GAMECLIENTEXE); intr.Wait(1500); return(true); }
public static bool ActivateClient(Interactor intr) { //intr.ExecuteStatement("ActivateNeverwinter()"); Screen.WindowActivate(intr, States.GAMECLIENTEXE); intr.Wait(1500); return true; }
private static void SelectProfTask(Interactor intr, string taskName) { intr.Log(LogEntryType.Debug, "Attempting to select profession task: '{0}'.", taskName); var searchButton = Screen.ImageSearch(intr, "ProfessionsSearchButton"); intr.Wait(50); Mouse.Click(intr, searchButton.Point, -100, 0); intr.Wait(50); Keyboard.SendKey(intr, "Shift", "Home"); intr.Wait(50); Keyboard.Send(intr, taskName); intr.Wait(50); Keyboard.SendKey(intr, "Enter"); intr.Wait(100); }
//public static bool ActivateClient(Interactor intr) { // //intr.ExecuteStatement("ActivateNeverwinter()"); // Screen.WindowActivate(intr, Game.GAMECLIENTEXE); // intr.Wait(1000); // return true; //} public static bool LogOut(Interactor intr) { //intr.ExecuteStatement("Logout()"); intr.Log(LogEntryType.Info, "Logging out..."); ClearDialogues(intr); MoveAround(intr); Keyboard.SendKey(intr, "Enter"); intr.Wait(50); Keyboard.Send(intr, "/gotocharacterselect"); intr.Wait(100); Keyboard.SendKey(intr, "Enter"); intr.Wait(100); //intr.Wait(3000); return true; }
//public static bool ActivateClient(Interactor intr) { // //intr.ExecuteStatement("ActivateNeverwinter()"); // Screen.WindowActivate(intr, Game.GAMECLIENTEXE); // intr.Wait(1000); // return true; //} public static bool LogOut(Interactor intr) { //intr.ExecuteStatement("Logout()"); intr.Log(LogEntryType.Info, "Logging out..."); ClearDialogues(intr); MoveAround(intr); Keyboard.SendKey(intr, "Enter"); intr.Wait(50); Keyboard.Send(intr, "/gotocharacterselect"); intr.Wait(100); Keyboard.SendKey(intr, "Enter"); intr.Wait(100); //intr.Wait(3000); return(true); }
public static bool CrashCheckRecovery(Interactor intr, int prev_tries_unimplemented) { intr.Log(LogEntryType.Info, "CrashCheckRecovery(): Initiating..."); Screen.Wake(intr); Mouse.Move(intr, 1, 1); intr.Wait(5000); ClearDialogues(intr); intr.Wait(2000); Screen.WindowKillTitle(intr, "Verify?"); KillAll(intr); return true; //switch (Game.DetermineGameState(intr)) { // case GameState.Closed: // intr.Log("CrashCheckRecovery(): GameState == Closed. Calling ProduceClientState().", LogEntryType.Info); // return ProduceClientState(intr, ClientState.CharSelect); // case GameState.Patcher: // intr.Log("CrashCheckRecovery(): GameState == Closed. Calling ProduceClientState().", LogEntryType.Info); // return ProduceClientState(intr, ClientState.CharSelect); // case GameState.ClientActive: // intr.Log("CrashCheckRecovery(): GameState == Closed. Killing all then calling ProduceClientState().", LogEntryType.Info); // KillAll(intr); // return ProduceClientState(intr, ClientState.CharSelect); // case GameState.Unknown: // default: // intr.Log("CrashCheckRecovery(): GameState unknown. Killing all."); // KillAll(intr); // return false; //} }
public static bool CrashCheckRecovery(Interactor intr, int prev_tries_unimplemented) { intr.Log(LogEntryType.Info, "CrashCheckRecovery(): Initiating..."); Screen.Wake(intr); Mouse.Move(intr, 1, 1); intr.Wait(5000); ClearDialogues(intr); intr.Wait(2000); Screen.WindowKillTitle(intr, "Verify?"); KillAll(intr); return(true); //switch (Game.DetermineGameState(intr)) { // case GameState.Closed: // intr.Log("CrashCheckRecovery(): GameState == Closed. Calling ProduceClientState().", LogEntryType.Info); // return ProduceClientState(intr, ClientState.CharSelect); // case GameState.Patcher: // intr.Log("CrashCheckRecovery(): GameState == Closed. Calling ProduceClientState().", LogEntryType.Info); // return ProduceClientState(intr, ClientState.CharSelect); // case GameState.ClientActive: // intr.Log("CrashCheckRecovery(): GameState == Closed. Killing all then calling ProduceClientState().", LogEntryType.Info); // KillAll(intr); // return ProduceClientState(intr, ClientState.CharSelect); // case GameState.Unknown: // default: // intr.Log("CrashCheckRecovery(): GameState unknown. Killing all."); // KillAll(intr); // return false; //} }
public static void KeyPress(Interactor intr, string key, int duration) { //intr.ExecuteStatement("SendInput { " + key + " down }"); //intr.Wait((int)duration + 180); //intr.ExecuteStatement("SendInput { " + key + " up }"); //intr.Wait(20); string cmd = @"Send {" + key + @" down} Sleep " + duration.ToString() + @" Send {" + key + @" up} Sleep " + duration.ToString() + @" " ; intr.ExecuteStatement(cmd); intr.Wait(duration * 3); }
//// Checks to ensure that the inventory was successfully opened. //public static bool InventoryIsOpen(Interactor intr) { // var invState = States.DetermineInventoryState(intr); // if (invState == InventoryState.None) { // return false; // } else { // return true; // } //} // Opens inventory. public static bool OpenInventory(Interactor intr) { intr.Log(LogEntryType.Debug, "Opening inventory..."); string openInventoryKey = intr.AccountSettings.GetSettingValOr("inventory", "gameHotkeys", Global.Default.InventoryKey); MoveAround(intr); Keyboard.SendKey(intr, openInventoryKey); intr.Wait(300); if (intr.WaitUntil(8, WorldWindowState.Inventory, States.IsWorldWindowState, null, 1)) { intr.Log(LogEntryType.Debug, "Inventory is open."); return true; } else { intr.Log(LogEntryType.Info, "Unable to open inventory. Could be a random glitch."); return false; } }
public static void KeyPress(Interactor intr, string key, int duration) { //intr.ExecuteStatement("SendInput { " + key + " down }"); //intr.Wait((int)duration + 180); //intr.ExecuteStatement("SendInput { " + key + " up }"); //intr.Wait(20); string cmd = @"Send {" + key + @" down} Sleep " + duration.ToString() + @" Send {" + key + @" up} Sleep " + duration.ToString() + @" "; intr.ExecuteStatement(cmd); intr.Wait(duration * 3); }
//// Checks to ensure that the inventory was successfully opened. //public static bool InventoryIsOpen(Interactor intr) { // var invState = States.DetermineInventoryState(intr); // if (invState == InventoryState.None) { // return false; // } else { // return true; // } //} // Opens inventory. public static bool OpenInventory(Interactor intr) { intr.Log(LogEntryType.Debug, "Opening inventory..."); string openInventoryKey = intr.AccountSettings.GetSettingValOr("inventory", "gameHotkeys", Global.Default.InventoryKey); MoveAround(intr); Keyboard.SendKey(intr, openInventoryKey); intr.Wait(300); if (intr.WaitUntil(8, WorldWindowState.Inventory, States.IsWorldWindowState, null, 1)) { intr.Log(LogEntryType.Debug, "Inventory is open."); return(true); } else { intr.Log(LogEntryType.Info, "Unable to open inventory. Could be a random glitch."); return(false); } }
public static void SendInput(Interactor intr, string key) { //intr.Wait(200); intr.ExecuteStatement("SendInput " + key); intr.Wait(20); }
public static CompletionStatus MaintainProfs(Interactor intr, uint charIdx, List <ProfessionTaskResult> completionList) { if (intr.CancelSource.IsCancellationRequested) { return(CompletionStatus.Cancelled); } string charLabel = intr.AccountSettings.CharNames[(int)charIdx]; string profsWinKey = intr.AccountSettings.GetSettingValOr("professions", "gameHotkeys", Global.Default.ProfessionsWindowKey); intr.Log(LogEntryType.Debug, "Opening professions window for " + charLabel + "."); Keyboard.SendKey(intr, profsWinKey); intr.Wait(1000); if (!Screen.ImageSearch(intr, "ProfessionsWindowTitle").Found) { MoveAround(intr); Keyboard.SendKey(intr, profsWinKey); intr.Wait(200); if (!Screen.ImageSearch(intr, "ProfessionsWindowTitle").Found) { intr.Log(LogEntryType.FatalWithScreenshot, "Unable to open professions window"); return(CompletionStatus.Failed); } } if (Mouse.ClickImage(intr, "ProfessionsOverviewInactiveTile")) { intr.Wait(500); } int profResultsCollected = 0; if (Screen.ImageSearch(intr, "ProfessionsCollectResult").Found) { while (profResultsCollected < 9) { if (!CollectCompleted(intr)) { break; } else { profResultsCollected += 1; } } intr.Log(LogEntryType.Debug, "Collected " + profResultsCollected + " profession results for " + charLabel + "."); } int noValidTaskId = 0; int noValidTaskCounter = 0; int currentTaskId = 0; var anySuccess = false; for (int slotId = 0; slotId < 9; slotId++) { if (intr.CancelSource.IsCancellationRequested) { return(CompletionStatus.Cancelled); } ; if (Mouse.ClickImage(intr, "ProfessionsOverviewInactiveTile")) { intr.Wait(400); } var EmptySlotResult = Screen.ImageSearch(intr, "ProfessionsEmptySlot"); if (EmptySlotResult.Found) { intr.Log(LogEntryType.Info, "Empty professions slot found at: " + EmptySlotResult.Point.ToString() + "."); } else { intr.Log(LogEntryType.Info, "All professions slots busy."); break; } // Click the "Choose Task" button below the empty slot: Mouse.Click(intr, EmptySlotResult.Point, 30, 90); intr.Wait(400); // Click the "Leadership" category tile if it is not selected (determined by color): Mouse.ClickImage(intr, "ProfessionsLeadershipTileUnselected"); intr.Wait(200); var taskContinueResult = Screen.ImageSearch(intr, "ProfessionsTaskContinueButton"); if (slotId == 0 || !taskContinueResult.Found) { while (true) { if (currentTaskId < ProfessionTasksRef.ProfessionTaskNames.Length) { SelectProfTask(intr, ProfessionTasksRef.ProfessionTaskNames[currentTaskId]); taskContinueResult = Screen.ImageSearch(intr, "ProfessionsTaskContinueButton"); if (taskContinueResult.Found) { intr.Log(LogEntryType.Debug, "Profession task: '{0}' has been selected.", ProfessionTasksRef.ProfessionTaskNames[currentTaskId]); break; } else { currentTaskId += 1; continue; } } else { // We've been stuck // if (noValidTaskId == currentTaskId) { // We have already set `noValidTaskId` for this task // if (noValidTaskCounter >= 2) { // This is the 3rd time we've been here // intr.Log(LogEntryType.Error, "Error starting profession task on " + charLabel + ":"); intr.Log(LogEntryType.Error, "- Ensure that profession assets are sorted correctly in inventory."); return(CompletionStatus.Stuck); } else { noValidTaskCounter += 1; } } else { noValidTaskId = currentTaskId; noValidTaskCounter = 1; } intr.Log(LogEntryType.Normal, "Could not find valid professions task."); CollectCompleted(intr); Mouse.ClickImage(intr, "ProfessionsWindowTitle"); Mouse.Move(intr, Screen.ImageSearch(intr, "ProfessionsWindowTitle").Point); } } } if (taskContinueResult.Found && currentTaskId < ProfessionTasksRef.ProfessionTaskNames.Length) { float bonusFactor = 0.0f; // Start the in-game task: if (ContinueTask(intr, taskContinueResult.Point, out bonusFactor)) { intr.Log(LogEntryType.Debug, "Profession task '{0}' (id: {1}, bf: {2}) started.", ProfessionTasksRef.ProfessionTaskNames[currentTaskId], currentTaskId, bonusFactor); completionList.Add(new ProfessionTaskResult(currentTaskId, bonusFactor)); anySuccess = true; } } } // Condense tasks into groups (of 3 generally): CondenseTasks(intr, completionList); if (intr.CancelSource.IsCancellationRequested) { return(CompletionStatus.Cancelled); } if (anySuccess) { return(CompletionStatus.Complete); } else { return(CompletionStatus.Immature); } }
public static void SendTest(Interactor intr, string key) { intr.Wait(3000); SendInput(intr, key); }
public static void SendEvent(Interactor intr, string keys) { intr.ExecuteStatement("SendEvent " + keys); intr.Wait(20); }
public static void ProcessCharacter( Interactor intr, TaskQueue queue ) { var currentTask = queue.NextTask; uint charIdx = currentTask.CharIdx; //string charLabel = intr.AccountSettings.CharNode(charIdx).GetAttribute("name"); string charLabel = intr.AccountSettings.CharNames[(int)charIdx]; //string charLabel = queue.NextTask.CharIdxLabel; int invokesToday = intr.AccountStates.GetCharStateOr(charIdx, "invokesToday", 0); bool skipInvocation = false; bool skipMaintInven = false; bool skipProfessions = false; DateTime invokesCompletedForDay = intr.AccountStates.GetCharStateOr(charIdx, "invokesCompleteFor", Global.Default.SomeOldDate); if (invokesCompletedForDay == TaskQueue.TodaysGameDate) { // Skip invocation if it's already done. skipInvocation = true; } else if (invokesCompletedForDay < TaskQueue.TodaysGameDate && invokesToday < 2 && currentTask.Kind == TaskKind.Invocation) { // Skip professions for the first few invokes of the day. intr.Log(LogEntryType.Info, "Skipping profession processing this round."); skipProfessions = true; } // Skip inventory processing for the first two invokes [0, 1] and every non invoke task: if (invokesToday < 2 || currentTask.Kind != TaskKind.Invocation) { intr.Log(LogEntryType.Info, "Skipping inventory processing this round."); skipMaintInven = true; } CompletionStatus invocationStatus = CompletionStatus.None; CompletionStatus professionsStatus = CompletionStatus.None; CompletionStatus maintStatus = CompletionStatus.None; bool processingIncomplete = false; intr.Log("Starting processing for " + charLabel + " ..."); // Reset `invokesToday` if `invokesCompletedOn` is if (invokesToday >= 6) { if (currentTask.Kind == TaskKind.Invocation) { if (invokesCompletedForDay == TaskQueue.TodaysGameDate) { intr.Log(LogEntryType.Info, charLabel + " has already invoked 6 times today. Queuing invocation for tomorrow"); queue.AdvanceInvocationTask(intr, charIdx, invokesToday, false); skipInvocation = true; skipMaintInven = true; //queue.QueueSubsequentInvocationTask(intr, charIdx, invokesToday); return; } else if (invokesCompletedForDay < TaskQueue.TodaysGameDate) { intr.Log(LogEntryType.Info, charLabel + ": Resetting InvokesToday to 0."); invokesToday = 0; intr.AccountStates.SaveCharState(invokesToday, charIdx, "invokesToday"); } else { var errMsg = charLabel + ": Internal error. `invokesCompletedOn` is in the future."; intr.Log(LogEntryType.Fatal, errMsg); throw new Exception(errMsg); } } } // CHECK TO SEE IF THERE ARE ANY UPCOMING TASKS FOR CHARACTER IN THE NEXT 29:59 MINUTES // IF SO -> CHECK TO SEE IF THERE ARE ANY TASKS IN THE 29:59 (TOTAL 59:59) MINUTES AFTER THAT // IF NOT -> MERGE TASKS // IF SO -> CONTINUE if (!ProduceClientState(intr, ClientState.CharSelect, 0)) { return; } intr.Log(LogEntryType.Info, "ProcessCharacter(): Selecting " + charLabel + " ..."); if (!SelectCharacter(intr, charIdx, ENTER_WORLD)) { return; } // [DO NOT REMOVE]: // //int selectAttemptCount = 0; //while (!SelectCharacter(intr, charIdx, ENTER_WORLD)) { // // Determine if login has been a success: // if (!intr.WaitUntil(90, ClientState.InWorld, Game.IsClientState, CharSelectFailure, 0)) { // ProduceClientState(intr, ClientState.CharSelect, attemptCount); // SelectCharacter(intr, charIdx, enterWorld, attemptCount); // //return false; // } // ClearDialogues(intr); // selectAttemptCount += 1; // if (selectAttemptCount >= SELECT_ATTEMPTS_MAX) { // intr.Log("ProcessCharacter(): Fatal error selecting " + charLabel + ".", LogEntryType.Fatal); // return; // } //} // NEW PLAN: // SelectCharacter() // Determine if client state is still ClientState.CharSelect // If so, FatalWithScreenShot // If not, start the 'Verification' loop which will look for signs of the 'World' // // // END [DO NOT REMOVE] if (!ENTER_WORLD) { #pragma warning disable CS0162 // Unreachable code detected queue.AdvanceInvocationTask(intr, charIdx, invokesToday, false); #pragma warning restore CS0162 // Unreachable code detected return; } // ################################## CLEAR AND MOVE ################################## intr.Wait(1500); ClearDialogues(intr); MoveAround(intr); // ############################### INVENTORY MAINTENANCE ############################## if (!skipMaintInven) { intr.Log(LogEntryType.Info, "ProcessCharacter(): Maintaining inventory for " + charLabel + " ..."); maintStatus = MaintainInventory(intr, charIdx); intr.Log(LogEntryType.Info, "ProcessCharacter(): Inventory maintenance status: " + maintStatus.ToString()); } // #################################### INVOCATION #################################### if (!skipInvocation) { intr.Log(LogEntryType.Info, "ProcessCharacter(): Invoking for " + charLabel + " ..."); invocationStatus = Invoke(intr, charIdx); intr.Log(LogEntryType.Info, "ProcessCharacter(): Invocation status: " + invocationStatus.ToString()); } // ################################### PROFESSIONS #################################### var professionTasksProcessed = new List<ProfessionTaskResult>(9); if (!skipProfessions) { intr.Log(LogEntryType.Info, "ProcessCharacter(): Maintaining profession tasks for " + charLabel + " ..."); professionsStatus = MaintainProfs(intr, charIdx, professionTasksProcessed); intr.Log(LogEntryType.Info, "ProcessCharacter(): Professions status: " + professionsStatus.ToString()); } // ##################################### LOG OUT ###################################### LogOut(intr); // ########################### INVOCATION QUEUE AND SETTINGS ########################## if (invocationStatus == CompletionStatus.Complete) { intr.Log(LogEntryType.Normal, "Invocation task for " + charLabel + ": Complete."); queue.AdvanceInvocationTask(intr, charIdx, invokesToday, true); } else if (invocationStatus == CompletionStatus.DayComplete) { intr.Log(LogEntryType.Normal, "Daily invocations for " + charLabel + ": Complete for day."); queue.AdvanceInvocationTask(intr, charIdx, 6, true); } else if (invocationStatus == CompletionStatus.Immature && currentTask.Kind == TaskKind.Invocation) { intr.Log(LogEntryType.Normal, "Invocation task for " + charLabel + ": Immature."); intr.Log(LogEntryType.Info, "Re-queuing task for " + charLabel + "."); queue.AdvanceInvocationTask(intr, charIdx, invokesToday, false); } else if (invocationStatus == CompletionStatus.Failed && currentTask.Kind == TaskKind.Invocation) { intr.Log(LogEntryType.Normal, "Invocation task for " + charLabel + ": Failed."); queue.AdvanceInvocationTask(intr, charIdx, invokesToday, false); //processingIncomplete = true; } else if (invocationStatus == CompletionStatus.Cancelled && currentTask.Kind == TaskKind.Invocation) { intr.Log(LogEntryType.Normal, "Invocation task for " + charLabel + ": Cancelled."); //processingIncomplete = true; } // ######################### PROFESSIONS QUEUE AND SETTINGS ########################### intr.Log(LogEntryType.Normal, "Profession task for " + charLabel + ": " + professionsStatus.ToString() + ", items complete: " + professionTasksProcessed.Count); if (professionsStatus == CompletionStatus.Complete) { foreach (ProfessionTaskResult taskResult in professionTasksProcessed) { queue.AdvanceProfessionsTask(intr, charIdx, taskResult.TaskId, taskResult.BonusFactor); } } else if (professionsStatus == CompletionStatus.Stuck && currentTask.Kind == TaskKind.Profession) { // I guess we have to do this to progress a task which is stuck: queue.AdvanceProfessionsTask(intr, currentTask.CharIdx, currentTask.TaskId, currentTask.BonusFactor); } else if (professionsStatus == CompletionStatus.Immature && currentTask.Kind == TaskKind.Profession) { // Pretty sure we still need this: queue.AdvanceProfessionsTask(intr, currentTask.CharIdx, currentTask.TaskId, currentTask.BonusFactor); } else if (currentTask.Kind == TaskKind.Profession) { // IF the status was NOT `CompletionStatus.Complete` AND the next task is a profession task for this character: processingIncomplete = true; // CANCELLED OR FAILED //queue.AdvanceTask(intr, currentTask.CharIdx, TaskKind.Profession, currentTask.TaskId); // SAME } //// EVALUATE WHETHER OR NOT TO BRING THIS BACK: //if (!processingIncomplete && !skipProfessions && !skipInvocation) { // intr.Log(LogEntryType.Normal, "Advancing all matured tasks for character {0}.", charIdx.ToString()); // queue.AdvanceMatured(intr, charIdx); //} if (processingIncomplete) { intr.Log(LogEntryType.Normal, "Processing incomplete for " + charLabel + "."); } else { intr.Log(LogEntryType.Normal, "Processing complete for " + charLabel + "."); } }
public static bool ProduceClientState(Interactor intr, ClientState desiredState, int attemptCount) { if (intr.CancelSource.Token.IsCancellationRequested) { return(false); } attemptCount += 1; intr.Log(LogEntryType.Info, "Attempting to produce client state: " + desiredState.ToString()); if (States.IsClientState(intr, desiredState)) { intr.Log(LogEntryType.Info, "Client state is already: " + desiredState.ToString()); return(true); } else if (desiredState == ClientState.Inactive) { if (States.IsGameState(intr, GameState.ClientActive)) { intr.Log("Minimizing client..."); Screen.WindowMinimize(intr, States.GAMECLIENTEXE); } return(true); } else if (desiredState == ClientState.None) { intr.Log("Attempting to close game client..."); KillAll(intr); return(true); } else if (desiredState == ClientState.CharSelect) { var currentClientState = States.DetermineClientState(intr); intr.Log(LogEntryType.Debug, "Interactions::ProduceClientState(): Current client state is " + currentClientState.ToString()); switch (currentClientState) { case ClientState.None: intr.Log("Launching patcher..."); return(PatcherLogin(intr, desiredState)); case ClientState.Inactive: intr.Log("Game client is currently in the background. Waiting 30 seconds " + "or until client is brought to foreground before continuing..."); const int waitIncr = 5000; for (int i = 0; i < 30000; i += waitIncr) { if (!States.IsClientState(intr, ClientState.Inactive)) { break; } intr.Wait(waitIncr); } //intr.Wait(30000); intr.Log("Activating Client..."); ActivateClient(intr); return(intr.WaitUntil(10, ClientState.CharSelect, States.IsClientState, ProduceClientState, attemptCount)); case ClientState.InWorld: if (attemptCount >= 10) { intr.Log(LogEntryType.FatalWithScreenshot, "Stuck at in world. Killing all and restarting."); KillAll(intr); intr.Wait(5000); return(ProduceClientState(intr, ClientState.CharSelect, 0)); } else { intr.Log("Logging out..."); LogOut(intr); return(intr.WaitUntil(45, ClientState.CharSelect, States.IsClientState, ProduceClientState, attemptCount)); } case ClientState.LogIn: if (attemptCount >= 10) { intr.Log(LogEntryType.FatalWithScreenshot, "Stuck at client login screen. Killing all and restarting."); KillAll(intr); intr.Wait(5000); return(ProduceClientState(intr, ClientState.CharSelect, 0)); } else { intr.Log("Client open, at login screen."); ClientSignIn(intr); return(intr.WaitUntil(30, ClientState.CharSelect, States.IsClientState, ProduceClientState, attemptCount)); } case ClientState.Unknown: default: ClearDialogues(intr); if (!intr.WaitUntil(30, ClientState.CharSelect, States.IsClientState, null, attemptCount)) { intr.Log(LogEntryType.Info, "Client state unknown. Attempting crash recovery..."); CrashCheckRecovery(intr, 0); return(ProduceClientState(intr, desiredState, attemptCount)); //var curState = Game.DetermineClientState(intr); //if (curState == ClientState.Unknown) { // //CrashCheckRecovery(intr); // return //} else { // return //} } else { return(true); } } } return(false); }
public static void ProcessCharacter( Interactor intr, TaskQueue queue ) { var currentTask = queue.NextTask; uint charIdx = currentTask.CharIdx; //string charLabel = intr.AccountSettings.CharNode(charIdx).GetAttribute("name"); string charLabel = intr.AccountSettings.CharNames[(int)charIdx]; //string charLabel = queue.NextTask.CharIdxLabel; int invokesToday = intr.AccountStates.GetCharStateOr(charIdx, "invokesToday", 0); bool skipInvocation = false; bool skipMaintInven = false; bool skipProfessions = false; DateTime invokesCompletedForDay = intr.AccountStates.GetCharStateOr(charIdx, "invokesCompleteFor", Global.Default.SomeOldDate); if (invokesCompletedForDay == TaskQueue.TodaysGameDate) { // Skip invocation if it's already done. skipInvocation = true; } else if (invokesCompletedForDay < TaskQueue.TodaysGameDate && invokesToday < 2 && currentTask.Kind == TaskKind.Invocation) { // Skip professions for the first few invokes of the day. intr.Log(LogEntryType.Info, "Skipping profession processing this round."); skipProfessions = true; } // Skip inventory processing for the first two invokes [0, 1] and every non invoke task: if (invokesToday < 2 || currentTask.Kind != TaskKind.Invocation) { intr.Log(LogEntryType.Info, "Skipping inventory processing this round."); skipMaintInven = true; } CompletionStatus invocationStatus = CompletionStatus.None; CompletionStatus professionsStatus = CompletionStatus.None; CompletionStatus maintStatus = CompletionStatus.None; bool processingIncomplete = false; intr.Log("Starting processing for " + charLabel + " ..."); // Reset `invokesToday` if `invokesCompletedOn` is if (invokesToday >= 6) { if (currentTask.Kind == TaskKind.Invocation) { if (invokesCompletedForDay == TaskQueue.TodaysGameDate) { intr.Log(LogEntryType.Info, charLabel + " has already invoked 6 times today. Queuing invocation for tomorrow"); queue.AdvanceInvocationTask(intr, charIdx, invokesToday, false); skipInvocation = true; skipMaintInven = true; //queue.QueueSubsequentInvocationTask(intr, charIdx, invokesToday); return; } else if (invokesCompletedForDay < TaskQueue.TodaysGameDate) { intr.Log(LogEntryType.Info, charLabel + ": Resetting InvokesToday to 0."); invokesToday = 0; intr.AccountStates.SaveCharState(invokesToday, charIdx, "invokesToday"); } else { var errMsg = charLabel + ": Internal error. `invokesCompletedOn` is in the future."; intr.Log(LogEntryType.Fatal, errMsg); throw new Exception(errMsg); } } } // CHECK TO SEE IF THERE ARE ANY UPCOMING TASKS FOR CHARACTER IN THE NEXT 29:59 MINUTES // IF SO -> CHECK TO SEE IF THERE ARE ANY TASKS IN THE 29:59 (TOTAL 59:59) MINUTES AFTER THAT // IF NOT -> MERGE TASKS // IF SO -> CONTINUE if (!ProduceClientState(intr, ClientState.CharSelect, 0)) { return; } intr.Log(LogEntryType.Info, "ProcessCharacter(): Selecting " + charLabel + " ..."); if (!SelectCharacter(intr, charIdx, ENTER_WORLD)) { return; } // [DO NOT REMOVE]: // //int selectAttemptCount = 0; //while (!SelectCharacter(intr, charIdx, ENTER_WORLD)) { // // Determine if login has been a success: // if (!intr.WaitUntil(90, ClientState.InWorld, Game.IsClientState, CharSelectFailure, 0)) { // ProduceClientState(intr, ClientState.CharSelect, attemptCount); // SelectCharacter(intr, charIdx, enterWorld, attemptCount); // //return false; // } // ClearDialogues(intr); // selectAttemptCount += 1; // if (selectAttemptCount >= SELECT_ATTEMPTS_MAX) { // intr.Log("ProcessCharacter(): Fatal error selecting " + charLabel + ".", LogEntryType.Fatal); // return; // } //} // NEW PLAN: // SelectCharacter() // Determine if client state is still ClientState.CharSelect // If so, FatalWithScreenShot // If not, start the 'Verification' loop which will look for signs of the 'World' // // // END [DO NOT REMOVE] if (!ENTER_WORLD) { #pragma warning disable CS0162 // Unreachable code detected queue.AdvanceInvocationTask(intr, charIdx, invokesToday, false); #pragma warning restore CS0162 // Unreachable code detected return; } // ################################## CLEAR AND MOVE ################################## intr.Wait(1500); ClearDialogues(intr); MoveAround(intr); // ############################### INVENTORY MAINTENANCE ############################## if (!skipMaintInven) { intr.Log(LogEntryType.Info, "ProcessCharacter(): Maintaining inventory for " + charLabel + " ..."); maintStatus = MaintainInventory(intr, charIdx); intr.Log(LogEntryType.Info, "ProcessCharacter(): Inventory maintenance status: " + maintStatus.ToString()); } // #################################### INVOCATION #################################### if (!skipInvocation) { intr.Log(LogEntryType.Info, "ProcessCharacter(): Invoking for " + charLabel + " ..."); invocationStatus = Invoke(intr, charIdx); intr.Log(LogEntryType.Info, "ProcessCharacter(): Invocation status: " + invocationStatus.ToString()); } // ################################### PROFESSIONS #################################### var professionTasksProcessed = new List <ProfessionTaskResult>(9); if (!skipProfessions) { intr.Log(LogEntryType.Info, "ProcessCharacter(): Maintaining profession tasks for " + charLabel + " ..."); professionsStatus = MaintainProfs(intr, charIdx, professionTasksProcessed); intr.Log(LogEntryType.Info, "ProcessCharacter(): Professions status: " + professionsStatus.ToString()); } // ##################################### LOG OUT ###################################### LogOut(intr); // ########################### INVOCATION QUEUE AND SETTINGS ########################## if (invocationStatus == CompletionStatus.Complete) { intr.Log(LogEntryType.Normal, "Invocation task for " + charLabel + ": Complete."); queue.AdvanceInvocationTask(intr, charIdx, invokesToday, true); } else if (invocationStatus == CompletionStatus.DayComplete) { intr.Log(LogEntryType.Normal, "Daily invocations for " + charLabel + ": Complete for day."); queue.AdvanceInvocationTask(intr, charIdx, 6, true); } else if (invocationStatus == CompletionStatus.Immature && currentTask.Kind == TaskKind.Invocation) { intr.Log(LogEntryType.Normal, "Invocation task for " + charLabel + ": Immature."); intr.Log(LogEntryType.Info, "Re-queuing task for " + charLabel + "."); queue.AdvanceInvocationTask(intr, charIdx, invokesToday, false); } else if (invocationStatus == CompletionStatus.Failed && currentTask.Kind == TaskKind.Invocation) { intr.Log(LogEntryType.Normal, "Invocation task for " + charLabel + ": Failed."); queue.AdvanceInvocationTask(intr, charIdx, invokesToday, false); //processingIncomplete = true; } else if (invocationStatus == CompletionStatus.Cancelled && currentTask.Kind == TaskKind.Invocation) { intr.Log(LogEntryType.Normal, "Invocation task for " + charLabel + ": Cancelled."); //processingIncomplete = true; } // ######################### PROFESSIONS QUEUE AND SETTINGS ########################### intr.Log(LogEntryType.Normal, "Profession task for " + charLabel + ": " + professionsStatus.ToString() + ", items complete: " + professionTasksProcessed.Count); if (professionsStatus == CompletionStatus.Complete) { foreach (ProfessionTaskResult taskResult in professionTasksProcessed) { queue.AdvanceProfessionsTask(intr, charIdx, taskResult.TaskId, taskResult.BonusFactor); } } else if (professionsStatus == CompletionStatus.Stuck && currentTask.Kind == TaskKind.Profession) { // I guess we have to do this to progress a task which is stuck: queue.AdvanceProfessionsTask(intr, currentTask.CharIdx, currentTask.TaskId, currentTask.BonusFactor); } else if (professionsStatus == CompletionStatus.Immature && currentTask.Kind == TaskKind.Profession) { // Pretty sure we still need this: queue.AdvanceProfessionsTask(intr, currentTask.CharIdx, currentTask.TaskId, currentTask.BonusFactor); } else if (currentTask.Kind == TaskKind.Profession) { // IF the status was NOT `CompletionStatus.Complete` AND the next task is a profession task for this character: processingIncomplete = true; // CANCELLED OR FAILED //queue.AdvanceTask(intr, currentTask.CharIdx, TaskKind.Profession, currentTask.TaskId); // SAME } //// EVALUATE WHETHER OR NOT TO BRING THIS BACK: //if (!processingIncomplete && !skipProfessions && !skipInvocation) { // intr.Log(LogEntryType.Normal, "Advancing all matured tasks for character {0}.", charIdx.ToString()); // queue.AdvanceMatured(intr, charIdx); //} if (processingIncomplete) { intr.Log(LogEntryType.Normal, "Processing incomplete for " + charLabel + "."); } else { intr.Log(LogEntryType.Normal, "Processing complete for " + charLabel + "."); } }
//public static bool ActivateClient(Interactor intr) { // //intr.ExecuteStatement("ActivateNeverwinter()"); // Screen.WindowActivate(intr, Game.GAMECLIENTEXE); // intr.Wait(1000); // return true; //} //public static bool LogOut(Interactor intr) { // //intr.ExecuteStatement("Logout()"); // intr.Log("Logging out...", LogEntryType.Info); // MoveAround(intr); // Keyboard.SendKey(intr, "Enter"); // intr.Wait(50); // Keyboard.Send(intr, "/gotocharacterselect"); // intr.Wait(100); // Keyboard.SendKey(intr, "Enter"); // intr.Wait(100); // intr.Wait(3000); // return true; //} public static bool ClientSignIn(Interactor intr) { intr.Log(LogEntryType.Info, "Signing in Client..."); //intr.ExecuteStatement("ClientLogin()"); intr.Wait(5000); ClearDialogues(intr); //if (!intr.WaitUntil(15, ClientState.LogIn, Game.IsClientState, null, 0)) { return false; } string gameUserName = intr.AccountSettings.GetSettingValOr("accountName", "general", ""); string gamePassword = intr.AccountSettings.GetSettingValOr("password", "general", ""); intr.Wait(1000); //var shiftHome = @"Send {Shift down} // Sleep 20 // Send { Home down} // Sleep 20 // Send { Shift up} // Sleep 20 // Send { Home up} // Sleep 20 //"; //intr.ExecuteStatement(shiftHome); Keyboard.SendKeyWithMod(intr, "Shift", "Tab", Keyboard.SendMode.Input); intr.Wait(200); Keyboard.SendKeyWithMod(intr, "Shift", "Home", Keyboard.SendMode.Input); Keyboard.Send(intr, gameUserName); Keyboard.SendKey(intr, "Tab"); intr.Wait(200); Keyboard.Send(intr, gamePassword); intr.Wait(200); Keyboard.SendKey(intr, "Enter"); intr.Wait(3000); // [TODO]: THIS NEEDS TO CLEAR VERIFY? DIALOGUE //ClearDialogues(intr); return true; //ClientLogin() { // global // While ((ToggleInv && !FindClientLoginButton()) && (A_Index < 10)) { // LogAppend("[Attempting to find ClientLoginButton.]") // sleep 1500 // } // if (ToggleInv && !FindClientLoginButton()) { // LogAppend("[Not sure if we found ClientLoginButton but continuing...]") // ; msgbox ClientLogin() Waited too long for Login Screen to appear. If you are at login screen please check or remake %Lb_ImageFile%. // } // if (ToggleInv) { // Sleep 2000 + Ran(500) // Send {Shift down} // Sleep 20 // Send {Home down} // Sleep 20 // Send {Shift up} // Sleep 20 // Send {Home up} // Sleep 20 // Send %NwUserName% // Sleep 50 // Send {Tab} // Sleep 200 + Ran(100) // Send %NwActPwd% // Sleep 200 + Ran(100) // Send {Enter} // Sleep AfterLoginDelay + Ran(120) // } //} }
public static CompletionStatus Invoke(Interactor intr, uint charIdx) { if (intr.CancelSource.IsCancellationRequested) { return CompletionStatus.Cancelled; } string charLabel = intr.AccountSettings.CharNames[(int)charIdx]; string invokeKey = intr.AccountSettings.GetSettingValOr("invoke", "gameHotkeys", Global.Default.InvokeKey); // Invocation Attempt (first): Keyboard.SendKey(intr, invokeKey); intr.Wait(300); if (Screen.ImageSearch(intr, "InvocationRewardsOfDevotionWindowTitle").Found) { intr.Wait(200); if (Screen.ImageSearch(intr, "InvocationRewardsOfDevotionInvokeReady").Found) { intr.Wait(2000); // Invocation Attempt: Keyboard.SendKey(intr, invokeKey); } else if (Screen.ImageSearch(intr, "InvocationRewardsOfDevotionDoneForDay").Found) { intr.Log("Unable to invoke: Invocation already finished for the day on " + charLabel + "."); return CompletionStatus.DayComplete; } else if (Screen.ImageSearch(intr, "InvocationRewardsOfDevotionPatience").Found) { intr.Log("Unable to invoke: Still waiting to invoke on " + charLabel + "."); return CompletionStatus.Immature; } else if (Screen.ImageSearch(intr, "InvocationRewardsOfDevotionNotInRestZone").Found) { intr.Log(LogEntryType.Error, "Unable to invoke: " + charLabel + " not in rest zone."); return CompletionStatus.Complete; } else if (Screen.ImageSearch(intr, "InvocationRewardsOfDevotionItemsInOverflow").Found) { intr.Log(LogEntryType.Error, "Unable to invoke: Items in overflow bag are preventing invocation for " + charLabel + ". Attempting to move to regular inventory..."); // Attempt to transfer overflow items to regular inventory: // // [NOTE]: Possibly Redundant. // - Determine if it is possible for new items to be added to inventory // between inventory management and here. // TransferOverflow(intr, false, false); MoveAround(intr); // Invocation Attempt: Keyboard.SendKey(intr, invokeKey); } else { intr.Log(LogEntryType.FatalWithScreenshot, "Unable to invoke for " + charLabel + "." + "[IN0]"); intr.Wait(30000); return CompletionStatus.Failed; } } else if (Screen.ImageSearch(intr, "InvocationMaximumBlessings").Found || DEBUG_ALWAYS_REDEEM) { // Vault of Piety // intr.Log(LogEntryType.Info, "Maximum blessings reached for " + charLabel + ". Redeeming through Vault of Piety..."); if (DEBUG_ALWAYS_REDEEM) { #pragma warning disable CS0162 // Unreachable code detected MoveAround(intr); #pragma warning restore CS0162 // Unreachable code detected } if (Redeem(intr, charIdx)) { MoveAround(intr); intr.Log(LogEntryType.Debug, "Redeeming Vault of Piety..."); // Invocation Attempt: Keyboard.SendKey(intr, invokeKey); } else { intr.Log(LogEntryType.Error, "Unable to invoke: Error collecting Vault of Piety rewards for " + charLabel + "."); return CompletionStatus.Failed; } } if (intr.CancelSource.IsCancellationRequested) { return CompletionStatus.Cancelled; } intr.Wait(2800); if (!intr.WaitUntil(5, DialogueBoxState.InvocationSuccess, States.IsDialogueBoxState, null, 0)) { // Invocation Attempt: Keyboard.SendKey(intr, invokeKey); intr.Wait(1500); MoveAround(intr); } //// [FIXME]: Not sure why this is here still or why it was needed: //if (Screen.ImageSearch(intr, "InvocationRewardsOfDevotionWindowTitle").Found) { // intr.Log("Closing Rewards of Devotion window and reassessing invocation success...", LogEntryType.Debug); // //Mouse.ClickImage(intr, "InvocationRewardsOfDevotionCloseButton"); //} if (!intr.WaitUntil(9, DialogueBoxState.InvocationSuccess, States.IsDialogueBoxState, null, 0)) { // Invocation Attempt Failure -- Display invocation screen for the screenshot: Keyboard.SendKey(intr, invokeKey); intr.Wait(1500); intr.Log(LogEntryType.FatalWithScreenshot, "Unable to invoke for character " + charLabel + "." + "[FN1]"); intr.Wait(30000); MoveAround(intr); return CompletionStatus.Failed; } intr.Log(LogEntryType.Info, "Invocation successful. Continuing..."); if (intr.CancelSource.IsCancellationRequested) { return CompletionStatus.Cancelled; } return CompletionStatus.Complete; }
// Actually queues a profession task: private static bool ContinueTask(Interactor intr, Point continueButton, out float bonusFactor) { Mouse.Click(intr, continueButton); intr.Wait(100); // Detect currently selected asset: LeadershipAsset primaryAsset = new LeadershipAsset(ProfessionAssetId.None, 1.00f); foreach (var asset in leadershipAssets) { if (Screen.ImageSearch(intr, asset.LargeTileImageLabel).Found) { primaryAsset = asset; break; } } if (primaryAsset.AssetId == ProfessionAssetId.None) { intr.Log(LogEntryType.Error, "Primary profession asset not detected."); bonusFactor = 0.0f; return(false); } else { intr.Log(LogEntryType.Debug, "Using primary profession asset: '{0}'.", primaryAsset.Label); } // Attempt to add optional assets: Mouse.ClickImage(intr, "ProfessionsAssetButton"); intr.Wait(50); LeadershipAsset optionalAsset = new LeadershipAsset(ProfessionAssetId.None, 1.00f); foreach (var asset in leadershipAssets) { if (Mouse.ClickImage(intr, asset.SmallIconImageLabel)) { optionalAsset = asset; break; } } if (optionalAsset.AssetId == ProfessionAssetId.None) { intr.Log(LogEntryType.Debug, "No optional profession assets found."); } else { intr.Log(LogEntryType.Debug, "Using optional profession asset: '{0}'.", optionalAsset.Label); } intr.Wait(50); // Enqueue the profession task: Mouse.ClickImage(intr, "ProfessionsStartTaskButton"); intr.Wait(500); if (primaryAsset.AssetId == ProfessionAssetId.Mercenary || primaryAsset.AssetId == ProfessionAssetId.Guard || primaryAsset.AssetId == ProfessionAssetId.Footman) { bonusFactor = optionalAsset.BonusFactor; } else { bonusFactor = primaryAsset.BonusFactor + optionalAsset.BonusFactor; } return(true); }
// Claims an Enchanted Key if at all possible. public static bool ClaimEnchantedKey(Interactor intr, uint charIdx, bool inventoryOpened) { // Offset between reward icon and claim button: int xOfs = 222; int yOfs = 12; string charLabel = intr.AccountSettings.CharNames[(int)charIdx]; intr.Wait(1000); intr.Log(LogEntryType.Debug, "Attempting to claim Enchanted Key for {0} ...", charLabel); // Open inventory if it has not already been pronounced open: if (!inventoryOpened) { intr.Log(LogEntryType.Debug, "Opening inventory ..."); if (!OpenInventory(intr)) { intr.Log(LogEntryType.Fatal, "Unable to open inventory while claiming Enchanted Key for {0}.", charLabel); } else { intr.Log(LogEntryType.Debug, "Inventory has been opened ..."); } // Sometimes takes a long time for icons to load... intr.Wait(3000); } // // If VIP tab is not active, click it's icon: //if (!States.IsInventoryState(intr, InventoryState.Vip)) { // intr.Log(LogEntryType.Debug, "VIP tab is not active, activating now..."); // var tabIcon = Screen.ImageSearch(intr, "InventoryTabIconVip"); // if (tabIcon.Found) { // Mouse.Click(intr, tabIcon.Point); // } else { // intr.Log(LogEntryType.FatalWithScreenshot, "Unable to find inventory VIP icon to click."); // return false; // } // intr.Wait(1800); // // Move mouse out of the way: // Mouse.Move(intr, tabIcon.Point.X - 30, tabIcon.Point.Y); // // Ensure that we're looking at the VIP tab: // if (!States.IsInventoryState(intr, InventoryState.Vip)) { // intr.Log(LogEntryType.FatalWithScreenshot, "Unable to select VIP Tab in Inventory window."); // return false; // } //} else { // intr.Log(LogEntryType.Debug, "VIP Tab is active."); //} // Click VIP tab icon: var vipTabIcon = Screen.ImageSearch(intr, "InventoryTabIconVip"); if (vipTabIcon.Found) { Mouse.Click(intr, vipTabIcon.Point); } else { intr.Log(LogEntryType.FatalWithScreenshot, "Unable to find inventory VIP icon to click."); return false; } // Move mouse out of the way: Mouse.Move(intr, vipTabIcon.Point.X - 30, vipTabIcon.Point.Y); // Ensure that we're looking at the VIP tab: if (!States.IsInventoryState(intr, InventoryState.Vip)) { intr.Log(LogEntryType.FatalWithScreenshot, "Unable to select VIP Tab in Inventory window."); return false; } else { intr.Log(LogEntryType.Debug, "VIP Tab is active."); } // Wait to make sure VIP tab page is drawn: intr.Wait(1800); // Get reward icon location/result: var iconLoc = Screen.ImageSearch(intr, "InventoryVipAccountRewardsIcon"); // If found, click on two locations: if (iconLoc.Found) { intr.Log(LogEntryType.Debug, "VIP Claim image found, moving mouse to: ({0},{1}) to claim...", (iconLoc.Point.X + xOfs), (iconLoc.Point.Y + yOfs)); // Click to the right of that image: Mouse.Move(intr, iconLoc.Point.X + xOfs, iconLoc.Point.Y + yOfs); Mouse.Click(intr,iconLoc.Point.X + xOfs, iconLoc.Point.Y + yOfs); intr.Wait(900); // Click again just to the right of the previous spot: Mouse.Move(intr, iconLoc.Point.X + xOfs + 15, iconLoc.Point.Y + yOfs); Mouse.Click(intr,iconLoc.Point.X + xOfs + 15, iconLoc.Point.Y + yOfs); //intr.Wait(2500); //// Verify that the VIP reward icon is no longer visible: //if (Screen.ImageSearch(intr, "InventoryVipAccountRewardsIcon").Found) { // intr.Log(LogEntryType.FatalWithScreenshot, "Error clicking on claim button."); // return false; //} else { // intr.Log(LogEntryType.Normal, "Enchanted key collected on {0}.", charLabel); // intr.AccountStates.SaveSetting(DateTime.Now.ToString("o"), "EnchKeyLastReceived", "invocation"); // return true; //} intr.Wait(200); intr.Log(LogEntryType.Normal, "Enchanted key collected on {0}.", charLabel); intr.AccountStates.SaveSetting(DateTime.Now.ToString("o"), "EnchKeyLastReceived", "invocation"); return true; } else { // If things didn't work, just advance it anyway with an error message. // intr.Log(LogEntryType.Error, "Failure to claim enchanted key on {0}.", charLabel); intr.Log(LogEntryType.Error, "Assuming key was manually collected and continuing."); intr.AccountStates.SaveSetting(DateTime.Now.ToString("o"), "EnchKeyLastReceived", "invocation"); return false; } }
public static CompletionStatus Invoke(Interactor intr, uint charIdx) { if (intr.CancelSource.IsCancellationRequested) { return(CompletionStatus.Cancelled); } string charLabel = intr.AccountSettings.CharNames[(int)charIdx]; string invokeKey = intr.AccountSettings.GetSettingValOr("invoke", "gameHotkeys", Global.Default.InvokeKey); // Invocation Attempt (first): Keyboard.SendKey(intr, invokeKey); intr.Wait(300); if (Screen.ImageSearch(intr, "InvocationRewardsOfDevotionWindowTitle").Found) { intr.Wait(200); if (Screen.ImageSearch(intr, "InvocationRewardsOfDevotionInvokeReady").Found) { intr.Wait(2000); // Invocation Attempt: Keyboard.SendKey(intr, invokeKey); } else if (Screen.ImageSearch(intr, "InvocationRewardsOfDevotionDoneForDay").Found) { intr.Log("Unable to invoke: Invocation already finished for the day on " + charLabel + "."); return(CompletionStatus.DayComplete); } else if (Screen.ImageSearch(intr, "InvocationRewardsOfDevotionPatience").Found) { intr.Log("Unable to invoke: Still waiting to invoke on " + charLabel + "."); return(CompletionStatus.Immature); } else if (Screen.ImageSearch(intr, "InvocationRewardsOfDevotionNotInRestZone").Found) { intr.Log(LogEntryType.Error, "Unable to invoke: " + charLabel + " not in rest zone."); return(CompletionStatus.Complete); } else if (Screen.ImageSearch(intr, "InvocationRewardsOfDevotionItemsInOverflow").Found) { intr.Log(LogEntryType.Error, "Unable to invoke: Items in overflow bag are preventing invocation for " + charLabel + ". Attempting to move to regular inventory..."); // Attempt to transfer overflow items to regular inventory: // // [NOTE]: Possibly Redundant. // - Determine if it is possible for new items to be added to inventory // between inventory management and here. // TransferOverflow(intr, false, false); MoveAround(intr); // Invocation Attempt: Keyboard.SendKey(intr, invokeKey); } else { intr.Log(LogEntryType.FatalWithScreenshot, "Unable to invoke for " + charLabel + "." + "[IN0]"); intr.Wait(30000); return(CompletionStatus.Failed); } } else if (Screen.ImageSearch(intr, "InvocationMaximumBlessings").Found || DEBUG_ALWAYS_REDEEM) { // Vault of Piety // intr.Log(LogEntryType.Info, "Maximum blessings reached for " + charLabel + ". Redeeming through Vault of Piety..."); if (DEBUG_ALWAYS_REDEEM) { #pragma warning disable CS0162 // Unreachable code detected MoveAround(intr); #pragma warning restore CS0162 // Unreachable code detected } if (Redeem(intr, charIdx)) { MoveAround(intr); intr.Log(LogEntryType.Debug, "Redeeming Vault of Piety..."); // Invocation Attempt: Keyboard.SendKey(intr, invokeKey); } else { intr.Log(LogEntryType.Error, "Unable to invoke: Error collecting Vault of Piety rewards for " + charLabel + "."); return(CompletionStatus.Failed); } } if (intr.CancelSource.IsCancellationRequested) { return(CompletionStatus.Cancelled); } intr.Wait(2800); if (!intr.WaitUntil(5, DialogueBoxState.InvocationSuccess, States.IsDialogueBoxState, null, 0)) { // Invocation Attempt: Keyboard.SendKey(intr, invokeKey); intr.Wait(1500); MoveAround(intr); } //// [FIXME]: Not sure why this is here still or why it was needed: //if (Screen.ImageSearch(intr, "InvocationRewardsOfDevotionWindowTitle").Found) { // intr.Log("Closing Rewards of Devotion window and reassessing invocation success...", LogEntryType.Debug); // //Mouse.ClickImage(intr, "InvocationRewardsOfDevotionCloseButton"); //} if (!intr.WaitUntil(9, DialogueBoxState.InvocationSuccess, States.IsDialogueBoxState, null, 0)) { // Invocation Attempt Failure -- Display invocation screen for the screenshot: Keyboard.SendKey(intr, invokeKey); intr.Wait(1500); intr.Log(LogEntryType.FatalWithScreenshot, "Unable to invoke for character " + charLabel + "." + "[FN1]"); intr.Wait(30000); MoveAround(intr); return(CompletionStatus.Failed); } intr.Log(LogEntryType.Info, "Invocation successful. Continuing..."); if (intr.CancelSource.IsCancellationRequested) { return(CompletionStatus.Cancelled); } return(CompletionStatus.Complete); }
public static void AutoCycle( Interactor intr, int startDelaySec) { if (intr.CancelSource.IsCancellationRequested) { return; } var queue = new TaskQueue(); int charsTotal = intr.AccountSettings.GetSettingValOr("characterCount", "general", 0); if (queue.IsEmpty) { intr.Log("Populating task queue: (0 -> " + (charsTotal).ToString() + ")"); queue.Populate(intr, charsTotal, RESET_DAY); intr.UpdateQueueList(queue.ListClone(intr)); } intr.Log("Starting AutoCycle in " + startDelaySec.ToString() + " seconds..."); intr.Wait(startDelaySec * 1000); if (intr.CancelSource.IsCancellationRequested) { return; } intr.Log("Beginning AutoCycle."); // ##### BEGIN AUTOCYCLE LOOP ##### while (!queue.IsEmpty && !intr.CancelSource.IsCancellationRequested) { if (IsCurfew()) { int sleepTime = intr.WaitRand(300000, 1800000); intr.Log("Curfew time. Sleeping for " + (sleepTime / 60000).ToString() + " minutes."); } intr.Log(LogEntryType.Debug, "AutoCycle(): Loop iteration starting."); TimeSpan nextTaskMatureDelay = queue.NextTaskMatureDelay(); intr.Log(LogEntryType.Debug, "AutoCycle(): Next task mature delay: " + nextTaskMatureDelay); if (nextTaskMatureDelay.Ticks <= 0) { // TASK TIMER HAS MATURED -> CONTINUE // ##### ENTRY POINT -- INVOKING & PROCESSING CHARACTER ##### ProcessCharacter(intr, queue); } else { // TASK TIMER NOT MATURE YET -> WAIT intr.Wait(1000); intr.Log("Next task matures in " + nextTaskMatureDelay.TotalMinutes.ToString("F0") + " minutes."); TimeSpan waitDelay = nextTaskMatureDelay; if (nextTaskMatureDelay.TotalMinutes > 8) { if (queue.NextTask.Kind == TaskKind.Profession) { waitDelay = nextTaskMatureDelay + intr.RandomDelay(9, 25); } else { waitDelay = nextTaskMatureDelay + intr.RandomDelay(9, 15); } ProduceClientState(intr, ClientState.None, 0); } else if (nextTaskMatureDelay.TotalSeconds > 1) { // Delay more than 1 sec, let the train catch up... ProduceClientState(intr, ClientState.Inactive, 0); waitDelay = nextTaskMatureDelay + intr.RandomDelay(5, 11); intr.Log("Minimizing client and waiting " + waitDelay.TotalMinutes.ToString("F0") + " minutes."); } if (waitDelay.TotalSeconds > 1) { intr.Log("Sleeping for " + waitDelay.TotalMinutes.ToString("F0") + " minutes before continuing..."); intr.Wait(waitDelay); Screen.Wake(intr); } } intr.Wait(100); } intr.Log(LogEntryType.Info, "Autocycle complete."); }
// Searches inventory for rewards such as Celestial Bags of Refining and opens each one. // // [TODO]: Need error handling channels if detected states don't align with expected. // public static CompletionStatus OpenRewardBags(Interactor intr, string RewardIconImgCode, bool InventoryOpened) { // Open inventory: if (!InventoryOpened) { OpenInventory(intr); } // If bags tab is not active, click it's icon. if (!(States.IsInventoryState(intr, InventoryState.Bags))) { var iconBags = Screen.ImageSearch(intr, "InventoryTabIconBags"); //Mouse.ClickImage(intr, "InventoryTabIconBags"); if (iconBags.Found) { Mouse.Click(intr, iconBags.Point); Mouse.Move(intr, iconBags.Point.X - 30, iconBags.Point.Y); intr.WaitRand(50, 100); } else { intr.Log(LogEntryType.Info, "Unable to find inventory tab: 'Bags'. Probably just a random timing error."); return(CompletionStatus.Failed); } } // //var imgCode = "InventoryCelestialBagOfRefinement"; int afterSearchDelay = 3200; // Determine if any reward bags are present: // First Search: var bagSearchResult = Screen.ImageSearch(intr, RewardIconImgCode); //var openAnotherBtnLoc = new Point(); if (bagSearchResult.Found) { intr.Log(LogEntryType.Debug, "Found reward icon with image code: '{0}'.", RewardIconImgCode); // Find a place to move the mouse out of the way to: var iconBags = Screen.ImageSearch(intr, "InventoryTabIconBags"); if (!iconBags.Found) { intr.Log(LogEntryType.Error, "Error determining inventory state."); } intr.Log(LogEntryType.Debug, "Opening reward bags..."); OpenRewardBag(intr, bagSearchResult); intr.Wait(100); // Move mouse out of the way: Mouse.Move(intr, iconBags.Point.X - 30, iconBags.Point.Y); intr.Wait(afterSearchDelay); // Determine 'Open Another' button location for future presses: var openAnotherBtnSearchResult = Screen.ImageSearch(intr, "InventoryRewardWindowOpenAnotherButton_2", "InventoryRewardWindowOpenAnotherButton"); if (openAnotherBtnSearchResult.Found) { var randOfs = new Point(intr.Rand(1, 60), intr.Rand(1, 10)); var openAnotherBtnLoc = new Point(openAnotherBtnSearchResult.Point.X + randOfs.X, openAnotherBtnSearchResult.Point.Y + randOfs.Y); int bagsOpened = 0; // Open remaining bags: while (true) { Mouse.Click(intr, openAnotherBtnLoc); intr.WaitRand(20, 40); bagsOpened += 1; if (!Screen.ImageSearch(intr, RewardIconImgCode).Found) { break; } // Something is probably stuck: if (bagsOpened >= 100) { TransferOverflow(intr, true, true); break; } } } else { // 'Open Another' button not found, just click them individually: while (true) { // Move mouse out of the way: Mouse.Move(intr, iconBags.Point.X - 30, iconBags.Point.Y); // Search for bag icon: bagSearchResult = Screen.ImageSearch(intr, RewardIconImgCode); if (!bagSearchResult.Found) { break; } // Open bag: OpenRewardBag(intr, bagSearchResult); intr.Wait(afterSearchDelay); } } } else { intr.Log(LogEntryType.Debug, "No reward icons with image code: '{0}' detected.", RewardIconImgCode); } return(CompletionStatus.Complete); }
//public static bool ActivateClient(Interactor intr) { // //intr.ExecuteStatement("ActivateNeverwinter()"); // Screen.WindowActivate(intr, Game.GAMECLIENTEXE); // intr.Wait(1000); // return true; //} //public static bool LogOut(Interactor intr) { // //intr.ExecuteStatement("Logout()"); // intr.Log("Logging out...", LogEntryType.Info); // MoveAround(intr); // Keyboard.SendKey(intr, "Enter"); // intr.Wait(50); // Keyboard.Send(intr, "/gotocharacterselect"); // intr.Wait(100); // Keyboard.SendKey(intr, "Enter"); // intr.Wait(100); // intr.Wait(3000); // return true; //} public static bool ClientSignIn(Interactor intr) { intr.Log(LogEntryType.Info, "Signing in Client..."); //intr.ExecuteStatement("ClientLogin()"); intr.Wait(5000); ClearDialogues(intr); //if (!intr.WaitUntil(15, ClientState.LogIn, Game.IsClientState, null, 0)) { return false; } string gameUserName = intr.AccountSettings.GetSettingValOr("accountName", "general", ""); string gamePassword = intr.AccountSettings.GetSettingValOr("password", "general", ""); intr.Wait(1000); //var shiftHome = @"Send {Shift down} // Sleep 20 // Send { Home down} // Sleep 20 // Send { Shift up} // Sleep 20 // Send { Home up} // Sleep 20 //"; //intr.ExecuteStatement(shiftHome); Keyboard.SendKeyWithMod(intr, "Shift", "Tab", Keyboard.SendMode.Input); intr.Wait(200); Keyboard.SendKeyWithMod(intr, "Shift", "Home", Keyboard.SendMode.Input); Keyboard.Send(intr, gameUserName); Keyboard.SendKey(intr, "Tab"); intr.Wait(200); Keyboard.Send(intr, gamePassword); intr.Wait(200); Keyboard.SendKey(intr, "Enter"); intr.Wait(3000); // [TODO]: THIS NEEDS TO CLEAR VERIFY? DIALOGUE //ClearDialogues(intr); return(true); //ClientLogin() { // global // While ((ToggleInv && !FindClientLoginButton()) && (A_Index < 10)) { // LogAppend("[Attempting to find ClientLoginButton.]") // sleep 1500 // } // if (ToggleInv && !FindClientLoginButton()) { // LogAppend("[Not sure if we found ClientLoginButton but continuing...]") // ; msgbox ClientLogin() Waited too long for Login Screen to appear. If you are at login screen please check or remake %Lb_ImageFile%. // } // if (ToggleInv) { // Sleep 2000 + Ran(500) // Send {Shift down} // Sleep 20 // Send {Home down} // Sleep 20 // Send {Shift up} // Sleep 20 // Send {Home up} // Sleep 20 // Send %NwUserName% // Sleep 50 // Send {Tab} // Sleep 200 + Ran(100) // Send %NwActPwd% // Sleep 200 + Ran(100) // Send {Enter} // Sleep AfterLoginDelay + Ran(120) // } //} }
//public static void SendInput(Interactor intr, string key) { // //intr.Wait(200); // intr.ExecuteStatement("SendInput " + key); // intr.Wait(50); //} //public static void SendPlay(Interactor intr, string keys) { // intr.ExecuteStatement("SendPlay " + keys); // intr.Wait(50); //} //public static void SendEvent(Interactor intr, string keys) { // intr.ExecuteStatement("SendEvent " + keys); // intr.Wait(50); //} public static void SendTest(Interactor intr, string key) { intr.Wait(3000); intr.ExecuteStatement("SendEvent " + key); intr.Wait(50); }
// Searches inventory for rewards such as Celestial Bags of Refining and opens each one. // // [TODO]: Need error handling channels if detected states don't align with expected. // public static CompletionStatus OpenRewardBags(Interactor intr, string RewardIconImgCode, bool InventoryOpened) { // Open inventory: if (!InventoryOpened) { OpenInventory(intr); } // If bags tab is not active, click it's icon. if (!(States.IsInventoryState(intr, InventoryState.Bags))) { var iconBags = Screen.ImageSearch(intr, "InventoryTabIconBags"); //Mouse.ClickImage(intr, "InventoryTabIconBags"); if (iconBags.Found) { Mouse.Click(intr, iconBags.Point); Mouse.Move(intr, iconBags.Point.X - 30, iconBags.Point.Y); intr.WaitRand(50, 100); } else { intr.Log(LogEntryType.Info, "Unable to find inventory tab: 'Bags'. Probably just a random timing error."); return CompletionStatus.Failed; } } // //var imgCode = "InventoryCelestialBagOfRefinement"; int afterSearchDelay = 3200; // Determine if any reward bags are present: // First Search: var bagSearchResult = Screen.ImageSearch(intr, RewardIconImgCode); //var openAnotherBtnLoc = new Point(); if (bagSearchResult.Found) { intr.Log(LogEntryType.Debug, "Found reward icon with image code: '{0}'.", RewardIconImgCode); // Find a place to move the mouse out of the way to: var iconBags = Screen.ImageSearch(intr, "InventoryTabIconBags"); if (!iconBags.Found) { intr.Log(LogEntryType.Error, "Error determining inventory state."); } intr.Log(LogEntryType.Debug, "Opening reward bags..."); OpenRewardBag(intr, bagSearchResult); intr.Wait(100); // Move mouse out of the way: Mouse.Move(intr, iconBags.Point.X - 30, iconBags.Point.Y); intr.Wait(afterSearchDelay); // Determine 'Open Another' button location for future presses: var openAnotherBtnSearchResult = Screen.ImageSearch(intr, "InventoryRewardWindowOpenAnotherButton_2", "InventoryRewardWindowOpenAnotherButton"); if (openAnotherBtnSearchResult.Found) { var randOfs = new Point(intr.Rand(1, 60), intr.Rand(1, 10)); var openAnotherBtnLoc = new Point(openAnotherBtnSearchResult.Point.X + randOfs.X, openAnotherBtnSearchResult.Point.Y + randOfs.Y); int bagsOpened = 0; // Open remaining bags: while (true) { Mouse.Click(intr, openAnotherBtnLoc); intr.WaitRand(20, 40); bagsOpened += 1; if (!Screen.ImageSearch(intr, RewardIconImgCode).Found) { break; } // Something is probably stuck: if (bagsOpened >= 100) { TransferOverflow(intr, true, true); break; } } } else { // 'Open Another' button not found, just click them individually: while (true) { // Move mouse out of the way: Mouse.Move(intr, iconBags.Point.X - 30, iconBags.Point.Y); // Search for bag icon: bagSearchResult = Screen.ImageSearch(intr, RewardIconImgCode); if (!bagSearchResult.Found) { break; } // Open bag: OpenRewardBag(intr, bagSearchResult); intr.Wait(afterSearchDelay); } } } else { intr.Log(LogEntryType.Debug, "No reward icons with image code: '{0}' detected.", RewardIconImgCode); } return CompletionStatus.Complete; }
public static void WheelUp(Interactor intr, int repeats) { for (int c = 0; c < repeats; c++) { intr.ExecuteStatement("SendEvent { Click WheelUp }"); intr.Wait(5); } }
/// <summary> /// Find an image and return it's upper left coordinate. /// </summary> /// This needs a crazy amount more error handling/reporting but it's just a huge pain. Most stuff is ignored. /// /// ErrorLevel is set to 0 if the image was found in the specified region, /// 1 if it was not found, or 2 if there was a problem that prevented the /// command from conducting the search(such as failure to open the image file /// or a badly formatted option). /// <param name="intr"></param> /// <param name="imgCode"></param> /// <param name="topLeft"></param> /// <param name="botRight"></param> /// <returns></returns> public static ImageSearchResult ImageSearch(Interactor intr, string imgCode, Point topLeft, Point botRight) { string imageFileName; if (!intr.ClientSettings.TryGetSetting(imgCode + "_ImageFile", "SearchRectanglesAnd_ImageFiles", out imageFileName)) { imageFileName = imgCode + ".png"; intr.ClientSettings.SaveSetting(imageFileName, imgCode + "_ImageFile", "SearchRectanglesAnd_ImageFiles"); } string imageFilePath; if (File.Exists(Settings.Default.ImagesFolderPath + "\\" + imageFileName)) { imageFilePath = Settings.Default.ImagesFolderPath + "\\" + imageFileName; } else { imageFilePath = SettingsForm.ProgramRootFolder + SettingsForm.BUILTIN_IMAGES_SUBPATH + "\\" + imageFileName; } intr.Log(new LogMessage(LogEntryType.Trace, "ImageSearch({0}): Searching for image: '{1}'" + " [TopLeft:{2} BotRight:{3}]", imgCode, imageFilePath, topLeft, botRight )); int outX = 0; int outY = 0; int errorLevel = 0; var imgSrcOptions = Settings.Default.ImageShadeVariation.ToString(); intr.SetVar(OUTPUT_VAR_X, outX.ToString()); intr.SetVar(OUTPUT_VAR_Y, outY.ToString()); var statement = string.Format("ImageSearch, {0}, {1}, {2}, {3}, {4}, {5}, {6} {7}", OUTPUT_VAR_X, OUTPUT_VAR_Y, topLeft.X.ToString(), topLeft.Y.ToString(), botRight.X.ToString(), botRight.Y.ToString(), "*" + imgSrcOptions, imageFilePath); intr.Wait(20); intr.ExecuteStatement(statement); int.TryParse(intr.GetVar(OUTPUT_VAR_X), out outX); int.TryParse(intr.GetVar(OUTPUT_VAR_Y), out outY); int.TryParse(intr.GetVar(ERROR_LEVEL), out errorLevel); switch (errorLevel) { case 0: intr.Log(LogEntryType.Trace, "ImageSearch({0}): Found.", imgCode); return(new ImageSearchResult(true, new Point(outX, outY))); case 1: intr.Log(LogEntryType.Trace, "ImageSearch({0}): Not Found.", imgCode); return(new ImageSearchResult(false, new Point(outX, outY))); case 2: intr.Log(LogEntryType.Info, "ImageSearch(" + imgCode + "): Results: " + " OutputVarX:" + intr.GetVar(OUTPUT_VAR_X) + " OutputVarY:" + intr.GetVar(OUTPUT_VAR_Y) + " ErrorLevel:" + intr.GetVar(ERROR_LEVEL)); intr.Log(LogEntryType.Fatal, "ImageSearch(" + imgCode + "): FATAL ERROR. INVALID IMAGE FILE OR OPTION FORMAT. " + "(Path: " + imageFilePath + ")"); return(new ImageSearchResult(false, new Point(outX, outY))); default: intr.Log(LogEntryType.Fatal, "ImageSearch(" + imgCode + "): Not Found."); return(new ImageSearchResult(false, new Point(outX, outY))); } }
/// <summary> /// Find an image and return it's upper left coordinate. /// </summary> /// This needs a crazy amount more error handling/reporting but it's just a huge pain. Most stuff is ignored. /// /// ErrorLevel is set to 0 if the image was found in the specified region, /// 1 if it was not found, or 2 if there was a problem that prevented the /// command from conducting the search(such as failure to open the image file /// or a badly formatted option). /// <param name="intr"></param> /// <param name="imgCode"></param> /// <param name="topLeft"></param> /// <param name="botRight"></param> /// <returns></returns> public static ImageSearchResult ImageSearch(Interactor intr, string imgCode, Point topLeft, Point botRight) { string imageFileName; if (!intr.ClientSettings.TryGetSetting(imgCode + "_ImageFile", "SearchRectanglesAnd_ImageFiles", out imageFileName)) { imageFileName = imgCode + ".png"; intr.ClientSettings.SaveSetting(imageFileName, imgCode + "_ImageFile", "SearchRectanglesAnd_ImageFiles"); } string imageFilePath; if (File.Exists(Settings.Default.ImagesFolderPath + "\\" + imageFileName)) { imageFilePath = Settings.Default.ImagesFolderPath + "\\" + imageFileName; } else { imageFilePath = SettingsForm.ProgramRootFolder + SettingsForm.BUILTIN_IMAGES_SUBPATH + "\\" + imageFileName; } intr.Log(new LogMessage(LogEntryType.Trace, "ImageSearch({0}): Searching for image: '{1}'" + " [TopLeft:{2} BotRight:{3}]", imgCode, imageFilePath, topLeft, botRight )); int outX = 0; int outY = 0; int errorLevel = 0; var imgSrcOptions = Settings.Default.ImageShadeVariation.ToString(); intr.SetVar(OUTPUT_VAR_X, outX.ToString()); intr.SetVar(OUTPUT_VAR_Y, outY.ToString()); var statement = string.Format("ImageSearch, {0}, {1}, {2}, {3}, {4}, {5}, {6} {7}", OUTPUT_VAR_X, OUTPUT_VAR_Y, topLeft.X.ToString(), topLeft.Y.ToString(), botRight.X.ToString(), botRight.Y.ToString(), "*" + imgSrcOptions, imageFilePath); intr.Wait(20); intr.ExecuteStatement(statement); int.TryParse(intr.GetVar(OUTPUT_VAR_X), out outX); int.TryParse(intr.GetVar(OUTPUT_VAR_Y), out outY); int.TryParse(intr.GetVar(ERROR_LEVEL), out errorLevel); switch (errorLevel) { case 0: intr.Log(LogEntryType.Trace, "ImageSearch({0}): Found.", imgCode); return new ImageSearchResult(true, new Point(outX, outY)); case 1: intr.Log(LogEntryType.Trace, "ImageSearch({0}): Not Found.", imgCode); return new ImageSearchResult(false, new Point(outX, outY)); case 2: intr.Log(LogEntryType.Info, "ImageSearch(" + imgCode + "): Results: " + " OutputVarX:" + intr.GetVar(OUTPUT_VAR_X) + " OutputVarY:" + intr.GetVar(OUTPUT_VAR_Y) + " ErrorLevel:" + intr.GetVar(ERROR_LEVEL)); intr.Log(LogEntryType.Fatal, "ImageSearch(" + imgCode + "): FATAL ERROR. INVALID IMAGE FILE OR OPTION FORMAT. " + "(Path: " + imageFilePath + ")"); return new ImageSearchResult(false, new Point(outX, outY)); default: intr.Log(LogEntryType.Fatal, "ImageSearch(" + imgCode + "): Not Found."); return new ImageSearchResult(false, new Point(outX, outY)); } }
public static bool Redeem(Interactor intr, uint charIdx) { VaultOfPietyItem item; try { item = (VaultOfPietyItem)Enum.Parse(typeof(VaultOfPietyItem), intr.AccountSettings.GetCharSetting(charIdx, "vaultOfPietyItem"), true); } catch (Exception) { item = DEFAULT_REDEMPTION_ITEM; } intr.Log(LogEntryType.Debug, "VaultOfPietyItem: " + item.ToString()); intr.Wait(500); string cursorModeKey = intr.AccountSettings.GetSettingValOr("toggleMouseCursor", "gameHotkeys", Global.Default.ToggleMouseCursor); if (Screen.ImageSearch(intr, "InvocationMaximumBlessings").Found) { intr.Wait(200); Mouse.ClickImage(intr, "InvocationMaximumBlessingsVaultOfPietyButton"); } else { intr.Wait(1000); Keyboard.SendKey(intr, cursorModeKey); intr.Wait(500); bool clicked = false; clicked |= Mouse.ClickImage(intr, "InvocationNotReady"); clicked |= Mouse.ClickImage(intr, "InvocationReady"); if (!clicked) { intr.Log(LogEntryType.FatalWithScreenshot, "Unable to click Vault of Piety button"); } } intr.WaitRand(2100, 2500); if (!Screen.ImageSearch(intr, "VaultOfPietyWindowTitle").Found) { return false; } Mouse.ClickImage(intr, "VaultOfPietyCelestialSynergyTabTitle"); intr.Wait(2000); string panelImage; string purchaseConfirmImage; //if (item == VaultOfPietyItem.ElixirOfFate) { // var panel = Screen.ImageSearch(intr, "VaultOfPietyCelestialSynergyElixirOfFate"); // if (panel.Found) { // Mouse.DoubleClick(intr, panel.Point); // intr.Wait(500); // Mouse.ClickImage(intr, "VaultOfPietyElixirOfFateSelectAmountOkButton"); // intr.Log(LogEntryType.Info, "Vault of Piety: 'Elixir of Fate' purchased successfully."); // } else { // intr.Log(LogEntryType.Fatal, "Vault of Piety Error: Could not find 'Elixir of Fate' icon/tile."); // return false; // } //} else if (item == VaultOfPietyItem.CofferOfCelestialArtifactEquipment) { // var panel = Screen.ImageSearch(intr, "VaultOfPietyCelestialSynergyCofferOfCelestialArtifactEquipment"); // if (panel.Found) { // Mouse.DoubleClick(intr, panel.Point); // intr.Wait(500); // Mouse.ClickImage(intr, "VaultOfPietyCofferOfCelestialArtifactEquipmentPurchaseConfirmOkButton"); // intr.Log(LogEntryType.Info, "Vault of Piety: 'Coffer of Celestial Artifact Equipment' purchased successfully."); // } else { // intr.Log(LogEntryType.Fatal, "Vault of Piety Error: Could not find 'Coffer of Celestial Artifact Equipment' icon/tile."); // return false; // } //} if (item == VaultOfPietyItem.ElixirOfFate) { panelImage = "VaultOfPietyCelestialSynergyElixirOfFate"; purchaseConfirmImage = "VaultOfPietyElixirOfFateSelectAmountOkButton"; } else if (item == VaultOfPietyItem.BlessedProfessionsElementalPack) { panelImage = "VaultOfPietyCelestialSynergyBlessedProfessionsElementalPack"; purchaseConfirmImage = "VaultOfPietyCofferOfCelestialArtifactEquipmentPurchaseConfirmOkButton"; } else if (item == VaultOfPietyItem.CofferOfCelestialEnchantments) { panelImage = "VaultOfPietyCelestialSynergyCofferOfCelestialEnchantments"; purchaseConfirmImage = "VaultOfPietyCofferOfCelestialArtifactEquipmentPurchaseConfirmOkButton"; } else if (item == VaultOfPietyItem.CofferOfCelestialArtifacts) { panelImage = "VaultOfPietyCelestialSynergyCofferOfCelestialArtifacts"; purchaseConfirmImage = "VaultOfPietyCofferOfCelestialArtifactEquipmentPurchaseConfirmOkButton"; } else if (item == VaultOfPietyItem.CofferOfCelestialArtifactEquipment) { panelImage = "VaultOfPietyCelestialSynergyCofferOfCelestialArtifactEquipment"; purchaseConfirmImage = "VaultOfPietyCofferOfCelestialArtifactEquipmentPurchaseConfirmOkButton"; } else { intr.Log(LogEntryType.Fatal, "Vault of Piety Error: Unknown item: '{0:G}'.", item); return false; } var panel = Screen.ImageSearch(intr, panelImage); if (panel.Found) { Mouse.DoubleClick(intr, panel.Point); intr.Wait(500); Mouse.ClickImage(intr, purchaseConfirmImage); intr.Log(LogEntryType.Info, "Vault of Piety: '{0:G}' purchased successfully.", item); } else { intr.Log(LogEntryType.Fatal, "Vault of Piety Error: Could not find '{0:G}' icon/panel.", item); return false; } // [FIXME]: Handle the fact that the VaultOfPietyItem is: `5` // [FIX THE HELL OUT OF ME][FIX THE HELL OUT OF ME] // [FIX THE HELL OUT OF ME][FIX THE HELL OUT OF ME][FIX THE HELL OUT OF ME][FIX THE HELL OUT OF ME] return true; }
public static bool ProduceClientState(Interactor intr, ClientState desiredState, int attemptCount) { if (intr.CancelSource.Token.IsCancellationRequested) { return false; } attemptCount += 1; intr.Log(LogEntryType.Info, "Attempting to produce client state: " + desiredState.ToString()); if (States.IsClientState(intr, desiredState)) { intr.Log(LogEntryType.Info, "Client state is already: " + desiredState.ToString()); return true; } else if (desiredState == ClientState.Inactive) { if (States.IsGameState(intr, GameState.ClientActive)) { intr.Log( "Minimizing client..."); Screen.WindowMinimize(intr, States.GAMECLIENTEXE); } return true; } else if (desiredState == ClientState.None) { intr.Log("Attempting to close game client..."); KillAll(intr); return true; } else if (desiredState == ClientState.CharSelect) { var currentClientState = States.DetermineClientState(intr); intr.Log(LogEntryType.Debug, "Interactions::ProduceClientState(): Current client state is " + currentClientState.ToString()); switch (currentClientState) { case ClientState.None: intr.Log("Launching patcher..."); return PatcherLogin(intr, desiredState); case ClientState.Inactive: intr.Log("Game client is currently in the background. Waiting 30 seconds " + "or until client is brought to foreground before continuing..."); const int waitIncr = 5000; for (int i = 0; i < 30000; i += waitIncr) { if (!States.IsClientState(intr, ClientState.Inactive)) { break; } intr.Wait(waitIncr); } //intr.Wait(30000); intr.Log("Activating Client..."); ActivateClient(intr); return intr.WaitUntil(10, ClientState.CharSelect, States.IsClientState, ProduceClientState, attemptCount); case ClientState.InWorld: if (attemptCount >= 10) { intr.Log(LogEntryType.FatalWithScreenshot, "Stuck at in world. Killing all and restarting."); KillAll(intr); intr.Wait(5000); return ProduceClientState(intr, ClientState.CharSelect, 0); } else { intr.Log("Logging out..."); LogOut(intr); return intr.WaitUntil(45, ClientState.CharSelect, States.IsClientState, ProduceClientState, attemptCount); } case ClientState.LogIn: if (attemptCount >= 10) { intr.Log(LogEntryType.FatalWithScreenshot, "Stuck at client login screen. Killing all and restarting."); KillAll(intr); intr.Wait(5000); return ProduceClientState(intr, ClientState.CharSelect, 0); } else { intr.Log("Client open, at login screen."); ClientSignIn(intr); return intr.WaitUntil(30, ClientState.CharSelect, States.IsClientState, ProduceClientState, attemptCount); } case ClientState.Unknown: default: ClearDialogues(intr); if (!intr.WaitUntil(30, ClientState.CharSelect, States.IsClientState, null, attemptCount)) { intr.Log(LogEntryType.Info, "Client state unknown. Attempting crash recovery..."); CrashCheckRecovery(intr, 0); return ProduceClientState(intr, desiredState, attemptCount); //var curState = Game.DetermineClientState(intr); //if (curState == ClientState.Unknown) { // //CrashCheckRecovery(intr); // return //} else { // return //} } else { return true; } } } return false; }
// Claims an Enchanted Key if at all possible. public static bool ClaimEnchantedKey(Interactor intr, uint charIdx, bool inventoryOpened) { // Offset between reward icon and claim button: int xOfs = 222; int yOfs = 12; string charLabel = intr.AccountSettings.CharNames[(int)charIdx]; intr.Wait(1000); intr.Log(LogEntryType.Debug, "Attempting to claim Enchanted Key for {0} ...", charLabel); // Open inventory if it has not already been pronounced open: if (!inventoryOpened) { intr.Log(LogEntryType.Debug, "Opening inventory ..."); if (!OpenInventory(intr)) { intr.Log(LogEntryType.Fatal, "Unable to open inventory while claiming Enchanted Key for {0}.", charLabel); } else { intr.Log(LogEntryType.Debug, "Inventory has been opened ..."); } // Sometimes takes a long time for icons to load... intr.Wait(3000); } // // If VIP tab is not active, click it's icon: //if (!States.IsInventoryState(intr, InventoryState.Vip)) { // intr.Log(LogEntryType.Debug, "VIP tab is not active, activating now..."); // var tabIcon = Screen.ImageSearch(intr, "InventoryTabIconVip"); // if (tabIcon.Found) { // Mouse.Click(intr, tabIcon.Point); // } else { // intr.Log(LogEntryType.FatalWithScreenshot, "Unable to find inventory VIP icon to click."); // return false; // } // intr.Wait(1800); // // Move mouse out of the way: // Mouse.Move(intr, tabIcon.Point.X - 30, tabIcon.Point.Y); // // Ensure that we're looking at the VIP tab: // if (!States.IsInventoryState(intr, InventoryState.Vip)) { // intr.Log(LogEntryType.FatalWithScreenshot, "Unable to select VIP Tab in Inventory window."); // return false; // } //} else { // intr.Log(LogEntryType.Debug, "VIP Tab is active."); //} // Click VIP tab icon: var vipTabIcon = Screen.ImageSearch(intr, "InventoryTabIconVip"); if (vipTabIcon.Found) { Mouse.Click(intr, vipTabIcon.Point); } else { intr.Log(LogEntryType.FatalWithScreenshot, "Unable to find inventory VIP icon to click."); return(false); } // Move mouse out of the way: Mouse.Move(intr, vipTabIcon.Point.X - 30, vipTabIcon.Point.Y); // Ensure that we're looking at the VIP tab: if (!States.IsInventoryState(intr, InventoryState.Vip)) { intr.Log(LogEntryType.FatalWithScreenshot, "Unable to select VIP Tab in Inventory window."); return(false); } else { intr.Log(LogEntryType.Debug, "VIP Tab is active."); } // Wait to make sure VIP tab page is drawn: intr.Wait(1800); // Get reward icon location/result: var iconLoc = Screen.ImageSearch(intr, "InventoryVipAccountRewardsIcon"); // If found, click on two locations: if (iconLoc.Found) { intr.Log(LogEntryType.Debug, "VIP Claim image found, moving mouse to: ({0},{1}) to claim...", (iconLoc.Point.X + xOfs), (iconLoc.Point.Y + yOfs)); // Click to the right of that image: Mouse.Move(intr, iconLoc.Point.X + xOfs, iconLoc.Point.Y + yOfs); Mouse.Click(intr, iconLoc.Point.X + xOfs, iconLoc.Point.Y + yOfs); intr.Wait(900); // Click again just to the right of the previous spot: Mouse.Move(intr, iconLoc.Point.X + xOfs + 15, iconLoc.Point.Y + yOfs); Mouse.Click(intr, iconLoc.Point.X + xOfs + 15, iconLoc.Point.Y + yOfs); //intr.Wait(2500); //// Verify that the VIP reward icon is no longer visible: //if (Screen.ImageSearch(intr, "InventoryVipAccountRewardsIcon").Found) { // intr.Log(LogEntryType.FatalWithScreenshot, "Error clicking on claim button."); // return false; //} else { // intr.Log(LogEntryType.Normal, "Enchanted key collected on {0}.", charLabel); // intr.AccountStates.SaveSetting(DateTime.Now.ToString("o"), "EnchKeyLastReceived", "invocation"); // return true; //} intr.Wait(200); intr.Log(LogEntryType.Normal, "Enchanted key collected on {0}.", charLabel); intr.AccountStates.SaveSetting(DateTime.Now.ToString("o"), "EnchKeyLastReceived", "invocation"); return(true); } else { // If things didn't work, just advance it anyway with an error message. // intr.Log(LogEntryType.Error, "Failure to claim enchanted key on {0}.", charLabel); intr.Log(LogEntryType.Error, "Assuming key was manually collected and continuing."); intr.AccountStates.SaveSetting(DateTime.Now.ToString("o"), "EnchKeyLastReceived", "invocation"); return(false); } }
//const int TILE_SIZE = 78; public static bool SelectCharacter(Interactor intr, uint charIdx, bool enterWorld) { if (intr.CancelSource.IsCancellationRequested) { return(false); } intr.Log(LogEntryType.Info, "Selecting character " + charIdx.ToString() + " ..."); int charCount = intr.AccountSettings.GetSettingValOr("characterCount", "general", 0); //int scrollBarTopX = intr.GameClient.GetSettingOrZero("CharacterSelectScrollBarTopX", "ClickLocations"); //int scrollBarTopY = intr.GameClient.GetSettingOrZero("CharacterSelectScrollBarTopY", "ClickLocations"); //int charSlotX = intr.GameClient.GetSettingOrZero("CharSlotX", "ClickLocations"); //int topSlotY = intr.GameClient.GetSettingOrZero("TopSlotY", "ClickLocations"); //int visibleSlots = intr.GameClient.GetSettingOrZero("VisibleCharacterSelectSlots", "KeyBindAndUi"); //int scrollsAlignBot = intr.GameClient.GetSettingOrZero("ScrollsToAlignBottomSlot", "KeyBindAndUi"); var charSel = new Global.ClientCharSelectDefaults(new Point(1920, 1080)); int scrollBarTopX = intr.ClientSettings.GetSettingValOr("scrollBarTopX", "characterSelect", charSel.ScrollBarTopX); int scrollBarTopY = intr.ClientSettings.GetSettingValOr("scrollBarTopY", "characterSelect", charSel.ScrollBarTopY); int charSlotX = intr.ClientSettings.GetSettingValOr("charSlotX", "characterSelect", charSel.CharSlotX); int topSlotY = intr.ClientSettings.GetSettingValOr("topSlotY", "characterSelect", charSel.TopSlotY); int visibleSlots = intr.ClientSettings.GetSettingValOr("visibleSlots", "characterSelect", charSel.VisibleSlots); int scrollsAlignBot = intr.ClientSettings.GetSettingValOr("scrollsToAlignBottomSlot", "characterSelect", charSel.ScrollsToAlignBottomSlot); if ((charCount == 0) || (charSlotX == 0) || (topSlotY == 0) || (visibleSlots == 0) || (scrollBarTopX == 0) || (scrollBarTopY == 0)) { intr.Log(LogEntryType.Fatal, "SelectCharacter(): Error loading ini file settings"); return(false); } int botSlotY = topSlotY + (TILE_SIZE * (visibleSlots - 1)) - (TILE_SIZE / 2); bool mustScroll = false; int scrolls = 0; int clickY = 0; if (charIdx < (visibleSlots - 1)) { clickY = topSlotY + (TILE_SIZE * ((int)charIdx)); } else { mustScroll = true; clickY = botSlotY; scrolls = (SCROLLS_PER_TILE * ((int)charIdx - (visibleSlots - 1))) + scrollsAlignBot; } int scrollUpClicks = (8 / visibleSlots) * 9; for (int i = 0; i < scrollUpClicks; i++) { Mouse.Click(intr, scrollBarTopX, scrollBarTopY); //intr.Wait(10); } Mouse.WheelUp(intr, 5); Mouse.Move(intr, charSlotX, clickY); intr.Wait(200); if (mustScroll) { Mouse.WheelDown(intr, scrolls); } if (!enterWorld) { return(true); } intr.Wait(400); Mouse.DoubleClick(intr, charSlotX, clickY); ClearSafeLogin(intr); //ClearDialogues(intr); intr.Wait(3000); // Determine if login has been a success: if (!intr.WaitUntil(90, ClientState.InWorld, States.IsClientState, CharSelectFailure, 0)) { // [NOTE]: Look into eliminating this recursion and moving control back up and iterating rather than delving deeper. ProduceClientState(intr, ClientState.CharSelect, 0); SelectCharacter(intr, charIdx, enterWorld); //return false; } // [TODO]: This should happen in the 'World Verification' loop: ClearDialogues(intr); return(true); }
public static bool Redeem(Interactor intr, uint charIdx) { VaultOfPietyItem item; try { item = (VaultOfPietyItem)Enum.Parse(typeof(VaultOfPietyItem), intr.AccountSettings.GetCharSetting(charIdx, "vaultOfPietyItem"), true); } catch (Exception) { item = DEFAULT_REDEMPTION_ITEM; } intr.Log(LogEntryType.Debug, "VaultOfPietyItem: " + item.ToString()); intr.Wait(500); string cursorModeKey = intr.AccountSettings.GetSettingValOr("toggleMouseCursor", "gameHotkeys", Global.Default.ToggleMouseCursor); if (Screen.ImageSearch(intr, "InvocationMaximumBlessings").Found) { intr.Wait(200); Mouse.ClickImage(intr, "InvocationMaximumBlessingsVaultOfPietyButton"); } else { intr.Wait(1000); Keyboard.SendKey(intr, cursorModeKey); intr.Wait(500); bool clicked = false; clicked |= Mouse.ClickImage(intr, "InvocationNotReady"); clicked |= Mouse.ClickImage(intr, "InvocationReady"); if (!clicked) { intr.Log(LogEntryType.FatalWithScreenshot, "Unable to click Vault of Piety button"); } } intr.WaitRand(2100, 2500); if (!Screen.ImageSearch(intr, "VaultOfPietyWindowTitle").Found) { return(false); } Mouse.ClickImage(intr, "VaultOfPietyCelestialSynergyTabTitle"); intr.Wait(2000); string panelImage; string purchaseConfirmImage; //if (item == VaultOfPietyItem.ElixirOfFate) { // var panel = Screen.ImageSearch(intr, "VaultOfPietyCelestialSynergyElixirOfFate"); // if (panel.Found) { // Mouse.DoubleClick(intr, panel.Point); // intr.Wait(500); // Mouse.ClickImage(intr, "VaultOfPietyElixirOfFateSelectAmountOkButton"); // intr.Log(LogEntryType.Info, "Vault of Piety: 'Elixir of Fate' purchased successfully."); // } else { // intr.Log(LogEntryType.Fatal, "Vault of Piety Error: Could not find 'Elixir of Fate' icon/tile."); // return false; // } //} else if (item == VaultOfPietyItem.CofferOfCelestialArtifactEquipment) { // var panel = Screen.ImageSearch(intr, "VaultOfPietyCelestialSynergyCofferOfCelestialArtifactEquipment"); // if (panel.Found) { // Mouse.DoubleClick(intr, panel.Point); // intr.Wait(500); // Mouse.ClickImage(intr, "VaultOfPietyCofferOfCelestialArtifactEquipmentPurchaseConfirmOkButton"); // intr.Log(LogEntryType.Info, "Vault of Piety: 'Coffer of Celestial Artifact Equipment' purchased successfully."); // } else { // intr.Log(LogEntryType.Fatal, "Vault of Piety Error: Could not find 'Coffer of Celestial Artifact Equipment' icon/tile."); // return false; // } //} if (item == VaultOfPietyItem.ElixirOfFate) { panelImage = "VaultOfPietyCelestialSynergyElixirOfFate"; purchaseConfirmImage = "VaultOfPietyElixirOfFateSelectAmountOkButton"; } else if (item == VaultOfPietyItem.BlessedProfessionsElementalPack) { panelImage = "VaultOfPietyCelestialSynergyBlessedProfessionsElementalPack"; purchaseConfirmImage = "VaultOfPietyCofferOfCelestialArtifactEquipmentPurchaseConfirmOkButton"; } else if (item == VaultOfPietyItem.CofferOfCelestialEnchantments) { panelImage = "VaultOfPietyCelestialSynergyCofferOfCelestialEnchantments"; purchaseConfirmImage = "VaultOfPietyCofferOfCelestialArtifactEquipmentPurchaseConfirmOkButton"; } else if (item == VaultOfPietyItem.CofferOfCelestialArtifacts) { panelImage = "VaultOfPietyCelestialSynergyCofferOfCelestialArtifacts"; purchaseConfirmImage = "VaultOfPietyCofferOfCelestialArtifactEquipmentPurchaseConfirmOkButton"; } else if (item == VaultOfPietyItem.CofferOfCelestialArtifactEquipment) { panelImage = "VaultOfPietyCelestialSynergyCofferOfCelestialArtifactEquipment"; purchaseConfirmImage = "VaultOfPietyCofferOfCelestialArtifactEquipmentPurchaseConfirmOkButton"; } else { intr.Log(LogEntryType.Fatal, "Vault of Piety Error: Unknown item: '{0:G}'.", item); return(false); } var panel = Screen.ImageSearch(intr, panelImage); if (panel.Found) { Mouse.DoubleClick(intr, panel.Point); intr.Wait(500); Mouse.ClickImage(intr, purchaseConfirmImage); intr.Log(LogEntryType.Info, "Vault of Piety: '{0:G}' purchased successfully.", item); } else { intr.Log(LogEntryType.Fatal, "Vault of Piety Error: Could not find '{0:G}' icon/panel.", item); return(false); } // [FIXME]: Handle the fact that the VaultOfPietyItem is: `5` // [FIX THE HELL OUT OF ME][FIX THE HELL OUT OF ME] // [FIX THE HELL OUT OF ME][FIX THE HELL OUT OF ME][FIX THE HELL OUT OF ME][FIX THE HELL OUT OF ME] return(true); }
//Potentially split into ProducePatcherState & Sub-functions public static bool PatcherLogin <TState>(Interactor intr, TState state) { //intr.ExecuteStatement("ActivateNeverwinter()"); string gameUserName = intr.AccountSettings.GetSettingValOr("accountName", "general", ""); string gamePassword = intr.AccountSettings.GetSettingValOr("password", "general", ""); if (gameUserName == "enter_user_name" || gameUserName == "" || gamePassword == "enter_password" || gamePassword == "") { intr.Log(LogEntryType.Fatal, "Username and/or Password not configured properly. Please edit " + "NeverClicker_GameAccount.ini and enter them there."); intr.CancelSource.Cancel(); return(false); } Mouse.Move(intr, 0, 0); // If patcher is already open, close it: if (States.DeterminePatcherState(intr) != PatcherState.None) { Screen.WindowKill(intr, States.GAMEPATCHEREXE); if (!intr.WaitUntil(15, PatcherState.None, States.IsPatcherState, PatcherKillFailure, 0)) { return(false); } } // Open patcher: Screen.WindowRun(intr, Properties.Settings.Default.NeverwinterExePath); if (!intr.WaitUntil(90, GameState.Patcher, States.IsGameState, PatcherRunFailure, 0)) { return(false); } // Set focus on patcher: intr.Wait(4000); Screen.WindowActivate(intr, States.GAMEPATCHEREXE); intr.Wait(1000); // Make sure server is up: if (States.IsServerState(intr, ServerState.Down)) { intr.Log("Server is down. Waiting until it comes up..."); //intr.Wait(1200000); //return false; // Check every 1min for 20min and return false (relaunching patcher) if unsuccessful. if (!intr.WaitUntil(1200, 60, ServerState.Up, States.IsServerState, PatcherServerFailure, 0)) { return(false); } } // Wait for login button to appear: if (!intr.WaitUntil(90, PatcherState.LogIn, States.IsPatcherState, PatcherRunFailure, 0)) { return(false); } // Set focus on patcher: Screen.WindowActivate(intr, States.GAMEPATCHEREXE); //while (intr.WaitUntil(10, PatcherState.LogIn, Game.IsPatcherState, null, 0)) { // //Keyboard.SendEvent(intr, "{Shift down}{Tab}{Shift up}"); // Keyboard.SendKeyWithMod(intr, "Shift", "Tab", Keyboard.SendMode.Event); // Keyboard.SendInput(intr, gameUserName); // intr.Wait(500); // Keyboard.SendInput(intr, "{Tab}"); // Keyboard.SendInput(intr, gamePassword); // intr.Wait(500); // Keyboard.SendInput(intr, "{Enter}"); // intr.Wait(10000); //} intr.Wait(500); Keyboard.SendKeyWithMod(intr, "Shift", "Tab", Keyboard.SendMode.Event); Keyboard.SendInput(intr, gameUserName); intr.Wait(500); Keyboard.SendInput(intr, "{Tab}"); Keyboard.SendInput(intr, gamePassword); intr.Wait(500); Keyboard.SendInput(intr, "{Enter}"); intr.Wait(10000); Screen.WindowKillTitle(intr, "Verify?"); // // Set focus on patcher: //Screen.WindowActivate(intr, Game.GAMEPATCHEREXE); if (!intr.WaitUntil(1800, PatcherState.PlayButton, States.IsPatcherState, PatcherLogInFailure, 0)) { return(false); } //intr.Wait(1000); //Keyboard.SendKeyWithMod(intr, "Shift", "Tab", Keyboard.SendMode.Event); //intr.Wait(300); //Keyboard.SendKeyWithMod(intr, "Shift", "Tab", Keyboard.SendMode.Event); //Keyboard.SendInput(intr, "{Enter}"); // Click play button image (may not be as reliable as above): Mouse.ClickImage(intr, "PatcherPlayButton"); return(intr.WaitUntil(60, ClientState.CharSelect, States.IsClientState, ProduceClientState, 0)); }