Example #1
0
        //// 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;
            }
        }
Example #2
0
        //// 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);
            }
        }
Example #3
0
        //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);
        }
Example #4
0
        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);
        }
Example #5
0
        //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));
        }
        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;
        }
Example #7
0
        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);
        }
Example #8
0
        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;
        }