diff --git a/.gitignore b/.gitignore index 25b090d2..b7b1466b 100644 --- a/.gitignore +++ b/.gitignore @@ -16,9 +16,13 @@ Scripts/*.ini *.bak !.gitkeep Accounts/Saved/**/*.xml +Accounts/SpecificCards/ +Accounts/GodPacks/ +Accounts/Saved/tmp/** Accounts/Trades/*.csv Accounts/Trades/*.json -Lab +Scripts/temp/** +Lab/ # macOS metadata files ._* @@ -29,4 +33,4 @@ Lab # Claude Code configuration .claude/ -.REFACTORING_SUMMARY.md \ No newline at end of file +.REFACTORING_SUMMARY.md diff --git a/Data/dictionary_cn.dat b/Data/dictionary_cn.dat index 471d1417..f70d0bc4 100644 --- a/Data/dictionary_cn.dat +++ b/Data/dictionary_cn.dat @@ -100,6 +100,7 @@ Txt_openExtraPack:額外多開一包 Txt_claimSpecialMissions:領取特殊任務 SortByText:注入排序: +Txt_ParadoxDrive:Paradox Drive Txt_PulsingAura:Pulsing Aura Txt_MegaShine:Mega Shine Txt_PaldeanWonders:Paldean Wonders diff --git a/Data/dictionary_de.dat b/Data/dictionary_de.dat index 672e8edb..ce7307c1 100644 --- a/Data/dictionary_de.dat +++ b/Data/dictionary_de.dat @@ -100,6 +100,7 @@ Txt_openExtraPack:Extra-Pack öffnen Txt_claimSpecialMissions:Spezialmissionen SortByText:Sortieren nach: +Txt_ParadoxDrive:Paradox Drive Txt_PulsingAura:Pulsing Aura Txt_MegaShine:Mega Shine Txt_PaldeanWonders:Paldean Wonders diff --git a/Data/dictionary_en.dat b/Data/dictionary_en.dat index fd234ec1..91af3f67 100644 --- a/Data/dictionary_en.dat +++ b/Data/dictionary_en.dat @@ -100,6 +100,7 @@ Txt_openExtraPack:Open Extra Pack Txt_claimSpecialMissions:Claim Special Missions SortByText:Sort By: +Txt_ParadoxDrive:Paradox Drive Txt_PulsingAura:Pulsing Aura Txt_MegaShine:Mega Shine Txt_PaldeanWonders:Paldean Wonders diff --git a/Data/dictionary_jp.dat b/Data/dictionary_jp.dat index 475ce48f..d518296c 100644 --- a/Data/dictionary_jp.dat +++ b/Data/dictionary_jp.dat @@ -100,6 +100,7 @@ Txt_openExtraPack:追加パックを開く Txt_claimSpecialMissions:イベント SortByText:注入序列: +Txt_ParadoxDrive:Paradox Drive Txt_PulsingAura:Pulsing Aura Txt_MegaShine:Mega Shine Txt_PaldeanWonders:Paldean Wonders diff --git a/Data/packdata.dat b/Data/packdata.dat index cc75a590..2f65e129 100644 --- a/Data/packdata.dat +++ b/Data/packdata.dat @@ -1,5 +1,5 @@ -# Pack list in Home screen -Home:Left|Mewtwo,Middle|PulsingAura,Right|MegaShine +# Pack list in Home screen +Home:Left|MegaShine,Middle|ParadoxDrive,Right|PulsingAura # Pack data(Structure) # PackID, Series Type, Number of packs in the set, Location of extension window, y Pos, Scroll Type @@ -22,14 +22,15 @@ Pack:Springs|A|1|Col-Second|298|0 Pack:Deluxe|A|1|Col-First|298|0 # B Series -Pack:MegaGyarados|B|3|Col-Second-Left|405|1 -Pack:MegaBlaziken|B|3|Col-Second-Middle|405|1 -Pack:MegaAltaria|B|3|Col-Second-Right|405|1 -Pack:CrimsonBlaze|B|1|Col-First|434|2 -Pack:Parade|B|1|Col-Second|434|0 -Pack:PaldeanWonders|B|1|Col-First|434|0 -Pack:MegaShine|B|1|Col-Second|298|0 -Pack:PulsingAura|B|1|Col-First|298|0 +Pack:MegaGyarados|B|3|Col-First-Left|405|1 +Pack:MegaBlaziken|B|3|Col-First-Middle|405|1 +Pack:MegaAltaria|B|3|Col-First-Right|405|1 +Pack:CrimsonBlaze|B|1|Col-Second|434|2 +Pack:Parade|B|1|Col-First|434|2 +Pack:PaldeanWonders|B|1|Col-Second|434|0 +Pack:MegaShine|B|1|Col-First|434|0 +Pack:PulsingAura|B|1|Col-Second|298|0 +Pack:ParadoxDrive|B|1|Col-First|298|0 # DO NOT Delete End ---END--- \ No newline at end of file diff --git a/PTCGPB.ahk b/PTCGPB.ahk index aabdbbdf..ec653edd 100644 --- a/PTCGPB.ahk +++ b/PTCGPB.ahk @@ -59,7 +59,11 @@ OnMessage(0x4A, "ReceiveData") if not A_IsAdmin { - Run *RunAs "%A_ScriptFullPath%" + try { + Run *RunAs "%A_ScriptFullPath%" + } catch { + MsgBox, 48, PTCGPB, Administrator permission is required to run PTCGPB.`n`nPlease launch it again and approve the permission prompt. + } ExitApp } @@ -81,11 +85,19 @@ botConfig.loadSettingsToConfig("ALL") SetTimer, ShowSwipeSpeedToolTip, 50 +displayScaleSetting := botConfig.get("DisplayScale") +if (displayScaleSetting = "") + displayScaleSetting := "Auto" +configuredDisplayScale := GetConfiguredDisplayScale() +if (displayScaleSetting = "Auto") + displayScaleLabel := "Auto (resolved to " . configuredDisplayScale . "%)" +else + displayScaleLabel := displayScaleSetting . "%" hasInvalidScale := false monitorScaleList := GetAllMonitorScales() For idx, scaleValue in monitorScaleList { - if(scaleValue != 100){ + if(scaleValue != configuredDisplayScale){ hasInvalidScale := true break } @@ -94,10 +106,11 @@ For idx, scaleValue in monitorScaleList { if (hasInvalidScale) { msgTitle := "Display Scale Warning" msgText := "WARNING: Display scale issue detected!`n`n" - . "To ensure the program works correctly, ALL monitors must be set to 100% scale in Windows settings.`n`n" - . "Please change your display scale to 100% and restart the program.`n`n" - . "[!] If you are ABSOLUTELY SURE all your monitors are already at 100% (script detection error), you can choose to ignore this warning.`n`n" - . "Do you want to ignore this warning and continue anyway?" + . "PTCGPB needs one matching display scale for coordinates and image search.`n" + . "Set the bot Display Scale and every Windows monitor to the same value (100% or 125%).`n`n" + . "Bot Display Scale: " displayScaleLabel "`n`n" + . "Restart the program after changing scale settings.`n`n" + . "Continue anyway?" MsgBox, 308, %msgTitle%, %msgText% @@ -312,7 +325,12 @@ NextStep: Gui, Font, s12 cWhite Bold Gui, Add, Text, x621 y20 w155 h50 Left BackgroundTrans cWhite, % dict["title_main"] Gui, Font, s10 cWhite Bold - Gui, Add, Text, x621 y20 w155 h150 Left BackgroundTrans cWhite, % "`n" localVersion "`n(for Scale 100%)`n`nModder: Crinity " modVersion + displayScaleCaption := botConfig.get("DisplayScale") + if (displayScaleCaption = "" || displayScaleCaption = "Auto") + displayScaleCaption := "Auto/" . GetConfiguredDisplayScale() . "%" + else + displayScaleCaption := displayScaleCaption . "%" + Gui, Add, Text, x621 y20 w155 h150 Left BackgroundTrans cWhite, % "`n" localVersion "`n(Scale " displayScaleCaption ")`n`nModder: Crinity " modVersion Gui, Add, Picture, gBuyMeCoffee x625 y130 w150, %A_ScriptDir%\GUI\Images\support_me_on_kofi.png @@ -1123,6 +1141,17 @@ ShowToolsAndSystemSettings: SelectedMonitorIndex := RegExReplace(botConfig.get("SelectedMonitorIndex"), ":.*$") Gui, ToolsAndSystemSelect:Add, DropDownList, x%col2X% y%yPos2% w100 vui_SelectedMonitorIndex_Popup Choose%SelectedMonitorIndex% Background2A2A2A cWhite, %MonitorOptions% yPos2 += 25 + + displayScaleList := "Auto|100|125" + displayScaleChoose := 1 + if (botConfig.get("DisplayScale") = "100") + displayScaleChoose := 2 + else if (botConfig.get("DisplayScale") = "125") + displayScaleChoose := 3 + displayScaleTextY := yPos2 + 2 + Gui, ToolsAndSystemSelect:Add, Text, x%col2X% y%displayScaleTextY% %sectionColor%, Display Scale + Gui, ToolsAndSystemSelect:Add, DropDownList, x325 y%yPos2% w60 vui_DisplayScale_Popup Choose%displayScaleChoose% Background2A2A2A cWhite, %displayScaleList% + yPos2 += 25 rowGapY := yPos2 + 2 Gui, ToolsAndSystemSelect:Add, Text, x%col2X% y%rowGapY% %sectionColor%, % dict["Txt_RowGap"] @@ -1222,6 +1251,7 @@ saveToolsAndSystemSettings: botConfig.set("wonderpickForEventMissions", ui_wonderpickForEventMissions_Popup, "ToolsAndSystem") botConfig.set("SelectedMonitorIndex", ui_SelectedMonitorIndex_Popup, "ToolsAndSystem") + botConfig.set("DisplayScale", ui_DisplayScale_Popup, "ToolsAndSystem") botConfig.set("RowGap", ui_RowGap_Popup, "ToolsAndSystem") botConfig.set("folderPath", ui_folderPath_Popup, "ToolsAndSystem") botConfig.set("ocrLanguage", ui_ocrLanguage_Popup, "ToolsAndSystem") @@ -1441,14 +1471,18 @@ BalanceXMLs: if !FileExist(saveDir) FileCreateDir, %saveDir% - tmpDir := A_ScriptDir "\Accounts\Saved\tmp" - if !FileExist(tmpDir) - FileCreateDir, %tmpDir% + tmpRoot := A_ScriptDir "\Accounts\Saved\tmp" + if !FileExist(tmpRoot) + FileCreateDir, %tmpRoot% + + FormatTime, balanceRunId,, yyyyMMddHHmmss + tmpDir := tmpRoot . "\balance_" . balanceRunId . "_" . A_TickCount + FileCreateDir, %tmpDir% Tooltip, Moving Files and Folders to tmp Loop, Files, %saveDir%*, D { - if (A_LoopFilePath == tmpDir) + if (A_LoopFilePath == tmpRoot) continue dest := tmpDir . "\" . A_LoopFileName @@ -1528,6 +1562,9 @@ BalanceXMLs: if (instance > botConfig.get("Instances")) instance := 1 } + + ToolTip, Restoring preserved files + RestorePreservedSavedReadmes(tmpDir, saveDir) instanceOneDir := saveDir . "1" counter := 0 @@ -1546,6 +1583,24 @@ BalanceXMLs: } return +RestorePreservedSavedReadmes(tmpDir, saveDir) { + Loop, Files, %tmpDir%\*, FR + { + if (A_LoopFileName != "readme.md") + continue + + relativePath := SubStr(A_LoopFileFullPath, StrLen(tmpDir) + 2) + if (!RegExMatch(relativePath, "i)^(\d+)\\readme\.md$", readmeMatch)) + continue + + restorePath := saveDir . readmeMatch1 . "\readme.md" + SplitPath, restorePath,, restoreDir + if !FileExist(restoreDir) + FileCreateDir, %restoreDir% + FileMove, %A_LoopFileFullPath%, %restorePath%, 1 + } +} + ; =================== Logic - Launch All Mumu Button Action =================== LaunchAllMumu: Gui, Submit, NoHide @@ -1575,9 +1630,10 @@ ArrangeWindows: SaveAllSettings() - scaleParam := 283 + windowMetrics := GetMumuWindowMetrics() + scaleParam := windowMetrics.scaleParam windowsPositioned := 0 - titleHeight := 40 + titleHeight := windowMetrics.titleHeight if(botConfig.get("SelectedMonitorIndex") = "") botConfig.set("SelectedMonitorIndex", "1:", "ToolsAndSystem") @@ -1595,7 +1651,7 @@ ArrangeWindows: instanceIndex := A_Index borderWidth := 4 - 1 - rowHeight := titleHeight + 492 + rowHeight := windowMetrics.rowHeight currentRow := Floor((instanceIndex - 1) / botConfig.get("Columns")) y := MonitorTop + (currentRow * rowHeight) + (currentRow * botConfig.get("rowGap")) x := MonitorLeft + (Mod((instanceIndex - 1), botConfig.get("Columns")) * (scaleParam - borderWidth * 2)) @@ -1626,7 +1682,7 @@ ArrangeWindows: instanceIndex := (botConfig.get("Mains") - 1) + A_Index + 1 borderWidth := 4 - 1 - rowHeight := titleHeight + 492 + rowHeight := windowMetrics.rowHeight currentRow := Floor((instanceIndex - 1) / botConfig.get("Columns")) y := MonitorTop + (currentRow * rowHeight) + (currentRow * botConfig.get("rowGap")) x := MonitorLeft + (Mod((instanceIndex - 1), botConfig.get("Columns")) * (scaleParam - borderWidth * 2)) @@ -1725,10 +1781,6 @@ SaveAllSettings() { botConfig.set("stopPreferenceMain", botConfig.get("stopPreferenceMain"), "Extra") botConfig.saveConfigToSettings("ALL") - - if (botConfig.get("debugMode")) { - FileAppend, % A_Now . " - Settings saved. DeleteMethod: " . botConfig.get("deleteMethod") . "`n", %A_ScriptDir%\debug_settings.log - } } ; =================== Logic - Reset account lists =================== @@ -1945,7 +1997,7 @@ StartBot() { discMessage .= selectMsg if(botConfig.get("groupRerollEnabled") || (!botConfig.get("groupRerollEnabled") && botConfig.get("heartBeatOwnerWebHookURL") = "")) - LogToDiscord(discMessage,, false,,, botConfig.get("heartBeatWebhookURL")) + LogToDiscord(discMessage,, false,,, botConfig.get("heartBeatWebhookURL"),, false) if(botConfig.get("heartBeatOwnerWebHookURL")){ FormatTime, currentTime, , yyyy-MM-dd HH:mm:ss @@ -1978,7 +2030,7 @@ StartBot() { discMessage .= "\n--------------------------------------------------" - LogToDiscord(discMessage,, false,,, botConfig.get("heartBeatOwnerWebHookURL")) + LogToDiscord(discMessage,, false,,, botConfig.get("heartBeatOwnerWebHookURL"),, false) } if (botConfig.get("debugMode")) { @@ -2024,7 +2076,7 @@ SendAllInstancesOfflineStatus() { discMessage .= selectMsg discMessage .= "\n\n All instances marked as OFFLINE" - LogToDiscord(discMessage,, false,,, botConfig.get("heartBeatWebhookURL")) + LogToDiscord(discMessage,, false,,, botConfig.get("heartBeatWebhookURL"),, false) } ReceiveData(wParam, lParam) { @@ -2207,4 +2259,4 @@ return ~+F12:: ListVars Pause ; 변수 목록을 확인하기 위해 스크립트를 잠시 멈춥니다. -return \ No newline at end of file +return diff --git a/Scripts/1.ahk b/Scripts/1.ahk index 97cc4d94..2c032d2d 100644 --- a/Scripts/1.ahk +++ b/Scripts/1.ahk @@ -1,4 +1,4 @@ -#SingleInstance on +#SingleInstance, Force SetMouseDelay, -1 SetDefaultMouseSpeed, 0 SetBatchLines, -1 @@ -34,9 +34,7 @@ pToken := Gdip_Startup() #Include SpecialEvent.ahk #Include Crinity_UnofficialPatch.ahk -; Allocate and hide the console window to reduce flashing -DllCall("AllocConsole") -WinHide % "ahk_id " DllCall("GetConsoleWindow", "ptr") +InitializeHiddenConsole() ; Register OnExit handler to clean up ADB shell properly when script exits ; DISABLED - was causing Reload delays due to blocking ADB shell communication @@ -124,6 +122,16 @@ if(botConfig.get("deleteMethod") != "Inject Wonderpick 96P+") session.set("packMethod", 0) IniRead, DeadCheck, % session.get("scriptIniFile"), UserSettings, DeadCheck, 0 +IniRead, friendCleanupPending, % session.get("scriptIniFile"), UserSettings, friendCleanupPending, 0 +if(friendCleanupPending = 1) { + DeadCheck := 1 + IniWrite, 1, % session.get("scriptIniFile"), UserSettings, DeadCheck + session.set("friended", true) + LogToFile("Friend cleanup pending found at startup. Entering cleanup recovery.", "GroupReroll.txt") +} +if(DeadCheck = 1) { + RestoreLoadedAccountForRecovery() +} IniRead, rerollsValue, % session.get("scriptIniFile"), Metrics, rerolls, 0 IniRead, rerollStartTimeValue, % session.get("scriptIniFile"), Metrics, rerollStartTime, -1 @@ -140,7 +148,8 @@ if(botConfig.get("heartBeat")) SetTimer, RefreshAccountLists, 3600000 ; Refresh Account list every hour -DirectlyPositionWindow() +windowCoverHwnd := GetMuMuCoverWindowForMaintenance(session.get("winTitle")) +DirectlyPositionWindow(windowCoverHwnd) Sleep, 500 setADBBaseInfo() @@ -150,7 +159,7 @@ Sleep, 500 CreateStatusMessage("Disabling background services...") DisableBackgroundServices() -resetWindows() +resetWindows(windowCoverHwnd) MaxRetries := 10 RetryCount := 0 Loop { @@ -159,7 +168,8 @@ Loop { sleep, 1000 OwnerWND := getMuMuHwnd(session.get("winTitle")) x4 := x + 4 - y4 := y + 529 + windowMetrics := GetMumuWindowMetrics() + y4 := y + windowMetrics.rowHeight - 3 buttonWidth := 50 Gui, New, +Owner%OwnerWND% -AlwaysOnTop +ToolWindow -Caption +LastFound -DPIScale @@ -174,6 +184,7 @@ Loop { DllCall("SetWindowPos", "Ptr", WinExist(), "Ptr", 1 ; HWND_BOTTOM , "Int", 0, "Int", 0, "Int", 0, "Int", 0, "UInt", 0x13) ; SWP_NOSIZE, SWP_NOMOVE, SWP_NOACTIVATE Gui, Show, NoActivate x%x4% y%y4% w275 h30 + RestoreMuMuCoverWindow(windowCoverHwnd, session.get("winTitle")) break } catch { @@ -203,7 +214,7 @@ SetTimer, LiveMetricsTimer, 5000 if(session.get("injectMethod") && DeadCheck != 1) { session.set("loadedAccount", loadAccount()) } else if(session.get("injectMethod") && DeadCheck = 1) { - ; DeadCheck = 1: Start the Pokemon app for the stuck account (don't inject new account) + ; DeadCheck/friend cleanup recovery: Start the existing app account (don't inject new account). startPTCGPApp() } @@ -234,21 +245,23 @@ if(DeadCheck = 1 && botConfig.get("deleteMethod") != "Create Bots (13P)") { Delay(1) startPreProcess(botConfig.get("deleteMethod")) RemoveFriends() - if(session.get("injectMethod") && session.get("loadedAccount") && !session.get("keepAccount")) { - MarkAccountAsUsed() + if(session.get("injectMethod") && session.get("loadedAccount")) { + LogToFile("Recovery cleanup complete. Keeping recovered account in queue unless its XML was already updated: " . session.get("accountFileName")) + ClearLoadedAccountRecovery() session.set("loadedAccount", false) + session.set("currentLoadedAccountIndex", 0) } DeadCheck := 0 IniWrite, 0, % session.get("scriptIniFile"), UserSettings, DeadCheck createAccountList(session.get("scriptName")) CleanupBeforeExit() - SafeReload() + SafeReload("DeadCheck friend cleanup complete") } else if(DeadCheck = 1 && botConfig.get("deleteMethod") = "Create Bots (13P)") { CreateStatusMessage("New account creation is stuck! Deleting account...") Delay(5) menuDeleteStart() CleanupBeforeExit() - SafeReload() + SafeReload("DeadCheck create bots cleanup complete") } else { ; in injection mode, we dont need to reload @@ -306,6 +319,7 @@ if(DeadCheck = 1 && botConfig.get("deleteMethod") != "Create Bots (13P)") { LogToFile("[" . A_ScriptName . "] GPU usage exceeds the threshold and restarts. VRAM Usage(" . session.get("VRAMUsage").Mode . "): " . session.get("VRAMUsage").Usage . " GB", "Restart.txt") CreateStatusMessage("Restarting Instance...",,,, false) restartInstance() + RefreshAdbConnectionAfterInstanceRestart(45000) DirectlyPositionWindow() CreateStatusMessage("Restart complete!",,,, false) LogToFile("[" . A_ScriptName . "] Restart complete!", "Restart.txt") @@ -854,7 +868,10 @@ FindOrLoseImage(needleName := "DEFAULT", EL := 1, safeTime := 0, searchVariation global botConfig, session, needlesDict static lastStatusTime := 0 - needleObj := needlesDict.Get(needleName) + needleObj := GetSearchNeedleObj(needleName, "FindOrLoseImage") + if (!IsObject(needleObj)) + return false + imageName := needleObj.imageName if(botConfig.get("slowMotion")) { @@ -893,7 +910,7 @@ FindOrLoseImage(needleName := "DEFAULT", EL := 1, safeTime := 0, searchVariation if (imageName = "CommunityShowcase" || imageName = "Search" || imageName = "inHamburgerMenu" || imageName = "Trade") { Path = %imagePath%Tutorial.png pNeedle := GetNeedle(Path) - vRet := Gdip_ImageSearch_wbb(pBitmap, pNeedle, vPosXY, 111, 115, 167, 121, searchVariation) + vRet := Gdip_ImageSearchProfile_wbb(pBitmap, pNeedle, vPosXY, [111, 115, 167, 121], [111, 115, 167, 121], searchVariation) if (vRet = 1) { adbClick_wbb(145, 451) } @@ -903,7 +920,7 @@ FindOrLoseImage(needleName := "DEFAULT", EL := 1, safeTime := 0, searchVariation if(imageName = "Points" || imageName = "Missions" || imageName = "WonderPick" || imageName = "Home" || imageName = "Country" || imageName = "Account2" || imageName = "Account" || imageName = "ClaimAll" || imageName = "inHamburgerMenu" || imageName = "Trade") { Path = %imagePath%Update.png pNeedle := GetNeedle(Path) - vRet := Gdip_ImageSearch_wbb(pBitmap, pNeedle, vPosXY, 15, 180, 53, 228, searchVariation) + vRet := Gdip_ImageSearchProfile_wbb(pBitmap, pNeedle, vPosXY, [15, 180, 53, 228], [15, 180, 53, 228], searchVariation) if (vRet = 1) { adbClick_wbb(137, 485) Gdip_DisposeImage(pBitmap) @@ -920,7 +937,7 @@ FindOrLoseImage(needleName := "DEFAULT", EL := 1, safeTime := 0, searchVariation Path = %imagePath%Delete2.png pNeedle := GetNeedle(Path) ; ImageSearch within the region - vRet := Gdip_ImageSearch_wbb(pBitmap, pNeedle, vPosXY, 118, 353, 135, 390, searchVariation) + vRet := Gdip_ImageSearchProfile_wbb(pBitmap, pNeedle, vPosXY, [118, 353, 135, 390], [118, 353, 135, 390], searchVariation) if (vRet = 1) { adbClick_wbb(74, 353) Delay(1) @@ -933,7 +950,7 @@ FindOrLoseImage(needleName := "DEFAULT", EL := 1, safeTime := 0, searchVariation Path = %imagePath%NoSave.png ; look for No Save Data error message > if loaded account > delete xml > reload pNeedle := GetNeedle(Path) ; ImageSearch within the region - vRet := Gdip_ImageSearch_wbb(pBitmap, pNeedle, vPosXY, 30, 331, 50, 449, searchVariation) + vRet := Gdip_ImageSearchProfile_wbb(pBitmap, pNeedle, vPosXY, [30, 331, 50, 449], [30, 331, 50, 449], searchVariation) if (vRet = 1) { adbWriteRaw("rm -rf /data/data/jp.pokemon.pokemontcgp/cache/*") ; clear cache waitadb() @@ -944,7 +961,7 @@ FindOrLoseImage(needleName := "DEFAULT", EL := 1, safeTime := 0, searchVariation } LogToFile("Restarted game. Reason: No save data found") CleanupBeforeExit() - SafeReload() + SafeReload("No save data found") } } @@ -969,7 +986,10 @@ FindOrLoseImage(needleName := "DEFAULT", EL := 1, safeTime := 0, searchVariation FindImageAndClick(needleName := "DEFAULT", clickx := 0, clicky := 0, searchVariation := 20, sleepTime := "", skip := false, safeTime := 0) { global botConfig, session, needlesDict - needleObj := needlesDict.Get(needleName) + needleObj := GetSearchNeedleObj(needleName, "FindImageAndClick") + if (!IsObject(needleObj)) + return false + imageName := needleObj.imageName if(botConfig.get("slowMotion")) { @@ -1024,7 +1044,7 @@ FindImageAndClick(needleName := "DEFAULT", clickx := 0, clicky := 0, searchVaria confirmed := vPosXY } else { ElapsedTime := (A_TickCount - session.get("StartSkipTime")) // 1000 - if(imageName = "Country") + if(imageName = "Country" || imageName = "Social" || imageName = "Points") FSTime := 90 else if(imageName = "Missions" || imageName = "DailyMissions" || imageName = "DexMissions") FSTime := 60 @@ -1053,7 +1073,7 @@ FindImageAndClick(needleName := "DEFAULT", clickx := 0, clicky := 0, searchVaria if (imageName = "CommunityShowcase" || imageName = "Add" || imageName = "Search") { Path = %imagePath%Tutorial.png pNeedle := GetNeedle(Path) - vRet := Gdip_ImageSearch_wbb(pBitmap, pNeedle, vPosXY, 111, 115, 167, 121, searchVariation) + vRet := Gdip_ImageSearchProfile_wbb(pBitmap, pNeedle, vPosXY, [111, 115, 167, 121], [111, 115, 167, 121], searchVariation) if (vRet = 1) { adbClick_wbb(145, 451) } @@ -1063,7 +1083,7 @@ FindImageAndClick(needleName := "DEFAULT", clickx := 0, clicky := 0, searchVaria if(imageName = "Points" || imageName = "Missions" || imageName = "WonderPick" || imageName = "Home" || imageName = "Country" || imageName = "Account2" || imageName = "Account" || imageName = "ClaimAll" || imageName = "inHamburgerMenu" || imageName = "Trade") { Path = %imagePath%Update.png pNeedle := GetNeedle(Path) - vRet := Gdip_ImageSearch_wbb(pBitmap, pNeedle, vPosXY, 20, 191, 36, 211, searchVariation) + vRet := Gdip_ImageSearchProfile_wbb(pBitmap, pNeedle, vPosXY, [20, 191, 36, 211], [20, 191, 36, 211], searchVariation) if (vRet = 1) { adbClick_wbb(137, 485) Gdip_DisposeImage(pBitmap) @@ -1080,7 +1100,7 @@ FindImageAndClick(needleName := "DEFAULT", clickx := 0, clicky := 0, searchVaria Path = %imagePath%NoSave.png ; look for No Save Data error message > if loaded account > delete xml > reload pNeedle := GetNeedle(Path) ; ImageSearch within the region - vRet := Gdip_ImageSearch_wbb(pBitmap, pNeedle, vPosXY, 30, 331, 50, 449, searchVariation) + vRet := Gdip_ImageSearchProfile_wbb(pBitmap, pNeedle, vPosXY, [30, 331, 50, 449], [30, 331, 50, 449], searchVariation) if (vRet = 1) { adbWriteRaw("rm -rf /data/data/jp.pokemon.pokemontcgp/cache/*") ; clear cache waitadb() @@ -1091,14 +1111,14 @@ FindImageAndClick(needleName := "DEFAULT", clickx := 0, clicky := 0, searchVaria } LogToFile("Restarted game. Reason: No save data found") CleanupBeforeExit() - SafeReload() + SafeReload("No save data found") } } if(imageName = "Skip2" || imageName = "Pack" || imageName = "Hourglass2") { Path = %imagePath%notenoughitems.png pNeedle := GetNeedle(Path) - vRet := Gdip_ImageSearch_wbb(pBitmap, pNeedle, vPosXY, 92, 299, 115, 317, 0) + vRet := Gdip_ImageSearchProfile_wbb(pBitmap, pNeedle, vPosXY, [92, 299, 115, 317], [92, 299, 115, 317], 0) if(vRet = 1) { session.set("cantOpenMorePacks", 1) return 0 @@ -1108,7 +1128,7 @@ FindImageAndClick(needleName := "DEFAULT", clickx := 0, clicky := 0, searchVaria if(imageName = "Mission_dino2") { Path = %imagePath%1solobattlemission.png pNeedle := GetNeedle(Path) - vRet := Gdip_ImageSearch_wbb(pBitmap, pNeedle, vPosXY, 108, 180, 177, 208, 0) + vRet := Gdip_ImageSearchProfile_wbb(pBitmap, pNeedle, vPosXY, [108, 180, 177, 208], [108, 180, 177, 208], 0) if(vRet = 1) { session.get("missionDoneList")["beginnerMissionsDone"] := 1 if(session.get("injectMethod") && session.get("loadedAccount")) @@ -1139,16 +1159,17 @@ FindImageAndClick(needleName := "DEFAULT", clickx := 0, clicky := 0, searchVaria return confirmed } -resetWindows() { - DirectlyPositionWindow() +resetWindows(coverHwnd := "") { + DirectlyPositionWindow(coverHwnd) return true } -DirectlyPositionWindow() { - global botConfig +DirectlyPositionWindow(coverHwnd := "") { + global botConfig, session - scaleParam := 283 + windowMetrics := GetMumuWindowMetrics() + scaleParam := windowMetrics.scaleParam rowGap := botConfig.get("rowGap") ; Get monitor information @@ -1157,6 +1178,8 @@ DirectlyPositionWindow() { ; Calculate position based on instance number Title := session.get("winTitle") + if (!coverHwnd) + coverHwnd := GetMuMuCoverWindowForMaintenance(Title) if (botConfig.get("runMain")) { instanceIndex := (botConfig.get("Mains") - 1) + Title + 1 @@ -1164,10 +1187,10 @@ DirectlyPositionWindow() { instanceIndex := Title } - titleHeight := 40 + titleHeight := windowMetrics.titleHeight borderWidth := 4 - 1 - rowHeight := titleHeight + 492 + rowHeight := windowMetrics.rowHeight currentRow := Floor((instanceIndex - 1) / botConfig.get("Columns")) y := MonitorTop + (currentRow * rowHeight) + (currentRow * rowGap) @@ -1181,6 +1204,7 @@ DirectlyPositionWindow() { FixInstanceScreen(session.get("winTitle")) CreateStatusMessage("Positioned window at x:" . x . " y:" . y,,,, false) + RestoreMuMuCoverWindow(coverHwnd, Title) return true } @@ -1206,21 +1230,31 @@ restartGameInstance(reason, RL := true) { if (isStuck) { logStr := "STUCK DETECTED - Reason: " . reason . " | injectMethod: " . (session.get("injectMethod") ? "true" : "false") . " | " logStr .= "loadedAccount: " . (session.get("loadedAccount") ? "true" : "false") . " | " + logStr .= "friended: " . (session.get("friended") ? "true" : "false") . " | " logStr .= "accountFileName: " . session.get("accountFileName") LogToFile(logStr) SaveStuckScreenshot(reason) + + if(session.get("injectMethod") && session.get("loadedAccount") && session.get("friended")) { + IniWrite, 1, % session.get("scriptIniFile"), UserSettings, DeadCheck + SetFriendCleanupPending("Stuck recovery: " . reason) + LogToFile("DeadCheck set for stuck recovery cleanup. Reason: " . reason) + } } if (RL = "GodPack") { LogToFile("Restarted game. Reason: " reason) IniWrite, 0, % session.get("scriptIniFile"), UserSettings, DeadCheck + ; Valid GP keeps friends by design; do not let startup recovery remove them. + ClearFriendCleanupPending() + session.set("friended", false) if (!botConfig.get("groupRerollEnabled")) AppendFriendCodeToManualVipIds(session.get("friendCode")) SendMetadataToPTCGPB(session.get("packsThisRun")) PersistStopAfterRunIfNeeded() CleanupBeforeExit() - Reload + SafeReload("GodPack restart") } else if (isStuck) { if(!checkInstance(session.get("scriptName"))){ LogToFile(" Found " . session.get("scriptName") . " instance down! start Instance") @@ -1242,7 +1276,7 @@ restartGameInstance(reason, RL := true) { PersistStopAfterRunIfNeeded() CleanupBeforeExit() - SafeReload() + SafeReload("Stuck restart: " . reason) } else { ; Non-stuck restart: just restart the Pokemon app, not the whole MuMu instance closePTCGPApp() @@ -1260,7 +1294,7 @@ restartGameInstance(reason, RL := true) { PersistStopAfterRunIfNeeded() CleanupBeforeExit() - SafeReload() + SafeReload("Restart game: " . reason) } if (session.get("stopToggle")) { @@ -1794,10 +1828,10 @@ Screenshot(fileType := "Valid", subDir := "", ByRef fileName := "") { filePath := fileDir "\" . fileName yBias := 40 - cropX := 18 + cropX := GetScaleProfileValue(18, 12) cropY := 170 - cropW := 240 - cropH := 227 + cropW := GetScaleProfileValue(240, 251) + cropH := GetScaleProfileValue(227, 245) if (fileType = "FRIENDCODE"){ cropX := 18 @@ -1847,7 +1881,7 @@ return ReloadScript: CleanupBeforeExit() - SafeReload() + SafeReload("Toolbar reload") return TestScript: @@ -2106,7 +2140,7 @@ Return ; ===== HOTKEYS ===== ~+F5:: CleanupBeforeExit() - SafeReload() + SafeReload("Shift+F5") return ~+F6::Pause ~+F7:: @@ -2426,14 +2460,29 @@ Gdip_ImageSearch_wbb(pBitmapHaystack,pNeedle,ByRef OutputList="" ,SearchDirection=1,Instances=1,LineDelim="`n",CoordDelim=",") { global session - vret := Gdip_ImageSearch(pBitmapHaystack,pNeedle.needle,OutputList,OuterX1,OuterY1,OuterX2,OuterY2,Variation,Trans,SearchDirection,Instances,LineDelim,CoordDelim) + windowMetrics := GetMumuWindowMetrics() + yBias := windowMetrics.imageSearchYBias + vret := Gdip_ImageSearch(pBitmapHaystack,pNeedle.needle,OutputList,OuterX1,OuterY1+yBias,OuterX2,OuterY2+yBias,Variation,Trans,SearchDirection,Instances,LineDelim,CoordDelim) if(session.get("dbg_bbox")) - bboxAndPause_immage(OuterX1, OuterY1, OuterX2, OuterY2, pNeedle, vret, session.get("dbg_bboxNpause")) + bboxAndPause_immage(OuterX1, OuterY1+yBias, OuterX2, OuterY2+yBias, pNeedle, vret, session.get("dbg_bboxNpause")) return vret } +Gdip_ImageSearchProfile_wbb(pBitmapHaystack, pNeedle, ByRef OutputList="" + , coords100="", coords125="", Variation=0, Trans="" + , SearchDirection=1, Instances=1, LineDelim="`n", CoordDelim=",") { + if (!IsObject(coords125)) + coords125 := coords100 + + coords := GetScaleProfileValue(coords100, coords125) + return Gdip_ImageSearch_wbb(pBitmapHaystack, pNeedle, OutputList + , coords[1], coords[2], coords[3], coords[4], Variation, Trans + , SearchDirection, Instances, LineDelim, CoordDelim) +} + GetNeedle(Path) { static NeedleBitmaps := Object() + Path := ResolveNeedlePath(Path) if (NeedleBitmaps.HasKey(Path)) { return NeedleBitmaps[Path] @@ -2461,10 +2510,13 @@ DoTutorial() { Delay(3) session.set("failSafe", A_TickCount) failSafeTime := 0 + ; The legacy Scale 125 birth-date needles are on opposite selector columns. + firstBirthNeedle := GetScaleProfileValue("Create_SelectedYear", "Create_SelectedMonth") + firstBirthLabel := GetScaleProfileValue("Year", "Month") Loop { Delay(3) - if(FindImageAndClick("Create_SelectedYear", , , , , 1, failSafeTime)) + if(FindImageAndClick(firstBirthNeedle, , , , , 1, failSafeTime)) break Delay(3) adbClick_wbb(142, 159) @@ -2475,7 +2527,7 @@ DoTutorial() { Delay(3) adbClick_wbb(82, 422) failSafeTime := (A_TickCount - session.get("failSafe")) // 1000 - CreateStatusMessage("Waiting for Year`n(" . failSafeTime . "/45 seconds)") + CreateStatusMessage("Waiting for " . firstBirthLabel . "`n(" . failSafeTime . "/45 seconds)") } ;select month and year and click adbClick_wbb(200, 400) @@ -2484,9 +2536,11 @@ DoTutorial() { Delay(3) session.set("failSafe", A_TickCount) failSafeTime := 0 + secondBirthNeedle := GetScaleProfileValue("Create_SelectedMonth", "Create_SelectedYear") + secondBirthLabel := GetScaleProfileValue("Month", "Year") Loop { ;select month and year and click Delay(3) - if(FindImageAndClick("Create_SelectedMonth", , , , , 1, failSafeTime)) + if(FindImageAndClick(secondBirthNeedle, , , , , 1, failSafeTime)) break Delay(3) adbClick_wbb(142, 159) @@ -2500,7 +2554,7 @@ DoTutorial() { adbClick_wbb(142, 159) Delay(3) failSafeTime := (A_TickCount - session.get("failSafe")) // 1000 - CreateStatusMessage("Waiting for Month`n(" . failSafeTime . "/45 seconds)") + CreateStatusMessage("Waiting for " . secondBirthLabel . "`n(" . failSafeTime . "/45 seconds)") } ;select month and year and click Delay(3) @@ -2848,7 +2902,7 @@ DoTutorial() { } SelectPack(HG := false) { - global session + global botConfig, session ; define constants mapPackX := {"Left":60, "Middle":140, "Right":215} @@ -2859,6 +2913,7 @@ SelectPack(HG := false) { packx := getPackCoordXInHome() packy := HomeScreenAllPackY + enteredPackScreenFromHome := false if(HG = "First" && session.get("injectMethod") && session.get("loadedAccount") ){ session.set("failSafe", A_TickCount) @@ -2894,9 +2949,11 @@ SelectPack(HG := false) { failSafeTime := (A_TickCount - session.get("failSafe")) // 1000 CreateStatusMessage("Waiting for Points`n(" . failSafeTime . "/90 seconds)") } + enteredPackScreenFromHome := true } - FindImageAndClick("Pack_PackPointButton", packx, packy, , 1000) + if (!enteredPackScreenFromHome) + FindImageAndClick("Pack_PackPointButton", packx, packy, , 1000) if(!session.get("isSkipSelectExpansion")) { FindImageAndClick("Pack_ScrollInSelectExpansion", 248, 459, , 300) @@ -3707,8 +3764,3 @@ CleanupBeforeExit(){ allSpecialEventDispose() GetGPUMemoryByPDH(-1, true) } - -^e:: - pToken := Gdip_Startup() - Screenshot_dev() -return diff --git a/Scripts/Include/ADB.ahk b/Scripts/Include/ADB.ahk index 22d70435..8dbac109 100644 --- a/Scripts/Include/ADB.ahk +++ b/Scripts/Include/ADB.ahk @@ -109,12 +109,57 @@ ConnectAdb() { CreateStatusMessage("Failed to connect to ADB after multiple retries. Please check your emulator and port settings.") else CreateStatusMessage("Failed to connect to ADB.",,,, false) - Reload + SafeReload("ADB connect failed") } } } } +RefreshAdbConnectionAfterInstanceRestart(timeoutMs = 30000) { + global session + + startTick := A_TickCount + oldPort := session.get("adbPort") + lastPort := oldPort + + Loop { + newPort := findAdbPorts() + if (newPort) { + if (newPort != lastPort) { + LogToFile("[" . A_ScriptName . "] ADB port refreshed after instance restart: " . lastPort . " -> " . newPort, "ADB.txt") + lastPort := newPort + } + + session.set("adbPort", newPort) + ip := "127.0.0.1:" . newPort + if (oldPort && oldPort != newPort) + CmdRet(session.get("adbPath") . " disconnect 127.0.0.1:" . oldPort) + + connectionResult := CmdRet(session.get("adbPath") . " connect " . ip) + if (InStr(connectionResult, "connected to " . ip) || InStr(connectionResult, "already connected to " . ip)) { + shellResult := CmdRet(session.get("adbPath") . " -s " . ip . " shell echo ready") + if (InStr(shellResult, "ready")) { + session.set("adbShell", "") + initializeAdbShell() + LogToFile("[" . A_ScriptName . "] ADB reconnected after instance restart on " . ip, "ADB.txt") + return true + } + } + + LogDebugToFile("[" . A_ScriptName . "] Waiting for ADB after instance restart on " . ip . ". Connection result: " . connectionResult, "ADB.txt") + } else { + LogDebugToFile("[" . A_ScriptName . "] Waiting for ADB port after instance restart.", "ADB.txt") + } + + if ((A_TickCount - startTick) > timeoutMs) { + LogToFile("[" . A_ScriptName . "] Failed to refresh ADB after instance restart within " . timeoutMs . "ms.", "ADB.txt") + return false + } + + Sleep, 2000 + } +} + DisableBackgroundServices() { global session @@ -382,14 +427,15 @@ waitadb(){ adbClick(X, Y) { static clickCommands := Object() - static convX := 540/283, convY := 960/488, offset := -40 - - key := X << 16 | Y + metrics := GetAdbClickMetrics() + key := X "|" Y "|" metrics.convX "|" metrics.convY "|" metrics.offset + physicalX := Round(X * metrics.convX) + physicalY := Round((Y + metrics.offset) * metrics.convY) if (!clickCommands.HasKey(key)) { clickCommands[key] := Format("input tap {} {}" - , Round(X * convX) - , Round((Y + offset) * convY)) + , physicalX + , physicalY) } adbWriteRaw(clickCommands[key]) } diff --git a/Scripts/Include/AccountManager.ahk b/Scripts/Include/AccountManager.ahk index 3995775f..1d305b62 100644 --- a/Scripts/Include/AccountManager.ahk +++ b/Scripts/Include/AccountManager.ahk @@ -138,6 +138,7 @@ loadAccount() { CreateStatusMessage(currentAccountInfo, "AccountInfo", 0, 46, false) SetTimer, DestoryAccountInfoUI, -15000 getMetaData() + PersistLoadedAccountForRecovery(loadFile) return loadFile } @@ -154,15 +155,19 @@ DestoryAccountInfoUI(){ ; MarkAccountAsUsed - Mark account as successfully used and remove from queue ;------------------------------------------------------------------------------- MarkAccountAsUsed() { - global session + global session, DeadCheck if (!session.get("currentLoadedAccountIndex") || !session.get("accountFileName")) { LogToFile("Warning: MarkAccountAsUsed called but no current account tracked") return } + if(DeadCheck = 1) + LogDebugToFile("MarkAccountAsUsed after cleanup start | account=" . session.get("accountFileName") . " | index=" . session.get("currentLoadedAccountIndex")) + saveDir := A_ScriptDir "\..\Accounts\Saved\" . session.get("scriptName") outputTxt := saveDir . "\list_current.txt" + foundByName := false ; Remove the account from list_current.txt if FileExist(outputTxt) { @@ -171,21 +176,91 @@ MarkAccountAsUsed() { newListContent := "" Loop, % fileLines.MaxIndex() { - if (A_Index != session.get("currentLoadedAccountIndex")) - newListContent .= fileLines[A_Index] "`r`n" + if (fileLines[A_Index] = session.get("accountFileName")) { + foundByName := true + continue + } + newListContent .= fileLines[A_Index] "`r`n" } - FileDelete, %outputTxt% - FileAppend, %newListContent%, %outputTxt% + if (!foundByName) { + newListContent := "" + Loop, % fileLines.MaxIndex() { + if (A_Index != session.get("currentLoadedAccountIndex")) + newListContent .= fileLines[A_Index] "`r`n" + } + } + + if (foundByName || session.get("currentLoadedAccountIndex")) { + FileDelete, %outputTxt% + FileAppend, %newListContent%, %outputTxt% + } } ; Track as used with timestamp TrackUsedAccount(session.get("accountFileName")) + ClearLoadedAccountRecovery() + + if(DeadCheck = 1) + LogDebugToFile("MarkAccountAsUsed after cleanup complete | account=" . session.get("accountFileName") . " | removedByName=" . foundByName) ; Reset tracking session.set("currentLoadedAccountIndex", 0) } +PersistLoadedAccountForRecovery(loadedAccountPath := "") { + global session + + if (loadedAccountPath = "") + loadedAccountPath := session.get("loadedAccount") + + IniWrite, %loadedAccountPath%, % session.get("scriptIniFile"), Recovery, loadedAccount + IniWrite, % session.get("accountFileName"), % session.get("scriptIniFile"), Recovery, accountFileName + IniWrite, % session.get("currentLoadedAccountIndex"), % session.get("scriptIniFile"), Recovery, currentLoadedAccountIndex + IniWrite, % session.get("loadDir"), % session.get("scriptIniFile"), Recovery, loadDir +} + +RestoreLoadedAccountForRecovery() { + global session + + IniRead, loadedAccount, % session.get("scriptIniFile"), Recovery, loadedAccount, + IniRead, accountFileName, % session.get("scriptIniFile"), Recovery, accountFileName, + IniRead, currentLoadedAccountIndex, % session.get("scriptIniFile"), Recovery, currentLoadedAccountIndex, 0 + IniRead, loadDir, % session.get("scriptIniFile"), Recovery, loadDir, + + if(loadedAccount != "") + session.set("loadedAccount", loadedAccount) + if(accountFileName != "") + session.set("accountFileName", accountFileName) + if(currentLoadedAccountIndex != "") + session.set("currentLoadedAccountIndex", currentLoadedAccountIndex) + if(loadDir != "") + session.set("loadDir", loadDir) + + return (accountFileName != "" && currentLoadedAccountIndex != 0) +} + +ClearLoadedAccountRecovery() { + global session + + IniDelete, % session.get("scriptIniFile"), Recovery +} + +SetFriendCleanupPending(reason := "") { + global session + + IniWrite, 1, % session.get("scriptIniFile"), UserSettings, friendCleanupPending + if(reason != "") + IniWrite, %reason%, % session.get("scriptIniFile"), Recovery, friendCleanupReason +} + +ClearFriendCleanupPending() { + global session + + IniWrite, 0, % session.get("scriptIniFile"), UserSettings, friendCleanupPending + IniDelete, % session.get("scriptIniFile"), Recovery, friendCleanupReason +} + ;------------------------------------------------------------------------------- ; saveAccount - Save current account from game to XML file ;------------------------------------------------------------------------------- @@ -386,6 +461,7 @@ UpdateAccount() { FileMove, % session.get("accountFile"), %accountNewFile% ;TODO enable FileSetTime,, %accountNewFile% session.set("accountFileName", AccountNewName) + PersistLoadedAccountForRecovery() } updateTotalTime() @@ -503,6 +579,7 @@ setMetaData() { accountNewFile := saveDir . "\" . AccountNewName FileMove, % session.get("accountFile"), %accountNewFile% session.set("accountFileName", AccountNewName) + PersistLoadedAccountForRecovery() } ;------------------------------------------------------------------------------- diff --git a/Scripts/Include/CardDetection.ahk b/Scripts/Include/CardDetection.ahk index b970fec8..cdd42d3e 100644 --- a/Scripts/Include/CardDetection.ahk +++ b/Scripts/Include/CardDetection.ahk @@ -29,7 +29,7 @@ DetectSixCardPack() { Path = %imagePath%6cardpackindicator.png if (FileExist(Path)) { pNeedle := GetNeedle(Path) - vRet := Gdip_ImageSearch_wbb(pBitmap, pNeedle, vPosXY, 228, 324, 248, 351, searchVariation) + vRet := Gdip_ImageSearchProfile_wbb(pBitmap, pNeedle, vPosXY, [228, 324, 248, 351], [228, 324, 248, 351], searchVariation) if (vRet = 1) { ; Found the check image, so this is a 5-card pack Gdip_DisposeImage(pBitmap) @@ -53,31 +53,70 @@ DetectFourCardPack() { return false } +GetCardLoadingBorderCoords(totalCardsInPack) { + return (GetConfiguredDisplayScale() = 125) + ? GetCardLoadingBorderCoords125(totalCardsInPack) + : GetCardLoadingBorderCoords100(totalCardsInPack) +} + +GetCardLoadingBorderCoords100(totalCardsInPack) { + if (totalCardsInPack = 4) { + return [[96, 279, 116, 281] + ,[181, 279, 201, 281] + ,[96, 394, 116, 396] + ,[181, 394, 201, 396]] + } + + if (totalCardsInPack = 6) { + return [[56, 279, 76, 281] + ,[139, 279, 159, 281] + ,[222, 279, 242, 281] + ,[56, 394, 76, 396] + ,[139, 394, 159, 396] + ,[222, 394, 242, 396]] + } + + return [[56, 279, 76, 281] + ,[139, 279, 159, 281] + ,[222, 279, 242, 281] + ,[96, 394, 116, 396] + ,[181, 394, 201, 396]] +} + +GetCardLoadingBorderCoords125(totalCardsInPack) { + if (totalCardsInPack = 4) { + return [[96, 284, 116, 286] + ,[181, 284, 201, 286] + ,[96, 399, 116, 401] + ,[181, 399, 201, 401]] + } + + if (totalCardsInPack = 6) { + return [[56, 284, 76, 286] + ,[139, 284, 159, 286] + ,[222, 284, 242, 286] + ,[56, 399, 76, 401] + ,[139, 399, 159, 401] + ,[222, 399, 242, 401]] + } + + return [[56, 284, 76, 286] + ,[139, 284, 159, 286] + ,[222, 284, 242, 286] + ,[96, 399, 116, 401] + ,[181, 399, 201, 401]] +} + +GetLoadingBoxBorderCoords() { + return GetScaleProfileValue([[121, 269, 154, 272], [121, 297, 154, 300]] + , [[121, 274, 154, 277], [121, 302, 154, 305]]) +} + CheckCardLoading(totalCardsInPack){ global session count := 0 - if (totalCardsInPack = 4) { - borderCoords := [[96, 279, 116, 281] ; Card 1 - ,[181, 279, 201, 281] ; Card 2 - ,[96, 394, 116, 396] ; Card 3 - ,[181, 394, 201, 396]] ; Card 4 - } else if (totalCardsInPack = 6) { - totalCardsInPack := 6 - borderCoords := [[56, 279, 76, 281] ; Top row card 1 - ,[139, 279, 159, 281] ; Top row card 2 - ,[222, 279, 242, 281] ; Top row card 3 - ,[56, 394, 76, 396] ; Bottom row card 1 - ,[139, 394, 159, 396] ; Bottom row card 2 - ,[222, 394, 242, 396]] ; Bottom row card 3 - } else { - ; 5-card pack - borderCoords := [[56, 279, 76, 281] ; Card 1 - ,[139, 279, 159, 281] ; Card 2 - ,[222, 279, 242, 281] ; Card 3 - ,[96, 394, 116, 396] ; Card 4 - ,[181, 394, 201, 396]] ; Card 5 - } + borderCoords := GetCardLoadingBorderCoords(totalCardsInPack) pBitmap := from_window(getMuMuHwnd(session.get("winTitle"))) for index, value in borderCoords { @@ -105,7 +144,7 @@ AnalysisBorder(totalCardsInPack) { global session, isDevelopment, rarityCheckers currentPackInfo := {"isVerified": false, "CardSlot": [], "TypeCount": {}} - loadingBorderCoords := [[121, 269, 154, 272], [121, 297, 154, 300]] + loadingBorderCoords := GetLoadingBoxBorderCoords() pBitmap := 0 Loop, { pBitmap := from_window(getMuMuHwnd(session.get("winTitle"))) @@ -314,6 +353,11 @@ GodPackFound(validity) { IniWrite, 0, % session.get("scriptIniFile"), UserSettings, DeadCheck if(validity = "Valid") { + ; A valid GP must keep friend requests even if a previous stuck recovery flag survived. + DeadCheck := 0 + ClearFriendCleanupPending() + session.set("friended", false) + LogToFile("Valid God Pack found; friend cleanup state cleared before notification | account=" . session.get("accountFileName")) Praise := ["Congrats!", "Congratulations!", "GG!", "Whoa!", "Praise Helix!", "Way to go!", "You did it!", "Awesome!", "Nice!", "Cool!", "You deserve it!", "Keep going!", "This one has to be live!", "No duds, no duds, no duds!", "Fantastic!", "Bravo!", "Excellent work!", "Impressive!", "You're amazing!", "Well done!", "You're crushing it!", "Keep up the great work!", "You're unstoppable!", "Exceptional!", "You nailed it!", "Hats off to you!", "Sweet!", "Kudos!", "Phenomenal!", "Boom! Nailed it!", "Marvelous!", "Outstanding!", "Legendary!", "Youre a rock star!", "Unbelievable!", "Keep shining!", "Way to crush it!", "You're on fire!", "Killing it!", "Top-notch!", "Superb!", "Epic!", "Cheers to you!", "Thats the spirit!", "Magnificent!", "Youre a natural!", "Gold star for you!", "You crushed it!", "Incredible!", "Shazam!", "You're a genius!", "Top-tier effort!", "This is your moment!", "Powerful stuff!", "Wicked awesome!", "Props to you!", "Big win!", "Yesss!", "Champion vibes!", "Spectacular!"] invalid := "" } else { diff --git a/Scripts/Include/Config.ahk b/Scripts/Include/Config.ahk index ee2b5438..c950d61d 100644 --- a/Scripts/Include/Config.ahk +++ b/Scripts/Include/Config.ahk @@ -51,10 +51,12 @@ , "slowMotion": 0 , "claimSpecialMissions": 0 , "SelectedMonitorIndex": 1 + , "DisplayScale": "Auto" , "instanceLaunchDelay": 5 , "folderPath": "C:\Program Files\Netease" , "RowGap": 105 , "debugMode": 0 + , "blockedFriendRequestHotfix": 0 , "stopPreference": "" , "stopPreferenceSingle": "" , "stopPreferenceMain": "" @@ -210,4 +212,4 @@ } } } -} \ No newline at end of file +} diff --git a/Scripts/Include/Coords.ahk b/Scripts/Include/Coords.ahk index bb514426..29db6dda 100644 --- a/Scripts/Include/Coords.ahk +++ b/Scripts/Include/Coords.ahk @@ -22,12 +22,15 @@ class Needle{ needleName := "" imageName := "" coords := "" + coords100 := "" + scale125Coords := "" __New(needleName, imageName, coords) { this.needleName := needleName this.imageName := imageName this.coords := coords + this.coords100 := coords } } @@ -40,7 +43,21 @@ class NeedlesDict{ } Get(needleName){ - return this.needles[needleName] + needleObj := this.needles[needleName] + + if (GetConfiguredDisplayScale() = 125 && needleObj.scale125Coords) + needleObj.coords := needleObj.scale125Coords + else + needleObj.coords := needleObj.coords100 + + return needleObj + } + + SetScale125(needleName, coords){ + if (!this.needles.HasKey(needleName)) + return + + this.needles[needleName].scale125Coords := coords } } @@ -53,6 +70,7 @@ needlesDict.Add(new Needle("Friend_AddButtonInFriendList", "Add", new Coordinate needlesDict.Add(new Needle("Friend_FriendListSubmenu", "Friends", new Coordinate(84, 457, 100, 469))) needlesDict.Add(new Needle("Friend_FriendRequestsSubMenu", "requests", new Coordinate(97, 447, 104, 471))) needlesDict.Add(new Needle("Friend_BottomDarkHomeIcon", "Home", new Coordinate(28, 504, 42, 518))) +needlesDict.Add(new Needle("Friend_SocialHubFriendButton", "Friend2", new Coordinate(20, 440, 70, 500))) needlesDict.Add(new Needle("Friend_ActivatedClearAllButton", "clearAll", new Coordinate(191, 493, 200, 509))) needlesDict.Add(new Needle("Friend_FriendListEmpty", "empty", new Coordinate(42, 163, 66, 185))) needlesDict.Add(new Needle("99ko", "99ko", new Coordinate(63, 106, 102, 120))) @@ -87,6 +105,7 @@ needlesDict.Add(new Needle("Friend_DenyButtonInApproveSubmenu", "DeleteFriend", needlesDict.Add(new Needle("Friend_RequestAlreadyClosedInApproveSubmenu", "RequestAlreadyClosed", new Coordinate(3, 330, 70, 345))) needlesDict.Add(new Needle("Friend_DisabledDenyAllRequestButtonInApproveSubmenu", "Accept", new Coordinate(190, 495, 202, 507))) needlesDict.Add(new Needle("Friend_BlankFriendSlotAreaInApproveSubmenu", "Approve", new Coordinate(177, 450, 190, 468))) +needlesDict.Add(new Needle("FriendLimit", "FriendLimit", new Coordinate(221, 267, 228, 272))) ;============================================================================================================================== @@ -188,6 +207,7 @@ needlesDict.Add(new Needle("Mission_MissionIconTopAreaInDetails", "Mission_dino2 needlesDict.Add(new Needle("Mission_GoToDexButtonIcon", "DexMissions", new Coordinate(18, 210, 30, 222))) needlesDict.Add(new Needle("Mission_DailyMissionImage", "DailyMissions", new Coordinate(204, 190, 223, 197))) needlesDict.Add(new Needle("Mission_CompleteGotAllClaims", "GotAllMissions", new Coordinate(257, 417, 271, 428))) +needlesDict.Add(new Needle("MissionDeck", "MissionDeck", new Coordinate(158, 104, 170, 117))) ;============================================================================================================================== @@ -240,4 +260,146 @@ needlesDict.Add(new Needle("GPTest_FriendRequestButtonInUserDetails", "Favourite ;needlesDict.Add(new Needle("CountrySelect2", ) ; Unknown -;Proceed \ No newline at end of file +;Proceed + +;============================================================================================================================== +; Scale 125 coordinate overrides from the last Scale 125 release (v9.5.9). +; Default coordinates above remain the Scale 100 profile. + +needlesDict.SetScale125("Create_SoloBattleMissionIconInDetail", new Coordinate(108, 180, 177, 208)) +needlesDict.SetScale125("Friend_DisabledDenyAllRequestButtonInApproveSubmenu", new Coordinate(186, 496, 206, 518)) +needlesDict.SetScale125("Menu_SettingButtonInMenu", new Coordinate(24, 158, 57, 189)) +needlesDict.SetScale125("Menu_RemoveAccountNintendoButtonInMenu", new Coordinate(56, 435, 108, 460)) +needlesDict.SetScale125("Friend_AddButtonInFriendList", new Coordinate(226, 100, 270, 135)) +needlesDict.SetScale125("Friend_SearchFriendButton", new Coordinate(10, 433, 45, 460)) +needlesDict.SetScale125("Friend_SearchFriendWindowCancelButtonCorner", new Coordinate(0, 375, 70, 430)) +needlesDict.SetScale125("Friend_BlankFriendSlotAreaInApproveSubmenu", new Coordinate(170, 450, 195, 480)) +needlesDict.SetScale125("Create_BirthConfirmCancelButton", new Coordinate(116, 352, 138, 389)) +needlesDict.SetScale125("Common_UnknownButton2", new Coordinate(75, 340, 195, 530)) +needlesDict.SetScale125("Common_ColorChangeButton", new Coordinate(100, 367, 190, 480)) +needlesDict.SetScale125("WonderPick_SelectCards", new Coordinate(160, 330, 200, 370)) +needlesDict.SetScale125("Create_CinematicBackground", new Coordinate(0, 46, 20, 70)) +needlesDict.SetScale125("Common_AlertForAppCrachDuringOpenPack", new Coordinate(241, 377, 269, 407)) +needlesDict.SetScale125("Create_DownloadComplete", new Coordinate(215, 371, 264, 418)) +needlesDict.SetScale125("Create_DownloadAlertWindow", new Coordinate(110, 350, 150, 404)) +needlesDict.SetScale125("Pack_BackButtonInSelectPackScreen", new Coordinate(121, 465, 140, 485)) +needlesDict.SetScale125("Create_CountryComboBoxButton", new Coordinate(105, 396, 121, 406)) +needlesDict.SetScale125("Mission_DailyMissionImage", new Coordinate(204, 195, 223, 202)) +needlesDict.SetScale125("Mission_GoToDexButtonIcon", new Coordinate(18, 215, 30, 227)) +needlesDict.SetScale125("MissionDeck", new Coordinate(150, 96, 180, 130)) +needlesDict.SetScale125("GPTest_FriendRequestButtonInUserDetails", new Coordinate(84, 397, 98, 410)) +needlesDict.SetScale125("GPTest_NotFavouriteInDetails", new Coordinate(245, 73, 260, 89)) +needlesDict.SetScale125("GPTest_FavouritedInDetails", new Coordinate(244, 73, 262, 88)) +needlesDict.SetScale125("Mission_FirstWonderpickMissionIconInDetails", new Coordinate(120, 185, 150, 215)) +needlesDict.SetScale125("Mission_CompleteGotAllClaims", new Coordinate(244, 406, 273, 449)) +needlesDict.SetScale125("Create_MustClickMissionBackground", new Coordinate(46, 368, 103, 411)) +needlesDict.SetScale125("Friend_BottomDarkHomeIcon", new Coordinate(20, 500, 55, 530)) +needlesDict.SetScale125("Create_TutorialUseResourceForOpenPack", new Coordinate(178, 193, 251, 282)) +needlesDict.SetScale125("Create_TutorialPremiumPass", new Coordinate(98, 184, 151, 224)) +needlesDict.SetScale125("Create_InfoIconInStandByOpenPack", new Coordinate(236, 198, 266, 226)) +needlesDict.SetScale125("Pack_HourglassImageAfterOpenPackClick", new Coordinate(60, 440, 90, 480)) +needlesDict.SetScale125("Create_NintendoLink", new Coordinate(51, 335, 107, 359)) +needlesDict.SetScale125("Create_FullFreepackInMainCenter", new Coordinate(120, 316, 143, 335)) +needlesDict.SetScale125("Menu_AgreementIconInIntroMenu", new Coordinate(20, 120, 50, 150)) +needlesDict.SetScale125("Create_ConfirmDexMissionComplete", new Coordinate(115, 255, 176, 308)) +needlesDict.SetScale125("Mission_ThemeCollectionButtonIcon", new Coordinate(180, 498, 190, 508)) +needlesDict.SetScale125("Mission_MissionIconTopAreaInDetails", new Coordinate(136, 158, 156, 190)) +needlesDict.SetScale125("Mission_ActivatedBeginnerMissionTabButton", new Coordinate(15, 456, 18, 473)) +needlesDict.SetScale125("Create_SelectedMonth", new Coordinate(100, 386, 138, 416)) +needlesDict.SetScale125("Create_NameInputIcon", new Coordinate(190, 241, 225, 270)) +needlesDict.SetScale125("Pack_NextButtonAfterOpenPack", new Coordinate(120, 70, 150, 100)) +needlesDict.SetScale125("Next2", new Coordinate(120, 70, 150, 100)) +needlesDict.SetScale125("Pack_NotEnoughItemsForOpenPack", new Coordinate(92, 299, 115, 317)) +needlesDict.SetScale125("Create_TutorialPackOpenNotifyIcon", new Coordinate(170, 160, 220, 200)) +needlesDict.SetScale125("WonderPick_NoEnergy", new Coordinate(37, 424, 57, 446)) +needlesDict.SetScale125("WonderPick_EnergyStatusAfterSelect", new Coordinate(20, 440, 45, 485)) +needlesDict.SetScale125("Create_DeactivatedOKButton", new Coordinate(0, 476, 40, 502)) +needlesDict.SetScale125("Friend_FriendIDInputReady", new Coordinate(0, 475, 25, 495)) +needlesDict.SetScale125("Common_SpeedMod1x", new Coordinate(20, 170, 24, 174)) +needlesDict.SetScale125("Pack_ResultAfterOpenPack", new Coordinate(170, 98, 270, 125)) +needlesDict.SetScale125("Pack_ReadyForOpenPack", new Coordinate(198, 273, 207, 287)) +needlesDict.SetScale125("Friend_AcceptButtonInApproveSubmenu", new Coordinate(225, 195, 250, 215)) +needlesDict.SetScale125("FriendLimit", new Coordinate(215, 260, 235, 280)) +needlesDict.SetScale125("GPTest_ReqeustCancelButtonInSearchResult", new Coordinate(188, 243, 221, 274)) +needlesDict.SetScale125("Create_TitleBottomBorderInWPSelectCard", new Coordinate(60, 130, 202, 142)) +needlesDict.SetScale125("Pack_PackPointButton", new Coordinate(233, 400, 264, 428)) +needlesDict.SetScale125("Create_TutorialDexMission", new Coordinate(115, 97, 174, 150)) +needlesDict.SetScale125("Pack_PokeGoldImageAfterOpenPackClick", new Coordinate(60, 440, 90, 480)) +needlesDict.SetScale125("Common_PopupXButtonInMain", new Coordinate(129, 477, 156, 494)) +needlesDict.SetScale125("Profile_EditNameButtonIcon", new Coordinate(203, 272, 237, 300)) +needlesDict.SetScale125("Create_TutorialDexMissionComplete", new Coordinate(124, 168, 162, 207)) +needlesDict.SetScale125("Friend_RemoveConfirmButtonInFriendDetails", new Coordinate(135, 355, 160, 385)) +needlesDict.SetScale125("Friend_RemoveConfirmButtonInSearchResult", new Coordinate(135, 355, 160, 385)) +needlesDict.SetScale125("Create_PackReturnButtonIcon", new Coordinate(121, 490, 161, 520)) +needlesDict.SetScale125("Create_BeginNewAccountButton", new Coordinate(30, 336, 53, 370)) +needlesDict.SetScale125("Pack_ScrollInSelectExpansion", new Coordinate(115, 140, 160, 155)) +needlesDict.SetScale125("Friend_RequestButtonInSearchResult", new Coordinate(165, 245, 190, 270)) +needlesDict.SetScale125("Friend_ReqeustButtonInFriendDetails", new Coordinate(70, 395, 100, 420)) +needlesDict.SetScale125("Menu_InventoryIconInMenu", new Coordinate(90, 260, 126, 290)) +; Group reroll rate-limit recovery opens the menu and returns to title. +; Keep managed needle names shared; legacy Scale125 images are only used by +; ResolveNeedlePath() for documented pixel-sensitive fallback exceptions. +needlesDict.SetScale125("Menu_GoToTitleButton_Up", new Coordinate(20, 418, 55, 447)) +needlesDict.SetScale125("Menu_GoToTitleButton_Down", new Coordinate(20, 458, 60, 488)) +needlesDict.SetScale125("Menu_MiscMenuLeftTop", new Coordinate(0, 65, 45, 105)) +needlesDict.SetScale125("Common_ShopButtonInMain", new Coordinate(191, 393, 211, 411)) +needlesDict.SetScale125("Common_CloseAlertWindowInMain", new Coordinate(0, 350, 70, 430)) +needlesDict.SetScale125("Common_ActivatedHomeInMainMenu", new Coordinate(20, 490, 60, 530)) +needlesDict.SetScale125("Pack_ActivatedBSeriesTab", new Coordinate(15, 450, 130, 482)) +needlesDict.SetScale125("Pack_SkipButtonAfterOpenPack", new Coordinate(233, 486, 272, 519)) +needlesDict.SetScale125("Pack_AnimationToReadyOpenPack", new Coordinate(233, 486, 272, 519)) +needlesDict.SetScale125("Common_ActivatedSocialInMainMenu", new Coordinate(120, 500, 155, 530)) +needlesDict.SetScale125("Common_SpeedModMenuButton", new Coordinate(158, 252, 177, 259)) +needlesDict.SetScale125("Create_SwipeForRegisterDexIcon", new Coordinate(34, 99, 74, 131)) +needlesDict.SetScale125("Create_ConfirmRegisteredCard", new Coordinate(133, 72, 141, 78)) +needlesDict.SetScale125("Common_SpeedMod3x", new Coordinate(187, 168, 191, 174)) +needlesDict.SetScale125("Create_TosCloseButton", new Coordinate(129, 477, 156, 494)) +needlesDict.SetScale125("Create_TosOpenButton", new Coordinate(210, 285, 250, 315)) +needlesDict.SetScale125("Common_SpeedMod2x", new Coordinate(102, 170, 107, 174)) +needlesDict.SetScale125("Create_WelcomePopup", new Coordinate(110, 230, 182, 257)) +needlesDict.SetScale125("Create_UnlockedWonerPickIconInLevelUp", new Coordinate(53, 281, 86, 310)) +needlesDict.SetScale125("Create_CardImageInTutorialWPFirstScreen", new Coordinate(75, 156, 83, 167)) +needlesDict.SetScale125("Create_WPItemBottomBorder", new Coordinate(114, 430, 155, 441)) +needlesDict.SetScale125("Create_SelectedWPItem", new Coordinate(155, 281, 192, 315)) +needlesDict.SetScale125("WonderPick_WonderPickButtonInHome", new Coordinate(240, 80, 265, 100)) +needlesDict.SetScale125("Create_SelectedYear", new Coordinate(148, 384, 256, 419)) + +; Additional Scale 125 overrides audited from v9.5.9 raw image-search calls. +needlesDict.SetScale125("Friend_FriendListSubmenu", new Coordinate(84, 463, 100, 475)) +needlesDict.SetScale125("Friend_FriendRequestsSubMenu", new Coordinate(97, 452, 104, 476)) +needlesDict.SetScale125("Friend_SocialHubFriendButton", new Coordinate(20, 450, 70, 500)) +needlesDict.SetScale125("Friend_ActivatedClearAllButton", new Coordinate(191, 498, 207, 514)) +needlesDict.SetScale125("Friend_FriendListEmpty", new Coordinate(42, 163, 66, 185)) +needlesDict.SetScale125("Friend_InputFormBlank", new Coordinate(15, 500, 68, 520)) +needlesDict.SetScale125("Friend_WithdrawButton", new Coordinate(165, 240, 255, 270)) +needlesDict.SetScale125("Friend_AcceptedButtonInSearchResult", new Coordinate(165, 250, 190, 275)) +needlesDict.SetScale125("Friend_AcceptedButtonInFriendDetails", new Coordinate(87, 401, 99, 412)) +needlesDict.SetScale125("Friend_DenyButtonInApproveSubmenu", new Coordinate(196, 196, 210, 209)) +needlesDict.SetScale125("Friend_FriendIDSearchWindow", new Coordinate(215, 252, 240, 277)) +needlesDict.SetScale125("Friend_ShowcaseIDInputFormBlank", new Coordinate(157, 498, 225, 522)) +needlesDict.SetScale125("Friend_CompleteClickShowcaseLike", new Coordinate(98, 187, 125, 214)) +needlesDict.SetScale125("Friend_CommunityShowcaseMain", new Coordinate(174, 464, 189, 479)) +needlesDict.SetScale125("Common_Error", new Coordinate(100, 180, 170, 230)) +needlesDict.SetScale125("Common_LevelUpBackground", new Coordinate(100, 86, 167, 116)) +needlesDict.SetScale125("StartupErrorX", new Coordinate(124, 423, 155, 455)) +needlesDict.SetScale125("Profile_UserNameArrowInSettingMenu", new Coordinate(230, 120, 260, 150)) +needlesDict.SetScale125("Profile_ShinedustIconInTrophyDetails", new Coordinate(122, 375, 161, 390)) +needlesDict.SetScale125("Shinedust_CopySupportIDButtonInSettings", new Coordinate(252, 78, 263, 92)) +needlesDict.SetScale125("Shinedust_ShinedustInInventorys", new Coordinate(26, 188, 43, 204)) +needlesDict.SetScale125("Shinedust_CloseButtonInDetailWindow", new Coordinate(133, 369, 148, 385)) +needlesDict.SetScale125("Menu_DeleteConfimButtonStep1", new Coordinate(200, 340, 250, 530)) +needlesDict.SetScale125("Pack_HourglassAndPokeGoldImageAfterOpenPackClick", new Coordinate(49, 449, 70, 474)) +needlesDict.SetScale125("Pack_PackImageBlankAreaForLunala", new Coordinate(58, 303, 74, 319)) +needlesDict.SetScale125("Mission_PremiumLockImage", new Coordinate(225, 444, 272, 470)) +needlesDict.SetScale125("GPTest_FriendedInSearcResult", new Coordinate(165, 250, 190, 275)) +needlesDict.SetScale125("GPTest_AccountNotFound", new Coordinate(211, 320, 245, 344)) + +; Scale 125 audit remains for these needles because v9.5.9 has no direct +; equivalent, or the current image name did not exist in the old asset set: +; 99ko, 99en, Common_Error_Cache, Common_Error_NoResponse, +; Common_Error_NoResponseDark, Common_Error_NoBackground_1Button, +; Common_Error_3ButtonError_Nodata, Friend_CannotFriendRequest, +; Friend_HamburgerMenuButtonInIntro, Friend_RequestAlreadyClosedInApproveSubmenu, +; Gift_ClaimAllButton, Gift_ReceivedWindowRightBorder, +; Pack_GetItemDialogAfterOpenPack, +; Profile_TrophyStandIconInProfile, CountrySelect, CountrySelect2. diff --git a/Scripts/Include/Crinity_UnofficialPatch.ahk b/Scripts/Include/Crinity_UnofficialPatch.ahk index 299c06f3..765f6cc4 100644 --- a/Scripts/Include/Crinity_UnofficialPatch.ahk +++ b/Scripts/Include/Crinity_UnofficialPatch.ahk @@ -106,21 +106,43 @@ startPreProcess(methodType){ pBitmap := 0 session.set("isSkipSelectExpansion", 0) isSkip := false - session.set("failSafe", A_TickCount) failSafeTime := 0 Loop, { + skipGenericButtonFallback := false + + if(methodType = "Inject Wonderpick 96P+" && DismissFriendFlowBlockingPopup("Entering Social")) + continue + if(FindOrLoseImage(needleName, 0, failSafeTime, , true)) break adbClick_wbb(clickX, clickY) Delay(0.5) + if(methodType = "Inject Wonderpick 96P+"){ + if(FindOrLoseImage(needleName, 0, , , true)) + break + + if(FindOrLoseImage("Common_ActivatedHomeInMainMenu", 0, , , true) + || FindOrLoseImage("Friend_BottomDarkHomeIcon", 0, , , true) + || FindOrLoseImage("Common_ShopButtonInMain", 0, , , true) + || FindOrLoseImage("WonderPick_WonderPickButtonInHome", 0, , , true) + || FindOrLoseImage("Pack_PackPointButton", 0, , , true) + || FindOrLoseImage("Pack_BackButtonInSelectPackScreen", 0, , , true) + || FindOrLoseImage("Pack_ReadyForOpenPack", 0, , , true) + || FindOrLoseImage("Pack_HourglassImageAfterOpenPackClick", 0, , , true) + || FindOrLoseImage("Pack_HourglassAndPokeGoldImageAfterOpenPackClick", 0, , , true) + || FindOrLoseImage("Pack_PokeGoldImageAfterOpenPackClick", 0, , , true)){ + skipGenericButtonFallback := true + } + } + pBitmap := from_window(getMuMuHwnd(session.get("winTitle"))) Path = %imagePath%CrashWhilePackOpen.png pNeedle := GetNeedle(Path) - vRet := Gdip_ImageSearch_wbb(pBitmap, pNeedle, vPosXY, 20, 180, 35, 182, searchVariation) + vRet := Gdip_ImageSearchProfile_wbb(pBitmap, pNeedle, vPosXY, [20, 180, 35, 182], [20, 180, 35, 182], searchVariation) if(vRet = 1){ CreateStatusMessage("Clearing problem opening pack pop-up",,,, false) adbClick_wbb(145, 370) @@ -164,7 +186,7 @@ startPreProcess(methodType){ Path = %imagePath%DataDownload.png pNeedle := GetNeedle(Path) - vRet := Gdip_ImageSearch_wbb(pBitmap, pNeedle, vPosXY, 41, 378, 92, 393, searchVariation) + vRet := Gdip_ImageSearchProfile_wbb(pBitmap, pNeedle, vPosXY, [41, 378, 92, 393], [41, 378, 92, 393], searchVariation) if(vRet = 1){ CreateStatusMessage("Downloading data",,,, false) Sleep, 1000 @@ -177,13 +199,16 @@ startPreProcess(methodType){ Path = %imagePath%Button.png pNeedle := GetNeedle(Path) - vRet := Gdip_ImageSearch_wbb(pBitmap, pNeedle, vPosXY, 95, 350, 195, 530, 80) - if(vRet = 1){ - if (InStr(vPosXY, ",")) { - StringSplit, pos, vPosXY, `, - adbClick_wbb(pos1, pos2) - } else - adbClick(137, 365) + if(!skipGenericButtonFallback){ + vRet := Gdip_ImageSearchProfile_wbb(pBitmap, pNeedle, vPosXY, [95, 350, 195, 530], [100, 367, 190, 480], 80) + if(vRet = 1){ + if (InStr(vPosXY, ",")) { + StringSplit, pos, vPosXY, `, + adbClick_wbb(pos1, pos2) + } else { + adbClick(137, 365) + } + } } DelayH(20) @@ -244,4 +269,4 @@ getDevelopmentScreenShot(packCardType, pBitmap := 0){ pBitmap := from_window(getMuMuHwnd(session.get("winTitle"))) Gdip_SaveBitmapToFile(pBitmap, filePath) -} \ No newline at end of file +} diff --git a/Scripts/Include/FriendManager.ahk b/Scripts/Include/FriendManager.ahk index f3048d6a..b408bc07 100644 --- a/Scripts/Include/FriendManager.ahk +++ b/Scripts/Include/FriendManager.ahk @@ -36,20 +36,27 @@ AddFriends(renew := false, getFC := false) { return false session.set("friended", true) + if(!getFC) + SetFriendCleanupPending("AddFriends started") session.set("failSafe", A_TickCount) failSafeTime := 0 Loop { + if(DismissFriendFlowBlockingPopup("Waiting for Social")) + continue + adbClick_wbb(143, 518) if(FindOrLoseImage("Common_ActivatedSocialInMainMenu", 0, failSafeTime)) { break } else if(!renew && !getFC) { Delay(3) - clickButton := FindOrLoseImage("Common_ColorChangeButton", 0, , 80) - if(clickButton) { - StringSplit, pos, clickButton, `, ; Split at ", " - adbClick_wbb(pos1, pos2) + if(!ShouldSkipGenericButtonInSocialWait()) { + clickButton := FindOrLoseImage("Common_ColorChangeButton", 0, , 80) + if(clickButton) { + StringSplit, pos, clickButton, `, ; Split at ", " + adbClick_wbb(pos1, pos2) + } } } else if(FindOrLoseImage("Create_TutorialUseResourceForOpenPack", 0)) { @@ -130,13 +137,14 @@ AddFriends(renew := false, getFC := false) { } session.set("failSafe", A_TickCount) failSafeTime := 0 + skipCurrentID := false Loop { isContinue := false isSendReqeest := false - Delay(1) - adbInput(value) - Delay(1) - adbClick_wbb(187, 365) + if(!SubmitFriendIDSearch(value, friendIDIdx, n)) { + skipCurrentID := true + break + } Delay(1) if(FindOrLoseImage("Friend_RequestButtonInSearchResult", 0, failSafeTime, 80)) { adbClick_wbb(243, 258) @@ -145,21 +153,30 @@ AddFriends(renew := false, getFC := false) { waitSendResult := A_TickCount interceptProc := true Loop{ - if(!isSendReqeest && FindOrLoseImage("Friend_RequestButtonInSearchResult", 0, failSafeTime) && (A_TickCount - waitSendResult) > 1000){ - adbClick_wbb(243, 258) - isSendReqeest := true - } Delay(0.25) if(FindOrLoseImage("Friend_WithdrawButton", 0, failSafeTime)) break else if(FindOrLoseImage("Friend_AcceptedButtonInSearchResult", 0, failSafeTime)) break else if(interceptErrorCheck("ADD")){ - isContinue := true + skipCurrentID := true + LogToFile("Skipping friend ID after ADD error | index=" . friendIDIdx) break } else if(FindOrLoseImage("Friend_CannotFriendRequest", 0, failSafeTime)) break + else if(FindOrLoseImage("FriendLimit", 0, failSafeTime)) { + LogToFile("Skipping friend ID because friend request limit/full state was detected | index=" . friendIDIdx) + break + } + if(!isSendReqeest + && (A_TickCount - waitSendResult) > 2500 + && FindOrLoseImage("Friend_RequestButtonInSearchResult", 0, failSafeTime, 40, true) + && !FindOrLoseImage("Friend_WithdrawButton", 0, failSafeTime, , true) + && !FindOrLoseImage("Friend_AcceptedButtonInSearchResult", 0, failSafeTime, , true)) { + adbClick_wbb(243, 258) + isSendReqeest := true + } if ((A_TickCount - waitSendResult) > 10000) break } @@ -168,6 +185,17 @@ AddFriends(renew := false, getFC := false) { } else if(FindOrLoseImage("Friend_WithdrawButton", 0, failSafeTime)) break + else if(FindOrLoseImage("Friend_CannotFriendRequest", 0, failSafeTime)) + break + else if(FindOrLoseImage("FriendLimit", 0, failSafeTime)) { + LogToFile("Skipping friend ID because friend request limit/full state was detected | index=" . friendIDIdx) + break + } + else if(interceptErrorCheck("ADD")) { + skipCurrentID := true + LogToFile("Skipping friend ID after ADD error | index=" . friendIDIdx) + break + } else if(FindOrLoseImage("Friend_AcceptedButtonInSearchResult", 0, failSafeTime)) { if(renew){ FindImageAndClick("Friend_RemoveConfirmButtonInSearchResult", 193, 258) @@ -186,6 +214,9 @@ AddFriends(renew := false, getFC := false) { CreateStatusMessage("Processing add friends for `n(" . failSafeTime . "/45 seconds)") } + if(skipCurrentID) + LogDebugToFile("Skipped friend ID during AddFriends | index=" . friendIDIdx) + if(isContinue) continue @@ -209,9 +240,38 @@ AddFriends(renew := false, getFC := false) { } ; ratelimit, only use this route when number of added ids is 6-10, 16-20, etc - if (Mod(n - 1, 10) >= 5) { - FindImageAndClick("Menu_InventoryIconInMenu", 240, 494) - FindImageAndClick("Menu_MiscMenuLeftTop", 105, 435, , 750) + rateLimitMod := Mod(n - 1, 10) + if (rateLimitMod >= 5) { + menuClickX := GetScaleProfileValue(240, 245) + menuClickY := GetScaleProfileValue(494, 520) + menuOpenSleepTime := GetScaleProfileValue(botConfig.get("Delay"), 1000) + inventoryIconPos := FindImageAndClick("Menu_InventoryIconInMenu", menuClickX, menuClickY, , menuOpenSleepTime) + menuSettleDelay := GetScaleProfileValue(0, 1) + if(menuSettleDelay > 0) + Delay(menuSettleDelay) + + if(!inventoryIconPos) { + restartGameInstance("Stuck at InSubMenu...") + return false + } + + StringSplit, inventoryIconCoord, inventoryIconPos, `, + miscClickX := inventoryIconCoord1 + GetScaleProfileValue(8, 7) + miscClickY := inventoryIconCoord2 + GetScaleProfileValue(170, 167) + ; Anchor the Misc tap to the visible inventory icon so 125-scale menu drift cannot hit Trade. + adbClick_wbb(miscClickX, miscClickY) + miscWaitStart := A_TickCount + Loop { + if(FindOrLoseImage("Menu_GoToTitleButton_Up", 0, , 60, true) + || FindOrLoseImage("Menu_GoToTitleButton_Down", 0, , 60, true)) + break + + if((A_TickCount - miscWaitStart) > 5000) { + restartGameInstance("Stuck at InSubMenu...") + return false + } + Delay(0.25) + } DelayH(600) clickX := 137 @@ -256,8 +316,13 @@ AddFriends(renew := false, getFC := false) { RemoveFriends() { global botConfig, session, interceptProc, DeadCheck + cleanupAccount := session.get("accountFileName") + LogToFile("RemoveFriends start | account=" . cleanupAccount) + LogDebugToFile("RemoveFriends start detail | account=" . cleanupAccount . " | friended=" . session.get("friended") . " | DeadCheck=" . DeadCheck . " | deleteMethod=" . botConfig.get("deleteMethod") . " | useSoloIdsFile=" . botConfig.get("useSoloIdsFile")) + ; Only allow RemoveFriends in Inject Wonderpick 96P+ mode if (botConfig.get("deleteMethod") != "Inject Wonderpick 96P+" && !botConfig.get("useSoloIdsFile")) { + LogToFile("RemoveFriends skipped: unsupported delete method | account=" . cleanupAccount . " | deleteMethod=" . botConfig.get("deleteMethod") . " | useSoloIdsFile=" . botConfig.get("useSoloIdsFile")) session.set("friended", false) return false } @@ -265,17 +330,27 @@ RemoveFriends() { session.set("friendIDs", ReadFile("ids")) if(!session.get("friendIDs") && botConfig.get("FriendID") = "") { - session.set("friended", false) - return false + if(!session.get("friended") && DeadCheck != 1) { + LogToFile("RemoveFriends skipped: no friend IDs and no cleanup pending | account=" . cleanupAccount . " | DeadCheck=" . DeadCheck) + session.set("friended", false) + return false + } + + LogToFile("Friend IDs unavailable during RemoveFriends; continuing because cleanup is pending | account=" . cleanupAccount . " | DeadCheck=" . DeadCheck) + LogToFile("Friend IDs unavailable during RemoveFriends; continuing because cleanup is pending | account=" . cleanupAccount . " | DeadCheck=" . DeadCheck, "GroupReroll.txt") } session.set("packsInPool", 0) ; if friends are removed, clear the pool CreateStatusMessage("Starting friend removal process...",,,, false) + LogDebugToFile("RemoveFriends navigation start | account=" . cleanupAccount) session.set("failSafe", A_TickCount) failSafeTime := 0 Loop { + if(DismissFriendFlowBlockingPopup("Waiting for Social")) + continue + adbClick_wbb(143, 518) if(FindOrLoseImage("Common_ActivatedSocialInMainMenu", 0, failSafeTime)) break @@ -293,12 +368,14 @@ RemoveFriends() { adbClick_wbb(203, 436) ; 203 436 } else if(!renew && !getFC && DeadCheck = 1) { - clickButton := FindOrLoseImage("Common_ColorChangeButton", 0, , 80) - if(clickButton) { - StringSplit, pos, clickButton, `, ; Split at ", " - adbClick_wbb(pos1, pos2) + if(!ShouldSkipGenericButtonInSocialWait()) { + clickButton := FindOrLoseImage("Common_ColorChangeButton", 0, , 80) + if(clickButton) { + StringSplit, pos, clickButton, `, ; Split at ", " + adbClick_wbb(pos1, pos2) } } + } Sleep, 500 failSafeTime := (A_TickCount - session.get("failSafe")) // 1000 CreateStatusMessage("Waiting for Social`n(" . failSafeTime . "/90 seconds)") @@ -306,6 +383,7 @@ RemoveFriends() { GoToFriendsList(false, true) Delay(2) + LogDebugToFile("RemoveFriends friend list reached | account=" . cleanupAccount) FindImageAndClick("Friend_FriendRequestsSubMenu", 167, 467, , 10) Delay(2) adbClick(167, 472) ; extra click since failing to get into requests sometimes @@ -313,6 +391,9 @@ RemoveFriends() { failSafeTime := 0 interceptProc := true Loop{ + if(DismissFriendFlowBlockingPopup("Waiting for clearAll")) + continue + if (FindOrLoseImage("Friend_ActivatedClearAllButton", 0, failSafeTime)) break adbClick(205, 510) @@ -339,6 +420,9 @@ RemoveFriends() { failSafeTime := 0 accepted := false Loop { + if(DismissFriendFlowBlockingPopup("Waiting for friend details")) + continue + adbClick(58, 190) Delay(1) if(FindOrLoseImage("Friend_AcceptedButtonInFriendDetails", 0, failSafeTime)){ @@ -366,6 +450,9 @@ RemoveFriends() { interceptProc := true isContinue := false Loop, { + if(DismissFriendFlowBlockingPopup("Confirming friend removal")) + continue + adbClick(200, 372) Delay(0.5) if(FindOrLoseImage("Friend_ReqeustButtonInFriendDetails", 0)) @@ -383,6 +470,9 @@ RemoveFriends() { failSafeTime := 0 ; Either find "Add" (expected), or if we accidentally went back too many pages to "Social", go back into friends. Loop { + if(DismissFriendFlowBlockingPopup("Returning to friend list")) + continue + adbClick(143, 507) Sleep, 750 if(FindOrLoseImage("Common_ActivatedSocialInMainMenu", 0, failSafeTime)) { @@ -399,8 +489,11 @@ RemoveFriends() { ; Exit friend removal process CreateStatusMessage("Friend removal completed. Processed " . friendsProcessed . " friends. Returning to main...",,,, false) + LogToFile("RemoveFriends complete | account=" . cleanupAccount . " | processed=" . friendsProcessed . " | DeadCheckBeforeClear=" . DeadCheck) IniWrite, 0, % session.get("scriptIniFile"), UserSettings, DeadCheck + ClearFriendCleanupPending() session.set("friended", false) + LogDebugToFile("RemoveFriends cleanup state cleared | account=" . cleanupAccount . " | processed=" . friendsProcessed) CreateStatusMessage("Friends removed successfully!",,,, false) if(session.get("stopToggle")) { @@ -429,14 +522,14 @@ ReEnterSocial(prevAction){ global interceptProc reEnterStart := A_TickCount Loop { + if(DismissFriendFlowBlockingPopup("Re-entering Social")) + continue + adbClick_wbb(143, 518) reEnterElapsed := (A_TickCount - reEnterStart) // 1000 if(FindOrLoseImage("Common_ActivatedSocialInMainMenu", 0, reEnterElapsed)) { break } - else if(FindOrLoseImage("Common_PopupXButtonInMain", 0, , , true)){ - adbClick_wbb(137, 480) - } Delay(0.25) } @@ -505,6 +598,47 @@ showcaseLikes() { ;------------------------------------------------------------------------------- ; EraseInput - Clear friend code input field ;------------------------------------------------------------------------------- +SubmitFriendIDSearch(value, num := 0, total := 0) { + global session + + Loop, 3 { + if(num) + CreateStatusMessage("Entering friend ID " . num . "/" . total . " (" . A_Index . "/3)",,,, false) + + FindImageAndClick("Friend_FriendIDInputReady", 138, 265, , 1000) + adbInputEvent("59 122 67") + Delay(0.25) + adbInput(value) + Delay(1) + adbClick_wbb(187, 365) + + submitStart := A_TickCount + Loop { + if(FindOrLoseImage("Friend_RequestButtonInSearchResult", 0, , 80, true) + || FindOrLoseImage("Friend_WithdrawButton", 0, , , true) + || FindOrLoseImage("Friend_AcceptedButtonInSearchResult", 0, , , true) + || FindOrLoseImage("Friend_CannotFriendRequest", 0, , , true) + || FindOrLoseImage("FriendLimit", 0, , , true) + || FindOrLoseImage("Common_Error", 0, , , true)) + return true + + if(!FindOrLoseImage("Friend_SearchFriendWindowCancelButtonCorner", 0, , , true)) + return true + + if((A_TickCount - submitStart) > 2000) + break + + Delay(0.25) + } + + LogToFile("Friend ID input did not submit; retrying | index=" . num . " | try=" . A_Index) + EraseInput(num, total) + } + + LogToFile("Friend ID input failed after retries | index=" . num) + return false +} + EraseInput(num := 0, total := 0) { global session @@ -519,9 +653,63 @@ EraseInput(num := 0, total := 0) { adbInputEvent("59 122 67") ; Press Shift + Home + Backspace if(FindOrLoseImage("Friend_InputFormBlank", 0, failSafeTime)) break + failSafeTime := (A_TickCount - session.get("failSafe")) // 1000 + if(failSafeTime > 10) { + LogToFile("EraseInput timeout | index=" . num) + break + } } } +ShouldSkipGenericButtonInSocialWait() { + reason := "" + if(FindOrLoseImage("Common_ActivatedHomeInMainMenu", 0, , , true)) + reason := "home active" + else if(FindOrLoseImage("Friend_BottomDarkHomeIcon", 0, , , true)) + reason := "bottom home" + else if(FindOrLoseImage("Common_ShopButtonInMain", 0, , , true)) + reason := "home shop" + else if(FindOrLoseImage("WonderPick_WonderPickButtonInHome", 0, , , true)) + reason := "home wonderpick" + else if(FindOrLoseImage("Pack_PackPointButton", 0, , , true)) + reason := "pack points" + else if(FindOrLoseImage("Pack_BackButtonInSelectPackScreen", 0, , , true)) + reason := "pack select" + else if(FindOrLoseImage("Pack_ReadyForOpenPack", 0, , , true)) + reason := "ready open pack" + else if(FindOrLoseImage("Pack_HourglassImageAfterOpenPackClick", 0, , , true)) + reason := "hourglass pack" + else if(FindOrLoseImage("Pack_HourglassAndPokeGoldImageAfterOpenPackClick", 0, , , true)) + reason := "hourglass/gold pack" + else if(FindOrLoseImage("Pack_PokeGoldImageAfterOpenPackClick", 0, , , true)) + reason := "gold pack" + + if(reason = "") + return false + + return true +} + +DismissFriendFlowBlockingPopup(context := "") { + if(!FindOrLoseImage("Common_PopupXButtonInMain", 0, , , true)) + return false + + LogDebugToFile("Dismissed friend flow blocking popup | context=" . context) + + if(context != "") + CreateStatusMessage("Closing popup during friend flow`n" . context,,,, false) + else + CreateStatusMessage("Closing popup during friend flow",,,, false) + + adbClick_wbb(137, 480) + Delay(1) + return true +} + +IsSocialHubReadyForFriends() { + return FindOrLoseImage("Friend_SocialHubFriendButton", 0, , 20, true) +} + GoToFriendsList(isKeepSearch := false, skipTutorialProc := false) { global session @@ -529,18 +717,15 @@ GoToFriendsList(isKeepSearch := false, skipTutorialProc := false) { failSafeTime := 0 mainLoopBreak := false Loop { - if(FindOrLoseImage("Common_ActivatedSocialInMainMenu", 0, failSafeTime, , true)) { - ; If main screen(social): Click friends button - adbClick_wbb(38, 460) - } - else if(FindOrLoseImage("Friend_AddButtonInFriendList", 0, failSafeTime, , true)) { - ; If friends list screen: Click Search button - adbClick_wbb(240, 120) - Delay(1) - } - else if(FindOrLoseImage("Friend_SearchFriendButton", 0, failSafeTime, , true)) { + if(DismissFriendFlowBlockingPopup("Goto friends screen")) + continue + + if(FindOrLoseImage("Friend_SearchFriendButton", 0, failSafeTime, , true)) { if(!isKeepSearch){ Loop { + if(DismissFriendFlowBlockingPopup("Leaving friend search")) + continue + if(FindOrLoseImage("Friend_SearchFriendButton", 0, failSafeTime, , true)) { adbInputEvent("111") ;send ESC } @@ -549,6 +734,11 @@ GoToFriendsList(isKeepSearch := false, skipTutorialProc := false) { break } Delay(2) + failSafeTime := (A_TickCount - session.get("failSafe")) // 1000 + if(failSafeTime > 45) { + restartGameInstance("Stuck at Goto friends screen") + return + } } } else @@ -557,6 +747,23 @@ GoToFriendsList(isKeepSearch := false, skipTutorialProc := false) { if(mainLoopBreak) break } + else if(FindOrLoseImage("Friend_AddButtonInFriendList", 0, failSafeTime, , true)) { + ; If friends list screen: Click Search button + adbClick_wbb(240, 120) + Delay(1) + } + else if(FindOrLoseImage("Common_ActivatedSocialInMainMenu", 0, failSafeTime, , true)) { + if(!IsSocialHubReadyForFriends()) { + failSafeTime := (A_TickCount - session.get("failSafe")) // 1000 + Delay(0.5) + CreateStatusMessage("Waiting for Social hub`n(" . failSafeTime . "/45 seconds)") + continue + } + + ; If main screen(social): Click friends button + adbClick_wbb(38, 460) + Delay(1) + } else{ ; For Tutorial Window if(!skipTutorialProc) @@ -565,6 +772,10 @@ GoToFriendsList(isKeepSearch := false, skipTutorialProc := false) { Delay(0.25) failSafeTime := (A_TickCount - session.get("failSafe")) // 1000 CreateStatusMessage("Goto friends screen`n(" . failSafeTime . "/45 seconds)") + if(failSafeTime > 45) { + restartGameInstance("Stuck at Goto friends screen") + return + } } } @@ -576,7 +787,6 @@ getFriendCode() { CreateStatusMessage("Getting friend code...",,,, false) Sleep, 2000 - FindImageAndClick("Pack_SkipButtonAfterOpenPack", 146, 494) ;click on next until skip button appears session.set("failSafe", A_TickCount) failSafeTime := 0 Loop { @@ -602,4 +812,4 @@ getFriendCode() { session.set("friendCode", AddFriends(false, true)) return session.get("friendCode") -} \ No newline at end of file +} diff --git a/Scripts/Include/Logging.ahk b/Scripts/Include/Logging.ahk index 0ff7f109..92f6163e 100644 --- a/Scripts/Include/Logging.ahk +++ b/Scripts/Include/Logging.ahk @@ -40,6 +40,7 @@ CreateStatusMessage(Message, GuiName := "StatusMessage", X := 0, Y := 565, debug guiWidth := 275 guiheight := 40 + Y := NormalizeStatusMessageY(Y) if(GuiName = "AvgRuns" || GuiName = "AutoGPTest" || GuiName = "AccountInfo") guiheight := 30 @@ -47,7 +48,7 @@ CreateStatusMessage(Message, GuiName := "StatusMessage", X := 0, Y := 565, debug guiWidth := 260 guiheight := 25 } - + try { ; Check if GUI with this name already exists. @@ -101,7 +102,7 @@ SetReposition(){ if(instanceHwnd){ WinGetPos, xpos, ypos, Width, Height, % session.get("winTitle") . " ahk_class Qt5156QWindowIcon" X := xpos + 5 -1 - Y := ypos + 5 + 565 - 11 + Y := ypos + 5 + NormalizeStatusMessageY(565) - 11 if (!X) X := 0 @@ -123,6 +124,18 @@ SetReposition(){ Gui, %GuiName%:Show, NoActivate %PosOption% } +NormalizeStatusMessageY(Y) { + windowMetrics := GetMumuWindowMetrics() + + if (Y = 565) + return windowMetrics.rowHeight + 33 + + if (Y = 605) + return windowMetrics.rowHeight + 73 + + return Y +} + ;Modified from https://stackoverflow.com/a/49354127 SetTextAndResize(controlHwnd, newText) { dc := DllCall("GetDC", "Ptr", controlHwnd) @@ -154,6 +167,9 @@ LogToFile(message, logFile := "") { } else logFile := LogsDir . "\" . logFile + if !FileExist(LogsDir) + FileCreateDir, %LogsDir% + RotateLogFileIfNeeded(logFile) FormatTime, readableTime, %A_Now%, MMMM dd, yyyy HH:mm:ss Loop, { @@ -164,7 +180,87 @@ LogToFile(message, logFile := "") { } } -LogToDiscord(message, screenshotFile := "", ping := false, xmlFile := "", screenshotFile2 := "", altWebhookURL := "", altUserId := "") { +LogDebugToFile(message, logFile := "") { + global Debug + + if (Debug) + LogToFile(message, logFile) +} + +RotateLogFileIfNeeded(logFile) { + static lastCheck := {} + maxBytes := 5 * 1024 * 1024 + checkIntervalMs := 60000 + + if (logFile = "" || !FileExist(logFile)) + return + + last := lastCheck.HasKey(logFile) ? lastCheck[logFile] : 0 + elapsed := A_TickCount - last + if (last && elapsed >= 0 && elapsed < checkIntervalMs) + return + lastCheck[logFile] := A_TickCount + + FileGetSize, fileSize, %logFile% + if (ErrorLevel || fileSize < maxBytes) + return + + SplitPath, logFile, fileName, logDir, ext, nameNoExt + if (logDir = "" || nameNoExt = "") + return + if (ext = "") + ext := "log" + + archiveDir := logDir . "\Archive" + if !FileExist(archiveDir) + FileCreateDir, %archiveDir% + + FormatTime, stamp, %A_Now%, yyyyMMdd_HHmmss + pid := DllCall("GetCurrentProcessId") + archivePath := archiveDir . "\" . nameNoExt . "_" . stamp . "_" . pid . "_" . A_TickCount . "." . ext + FileMove, %logFile%, %archivePath%, 0 + if ErrorLevel + return + + PruneLogArchives(archiveDir, nameNoExt, ext) +} + +PruneLogArchives(archiveDir, nameNoExt, ext) { + keepArchives := 3 + archiveList := "" + archivePattern := archiveDir . "\" . nameNoExt . "_*." . ext + + Loop, Files, %archivePattern%, F + { + FileGetTime, fileTime, %A_LoopFileFullPath%, M + if !ErrorLevel + archiveList .= fileTime . A_Tab . A_LoopFileFullPath . "`n" + } + + if (archiveList = "") + return + + Sort, archiveList, R + archiveCount := 0 + Loop, Parse, archiveList, `n, `r + { + if (A_LoopField = "") + continue + + archiveCount++ + if (archiveCount <= keepArchives) + continue + + tabPos := InStr(A_LoopField, A_Tab) + if (!tabPos) + continue + + oldArchive := SubStr(A_LoopField, tabPos + 1) + FileDelete, %oldArchive% + } +} + +LogToDiscord(message, screenshotFile := "", ping := false, xmlFile := "", screenshotFile2 := "", altWebhookURL := "", altUserId := "", logSuccessfulDelivery := true) { discordPing := "" if (ping) { @@ -183,9 +279,15 @@ LogToDiscord(message, screenshotFile := "", ping := false, xmlFile := "", screen webhookURL := (altWebhookURL ? altWebhookURL : discordWebhookURL) + if (webhookURL = "") { + LogToFile("Discord send skipped: missing webhook URL", "Discord.txt") + return + } + if (webhookURL != "") { - MaxRetries := 10 + MaxRetries := 3 RetryCount := 0 + discordTraceId := CreateDiscordTraceId() try { RegRead, proxyEnabled, HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings, ProxyEnable RegRead, proxyServer, HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings, ProxyServer @@ -193,21 +295,29 @@ LogToDiscord(message, screenshotFile := "", ping := false, xmlFile := "", screen ProxyEnable := false ProxyServer := "" } - if (proxyEnabled) { - curlChar := "curl -k -x " . proxyServer . "/ " + if (proxyEnabled && proxyServer != "") { + curlChar := "curl.exe -k -sS --retry 2 --retry-delay 2 --connect-timeout 10 --max-time 60 -o NUL -w ""HTTP_STATUS:%{http_code}"" -x """ . proxyServer . """ " } else { - curlChar := "curl -k " + curlChar := "curl.exe -k -sS --retry 2 --retry-delay 2 --connect-timeout 10 --max-time 60 -o NUL -w ""HTTP_STATUS:%{http_code}"" " + } + + payloadFile := CreateDiscordPayloadFile(discordPing . message) + if (payloadFile = "") { + LogToFile("Discord send failed before curl: could not create payload file | trace=" . discordTraceId . " | webhook=" . RedactDiscordWebhookURL(webhookURL), "Discord.txt") + return } + Loop { + RetryCount++ try { ; Base command - curlCommand := curlChar - . "-F ""payload_json={\""content\"":\""" . discordPing . message . "\""};type=application/json;charset=UTF-8"" " + curlCommand := curlChar . "-F ""payload_json=<" . payloadFile . ";type=application/json;charset=UTF-8"" " ; If an screenshot or xml file is provided, send it sendScreenshot1 := screenshotFile != "" && FileExist(screenshotFile) sendScreenshot2 := screenshotFile2 != "" && FileExist(screenshotFile2) sendAccountXml := xmlFile != "" && FileExist(xmlFile) + fileCount := sendScreenshot1 + sendScreenshot2 + sendAccountXml if (sendScreenshot1 + sendScreenshot2 + sendAccountXml > 1) { fileIndex := 0 if (sendScreenshot1) { @@ -232,23 +342,100 @@ LogToDiscord(message, screenshotFile := "", ping := false, xmlFile := "", screen curlCommand := curlCommand . "-F ""file=@" . xmlFile . """ " } ; Add the webhook - curlCommand := curlCommand . webhookURL + curlCommand := curlCommand . """" . webhookURL . """" - LogToFile(curlCommand, "Discord.txt") + if(logSuccessfulDelivery) + LogToFile("Discord send attempt | trace=" . discordTraceId . " | attempt=" . RetryCount . "/" . MaxRetries . " | webhook=" . RedactDiscordWebhookURL(webhookURL) . " | files=" . fileCount . " | messageLen=" . StrLen(message), "Discord.txt") ; Send the message using curl - RunWait, %curlCommand%,, Hide - break - } - catch { - RetryCount++ - if (RetryCount >= MaxRetries) { - CreateStatusMessage("Failed to send discord message.") + if (IsFunc("CmdRet")) { + cmdFn := Func("CmdRet") + curlResult := cmdFn.Call(curlCommand) + } else { + RunWait, %curlCommand%,, Hide + curlResult := "HTTP_STATUS:" . ErrorLevel + } + + httpStatus := GetDiscordCurlHttpStatus(curlResult) + if (httpStatus >= 200 && httpStatus < 300) { + if(logSuccessfulDelivery || RetryCount > 1) + LogToFile("Discord send complete | trace=" . discordTraceId . " | status=" . httpStatus . " | webhook=" . RedactDiscordWebhookURL(webhookURL) . " | files=" . fileCount . " | messageLen=" . StrLen(message), "Discord.txt") break } - Sleep, 250 + + LogToFile("Discord send failed | trace=" . discordTraceId . " | attempt=" . RetryCount . "/" . MaxRetries . " | status=" . httpStatus . " | webhook=" . RedactDiscordWebhookURL(webhookURL) . " | files=" . fileCount . " | result=" . TrimDiscordCurlResult(curlResult), "Discord.txt") + } + catch e { + LogToFile("Discord send exception | trace=" . discordTraceId . " | attempt=" . RetryCount . "/" . MaxRetries . " | webhook=" . RedactDiscordWebhookURL(webhookURL) . " | error=" . FormatDiscordException(e), "Discord.txt") } - Sleep, 250 + + if (RetryCount >= MaxRetries) { + LogToFile("Discord send exhausted | trace=" . discordTraceId . " | attempts=" . RetryCount . " | webhook=" . RedactDiscordWebhookURL(webhookURL), "Discord.txt") + CreateStatusMessage("Failed to send discord message.") + break + } + Sleep, % 1000 * RetryCount } + + FileDelete, %payloadFile% + } +} + +CreateDiscordTraceId() { + static sequence := 0 + sequence++ + return A_Now . "_" . DllCall("GetCurrentProcessId") . "_" . A_TickCount . "_" . sequence +} + +CreateDiscordPayloadFile(content) { + payloadJson := "{""content"":""" . DiscordEscapeJson(content) . """}" + payloadFile := A_Temp . "\ptcgpb_discord_payload_" . DllCall("GetCurrentProcessId") . "_" . A_TickCount . ".json" + + FileDelete, %payloadFile% + FileAppend, %payloadJson%, %payloadFile%, UTF-8-RAW + if (ErrorLevel || !FileExist(payloadFile)) + return "" + + return payloadFile +} + +DiscordEscapeJson(text) { + text := StrReplace(text, "\n", "`n") + text := StrReplace(text, Chr(92), Chr(92) . Chr(92)) + text := StrReplace(text, Chr(34), Chr(92) . Chr(34)) + text := StrReplace(text, "`r", "") + text := StrReplace(text, "`n", Chr(92) . "n") + text := StrReplace(text, "`t", Chr(92) . "t") + return text +} + +GetDiscordCurlHttpStatus(curlResult) { + if RegExMatch(curlResult, "HTTP_STATUS:(\d{3})", match) + return match1 + 0 + return 0 +} + +TrimDiscordCurlResult(curlResult) { + curlResult := StrReplace(curlResult, "`r", " ") + curlResult := StrReplace(curlResult, "`n", " ") + curlResult := Trim(curlResult) + + if (StrLen(curlResult) > 500) + curlResult := SubStr(curlResult, 1, 500) . "..." + + return curlResult +} + +RedactDiscordWebhookURL(webhookURL) { + return RegExReplace(webhookURL, "i)(/api/webhooks/[^/]+/)[^?\s]+", "$1") +} + +FormatDiscordException(e) { + if (IsObject(e)) { + if (e.Message != "") + return e.Message + if (e.What != "") + return e.What } + return e } diff --git a/Scripts/Include/Monitor.ahk b/Scripts/Include/Monitor.ahk index 8cbdc700..7480a998 100644 --- a/Scripts/Include/Monitor.ahk +++ b/Scripts/Include/Monitor.ahk @@ -83,6 +83,8 @@ Loop { LogToFile(msg, "Monitor.txt") scriptName := instanceNum . ".ahk" + coverHwnd := CaptureMuMuCoverWindow(instanceNum) + StoreMuMuCoverWindow(instanceNum, coverHwnd) killedAHK := killAHK(scriptName) killedInstance := killInstance(instanceNum) @@ -173,19 +175,11 @@ killAHK(scriptName := "") if(scriptName != "") { DetectHiddenWindows, On - WinGet, IDList, List, ahk_class AutoHotkey - Loop %IDList% - { - ID:=IDList%A_Index% - WinGetTitle, ATitle, ahk_id %ID% - if InStr(ATitle, "\" . scriptName) { - ; Use Process Close (TerminateProcess) instead of WinKill (WM_CLOSE) - ; to guarantee the process dies even if blocked on ADB/Sleep - WinGet, ahkPID, PID, ahk_id %ID% - Process, Close, %ahkPID% - killed := killed + 1 - } - } + killedPIDs := {} + killed += killAHKWindowsByClass(scriptName, "AutoHotkey", killedPIDs) + killed += killAHKWindowsByClass(scriptName, "#32770", killedPIDs) + killed += killAHKWindowsByClass(scriptName, "ConsoleWindowClass", killedPIDs) + killed += killAHKProcessesByCommandLine(scriptName, killedPIDs) } return killed @@ -197,18 +191,103 @@ checkAHK(scriptName := "") if(scriptName != "") { DetectHiddenWindows, On - WinGet, IDList, List, ahk_class AutoHotkey - Loop %IDList% - { - ID:=IDList%A_Index% - WinGetTitle, ATitle, ahk_id %ID% - if InStr(ATitle, "\" . scriptName) { + seenPIDs := {} + cnt += countAHKWindowsByClass(scriptName, "AutoHotkey", seenPIDs) + cnt += countAHKWindowsByClass(scriptName, "#32770", seenPIDs) + cnt += countAHKWindowsByClass(scriptName, "ConsoleWindowClass", seenPIDs) + cnt += countAHKProcessesByCommandLine(scriptName, seenPIDs) + } + + return cnt +} + +killAHKWindowsByClass(scriptName, winClass, killedPIDs) +{ + killed := 0 + WinGet, IDList, List, ahk_class %winClass% + Loop %IDList% + { + ID := IDList%A_Index% + WinGetTitle, ATitle, ahk_id %ID% + if (isAHKScriptWindowTitle(ATitle, scriptName)) { + ; Use Process Close (TerminateProcess) instead of WinKill (WM_CLOSE) + ; to guarantee the process dies even if blocked on ADB/Sleep. + WinGet, ahkPID, PID, ahk_id %ID% + if (ahkPID && !killedPIDs.HasKey(ahkPID)) { + Process, Close, %ahkPID% + killedPIDs[ahkPID] := true + killed := killed + 1 + } + } + } + + return killed +} + +countAHKWindowsByClass(scriptName, winClass, seenPIDs) +{ + cnt := 0 + WinGet, IDList, List, ahk_class %winClass% + Loop %IDList% + { + ID := IDList%A_Index% + WinGetTitle, ATitle, ahk_id %ID% + if (isAHKScriptWindowTitle(ATitle, scriptName)) { + WinGet, ahkPID, PID, ahk_id %ID% + if (ahkPID && !seenPIDs.HasKey(ahkPID)) { + seenPIDs[ahkPID] := true cnt := cnt + 1 } } } - + return cnt } -~+F7::ExitApp \ No newline at end of file +killAHKProcessesByCommandLine(scriptName, killedPIDs) +{ + killed := 0 + scriptNeedle := "\" . scriptName + + for process in ComObjGet("winmgmts:").ExecQuery("Select ProcessId, Name, CommandLine from Win32_Process Where Name like 'AutoHotkey%'") + { + commandLine := process.CommandLine + if(commandLine != "" && InStr(commandLine, scriptNeedle)) { + ahkPID := process.ProcessId + if (ahkPID && !killedPIDs.HasKey(ahkPID)) { + Process, Close, %ahkPID% + killedPIDs[ahkPID] := true + killed := killed + 1 + } + } + } + + return killed +} + +countAHKProcessesByCommandLine(scriptName, seenPIDs) +{ + cnt := 0 + scriptNeedle := "\" . scriptName + + for process in ComObjGet("winmgmts:").ExecQuery("Select ProcessId, Name, CommandLine from Win32_Process Where Name like 'AutoHotkey%'") + { + commandLine := process.CommandLine + if(commandLine != "" && InStr(commandLine, scriptNeedle)) { + ahkPID := process.ProcessId + if (ahkPID && !seenPIDs.HasKey(ahkPID)) { + seenPIDs[ahkPID] := true + cnt := cnt + 1 + } + } + } + + return cnt +} + +isAHKScriptWindowTitle(ATitle, scriptName) +{ + return (InStr(ATitle, "\" . scriptName) || ATitle = scriptName) +} + +~+F7::ExitApp diff --git a/Scripts/Include/MonitorOnce.ahk b/Scripts/Include/MonitorOnce.ahk index 4d761780..958e697a 100644 --- a/Scripts/Include/MonitorOnce.ahk +++ b/Scripts/Include/MonitorOnce.ahk @@ -39,6 +39,8 @@ Loop %Instances% { LogToFile(msg, "Monitor.txt") scriptName := instanceNum . ".ahk" + coverHwnd := CaptureMuMuCoverWindow(instanceNum) + StoreMuMuCoverWindow(instanceNum, coverHwnd) killedAHK := killAHK(scriptName) killedInstance := killInstance(instanceNum) @@ -61,7 +63,7 @@ Loop %Instances% { ;Command := "Scripts\" . scriptName ;Run, %Command% scriptPath := A_ScriptDir "\.." "\" scriptName - Run, "%A_AhkPath%" /restart "%scriptPath% + Run, "%A_AhkPath%" /restart "%scriptPath%" } } } @@ -74,18 +76,11 @@ killAHK(scriptName := "") if(scriptName != "") { DetectHiddenWindows, On - WinGet, IDList, List, ahk_class AutoHotkey - Loop %IDList% - { - ID:=IDList%A_Index% - WinGetTitle, ATitle, ahk_id %ID% - if InStr(ATitle, "\" . scriptName) { - ; MsgBox, Killing: %ATitle% - WinKill, ahk_id %ID% ;kill - ; WinClose, %fullScriptPath% ahk_class AutoHotkey - killed := killed + 1 - } - } + killedPIDs := {} + killed += killAHKWindowsByClass(scriptName, "AutoHotkey", killedPIDs) + killed += killAHKWindowsByClass(scriptName, "#32770", killedPIDs) + killed += killAHKWindowsByClass(scriptName, "ConsoleWindowClass", killedPIDs) + killed += killAHKProcessesByCommandLine(scriptName, killedPIDs) } return killed @@ -97,58 +92,101 @@ checkAHK(scriptName := "") if(scriptName != "") { DetectHiddenWindows, On - WinGet, IDList, List, ahk_class AutoHotkey - Loop %IDList% - { - ID:=IDList%A_Index% - WinGetTitle, ATitle, ahk_id %ID% - if InStr(ATitle, "\" . scriptName) { + seenPIDs := {} + cnt += countAHKWindowsByClass(scriptName, "AutoHotkey", seenPIDs) + cnt += countAHKWindowsByClass(scriptName, "#32770", seenPIDs) + cnt += countAHKWindowsByClass(scriptName, "ConsoleWindowClass", seenPIDs) + cnt += countAHKProcessesByCommandLine(scriptName, seenPIDs) + } + + return cnt +} + +killAHKWindowsByClass(scriptName, winClass, killedPIDs) +{ + killed := 0 + WinGet, IDList, List, ahk_class %winClass% + Loop %IDList% + { + ID := IDList%A_Index% + WinGetTitle, ATitle, ahk_id %ID% + if (isAHKScriptWindowTitle(ATitle, scriptName)) { + WinGet, ahkPID, PID, ahk_id %ID% + if (ahkPID && !killedPIDs.HasKey(ahkPID)) { + Process, Close, %ahkPID% + killedPIDs[ahkPID] := true + killed := killed + 1 + } + } + } + + return killed +} + +countAHKWindowsByClass(scriptName, winClass, seenPIDs) +{ + cnt := 0 + WinGet, IDList, List, ahk_class %winClass% + Loop %IDList% + { + ID := IDList%A_Index% + WinGetTitle, ATitle, ahk_id %ID% + if (isAHKScriptWindowTitle(ATitle, scriptName)) { + WinGet, ahkPID, PID, ahk_id %ID% + if (ahkPID && !seenPIDs.HasKey(ahkPID)) { + seenPIDs[ahkPID] := true cnt := cnt + 1 } } } - + return cnt } -killInstance(instanceNum := "") +killAHKProcessesByCommandLine(scriptName, killedPIDs) { killed := 0 - - pID := checkInstance(instanceNum) - if pID { - Process, Close, %pID% - killed := killed + 1 + scriptNeedle := "\" . scriptName + + for process in ComObjGet("winmgmts:").ExecQuery("Select ProcessId, Name, CommandLine from Win32_Process Where Name like 'AutoHotkey%'") + { + commandLine := process.CommandLine + if(commandLine != "" && InStr(commandLine, scriptNeedle)) { + ahkPID := process.ProcessId + if (ahkPID && !killedPIDs.HasKey(ahkPID)) { + Process, Close, %ahkPID% + killedPIDs[ahkPID] := true + killed := killed + 1 + } + } } - + return killed } -checkInstance(instanceNum := "") +countAHKProcessesByCommandLine(scriptName, seenPIDs) { - ret := WinExist(instanceNum) - if(ret) + cnt := 0 + scriptNeedle := "\" . scriptName + + for process in ComObjGet("winmgmts:").ExecQuery("Select ProcessId, Name, CommandLine from Win32_Process Where Name like 'AutoHotkey%'") { - WinGet, temp_pid, PID, ahk_id %ret% - return temp_pid + commandLine := process.CommandLine + if(commandLine != "" && InStr(commandLine, scriptNeedle)) { + ahkPID := process.ProcessId + if (ahkPID && !seenPIDs.HasKey(ahkPID)) { + seenPIDs[ahkPID] := true + cnt := cnt + 1 + } + } } - - return "" + + return cnt } -launchInstance(instanceNum := "") +isAHKScriptWindowTitle(ATitle, scriptName) { - global mumuFolder - - if(instanceNum != "") { - mumuNum := getMumuInstanceNum(instanceNum, mumuFolder) - if(mumuNum != "") { - mumuExe := mumuFolder . "\shell\MuMuPlayer.exe" - if !FileExist(mumuExe) - mumuExe := mumuFolder . "\nx_main\MuMuNxMain.exe" - Run_(mumuExe, "-v " . mumuNum) - } - } + return (InStr(ATitle, "\" . scriptName) || ATitle = scriptName) } ~+F7::ExitApp diff --git a/Scripts/Include/RarityBorder.ahk b/Scripts/Include/RarityBorder.ahk index 346d36ae..ade83c18 100644 --- a/Scripts/Include/RarityBorder.ahk +++ b/Scripts/Include/RarityBorder.ahk @@ -8,6 +8,9 @@ class RarityBorder { static DefaultCommon := { 4: [ new Coordinate(96, 279, 116, 281), new Coordinate(181, 279, 201, 281), new Coordinate(96, 394, 116, 396), new Coordinate(181, 394, 201, 396) ] , 5: [ new Coordinate(56, 279, 76, 281), new Coordinate(139, 279, 159, 281), new Coordinate(222, 279, 242, 281), new Coordinate(96, 394, 116, 396), new Coordinate(181, 394, 201, 396) ] , 6: [ new Coordinate(56, 279, 76, 281), new Coordinate(139, 279, 159, 281), new Coordinate(222, 279, 242, 281), new Coordinate(56, 394, 76, 396), new Coordinate(139, 394, 159, 396), new Coordinate(222, 394, 242, 396) ] } + static DefaultCommon125 := { 4: [ new Coordinate(96, 284, 123, 286), new Coordinate(181, 284, 208, 286), new Coordinate(96, 399, 123, 401), new Coordinate(181, 399, 208, 401) ] + , 5: [ new Coordinate(56, 284, 83, 286), new Coordinate(139, 284, 166, 286), new Coordinate(222, 284, 249, 286), new Coordinate(96, 399, 123, 401), new Coordinate(181, 399, 208, 401) ] + , 6: [ new Coordinate(56, 284, 83, 286), new Coordinate(139, 284, 166, 286), new Coordinate(222, 284, 249, 286), new Coordinate(56, 399, 83, 401), new Coordinate(139, 399, 166, 401), new Coordinate(256, 386, 260, 402) ] } ; ========================================================= ; [Static] MASK 모드용 단일 기준점(좌상단 x, y) 앵커 좌표 @@ -22,8 +25,11 @@ class RarityBorder { this.SearchMode := searchMode this.AdditionalSets := { 4: [], 5: [], 6: [] } + this.Scale125AdditionalSets := { 4: [], 5: [], 6: [] } this.CommonCoords := RarityBorder.DefaultCommon + this.CommonCoords125 := RarityBorder.DefaultCommon125 this.MaskAnchors := RarityBorder.DefaultMaskAnchors + this.Scale125MaskAnchors := "" this.ValidPixelSets := [] } @@ -69,6 +75,14 @@ class RarityBorder { this.MaskAnchors := anchorsObj } + SetScale125MaskAnchors(anchorsObj) { + if (!anchorsObj.HasKey(4) || !anchorsObj.HasKey(5) || !anchorsObj.HasKey(6)) { + MsgBox, 16, Error, % this.RarityName " Scale 125 Mask Anchors Register failed!" + return + } + this.Scale125MaskAnchors := anchorsObj + } + SetCustomCommon(coordsObj) { if (!coordsObj.HasKey(4) || !coordsObj.HasKey(5) || !coordsObj.HasKey(6)) { MsgBox, 16, Error, % this.RarityName " Register failed!" @@ -77,6 +91,14 @@ class RarityBorder { this.CommonCoords := coordsObj } + SetScale125Common(coordsObj) { + if (!coordsObj.HasKey(4) || !coordsObj.HasKey(5) || !coordsObj.HasKey(6)) { + MsgBox, 16, Error, % this.RarityName " Scale 125 Register failed!" + return + } + this.CommonCoords125 := coordsObj + } + AddAdditionalSet(setPrefix, coordsObj) { if (!coordsObj.HasKey(4) || !coordsObj.HasKey(5) || !coordsObj.HasKey(6)) { MsgBox, 16, Error, % this.RarityName " [" setPrefix "] register failed!" @@ -87,62 +109,84 @@ class RarityBorder { this.AdditionalSets[6].Push({ Prefix: setPrefix, Coords: coordsObj[6] }) } + AddScale125AdditionalSet(setPrefix, coordsObj) { + if (!coordsObj.HasKey(4) || !coordsObj.HasKey(5) || !coordsObj.HasKey(6)) { + MsgBox, 16, Error, % this.RarityName " Scale 125 [" setPrefix "] register failed!" + return + } + this.Scale125AdditionalSets[4].Push({ Prefix: setPrefix, Coords: coordsObj[4] }) + this.Scale125AdditionalSets[5].Push({ Prefix: setPrefix, Coords: coordsObj[5] }) + this.Scale125AdditionalSets[6].Push({ Prefix: setPrefix, Coords: coordsObj[6] }) + } + Search(pBitmap, cardCount, targetIndex) { - if (this.SearchMode == "MASK") { - anchor := this.MaskAnchors[cardCount][targetIndex] - if (!anchor || anchor.x == "") - return false - return this.DoMaskSearch(pBitmap, anchor.x, anchor.y) + isScale125 := (GetConfiguredDisplayScale() = 125) + searchMode := this.SearchMode + basePrefix := this.BasePrefix + + if (searchMode == "MASK") { + maskAnchors := this.MaskAnchors + if (isScale125 && this.Scale125MaskAnchors) + maskAnchors := this.Scale125MaskAnchors + + anchor := maskAnchors[cardCount][targetIndex] + return (anchor && anchor.x != "" && this.DoMaskSearch(pBitmap, anchor.x, anchor.y)) } - commonCoord := this.CommonCoords[cardCount][targetIndex] + commonCoords := this.CommonCoords + if (isScale125 && this.CommonCoords125) + commonCoords := this.CommonCoords125 + commonCoord := commonCoords[cardCount][targetIndex] additionalGroups := this.AdditionalSets[cardCount] + if (isScale125 && this.Scale125AdditionalSets[cardCount].MaxIndex()) + additionalGroups := this.Scale125AdditionalSets[cardCount] if (!commonCoord || commonCoord.startX == "") return false - if (this.SearchMode == "COMMON_ONLY") { - return this.DoSearch(pBitmap, commonCoord, this.BasePrefix) + if (searchMode == "COMMON_ONLY") { + return this.DoSearch(pBitmap, commonCoord, basePrefix, cardCount, targetIndex) } - else if (this.SearchMode == "ALL") { - if !this.DoSearch(pBitmap, commonCoord, this.BasePrefix) + else if (searchMode == "ALL") { + if !this.DoSearch(pBitmap, commonCoord, basePrefix, cardCount, targetIndex) return false for i, altSet in additionalGroups { altCoord := altSet.Coords[targetIndex] - if !this.DoSearch(pBitmap, altCoord, altSet.Prefix) + if !this.DoSearch(pBitmap, altCoord, altSet.Prefix, cardCount, targetIndex) return false } return true } - else if (this.SearchMode == "ANY") { - if this.DoSearch(pBitmap, commonCoord, this.BasePrefix) + else if (searchMode == "ANY") { + if this.DoSearch(pBitmap, commonCoord, basePrefix, cardCount, targetIndex) return true for i, altSet in additionalGroups { altCoord := altSet.Coords[targetIndex] - if this.DoSearch(pBitmap, altCoord, altSet.Prefix) + if this.DoSearch(pBitmap, altCoord, altSet.Prefix, cardCount, targetIndex) return true } return false } } - DoSearch(pBitmap, coord, targetPrefix) { + DoSearch(pBitmap, coord, targetPrefix, cardCount := "", targetIndex := "") { if (!coord || coord.startX == "") return false - + + return this.DoPrimarySearch(pBitmap, coord, targetPrefix, cardCount, targetIndex) + } + + DoPrimarySearch(pBitmap, coord, targetPrefix, cardCount := "", targetIndex := "") { imageIdx := 1 Loop { vRet := false - Path := A_ScriptDir . "\Needles\" . targetPrefix . imageIdx . ".png" - if(!FileExist(Path)) + Path := A_ScriptDir . "\Needles\" . targetPrefix . imageIdx . ".png" + if(!FileExist(ResolveNeedlePath(Path))) break - pNeedle := GetNeedle(Path) - vRet := Gdip_ImageSearch_wbb(pBitmap, pNeedle, vPosXY, coord.startX, coord.startY, coord.endX, coord.endY, 40) - - if(vRet = 1) + if (this.SearchNeedlePath(pBitmap, coord, Path, cardCount, targetIndex)) return true else imageIdx += 1 @@ -150,6 +194,38 @@ class RarityBorder { return false } + GetSearchVariation(cardCount := "", targetIndex := "") { + isScale125 := (GetConfiguredDisplayScale() = 125) + + if (isScale125 && this.RarityName = "normal") { + if (cardCount = 4) + return 60 + + if (cardCount = 6 && targetIndex >= 4) + return 60 + + return 40 + } + + if (this.RarityName = "normal") + return 40 + + if (cardCount = 6 && targetIndex >= 4) + return 80 + + return 60 + } + + SearchNeedlePath(pBitmap, coord, Path, cardCount := "", targetIndex := "") { + if(!FileExist(ResolveNeedlePath(Path))) + return false + + pNeedle := GetNeedle(Path) + searchVariation := this.GetSearchVariation(cardCount, targetIndex) + vRet := Gdip_ImageSearch_wbb(pBitmap, pNeedle, vPosXY, coord.startX, coord.startY, coord.endX, coord.endY, searchVariation) + return (vRet = 1) + } + DoMaskSearch(pBitmap, cardX, cardY) { vRet := false Sleep, 20 @@ -221,6 +297,9 @@ borderTrainer := new RarityBorder("trainer", "trainer") borderRainbow := new RarityBorder("rainbow", "rainbow") borderFullArt := new RarityBorder("fullart", "fullart", "MASK") borderFullArt.LoadMaskReferences(A_ScriptDir . "\Mask") +borderFullArt.SetScale125MaskAnchors({ 4: [ {x: 57, y: 186}, {x: 142, y: 186}, {x: 57, y: 301}, {x: 142, y: 301} ] + , 5: [ {x: 17, y: 181}, {x: 100, y: 181}, {x: 182, y: 181}, {x: 57, y: 301}, {x: 142, y: 301} ] + , 6: [ {x: 17, y: 181}, {x: 100, y: 181}, {x: 182, y: 181}, {x: 17, y: 301}, {x: 100, y: 301}, {x: 182, y: 301} ] }) borderImmersive := new RarityBorder("immersive", "immersive") borderCrown := new RarityBorder("crown", "crown") borderGimmighoul := new RarityBorder("gimmighoul", "gimmighoul") @@ -258,6 +337,53 @@ borderShinyEx.AddAdditionalSet("ShinyEx_ex_", { 4: [ new Coordinate(100, 272, 11 , new Coordinate(143, 387, 153, 389) , new Coordinate(225, 387, 235, 389) ] }) +borderShinyEx.SetScale125Common({ 4: [ new Coordinate(90, 261, 93, 283) + , new Coordinate(173, 261, 176, 283) + , new Coordinate(130, 376, 133, 398) + , new Coordinate(215, 376, 218, 398) ] + , 5: [ new Coordinate(90, 261, 93, 283) + , new Coordinate(173, 261, 176, 283) + , new Coordinate(255, 261, 258, 283) + , new Coordinate(130, 376, 133, 398) + , new Coordinate(215, 376, 218, 398) ] + , 6: [ new Coordinate(90, 261, 93, 283) + , new Coordinate(173, 261, 176, 283) + , new Coordinate(255, 261, 258, 283) + , new Coordinate(90, 376, 93, 398) + , new Coordinate(173, 376, 176, 398) + , new Coordinate(254, 384, 258, 400) ] }) +borderShinyEx.AddScale125AdditionalSet("ShinyEx_ex_", { 4: [ new Coordinate(110, 175, 140, 187) + , new Coordinate(192, 175, 223, 187) + , new Coordinate(110, 293, 140, 305) + , new Coordinate(192, 293, 223, 305) ] + , 5: [ new Coordinate(74, 175, 97, 187) + , new Coordinate(153, 175, 180, 187) + , new Coordinate(237, 175, 262, 187) + , new Coordinate(110, 293, 140, 305) + , new Coordinate(192, 293, 223, 305) ] + , 6: [ new Coordinate(74, 175, 97, 187) + , new Coordinate(153, 175, 180, 187) + , new Coordinate(237, 175, 262, 187) + , new Coordinate(74, 293, 97, 305) + , new Coordinate(153, 293, 180, 305) + , new Coordinate(253, 385, 259, 402) ] }) + +borderShiny1Star.SetScale125Common({ 4: [ new Coordinate(90, 261, 93, 283) + , new Coordinate(173, 261, 176, 283) + , new Coordinate(130, 376, 133, 398) + , new Coordinate(215, 376, 218, 398) ] + , 5: [ new Coordinate(90, 261, 93, 283) + , new Coordinate(173, 261, 176, 283) + , new Coordinate(255, 261, 258, 283) + , new Coordinate(130, 376, 133, 398) + , new Coordinate(215, 376, 218, 398) ] + , 6: [ new Coordinate(90, 261, 93, 283) + , new Coordinate(173, 261, 176, 283) + , new Coordinate(255, 261, 258, 283) + , new Coordinate(90, 376, 93, 398) + , new Coordinate(173, 376, 176, 398) + , new Coordinate(254, 384, 258, 400) ] }) + rarityCheckers.Push(borderNormal) rarityCheckers.Push(border3Diamond) rarityCheckers.Push(border1Star) @@ -268,4 +394,4 @@ rarityCheckers.Push(borderImmersive) rarityCheckers.Push(borderCrown) rarityCheckers.Push(borderGimmighoul) rarityCheckers.Push(borderShinyEx) -rarityCheckers.Push(borderShiny1Star) \ No newline at end of file +rarityCheckers.Push(borderShiny1Star) diff --git a/Scripts/Include/ResetLists.ahk b/Scripts/Include/ResetLists.ahk index dae38889..b7471a88 100644 --- a/Scripts/Include/ResetLists.ahk +++ b/Scripts/Include/ResetLists.ahk @@ -15,12 +15,78 @@ if (!FileExist(logsDir)) { ; Custom logging function for ResetLists (self-contained) LogToResetListFile(message) { global resetListLogFile + RotateResetListLogIfNeeded(resetListLogFile) timestamp := A_Now FormatTime, formattedTime, %timestamp%, yyyy-MM-dd HH:mm:ss logEntry := formattedTime . " - " . message . "`n" FileAppend, %logEntry%, %resetListLogFile% } +RotateResetListLogIfNeeded(logFile) { + maxBytes := 5 * 1024 * 1024 + + if (logFile = "" || !FileExist(logFile)) + return + + FileGetSize, fileSize, %logFile% + if (ErrorLevel || fileSize < maxBytes) + return + + SplitPath, logFile, fileName, logDir, ext, nameNoExt + if (logDir = "" || nameNoExt = "") + return + if (ext = "") + ext := "log" + + archiveDir := logDir . "\Archive" + if !FileExist(archiveDir) + FileCreateDir, %archiveDir% + + FormatTime, stamp, %A_Now%, yyyyMMdd_HHmmss + pid := DllCall("GetCurrentProcessId") + archivePath := archiveDir . "\" . nameNoExt . "_" . stamp . "_" . pid . "_" . A_TickCount . "." . ext + FileMove, %logFile%, %archivePath%, 0 + if ErrorLevel + return + + PruneResetListLogArchives(archiveDir, nameNoExt, ext) +} + +PruneResetListLogArchives(archiveDir, nameNoExt, ext) { + keepArchives := 3 + archiveList := "" + archivePattern := archiveDir . "\" . nameNoExt . "_*." . ext + + Loop, Files, %archivePattern%, F + { + FileGetTime, fileTime, %A_LoopFileFullPath%, M + if !ErrorLevel + archiveList .= fileTime . A_Tab . A_LoopFileFullPath . "`n" + } + + if (archiveList = "") + return + + Sort, archiveList, R + archiveCount := 0 + Loop, Parse, archiveList, `n, `r + { + if (A_LoopField = "") + continue + + archiveCount++ + if (archiveCount <= keepArchives) + continue + + tabPos := InStr(A_LoopField, A_Tab) + if (!tabPos) + continue + + oldArchive := SubStr(A_LoopField, tabPos + 1) + FileDelete, %oldArchive% + } +} + ; Log script start LogToResetListFile("ResetLists.ahk started - Beginning cleanup session") @@ -230,4 +296,4 @@ if (remainingFiles = 0) { LogToResetListFile("ResetLists.ahk completed") -ExitApp \ No newline at end of file +ExitApp diff --git a/Scripts/Include/Utils.ahk b/Scripts/Include/Utils.ahk index 97b85483..808b537a 100644 --- a/Scripts/Include/Utils.ahk +++ b/Scripts/Include/Utils.ahk @@ -317,16 +317,100 @@ CompareIndicesByPacksDesc(packs, a, b) { ;------------------------------------------------------------------------------- ; SafeReload - Restart the script without race conditions ;------------------------------------------------------------------------------- -; Launches a new instance then immediately kills the current process. -; Unlike Reload (which keeps the old process alive and relies on the NEW -; instance to close it via WM_CLOSE), this has the OLD process kill itself. -; ExitApp terminates in microseconds; the new AHK process takes hundreds of -; milliseconds to load and reach #SingleInstance - so the old process is -; long dead before any conflict can occur. -SafeReload() { - ;Run, "%A_AhkPath%" "%A_ScriptFullPath%" - ;ExitApp +; Use AutoHotkey's built-in Reload path. Keep a small diagnostic trail, but do +; not spawn a separate replacement process from this common reload helper. +SafeReload(reason := "") { + static reloadInProgress := false + + if (reloadInProgress) { + LogReloadMessage("SafeReload re-entered; exiting current process | reason=" . reason) + ExitApp + } + + reloadInProgress := true + currentPID := DllCall("GetCurrentProcessId", "UInt") + LogReloadMessage("SafeReload requested | script=" . A_ScriptName . " | pid=" . currentPID . " | reason=" . reason) + + if(IsFunc("CleanupBeforeExit")) { + OnExit("CleanupBeforeExit", 0) + cleanupFn := Func("CleanupBeforeExit") + cleanupFn.Call() + } + Reload + Sleep, 1000 + if (ErrorLevel) { + LogReloadMessage("Built-in Reload returned ErrorLevel=" . ErrorLevel . " | reason=" . reason) + reloadInProgress := false + } +} + +LogReloadMessage(message) { + if (IsFunc("LogToFile")) { + logFn := Func("LogToFile") + logFn.Call(message, "Reload.txt") + return + } + + logDir := A_ScriptDir . "\..\Logs" + if (!FileExist(logDir) && FileExist(A_ScriptDir . "\..\..\Logs")) + logDir := A_ScriptDir . "\..\..\Logs" + if (!FileExist(logDir)) + FileCreateDir, %logDir% + + logFile := logDir . "\Reload.txt" + FormatTime, now,, yyyy-MM-dd HH:mm:ss + FileAppend, % "[" . now . "] " . message . "`n", %logFile% +} + +LogUtilityMessage(message) { + if (IsFunc("LogToFile")) { + logFn := Func("LogToFile") + logFn.Call(message) + return + } + + logDir := A_ScriptDir . "\..\Logs" + if (!FileExist(logDir) && FileExist(A_ScriptDir . "\..\..\Logs")) + logDir := A_ScriptDir . "\..\..\Logs" + if (!FileExist(logDir)) + FileCreateDir, %logDir% + + logFile := logDir . "\Utility.txt" + FormatTime, now,, yyyy-MM-dd HH:mm:ss + FileAppend, % "[" . now . "] " . message . "`n", %logFile% +} + +GetSearchNeedleObj(needleName, caller := "") { + global needlesDict, session + static loggedNeedles := {} + + scriptName := A_ScriptName + if (IsObject(session)) { + sessionScriptName := session.get("scriptName") + if (sessionScriptName != "") + scriptName := sessionScriptName + } + + logKey := scriptName . "|" . caller . "|" . needleName + if (!IsObject(needlesDict) || !needlesDict.needles.HasKey(needleName)) { + if (!loggedNeedles.HasKey(logKey)) { + LogUtilityMessage("Missing needle definition: " . needleName . " in " . caller) + loggedNeedles[logKey] := true + } + return "" + } + + needleObj := needlesDict.Get(needleName) + if (!IsObject(needleObj) || needleObj.imageName = "" || !IsObject(needleObj.coords) || !needleObj.coords.isValid) { + if (!loggedNeedles.HasKey(logKey)) { + LogUtilityMessage("Invalid needle definition: " . needleName . " in " . caller) + loggedNeedles[logKey] := true + } + return "" + } + + return needleObj } ;------------------------------------------------------------------------------- @@ -399,6 +483,171 @@ ShellRun(prms*) { } } +InitializeHiddenConsole() { + previousHwnd := DllCall("GetForegroundWindow", "Ptr") + + if (!DllCall("GetConsoleWindow", "Ptr")) + DllCall("AllocConsole") + + DllCall("SetConsoleTitle", "Str", A_ScriptFullPath) + HideAllocatedConsole() + SetTimer, HideAllocatedConsole, -1000 + + RestorePreviousForegroundWindow(previousHwnd) +} + +RestorePreviousForegroundWindow(previousHwnd) { + if (!previousHwnd || !DllCall("IsWindow", "Ptr", previousHwnd) || !DllCall("IsWindowVisible", "Ptr", previousHwnd)) + return false + + if (DllCall("IsIconic", "Ptr", previousHwnd)) + return false + + return DllCall("SetForegroundWindow", "Ptr", previousHwnd) +} + +HideAllocatedConsole() { + consoleHwnd := DllCall("GetConsoleWindow", "Ptr") + if (consoleHwnd) { + DllCall("ShowWindow", "Ptr", consoleHwnd, "Int", 0) + WinHide, ahk_id %consoleHwnd% + } +} + +GetScriptIniPathByName(scriptName) { + scriptName := StrReplace(scriptName, ".ahk") + if (RegExMatch(A_ScriptDir, "i)\\Include$")) + return A_ScriptDir . "\..\" . scriptName . ".ini" + return A_ScriptDir . "\" . scriptName . ".ini" +} + +GetWindowRect(hwnd) { + if (!hwnd || !DllCall("IsWindow", "Ptr", hwnd)) + return "" + + VarSetCapacity(rect, 16, 0) + if (!DllCall("GetWindowRect", "Ptr", hwnd, "Ptr", &rect)) + return "" + + return {left: NumGet(rect, 0, "Int") + , top: NumGet(rect, 4, "Int") + , right: NumGet(rect, 8, "Int") + , bottom: NumGet(rect, 12, "Int")} +} + +RectsOverlap(rectA, rectB, minArea := 1024) { + if (!IsObject(rectA) || !IsObject(rectB)) + return false + + left := (rectA.left > rectB.left) ? rectA.left : rectB.left + top := (rectA.top > rectB.top) ? rectA.top : rectB.top + right := (rectA.right < rectB.right) ? rectA.right : rectB.right + bottom := (rectA.bottom < rectB.bottom) ? rectA.bottom : rectB.bottom + + overlapW := right - left + overlapH := bottom - top + return (overlapW > 0 && overlapH > 0 && (overlapW * overlapH) >= minArea) +} + +IsIgnoredCoverWindow(hwnd, targetHwnd) { + if (!hwnd || hwnd = targetHwnd) + return true + + if (!DllCall("IsWindow", "Ptr", hwnd) || !DllCall("IsWindowVisible", "Ptr", hwnd)) + return true + + if (DllCall("IsIconic", "Ptr", hwnd)) + return true + + WinGetClass, winClass, ahk_id %hwnd% + if (winClass = "Qt5156QWindowIcon" || winClass = "AutoHotkey" || winClass = "AutoHotkeyGUI" || winClass = "#32770") + return true + + if (winClass = "Progman" || winClass = "WorkerW" || winClass = "Shell_TrayWnd" || winClass = "Button") + return true + + WinGet, style, Style, ahk_id %hwnd% + if (!(style & 0x10000000)) + return true + + WinGet, exStyle, ExStyle, ahk_id %hwnd% + if (exStyle & 0x80) + return true + + return false +} + +CaptureMuMuCoverWindow(winTitle) { + targetHwnd := WinExist(winTitle . " ahk_class Qt5156QWindowIcon") + if (!targetHwnd) + return "" + + targetRect := GetWindowRect(targetHwnd) + if (!IsObject(targetRect)) + return "" + + WinGet, IDList, List + Loop %IDList% + { + hwnd := IDList%A_Index% + if (hwnd = targetHwnd) + break + + if (IsIgnoredCoverWindow(hwnd, targetHwnd)) + continue + + coverRect := GetWindowRect(hwnd) + if (RectsOverlap(targetRect, coverRect)) + return hwnd + } + + return "" +} + +StoreMuMuCoverWindow(winTitle, coverHwnd := "") { + iniFile := GetScriptIniPathByName(winTitle) + if (coverHwnd && DllCall("IsWindow", "Ptr", coverHwnd)) + IniWrite, %coverHwnd%, %iniFile%, WindowState, coverHwnd + else + IniDelete, %iniFile%, WindowState, coverHwnd +} + +GetStoredMuMuCoverWindow(winTitle) { + iniFile := GetScriptIniPathByName(winTitle) + IniRead, coverHwnd, %iniFile%, WindowState, coverHwnd, + if (coverHwnd && DllCall("IsWindow", "Ptr", coverHwnd)) + return coverHwnd + return "" +} + +ClearStoredMuMuCoverWindow(winTitle) { + iniFile := GetScriptIniPathByName(winTitle) + IniDelete, %iniFile%, WindowState, coverHwnd +} + +GetMuMuCoverWindowForMaintenance(winTitle) { + coverHwnd := GetStoredMuMuCoverWindow(winTitle) + if (coverHwnd) + return coverHwnd + + return CaptureMuMuCoverWindow(winTitle) +} + +RestoreMuMuCoverWindow(coverHwnd, winTitle := "") { + if (winTitle != "") + ClearStoredMuMuCoverWindow(winTitle) + + if (!coverHwnd || !DllCall("IsWindow", "Ptr", coverHwnd) || !DllCall("IsWindowVisible", "Ptr", coverHwnd)) + return false + + if (DllCall("IsIconic", "Ptr", coverHwnd)) + return false + + ; Raise the previous covering window back above MuMu without stealing focus. + return DllCall("SetWindowPos", "Ptr", coverHwnd, "Ptr", 0 + , "Int", 0, "Int", 0, "Int", 0, "Int", 0, "UInt", 0x53) +} + CmdRet(sCmd, callBackFuncObj := "", encoding := "") { static HANDLE_FLAG_INHERIT := 0x00000001, flags := HANDLE_FLAG_INHERIT , STARTF_USESTDHANDLES := 0x100, CREATE_NO_WINDOW := 0x08000000 @@ -456,6 +705,8 @@ SerializeArray(arr) { restartInstance(){ global session + coverHwnd := CaptureMuMuCoverWindow(session.get("scriptName")) + StoreMuMuCoverWindow(session.get("scriptName"), coverHwnd) killInstance(session.get("scriptName")) Sleep, 2000 launchInstance(session.get("scriptName")) @@ -691,12 +942,13 @@ getScreenHandle(ParentTitle){ } FixInstanceScreen(instanceNo){ + windowMetrics := GetMumuWindowMetrics() instanceTitle := instanceNo . " ahk_class Qt5156QWindowIcon" SendMessage, 0x0005, 1, 0,, %instanceTitle% Sleep, 50 SendMessage, 0x0005, 0, 0,, %instanceTitle% Sleep, 500 - WinMove, %instanceTitle%, , , , 283, 532 + WinMove, %instanceTitle%, , , , % windowMetrics.scaleParam, % windowMetrics.rowHeight } getMuMuHwnd(winTitle) { @@ -746,6 +998,10 @@ AppendGPlog(message) { SplitPath, logPath,, logDir if !FileExist(logDir) FileCreateDir, %logDir% + if (IsFunc("RotateLogFileIfNeeded")) { + rotateFn := Func("RotateLogFileIfNeeded") + rotateFn.Call(logPath) + } FormatTime, readableTime, %A_Now%, MMMM dd, yyyy HH:mm:ss Loop, { FileAppend, % "[" readableTime "] " message "`n", %logPath% @@ -1007,8 +1263,158 @@ findAdbPath(targetDir) { return "" } +GetConfiguredDisplayScale() { + global botConfig + + displayScale := "" + try { + displayScale := botConfig.get("DisplayScale") + } catch { + } + + if (displayScale = "" || displayScale = "Auto") { + selectedMonitorIndex := "1" + try { + selectedMonitorIndex := RegExReplace(botConfig.get("SelectedMonitorIndex"), ":.*$") + } catch { + } + + monitorScales := GetAllMonitorScales() + if (monitorScales.HasKey(selectedMonitorIndex)) + return monitorScales[selectedMonitorIndex] + + return 100 + } + + if (InStr(displayScale, "125")) + return 125 + + return 100 +} + +GetMumuWindowMetrics() { + displayScale := GetConfiguredDisplayScale() + metrics := {} + + if (displayScale = 125) { + if (IsMuMuv5()) { + metrics.scaleParam := 283 + metrics.titleHeight := 50 + } else { + metrics.scaleParam := 277 + metrics.titleHeight := 45 + } + } else { + metrics.scaleParam := 283 + metrics.titleHeight := 40 + } + + metrics.rowHeight := metrics.titleHeight + 492 + metrics.imageSearchYBias := (displayScale = 125) ? metrics.titleHeight - 45 : 0 + return metrics +} + +GetAdbClickMetrics() { + metrics := {} + + if (GetConfiguredDisplayScale() = 125) { + ; Keep the working Scale 125 tap mapping from v9.5.9. This coordinate + ; space is independent from the window chrome/image-search yBias. + metrics.convX := 540/277 + metrics.convY := 960/489 + metrics.offset := -44 + } else { + metrics.convX := 540/283 + metrics.convY := 960/488 + metrics.offset := -40 + } + + return metrics +} + +IsMuMuv5() { + static cachedIsMuMuv5 := "" + + if (cachedIsMuMuv5 != "") + return cachedIsMuMuv5 + + mumuFolder := getMuMuFolder() + cachedIsMuMuv5 := (mumuFolder != "" && FileExist(mumuFolder . "\nx_main")) ? 1 : 0 + return cachedIsMuMuv5 +} + +ResolveNeedlePath(path) { + if (GetConfiguredDisplayScale() != 125) + return path + + if (!IsScale125NeedleFallbackAllowed(path)) + return path + + scale125Path := StrReplace(path, "\Needles\", "\Scale125\") + if (scale125Path != path && FileExist(scale125Path)) + return scale125Path + + return path +} + +IsScale125NeedleFallbackAllowed(path) { + SplitPath, path, fileName + + if (fileName = "") + return false + + if (IsScale125RarityNeedle(fileName)) + return true + + static allowedUiNeedles := "" + if (!IsObject(allowedUiNeedles)) { + allowedUiNeedles := {} + ; Shared Needles are the default. These are legacy pixel-sensitive + ; Scale 125 UI fallbacks that differ from the shared asset set. + for _, allowedName in ["Account.png" + , "CloseAlertWindow.png" + , "Error.png" + , "Friend2.png" + , "FriendSearchButton.png" + , "GoToTitle.png" + , "HardwareReqs.png" + , "Hourglass1.png" + , "InSubMenu.png" + , "Mission_dino2.png" + , "noWPenergy.png" + , "OK2.png" + , "One.png" + , "Settings.png" + , "speedmodMenu.png" + , "SwipeUp.png" + , "Three.png" + , "Two.png" + , "WonderPickRaminItems.png"] { + allowedUiNeedles[allowedName] := true + } + } + + return allowedUiNeedles.HasKey(fileName) +} + +IsScale125RarityNeedle(fileName) { + return RegExMatch(fileName, "i)^(1star|3diamond|crown|gimmighoul|immersive|normal|rainbow|shiny1star|ShinyEx_ex_|trainer)\d+\.png$") +} + +GetScaleProfileValue(scale100Value, scale125Value) { + return (GetConfiguredDisplayScale() = 125) ? scale125Value : scale100Value +} + GetAllMonitorScales() { scales := {} + oldDpiContext := 0 + try { + ; GetDpiForMonitor returns system DPI for every monitor unless the + ; calling thread is per-monitor DPI aware while querying. + oldDpiContext := DllCall("User32\SetThreadDpiAwarenessContext", "Ptr", -3, "Ptr") + } catch { + oldDpiContext := 0 + } SysGet, monitorCount, MonitorCount @@ -1029,6 +1435,13 @@ GetAllMonitorScales() { scales[A_Index] := scalePercent } } + + if (oldDpiContext) { + try { + DllCall("User32\SetThreadDpiAwarenessContext", "Ptr", oldDpiContext, "Ptr") + } catch { + } + } return scales -} \ No newline at end of file +} diff --git a/Scripts/Main.ahk b/Scripts/Main.ahk index d81aa249..80a6da6e 100644 --- a/Scripts/Main.ahk +++ b/Scripts/Main.ahk @@ -1,4 +1,4 @@ -#SingleInstance on +#SingleInstance, Force SetMouseDelay, -1 SetDefaultMouseSpeed, 0 SetBatchLines, -1 @@ -30,9 +30,7 @@ CoordMode, Pixel, Screen #Include Utils.ahk #Include Crinity_UnofficialPatch.ahk -; Allocate and hide the console window to reduce flashing -DllCall("AllocConsole") -WinHide % "ahk_id " DllCall("GetConsoleWindow", "ptr") +InitializeHiddenConsole() pToken := Gdip_Startup() @@ -70,14 +68,14 @@ session.set("isDead", isDeadValue) if (!botConfig.get("groupRerollEnabled")) { session.set("autoUseGPTest", 0) session.set("TestTime", 3600) - session.set("hasUnopenedPack", 0) } session.set("vipListTrimMode", (!botConfig.get("vipListTrimMode")) ? "bottom" : botConfig.get("vipListTrimMode")) session.set("vipListTrimCount", (!botConfig.get("vipListTrimCount")) ? 60 : botConfig.get("vipListTrimCount")) (session.get("vipListTrimCount") = "" || session.get("vipListTrimCount") < 1) ? session.set("vipListTrimCount", 60) -DirectlyPositionWindow() +windowCoverHwnd := GetMuMuCoverWindowForMaintenance(session.get("winTitle")) +DirectlyPositionWindow(windowCoverHwnd) Sleep, 1000 setADBBaseInfo() @@ -88,7 +86,7 @@ Sleep, 1000 CreateStatusMessage("Disabling background services...") DisableBackgroundServices() -resetWindows() +resetWindows(windowCoverHwnd) MaxRetries := 10 RetryCount := 0 Loop { @@ -112,6 +110,7 @@ Loop { DllCall("SetWindowPos", "Ptr", WinExist(), "Ptr", 1 ; HWND_BOTTOM , "Int", 0, "Int", 0, "Int", 0, "Int", 0, "UInt", 0x13) ; SWP_NOSIZE, SWP_NOMOVE, SWP_NOACTIVATE Gui, ToolBar:Show, NoActivate x%x4% y%y4% w275 h30 + RestoreMuMuCoverWindow(windowCoverHwnd, session.get("winTitle")) break } catch { @@ -203,33 +202,14 @@ Loop { Delay(1) clickButton := FindOrLoseImage("Common_ColorChangeButton", 0, failSafeTime, 80) requestAlreadyClosed := FindOrLoseImage("Friend_RequestAlreadyClosedInApproveSubmenu", 0, failSafeTime) - if(FindOrLoseImage("Friend_FriendList99", 0, failSafeTime)) { + if(FindOrLoseImage("FriendLimit", 0, failSafeTime)) { + if (botConfig.get("blockedFriendRequestHotfix")) { + if (HandleBlockedFriendRequest(failSafeTime)) + Break, 2 + } done := true break } - else if(FindOrLoseImage("Friend_AcceptButtonInApproveSubmenu", 0, failSafeTime)) { - if (session.get("GPTest")) - break - Loop{ - if FindOrLoseImage("Friend_StuckMessageBackground", 0, failSafeTime){ - Delay(2) - }else{ - adbClick(237, 202) - Delay(1) - if FindOrLoseImage("Friend_StuckMessageBackground", 0, failSafeTime){ - Loop{ - if FindOrLoseImage("Friend_StuckMessageBackground", 1, failSafeTime){ - break - }else{ - Delay(1) - } - } - FindImageAndClick("Friend_StuckMessageBackground", 202, 202, , 1000) - } - break - } - } - } else if(FindOrLoseImage("Common_Error", 0, failSafeTime)) { ; Handle communication error CreateStatusMessage("Error message detected. Clicking retry...",,,, false) @@ -239,7 +219,7 @@ Loop { Sleep, 1000 adbClick(139, 386) ; Click OK/confirm Sleep, 1000 - SafeReload() + SafeReload("Main communication error") } else if(FindOrLoseImage("StartupErrorX", 0, failSafeTime)) { ; Handle startup error with X button CreateStatusMessage("Start-up error detected. Clearing and reloading...",,,, false) @@ -247,7 +227,7 @@ Loop { Sleep, 2000 adbClick(139, 440) ; Click X to close error Sleep, 4000 - SafeReload() + SafeReload("Main startup error") } else if(requestAlreadyClosed || clickButton) { okClickSpacing := botConfig.get("Delay") * 2 if (okClickSpacing < 700) @@ -293,11 +273,61 @@ Loop { } return +HandleBlockedFriendRequest(ByRef failSafeTime) { + global session + + CreateStatusMessage("Blocked friend request detected. Denying...",,,, false) + LogToFile("Blocked friend request detected in Main " . session.get("scriptName") . ". Denying top request...") + + WaitForFriendLimitNoticeToClear(failSafeTime) + + if (FindOrLoseImage("Friend_DenyButtonInApproveSubmenu", 0, failSafeTime, 20, 1)) { + adbClick(202, 210) + if (WaitForFriendLimitNotice(failSafeTime)) + WaitForFriendLimitNoticeToClear(failSafeTime) + return true + } + + LogToFile("Blocked friend request handling skipped in Main " . session.get("scriptName") . ": deny button not found.") + return false +} + +WaitForFriendLimitNotice(ByRef failSafeTime, maxSeconds := 3) { + global session + + startTime := A_TickCount + Loop { + if (FindOrLoseImage("FriendLimit", 0, failSafeTime, 20, 1)) + return true + if ((A_TickCount - startTime) >= maxSeconds * 1000) + return false + Delay(0.25) + failSafeTime := (A_TickCount - session.get("failSafe")) // 1000 + } +} + +WaitForFriendLimitNoticeToClear(ByRef failSafeTime, maxSeconds := 10) { + global session + + startTime := A_TickCount + Loop { + if (!FindOrLoseImage("FriendLimit", 0, failSafeTime, 20, 1)) + return true + if ((A_TickCount - startTime) >= maxSeconds * 1000) + return false + Delay(0.5) + failSafeTime := (A_TickCount - session.get("failSafe")) // 1000 + } +} + FindOrLoseImage(needleName := "DEFAULT", EL := 1, safeTime := 0, searchVariation := 20, notShowFinding := 0) { global session, needlesDict static lastStatusTime := 0 - needleObj := needlesDict.Get(needleName) + needleObj := GetSearchNeedleObj(needleName, "FindOrLoseImage") + if (!IsObject(needleObj)) + return false + imageName := needleObj.imageName imagePath := A_ScriptDir . "\Needles\" @@ -319,7 +349,7 @@ FindOrLoseImage(needleName := "DEFAULT", EL := 1, safeTime := 0, searchVariation ;bboxAndPause(X1, Y1, X2, Y2) ; ImageSearch within the region - vRet := Gdip_ImageSearch(pBitmap, pNeedle, vPosXY, X1, Y1, X2, Y2, searchVariation) + vRet := Gdip_ImageSearch_wbb(pBitmap, pNeedle, vPosXY, X1, Y1, X2, Y2, searchVariation) ErrorCheckInScreen(pBitmap) Gdip_DisposeImage(pBitmap) if(EL = 0) @@ -348,7 +378,10 @@ FindOrLoseImage(needleName := "DEFAULT", EL := 1, safeTime := 0, searchVariation FindImageAndClick(needleName := "DEFAULT", clickx := 0, clicky := 0, searchVariation := 20, sleepTime := "", skip := false, safeTime := 0) { global botConfig, session, needlesDict - needleObj := needlesDict.Get(needleName) + needleObj := GetSearchNeedleObj(needleName, "FindImageAndClick") + if (!IsObject(needleObj)) + return false + imageName := needleObj.imageName if (sleepTime = "") { @@ -394,7 +427,7 @@ FindImageAndClick(needleName := "DEFAULT", clickx := 0, clicky := 0, searchVaria Y2 := needleObj.coords.endY ;bboxAndPause(X1, Y1, X2, Y2) ; ImageSearch within the region - vRet := Gdip_ImageSearch(pBitmap, pNeedle, vPosXY, X1, Y1, X2, Y2, searchVariation) + vRet := Gdip_ImageSearch_wbb(pBitmap, pNeedle, vPosXY, X1, Y1, X2, Y2, searchVariation) ErrorCheckInScreen(pBitmap) Gdip_DisposeImage(pBitmap) if (!confirmed && vRet = 1) { @@ -416,7 +449,7 @@ FindImageAndClick(needleName := "DEFAULT", clickx := 0, clicky := 0, searchVaria Path = %imagePath%Error1.png pNeedle := GetNeedle(Path) ; ImageSearch within the region - vRet := Gdip_ImageSearch(pBitmap, pNeedle, vPosXY, 15, 155, 270, 420, searchVariation) + vRet := Gdip_ImageSearchProfile_wbb(pBitmap, pNeedle, vPosXY, [15, 155, 270, 420], [15, 155, 270, 420], searchVariation) Gdip_DisposeImage(pBitmap) if (vRet = 1) { CreateStatusMessage("Error message in " . session.get("scriptName") . ". Clicking retry...") @@ -443,10 +476,11 @@ FindImageAndClick(needleName := "DEFAULT", clickx := 0, clicky := 0, searchVaria return confirmed } -resetWindows(){ - global botConfig +resetWindows(coverHwnd := ""){ + global botConfig, session - scaleParam := 283 + windowMetrics := GetMumuWindowMetrics() + scaleParam := windowMetrics.scaleParam CreateStatusMessage("Arranging window positions and sizes") RetryCount := 0 MaxRetries := 10 @@ -455,13 +489,15 @@ resetWindows(){ SelectedMonitorIndex := RegExReplace(botConfig.get("SelectedMonitorIndex"), ":.*$") SysGet, Monitor, Monitor, %SelectedMonitorIndex% Title := session.get("winTitle") + if (!coverHwnd) + coverHwnd := GetMuMuCoverWindowForMaintenance(Title) instanceIndex := StrReplace(Title, "Main", "") if (instanceIndex = "") instanceIndex := 1 borderWidth := 4 - 1 - rowHeight := 40 + 492 + rowHeight := windowMetrics.rowHeight currentRow := Floor((instanceIndex - 1) / botConfig.get("Columns")) y := MonitorTop + (currentRow * rowHeight) + (currentRow * botConfig.get("rowGap")) @@ -471,6 +507,7 @@ resetWindows(){ WinMove, %Title%, , %x%, %y%, %scaleParam%, %rowHeight% WinSet, Style, +0xC00000, %Title% WinSet, Redraw, , %Title% + RestoreMuMuCoverWindow(coverHwnd, Title) break } catch { @@ -488,6 +525,9 @@ resetWindows(){ restartGameInstance(reason, RL := true){ global botConfig, session + if (InStr(reason, "Stuck at ")) + SaveStuckScreenshot(reason) + if(botConfig.get("heartBeatOwnerWebHookURL") != "") LogToDiscord(A_ScriptName . " instance has begin restart. Please verify that GodPack has not disappeared upon entering the main screen.\nReasion: " . reason,, true,,, botConfig.get("heartBeatOwnerWebHookURL")) @@ -506,7 +546,31 @@ restartGameInstance(reason, RL := true){ LogToFile("Restarted game. Reason: " reason) session.set("isDead", true) IniWrite, 1, % session.get("scriptIniFile"), Metrics, isDead - SafeReload() + SafeReload("Main restart game: " . reason) + } +} + +SaveStuckScreenshot(reason) { + global session + + fileDir := A_ScriptDir . "\..\Screenshots\Stuck" + if !FileExist(fileDir) + FileCreateDir, %fileDir% + + safeReason := RegExReplace(reason, "[\\/:*?""<>|]", "_") + safeReason := RegExReplace(safeReason, "\s+", "_") + safeReason := SubStr(safeReason, 1, 80) + filePath := fileDir . "\" . A_Now . "_inst" . session.get("scriptName") . "_" . safeReason . ".png" + + hWnd := getMuMuHwnd(session.get("winTitle")) + if (!hWnd) + return + + pBitmap := from_window(hWnd) + if (pBitmap) { + Gdip_SaveBitmapToFile(pBitmap, filePath) + Gdip_DisposeImage(pBitmap) + LogToFile("Saved stuck screenshot: " . filePath) } } @@ -553,7 +617,8 @@ Screenshot(fileType := "Valid", subDir := "", ByRef fileName := "") { fileName := "packstats_temp.png" filePath := fileDir "\" . fileName - yBias := 40 - 45 + windowMetrics := GetMumuWindowMetrics() + yBias := windowMetrics.titleHeight - 45 pBitmapW := from_window(getMuMuHwnd(session.get("winTitle"))) pBitmap := Gdip_CloneBitmapArea(pBitmapW, 18, 71+yBias, 240, 165) @@ -708,7 +773,7 @@ VipTrimGuiEscape: return ReloadScript: - SafeReload() + SafeReload("Main toolbar reload") return TestScript: @@ -738,7 +803,7 @@ ToggleTestScript() { } } -~+F5::SafeReload() +~+F5::SafeReload("Main Shift+F5") ~+F6::Pause ~+F10:: Gosub, StopScript @@ -775,12 +840,19 @@ bboxAndPause(X1, Y1, X2, Y2, doPause := False) { GetNeedle(Path) { static NeedleBitmaps := Object() + Path := ResolveNeedlePath(Path) + if (NeedleBitmaps.HasKey(Path)) { return NeedleBitmaps[Path] } else { pNeedle := Gdip_CreateBitmapFromFile(Path) - NeedleBitmaps[Path] := pNeedle - return pNeedle + needleObj := Object() + needleObj.Path := Path + pathsplit := StrSplit(Path , "\") + needleObj.Name := pathsplit[pathsplit.MaxIndex()] + needleObj.needle := pNeedle + NeedleBitmaps[Path] := needleObj + return needleObj } } @@ -842,9 +914,11 @@ CheckFriendOpsRateLimit() { session.set("friendOpsCount", 0) session.set("friendOpsWindowStart", A_TickCount) } else if (session.get("A_gptest")) { + LogToFile("FriendOps rate limit reached | script=" . session.get("scriptName") . " | mode=auto | count=" . session.get("friendOpsCount") . " | remainingMs=" . remaining, "GroupReroll.txt") return false } else { ; Manual mode: show countdown dialog with two cancel options + LogToFile("FriendOps rate limit reached | script=" . session.get("scriptName") . " | mode=manual | count=" . session.get("friendOpsCount") . " | remainingMs=" . remaining, "GroupReroll.txt") session.set("rateLimitAction", "") Gui, RateLimit:Destroy Gui, RateLimit:New, +AlwaysOnTop, GP Test - Rate Limit @@ -872,6 +946,7 @@ CheckFriendOpsRateLimit() { ; Timer expired ? reset and continue session.set("friendOpsCount", 0) session.set("friendOpsWindowStart", A_TickCount) + LogToFile("FriendOps rate limit wait complete | script=" . session.get("scriptName"), "GroupReroll.txt") } } session.set("friendOpsCount", session.get("friendOpsCount") + 1) @@ -1067,11 +1142,14 @@ FavoriteVipFriends() { } rateLimitHit := false FindImageAndClick("Friend_RemoveConfirmButtonInFriendDetails", 145, 407, , 500) + removeWaitStart := A_TickCount + interceptProc := true Loop { + removeWaitTime := (A_TickCount - removeWaitStart) // 1000 adbClick_wbb(200, 372) - if (FindOrLoseImage("Friend_ReqeustButtonInFriendDetails", 0)) + if (FindOrLoseImage("Friend_ReqeustButtonInFriendDetails", 0, removeWaitTime)) break - if (session.get("hasUnopenedPack") && FindOrLoseImage("Common_Error", 0)) { + if (session.get("hasUnopenedPack") && FindOrLoseImage("Common_Error", 0, removeWaitTime)) { CreateStatusMessage("Rate limit hit. Recovering...",,,, false) interceptProc := true Loop, 5 { @@ -1105,6 +1183,7 @@ FavoriteVipFriends() { } Delay(1) } + interceptProc := false if (rateLimitHit) continue 2 Delay(1) @@ -1202,7 +1281,7 @@ FavoriteVipFriends() { ; Removes non-favourited friends starting from the bottom of the list. ; Stops when a favourited (VIP) friend is encountered. RemoveNonVipFriends() { - global session + global session, interceptProc ; Navigate to Social screen session.set("failSafe", A_TickCount) @@ -1365,11 +1444,14 @@ RemoveNonVipFriends() { } rateLimitHit := false FindImageAndClick("Friend_RemoveConfirmButtonInFriendDetails", 145, 407, , 500) + removeWaitStart := A_TickCount + interceptProc := true Loop { + removeWaitTime := (A_TickCount - removeWaitStart) // 1000 adbClick_wbb(200, 372) - if (FindOrLoseImage("Friend_ReqeustButtonInFriendDetails", 0)) + if (FindOrLoseImage("Friend_ReqeustButtonInFriendDetails", 0, removeWaitTime)) break - if (session.get("hasUnopenedPack") && FindOrLoseImage("Common_Error", 0)) { + if (session.get("hasUnopenedPack") && FindOrLoseImage("Common_Error", 0, removeWaitTime)) { CreateStatusMessage("Rate limit hit. Recovering...",,,, false) Loop, 5 { adbClick_wbb(139, 371) @@ -1404,6 +1486,7 @@ RemoveNonVipFriends() { } Delay(1) } + interceptProc := false if (rateLimitHit) continue FindImageAndClick("Friend_AddButtonInFriendList", 143, 507, , 1500) @@ -1416,11 +1499,18 @@ RemoveNonVipFriends() { session.set("A_gptest", 0) session.set("autotest", A_TickCount) ToggleTestScript() + } else { + session.set("triggerTestNeeded", false) + CreateStatusMessage("GP Test cleanup done. Waiting.",,,, false) + return } CreateStatusMessage("Ready to test.",,,, false) } else if (session.get("A_gptest") && session.get("autoUseGPTest")) { session.set("A_gptest", 0) ToggleTestScript() + } else { + session.set("triggerTestNeeded", false) + CreateStatusMessage("GP Test cleanup done. Waiting.",,,, false) } } @@ -1948,17 +2038,31 @@ Gdip_ImageSearch_wbb(pBitmapHaystack,pNeedle,ByRef OutputList="" ; Returns: Result from Gdip_ImageSearch ; ------------------------------------------------------------------------------ global session - yBias := 40 - 45 + windowMetrics := GetMumuWindowMetrics() + yBias := windowMetrics.imageSearchYBias vret := Gdip_ImageSearch(pBitmapHaystack,pNeedle.needle,OutputList,OuterX1,OuterY1+yBias,OuterX2,OuterY2+yBias,Variation,Trans,SearchDirection,Instances,LineDelim,CoordDelim) if(session.get("dbg_bbox")) bboxAndPause_immage(OuterX1, OuterY1+yBias, OuterX2, OuterY2+yBias, pNeedle, vret, session.get("dbg_bboxNpause")) return vret } -DirectlyPositionWindow() { +Gdip_ImageSearchProfile_wbb(pBitmapHaystack, pNeedle, ByRef OutputList="" + , coords100="", coords125="", Variation=0, Trans="" + , SearchDirection=1, Instances=1, LineDelim="`n", CoordDelim=",") { + if (!IsObject(coords125)) + coords125 := coords100 + + coords := GetScaleProfileValue(coords100, coords125) + return Gdip_ImageSearch_wbb(pBitmapHaystack, pNeedle, OutputList + , coords[1], coords[2], coords[3], coords[4], Variation, Trans + , SearchDirection, Instances, LineDelim, CoordDelim) +} + +DirectlyPositionWindow(coverHwnd := "") { global botConfig, session - scaleParam := 283 + windowMetrics := GetMumuWindowMetrics() + scaleParam := windowMetrics.scaleParam rowGap := botConfig.get("RowGap") ; Get monitor information @@ -1967,15 +2071,17 @@ DirectlyPositionWindow() { ; Calculate position based on instance number Title := session.get("winTitle") + if (!coverHwnd) + coverHwnd := GetMuMuCoverWindowForMaintenance(Title) instanceIndex := StrReplace(Title, "Main", "") if (instanceIndex = "") instanceIndex := 1 - titleHeight := 40 + titleHeight := windowMetrics.titleHeight borderWidth := 4 - 1 - rowHeight := titleHeight + 492 + rowHeight := windowMetrics.rowHeight currentRow := Floor((instanceIndex - 1) / botConfig.get("Columns")) y := MonitorTop + (currentRow * rowHeight) + (currentRow * rowGap) @@ -1987,6 +2093,7 @@ DirectlyPositionWindow() { WinSet, Redraw, , %Title% CreateStatusMessage("Positioned window at x:" . x . " y:" . y,,,, false) + RestoreMuMuCoverWindow(coverHwnd, Title) return true } diff --git a/Scripts/Needles/Friend2.png b/Scripts/Needles/Friend2.png new file mode 100644 index 00000000..6e215377 Binary files /dev/null and b/Scripts/Needles/Friend2.png differ diff --git a/Scripts/Needles/FriendLimit.png b/Scripts/Needles/FriendLimit.png new file mode 100644 index 00000000..861fd5c3 Binary files /dev/null and b/Scripts/Needles/FriendLimit.png differ diff --git a/Scripts/Scale125/MissionDeck.png b/Scripts/Needles/MissionDeck.png similarity index 100% rename from Scripts/Scale125/MissionDeck.png rename to Scripts/Needles/MissionDeck.png diff --git a/Scripts/Scale125/Update.png b/Scripts/Needles/Update.png similarity index 100% rename from Scripts/Scale125/Update.png rename to Scripts/Needles/Update.png diff --git a/Scripts/Scale125/1solobattlemission.png b/Scripts/Scale125/1solobattlemission.png deleted file mode 100644 index eba150b5..00000000 Binary files a/Scripts/Scale125/1solobattlemission.png and /dev/null differ diff --git a/Scripts/Scale125/1star6card4.png b/Scripts/Scale125/1star6card4.png deleted file mode 100644 index c9565f94..00000000 Binary files a/Scripts/Scale125/1star6card4.png and /dev/null differ diff --git a/Scripts/Scale125/1star6card6.png b/Scripts/Scale125/1star6card6.png deleted file mode 100644 index 29bcd3c9..00000000 Binary files a/Scripts/Scale125/1star6card6.png and /dev/null differ diff --git a/Scripts/Scale125/3diamond6card4.png b/Scripts/Scale125/3diamond6card4.png deleted file mode 100644 index b0e29476..00000000 Binary files a/Scripts/Scale125/3diamond6card4.png and /dev/null differ diff --git a/Scripts/Scale125/3diamond6card5.png b/Scripts/Scale125/3diamond6card5.png deleted file mode 100644 index 199882f7..00000000 Binary files a/Scripts/Scale125/3diamond6card5.png and /dev/null differ diff --git a/Scripts/Scale125/6cardpackindicator.png b/Scripts/Scale125/6cardpackindicator.png deleted file mode 100644 index 4cb4a405..00000000 Binary files a/Scripts/Scale125/6cardpackindicator.png and /dev/null differ diff --git a/Scripts/Scale125/99cn.png b/Scripts/Scale125/99cn.png deleted file mode 100644 index fdaf52d4..00000000 Binary files a/Scripts/Scale125/99cn.png and /dev/null differ diff --git a/Scripts/Scale125/99de.png b/Scripts/Scale125/99de.png deleted file mode 100644 index 4c404cdd..00000000 Binary files a/Scripts/Scale125/99de.png and /dev/null differ diff --git a/Scripts/Scale125/99en.png b/Scripts/Scale125/99en.png deleted file mode 100644 index 3e5e3ca9..00000000 Binary files a/Scripts/Scale125/99en.png and /dev/null differ diff --git a/Scripts/Scale125/99es.png b/Scripts/Scale125/99es.png deleted file mode 100644 index fa658232..00000000 Binary files a/Scripts/Scale125/99es.png and /dev/null differ diff --git a/Scripts/Scale125/99fr.png b/Scripts/Scale125/99fr.png deleted file mode 100644 index ae2a748d..00000000 Binary files a/Scripts/Scale125/99fr.png and /dev/null differ diff --git a/Scripts/Scale125/99it.png b/Scripts/Scale125/99it.png deleted file mode 100644 index c84f1235..00000000 Binary files a/Scripts/Scale125/99it.png and /dev/null differ diff --git a/Scripts/Scale125/99jp.png b/Scripts/Scale125/99jp.png deleted file mode 100644 index 845bfb97..00000000 Binary files a/Scripts/Scale125/99jp.png and /dev/null differ diff --git a/Scripts/Scale125/99ko.png b/Scripts/Scale125/99ko.png deleted file mode 100644 index ba0598b9..00000000 Binary files a/Scripts/Scale125/99ko.png and /dev/null differ diff --git a/Scripts/Scale125/99pt.png b/Scripts/Scale125/99pt.png deleted file mode 100644 index 68df2688..00000000 Binary files a/Scripts/Scale125/99pt.png and /dev/null differ diff --git a/Scripts/Scale125/Accept.png b/Scripts/Scale125/Accept.png deleted file mode 100644 index 57511ab8..00000000 Binary files a/Scripts/Scale125/Accept.png and /dev/null differ diff --git a/Scripts/Scale125/Accepted.png b/Scripts/Scale125/Accepted.png deleted file mode 100644 index c3d9de15..00000000 Binary files a/Scripts/Scale125/Accepted.png and /dev/null differ diff --git a/Scripts/Scale125/Accepted2.png b/Scripts/Scale125/Accepted2.png deleted file mode 100644 index 2e4aa34f..00000000 Binary files a/Scripts/Scale125/Accepted2.png and /dev/null differ diff --git a/Scripts/Scale125/Account2.png b/Scripts/Scale125/Account2.png deleted file mode 100644 index 28ea9c2f..00000000 Binary files a/Scripts/Scale125/Account2.png and /dev/null differ diff --git a/Scripts/Scale125/Add.png b/Scripts/Scale125/Add.png deleted file mode 100644 index b9944623..00000000 Binary files a/Scripts/Scale125/Add.png and /dev/null differ diff --git a/Scripts/Scale125/Add2.png b/Scripts/Scale125/Add2.png deleted file mode 100644 index 1c325a8d..00000000 Binary files a/Scripts/Scale125/Add2.png and /dev/null differ diff --git a/Scripts/Scale125/AddGray.png b/Scripts/Scale125/AddGray.png deleted file mode 100644 index 2e74db79..00000000 Binary files a/Scripts/Scale125/AddGray.png and /dev/null differ diff --git a/Scripts/Scale125/Album.png b/Scripts/Scale125/Album.png deleted file mode 100644 index 5137ce0e..00000000 Binary files a/Scripts/Scale125/Album.png and /dev/null differ diff --git a/Scripts/Scale125/App.png b/Scripts/Scale125/App.png deleted file mode 100644 index 5950f4af..00000000 Binary files a/Scripts/Scale125/App.png and /dev/null differ diff --git a/Scripts/Scale125/Approve.png b/Scripts/Scale125/Approve.png deleted file mode 100644 index 59183260..00000000 Binary files a/Scripts/Scale125/Approve.png and /dev/null differ diff --git a/Scripts/Scale125/Badge.png b/Scripts/Scale125/Badge.png deleted file mode 100644 index a05413a5..00000000 Binary files a/Scripts/Scale125/Badge.png and /dev/null differ diff --git a/Scripts/Scale125/Birth.png b/Scripts/Scale125/Birth.png deleted file mode 100644 index aea48361..00000000 Binary files a/Scripts/Scale125/Birth.png and /dev/null differ diff --git a/Scripts/Scale125/Booster.png b/Scripts/Scale125/Booster.png deleted file mode 100644 index 23d23bf0..00000000 Binary files a/Scripts/Scale125/Booster.png and /dev/null differ diff --git a/Scripts/Scale125/Border.png b/Scripts/Scale125/Border.png deleted file mode 100644 index 8eb4781e..00000000 Binary files a/Scripts/Scale125/Border.png and /dev/null differ diff --git a/Scripts/Scale125/Bulba.png b/Scripts/Scale125/Bulba.png deleted file mode 100644 index 46431f1c..00000000 Binary files a/Scripts/Scale125/Bulba.png and /dev/null differ diff --git a/Scripts/Scale125/Button.png b/Scripts/Scale125/Button.png deleted file mode 100644 index d5e30b02..00000000 Binary files a/Scripts/Scale125/Button.png and /dev/null differ diff --git a/Scripts/Scale125/Button2.png b/Scripts/Scale125/Button2.png deleted file mode 100644 index d04d6d53..00000000 Binary files a/Scripts/Scale125/Button2.png and /dev/null differ diff --git a/Scripts/Scale125/Card.png b/Scripts/Scale125/Card.png deleted file mode 100644 index 58fa2836..00000000 Binary files a/Scripts/Scale125/Card.png and /dev/null differ diff --git a/Scripts/Scale125/ChooseEevee.png b/Scripts/Scale125/ChooseEevee.png deleted file mode 100644 index 59ee5290..00000000 Binary files a/Scripts/Scale125/ChooseEevee.png and /dev/null differ diff --git a/Scripts/Scale125/ChooseErika.png b/Scripts/Scale125/ChooseErika.png deleted file mode 100644 index 59ee5290..00000000 Binary files a/Scripts/Scale125/ChooseErika.png and /dev/null differ diff --git a/Scripts/Scale125/ChosenTag.png b/Scripts/Scale125/ChosenTag.png deleted file mode 100644 index a52a56af..00000000 Binary files a/Scripts/Scale125/ChosenTag.png and /dev/null differ diff --git a/Scripts/Scale125/Cinematic.png b/Scripts/Scale125/Cinematic.png deleted file mode 100644 index 93936ac5..00000000 Binary files a/Scripts/Scale125/Cinematic.png and /dev/null differ diff --git a/Scripts/Scale125/ClaimAll.png b/Scripts/Scale125/ClaimAll.png deleted file mode 100644 index 7e1d4599..00000000 Binary files a/Scripts/Scale125/ClaimAll.png and /dev/null differ diff --git a/Scripts/Scale125/CloseAlertWindow.png b/Scripts/Scale125/CloseAlertWindow.png new file mode 100644 index 00000000..de58e5c6 Binary files /dev/null and b/Scripts/Scale125/CloseAlertWindow.png differ diff --git a/Scripts/Scale125/CollectDailies.png b/Scripts/Scale125/CollectDailies.png deleted file mode 100644 index c33adc57..00000000 Binary files a/Scripts/Scale125/CollectDailies.png and /dev/null differ diff --git a/Scripts/Scale125/CommunityShowcase.png b/Scripts/Scale125/CommunityShowcase.png deleted file mode 100644 index aec5e073..00000000 Binary files a/Scripts/Scale125/CommunityShowcase.png and /dev/null differ diff --git a/Scripts/Scale125/Complete.png b/Scripts/Scale125/Complete.png deleted file mode 100644 index 62cd15e1..00000000 Binary files a/Scripts/Scale125/Complete.png and /dev/null differ diff --git a/Scripts/Scale125/Confirm.png b/Scripts/Scale125/Confirm.png deleted file mode 100644 index cf3562b2..00000000 Binary files a/Scripts/Scale125/Confirm.png and /dev/null differ diff --git a/Scripts/Scale125/ConfirmPack.png b/Scripts/Scale125/ConfirmPack.png deleted file mode 100644 index 7ad12c13..00000000 Binary files a/Scripts/Scale125/ConfirmPack.png and /dev/null differ diff --git a/Scripts/Scale125/Country.png b/Scripts/Scale125/Country.png deleted file mode 100644 index b552a4e5..00000000 Binary files a/Scripts/Scale125/Country.png and /dev/null differ diff --git a/Scripts/Scale125/CountrySelect.png b/Scripts/Scale125/CountrySelect.png deleted file mode 100644 index 6e80da84..00000000 Binary files a/Scripts/Scale125/CountrySelect.png and /dev/null differ diff --git a/Scripts/Scale125/CountrySelect2.png b/Scripts/Scale125/CountrySelect2.png deleted file mode 100644 index 26449542..00000000 Binary files a/Scripts/Scale125/CountrySelect2.png and /dev/null differ diff --git a/Scripts/Scale125/DailyMissions.png b/Scripts/Scale125/DailyMissions.png deleted file mode 100644 index 1fb9fb86..00000000 Binary files a/Scripts/Scale125/DailyMissions.png and /dev/null differ diff --git a/Scripts/Scale125/DataDownload.png b/Scripts/Scale125/DataDownload.png deleted file mode 100644 index bfc0248f..00000000 Binary files a/Scripts/Scale125/DataDownload.png and /dev/null differ diff --git a/Scripts/Scale125/Delete.png b/Scripts/Scale125/Delete.png deleted file mode 100644 index e8250f7f..00000000 Binary files a/Scripts/Scale125/Delete.png and /dev/null differ diff --git a/Scripts/Scale125/Delete2.png b/Scripts/Scale125/Delete2.png deleted file mode 100644 index 9a1993b0..00000000 Binary files a/Scripts/Scale125/Delete2.png and /dev/null differ diff --git a/Scripts/Scale125/Delete3.png b/Scripts/Scale125/Delete3.png deleted file mode 100644 index 8795dbce..00000000 Binary files a/Scripts/Scale125/Delete3.png and /dev/null differ diff --git a/Scripts/Scale125/DeleteAll.png b/Scripts/Scale125/DeleteAll.png deleted file mode 100644 index 7c28547c..00000000 Binary files a/Scripts/Scale125/DeleteAll.png and /dev/null differ diff --git a/Scripts/Scale125/DeleteFriend.png b/Scripts/Scale125/DeleteFriend.png deleted file mode 100644 index 838e9b6a..00000000 Binary files a/Scripts/Scale125/DeleteFriend.png and /dev/null differ diff --git a/Scripts/Scale125/DexMissions.png b/Scripts/Scale125/DexMissions.png deleted file mode 100644 index 9693195c..00000000 Binary files a/Scripts/Scale125/DexMissions.png and /dev/null differ diff --git a/Scripts/Scale125/Eevee.png b/Scripts/Scale125/Eevee.png deleted file mode 100644 index f64e5057..00000000 Binary files a/Scripts/Scale125/Eevee.png and /dev/null differ diff --git a/Scripts/Scale125/Erase.png b/Scripts/Scale125/Erase.png deleted file mode 100644 index 1fee93d4..00000000 Binary files a/Scripts/Scale125/Erase.png and /dev/null differ diff --git a/Scripts/Scale125/Erika.png b/Scripts/Scale125/Erika.png deleted file mode 100644 index 39b34ef3..00000000 Binary files a/Scripts/Scale125/Erika.png and /dev/null differ diff --git a/Scripts/Scale125/FavouriteFriend.png b/Scripts/Scale125/FavouriteFriend.png deleted file mode 100644 index 14f3cfe9..00000000 Binary files a/Scripts/Scale125/FavouriteFriend.png and /dev/null differ diff --git a/Scripts/Scale125/FavouriteFriend2.png b/Scripts/Scale125/FavouriteFriend2.png deleted file mode 100644 index 99616609..00000000 Binary files a/Scripts/Scale125/FavouriteFriend2.png and /dev/null differ diff --git a/Scripts/Scale125/FavouriteN.png b/Scripts/Scale125/FavouriteN.png deleted file mode 100644 index 6b2a3448..00000000 Binary files a/Scripts/Scale125/FavouriteN.png and /dev/null differ diff --git a/Scripts/Scale125/FavouriteY.png b/Scripts/Scale125/FavouriteY.png deleted file mode 100644 index 5717f576..00000000 Binary files a/Scripts/Scale125/FavouriteY.png and /dev/null differ diff --git a/Scripts/Scale125/FeatureUnlocked1.png b/Scripts/Scale125/FeatureUnlocked1.png deleted file mode 100644 index 850f9c17..00000000 Binary files a/Scripts/Scale125/FeatureUnlocked1.png and /dev/null differ diff --git a/Scripts/Scale125/FirstAnniversaryCelebration.png b/Scripts/Scale125/FirstAnniversaryCelebration.png deleted file mode 100644 index 755a7192..00000000 Binary files a/Scripts/Scale125/FirstAnniversaryCelebration.png and /dev/null differ diff --git a/Scripts/Scale125/FirstMission.png b/Scripts/Scale125/FirstMission.png deleted file mode 100644 index e1546243..00000000 Binary files a/Scripts/Scale125/FirstMission.png and /dev/null differ diff --git a/Scripts/Scale125/Friend.png b/Scripts/Scale125/Friend.png deleted file mode 100644 index a72b1fbd..00000000 Binary files a/Scripts/Scale125/Friend.png and /dev/null differ diff --git a/Scripts/Scale125/FriendIDSearch.png b/Scripts/Scale125/FriendIDSearch.png deleted file mode 100644 index b295885d..00000000 Binary files a/Scripts/Scale125/FriendIDSearch.png and /dev/null differ diff --git a/Scripts/Scale125/FriendSearchButton.png b/Scripts/Scale125/FriendSearchButton.png new file mode 100644 index 00000000..923ab808 Binary files /dev/null and b/Scripts/Scale125/FriendSearchButton.png differ diff --git a/Scripts/Scale125/Friends.png b/Scripts/Scale125/Friends.png deleted file mode 100644 index 6d32f403..00000000 Binary files a/Scripts/Scale125/Friends.png and /dev/null differ diff --git a/Scripts/Scale125/GPTest_NotFound.png b/Scripts/Scale125/GPTest_NotFound.png deleted file mode 100644 index 920b5680..00000000 Binary files a/Scripts/Scale125/GPTest_NotFound.png and /dev/null differ diff --git a/Scripts/Scale125/GholdengoEmblem.png b/Scripts/Scale125/GholdengoEmblem.png deleted file mode 100644 index fed3fbf5..00000000 Binary files a/Scripts/Scale125/GholdengoEmblem.png and /dev/null differ diff --git a/Scripts/Scale125/GoToTitle.png b/Scripts/Scale125/GoToTitle.png new file mode 100644 index 00000000..a836cab9 Binary files /dev/null and b/Scripts/Scale125/GoToTitle.png differ diff --git a/Scripts/Scale125/GotAllMissions.PNG b/Scripts/Scale125/GotAllMissions.PNG deleted file mode 100644 index dc516c49..00000000 Binary files a/Scripts/Scale125/GotAllMissions.PNG and /dev/null differ diff --git a/Scripts/Scale125/Gray.png b/Scripts/Scale125/Gray.png deleted file mode 100644 index fae06769..00000000 Binary files a/Scripts/Scale125/Gray.png and /dev/null differ diff --git a/Scripts/Scale125/HardwareReq2.png b/Scripts/Scale125/HardwareReq2.png deleted file mode 100644 index a4f37975..00000000 Binary files a/Scripts/Scale125/HardwareReq2.png and /dev/null differ diff --git a/Scripts/Scale125/Home.png b/Scripts/Scale125/Home.png deleted file mode 100644 index d1429f04..00000000 Binary files a/Scripts/Scale125/Home.png and /dev/null differ diff --git a/Scripts/Scale125/HourGlassAndPokeGoldPack.png b/Scripts/Scale125/HourGlassAndPokeGoldPack.png deleted file mode 100644 index fa1a08d8..00000000 Binary files a/Scripts/Scale125/HourGlassAndPokeGoldPack.png and /dev/null differ diff --git a/Scripts/Scale125/Hourglass.png b/Scripts/Scale125/Hourglass.png deleted file mode 100644 index c9b34017..00000000 Binary files a/Scripts/Scale125/Hourglass.png and /dev/null differ diff --git a/Scripts/Scale125/Hourglass2.png b/Scripts/Scale125/Hourglass2.png deleted file mode 100644 index 247b6b81..00000000 Binary files a/Scripts/Scale125/Hourglass2.png and /dev/null differ diff --git a/Scripts/Scale125/Hourglass3.png b/Scripts/Scale125/Hourglass3.png deleted file mode 100644 index a15a6932..00000000 Binary files a/Scripts/Scale125/Hourglass3.png and /dev/null differ diff --git a/Scripts/Scale125/HourglassPack.png b/Scripts/Scale125/HourglassPack.png deleted file mode 100644 index 420bf7b2..00000000 Binary files a/Scripts/Scale125/HourglassPack.png and /dev/null differ diff --git a/Scripts/Scale125/InSubMenu.png b/Scripts/Scale125/InSubMenu.png new file mode 100644 index 00000000..6f3dd0e5 Binary files /dev/null and b/Scripts/Scale125/InSubMenu.png differ diff --git a/Scripts/Scale125/LevelUp.png b/Scripts/Scale125/LevelUp.png deleted file mode 100644 index 2fdb5bd8..00000000 Binary files a/Scripts/Scale125/LevelUp.png and /dev/null differ diff --git a/Scripts/Scale125/Link.png b/Scripts/Scale125/Link.png deleted file mode 100644 index 3897a50b..00000000 Binary files a/Scripts/Scale125/Link.png and /dev/null differ diff --git a/Scripts/Scale125/LoadingBox.png b/Scripts/Scale125/LoadingBox.png deleted file mode 100644 index 0267c7b3..00000000 Binary files a/Scripts/Scale125/LoadingBox.png and /dev/null differ diff --git a/Scripts/Scale125/Mail.png b/Scripts/Scale125/Mail.png deleted file mode 100644 index 10250d3c..00000000 Binary files a/Scripts/Scale125/Mail.png and /dev/null differ diff --git a/Scripts/Scale125/Main.png b/Scripts/Scale125/Main.png deleted file mode 100644 index 1013e158..00000000 Binary files a/Scripts/Scale125/Main.png and /dev/null differ diff --git a/Scripts/Scale125/Menu.png b/Scripts/Scale125/Menu.png deleted file mode 100644 index 967e503e..00000000 Binary files a/Scripts/Scale125/Menu.png and /dev/null differ diff --git a/Scripts/Scale125/Mission.png b/Scripts/Scale125/Mission.png deleted file mode 100644 index fff93dc0..00000000 Binary files a/Scripts/Scale125/Mission.png and /dev/null differ diff --git a/Scripts/Scale125/MissionDarkBlue.png b/Scripts/Scale125/MissionDarkBlue.png deleted file mode 100644 index 6bb934f6..00000000 Binary files a/Scripts/Scale125/MissionDarkBlue.png and /dev/null differ diff --git a/Scripts/Scale125/MissionLightBlue.png b/Scripts/Scale125/MissionLightBlue.png deleted file mode 100644 index c508abb1..00000000 Binary files a/Scripts/Scale125/MissionLightBlue.png and /dev/null differ diff --git a/Scripts/Scale125/MissionLightPurple.png b/Scripts/Scale125/MissionLightPurple.png deleted file mode 100644 index 9f8d28fe..00000000 Binary files a/Scripts/Scale125/MissionLightPurple.png and /dev/null differ diff --git a/Scripts/Scale125/MissionOliveGreen.png b/Scripts/Scale125/MissionOliveGreen.png deleted file mode 100644 index 08f75ae3..00000000 Binary files a/Scripts/Scale125/MissionOliveGreen.png and /dev/null differ diff --git a/Scripts/Scale125/MissionYellow.png b/Scripts/Scale125/MissionYellow.png deleted file mode 100644 index 2fa20c5b..00000000 Binary files a/Scripts/Scale125/MissionYellow.png and /dev/null differ diff --git a/Scripts/Scale125/Mission_dino1.png b/Scripts/Scale125/Mission_dino1.png deleted file mode 100644 index d8ac44e6..00000000 Binary files a/Scripts/Scale125/Mission_dino1.png and /dev/null differ diff --git a/Scripts/Scale125/Missions.png b/Scripts/Scale125/Missions.png deleted file mode 100644 index 356e6738..00000000 Binary files a/Scripts/Scale125/Missions.png and /dev/null differ diff --git a/Scripts/Scale125/Month.png b/Scripts/Scale125/Month.png deleted file mode 100644 index e5089f8d..00000000 Binary files a/Scripts/Scale125/Month.png and /dev/null differ diff --git a/Scripts/Scale125/Move.png b/Scripts/Scale125/Move.png deleted file mode 100644 index f956b07b..00000000 Binary files a/Scripts/Scale125/Move.png and /dev/null differ diff --git a/Scripts/Scale125/MuMuFolder.png b/Scripts/Scale125/MuMuFolder.png deleted file mode 100644 index 337b77db..00000000 Binary files a/Scripts/Scale125/MuMuFolder.png and /dev/null differ diff --git a/Scripts/Scale125/Name.png b/Scripts/Scale125/Name.png deleted file mode 100644 index 7dd56137..00000000 Binary files a/Scripts/Scale125/Name.png and /dev/null differ diff --git a/Scripts/Scale125/Next.png b/Scripts/Scale125/Next.png deleted file mode 100644 index dcaf4914..00000000 Binary files a/Scripts/Scale125/Next.png and /dev/null differ diff --git a/Scripts/Scale125/Next2.png b/Scripts/Scale125/Next2.png deleted file mode 100644 index 6453b9b3..00000000 Binary files a/Scripts/Scale125/Next2.png and /dev/null differ diff --git a/Scripts/Scale125/NoGifts.png b/Scripts/Scale125/NoGifts.png deleted file mode 100644 index a4c8b7b6..00000000 Binary files a/Scripts/Scale125/NoGifts.png and /dev/null differ diff --git a/Scripts/Scale125/NoResponse.png b/Scripts/Scale125/NoResponse.png deleted file mode 100644 index 5738f460..00000000 Binary files a/Scripts/Scale125/NoResponse.png and /dev/null differ diff --git a/Scripts/Scale125/NoResponseDark.png b/Scripts/Scale125/NoResponseDark.png deleted file mode 100644 index 984d5784..00000000 Binary files a/Scripts/Scale125/NoResponseDark.png and /dev/null differ diff --git a/Scripts/Scale125/NoSave.png b/Scripts/Scale125/NoSave.png deleted file mode 100644 index abee88a7..00000000 Binary files a/Scripts/Scale125/NoSave.png and /dev/null differ diff --git a/Scripts/Scale125/NotFound.png b/Scripts/Scale125/NotFound.png deleted file mode 100644 index fc9d7a96..00000000 Binary files a/Scripts/Scale125/NotFound.png and /dev/null differ diff --git a/Scripts/Scale125/Notifications.png b/Scripts/Scale125/Notifications.png deleted file mode 100644 index 5ccd972a..00000000 Binary files a/Scripts/Scale125/Notifications.png and /dev/null differ diff --git a/Scripts/Scale125/OK.png b/Scripts/Scale125/OK.png deleted file mode 100644 index 21698649..00000000 Binary files a/Scripts/Scale125/OK.png and /dev/null differ diff --git a/Scripts/Scale125/OK2.png b/Scripts/Scale125/OK2.png index 01fcb66a..ffb6b8c4 100644 Binary files a/Scripts/Scale125/OK2.png and b/Scripts/Scale125/OK2.png differ diff --git a/Scripts/Scale125/Opening.png b/Scripts/Scale125/Opening.png deleted file mode 100644 index b9263346..00000000 Binary files a/Scripts/Scale125/Opening.png and /dev/null differ diff --git a/Scripts/Scale125/Pack.png b/Scripts/Scale125/Pack.png deleted file mode 100644 index d83d26cc..00000000 Binary files a/Scripts/Scale125/Pack.png and /dev/null differ diff --git a/Scripts/Scale125/PackIsMissing.png b/Scripts/Scale125/PackIsMissing.png deleted file mode 100644 index a817681a..00000000 Binary files a/Scripts/Scale125/PackIsMissing.png and /dev/null differ diff --git a/Scripts/Scale125/Pending.png b/Scripts/Scale125/Pending.png deleted file mode 100644 index 6ff26517..00000000 Binary files a/Scripts/Scale125/Pending.png and /dev/null differ diff --git a/Scripts/Scale125/PendingFriendRequest.png b/Scripts/Scale125/PendingFriendRequest.png deleted file mode 100644 index 30087cdd..00000000 Binary files a/Scripts/Scale125/PendingFriendRequest.png and /dev/null differ diff --git a/Scripts/Scale125/Pick.png b/Scripts/Scale125/Pick.png deleted file mode 100644 index fa959fa6..00000000 Binary files a/Scripts/Scale125/Pick.png and /dev/null differ diff --git a/Scripts/Scale125/Points.png b/Scripts/Scale125/Points.png deleted file mode 100644 index 2c93ce19..00000000 Binary files a/Scripts/Scale125/Points.png and /dev/null differ diff --git a/Scripts/Scale125/PokeGoldPack.png b/Scripts/Scale125/PokeGoldPack.png deleted file mode 100644 index 9e61b4ba..00000000 Binary files a/Scripts/Scale125/PokeGoldPack.png and /dev/null differ diff --git a/Scripts/Scale125/PokeGoldPack2.png b/Scripts/Scale125/PokeGoldPack2.png deleted file mode 100644 index 81b9dcca..00000000 Binary files a/Scripts/Scale125/PokeGoldPack2.png and /dev/null differ diff --git a/Scripts/Scale125/Pokeball.png b/Scripts/Scale125/Pokeball.png deleted file mode 100644 index b45a2467..00000000 Binary files a/Scripts/Scale125/Pokeball.png and /dev/null differ diff --git a/Scripts/Scale125/Premium.PNG b/Scripts/Scale125/Premium.PNG deleted file mode 100644 index 02d8fd27..00000000 Binary files a/Scripts/Scale125/Premium.PNG and /dev/null differ diff --git a/Scripts/Scale125/Privacy.png b/Scripts/Scale125/Privacy.png deleted file mode 100644 index 2d804914..00000000 Binary files a/Scripts/Scale125/Privacy.png and /dev/null differ diff --git a/Scripts/Scale125/Proceed.png b/Scripts/Scale125/Proceed.png deleted file mode 100644 index ca023fb0..00000000 Binary files a/Scripts/Scale125/Proceed.png and /dev/null differ diff --git a/Scripts/Scale125/Profile.png b/Scripts/Scale125/Profile.png deleted file mode 100644 index 5b985925..00000000 Binary files a/Scripts/Scale125/Profile.png and /dev/null differ diff --git a/Scripts/Scale125/Rainbow.png b/Scripts/Scale125/Rainbow.png deleted file mode 100644 index 6c576ae8..00000000 Binary files a/Scripts/Scale125/Rainbow.png and /dev/null differ diff --git a/Scripts/Scale125/Register.png b/Scripts/Scale125/Register.png deleted file mode 100644 index 2f47e407..00000000 Binary files a/Scripts/Scale125/Register.png and /dev/null differ diff --git a/Scripts/Scale125/Remove.png b/Scripts/Scale125/Remove.png deleted file mode 100644 index fde1a752..00000000 Binary files a/Scripts/Scale125/Remove.png and /dev/null differ diff --git a/Scripts/Scale125/Return.png b/Scripts/Scale125/Return.png deleted file mode 100644 index 547b13e2..00000000 Binary files a/Scripts/Scale125/Return.png and /dev/null differ diff --git a/Scripts/Scale125/Save.png b/Scripts/Scale125/Save.png deleted file mode 100644 index 6814f3d1..00000000 Binary files a/Scripts/Scale125/Save.png and /dev/null differ diff --git a/Scripts/Scale125/Search.png b/Scripts/Scale125/Search.png deleted file mode 100644 index 5a43d704..00000000 Binary files a/Scripts/Scale125/Search.png and /dev/null differ diff --git a/Scripts/Scale125/Search2.png b/Scripts/Scale125/Search2.png deleted file mode 100644 index 5a137bd9..00000000 Binary files a/Scripts/Scale125/Search2.png and /dev/null differ diff --git a/Scripts/Scale125/SelectExpansion.png b/Scripts/Scale125/SelectExpansion.png deleted file mode 100644 index 77c75c95..00000000 Binary files a/Scripts/Scale125/SelectExpansion.png and /dev/null differ diff --git a/Scripts/Scale125/Send.png b/Scripts/Scale125/Send.png deleted file mode 100644 index 1e55acd4..00000000 Binary files a/Scripts/Scale125/Send.png and /dev/null differ diff --git a/Scripts/Scale125/Send2.png b/Scripts/Scale125/Send2.png deleted file mode 100644 index c88c1ba1..00000000 Binary files a/Scripts/Scale125/Send2.png and /dev/null differ diff --git a/Scripts/Scale125/Settings.png b/Scripts/Scale125/Settings.png index 3f2d9c3d..5f3491a5 100644 Binary files a/Scripts/Scale125/Settings.png and b/Scripts/Scale125/Settings.png differ diff --git a/Scripts/Scale125/Share.png b/Scripts/Scale125/Share.png deleted file mode 100644 index b3cdd5af..00000000 Binary files a/Scripts/Scale125/Share.png and /dev/null differ diff --git a/Scripts/Scale125/shiny2star1.png b/Scripts/Scale125/ShinyEx_ex_1.png similarity index 100% rename from Scripts/Scale125/shiny2star1.png rename to Scripts/Scale125/ShinyEx_ex_1.png diff --git a/Scripts/Scale125/Shop.png b/Scripts/Scale125/Shop.png deleted file mode 100644 index b6fe36aa..00000000 Binary files a/Scripts/Scale125/Shop.png and /dev/null differ diff --git a/Scripts/Scale125/ShopTicket.png b/Scripts/Scale125/ShopTicket.png deleted file mode 100644 index 9a229f2b..00000000 Binary files a/Scripts/Scale125/ShopTicket.png and /dev/null differ diff --git a/Scripts/Scale125/ShowcaseInput.png b/Scripts/Scale125/ShowcaseInput.png deleted file mode 100644 index f941cb32..00000000 Binary files a/Scripts/Scale125/ShowcaseInput.png and /dev/null differ diff --git a/Scripts/Scale125/ShowcaseLiked.png b/Scripts/Scale125/ShowcaseLiked.png deleted file mode 100644 index a6a3981d..00000000 Binary files a/Scripts/Scale125/ShowcaseLiked.png and /dev/null differ diff --git a/Scripts/Scale125/Skip.png b/Scripts/Scale125/Skip.png deleted file mode 100644 index 8b012dd3..00000000 Binary files a/Scripts/Scale125/Skip.png and /dev/null differ diff --git a/Scripts/Scale125/Skip2.png b/Scripts/Scale125/Skip2.png deleted file mode 100644 index c4d1aa87..00000000 Binary files a/Scripts/Scale125/Skip2.png and /dev/null differ diff --git a/Scripts/Scale125/Social.png b/Scripts/Scale125/Social.png deleted file mode 100644 index 02d5e883..00000000 Binary files a/Scripts/Scale125/Social.png and /dev/null differ diff --git a/Scripts/Scale125/SocialAlert.png b/Scripts/Scale125/SocialAlert.png deleted file mode 100644 index 712d3d94..00000000 Binary files a/Scripts/Scale125/SocialAlert.png and /dev/null differ diff --git a/Scripts/Scale125/StartupErrorX.png b/Scripts/Scale125/StartupErrorX.png deleted file mode 100644 index 1047bfae..00000000 Binary files a/Scripts/Scale125/StartupErrorX.png and /dev/null differ diff --git a/Scripts/Scale125/Swipe.png b/Scripts/Scale125/Swipe.png deleted file mode 100644 index 5606bbee..00000000 Binary files a/Scripts/Scale125/Swipe.png and /dev/null differ diff --git a/Scripts/Scale125/Swipe2.png b/Scripts/Scale125/Swipe2.png deleted file mode 100644 index 96da0306..00000000 Binary files a/Scripts/Scale125/Swipe2.png and /dev/null differ diff --git a/Scripts/Scale125/Tos.png b/Scripts/Scale125/Tos.png deleted file mode 100644 index 2d804914..00000000 Binary files a/Scripts/Scale125/Tos.png and /dev/null differ diff --git a/Scripts/Scale125/TosScreen.png b/Scripts/Scale125/TosScreen.png deleted file mode 100644 index ec9baf08..00000000 Binary files a/Scripts/Scale125/TosScreen.png and /dev/null differ diff --git a/Scripts/Scale125/Trace.png b/Scripts/Scale125/Trace.png deleted file mode 100644 index edbcc440..00000000 Binary files a/Scripts/Scale125/Trace.png and /dev/null differ diff --git a/Scripts/Scale125/Trade.png b/Scripts/Scale125/Trade.png deleted file mode 100644 index 342d1282..00000000 Binary files a/Scripts/Scale125/Trade.png and /dev/null differ diff --git a/Scripts/Scale125/Tutorial.png b/Scripts/Scale125/Tutorial.png deleted file mode 100644 index 01f5ae77..00000000 Binary files a/Scripts/Scale125/Tutorial.png and /dev/null differ diff --git a/Scripts/Scale125/UserProfile.png b/Scripts/Scale125/UserProfile.png deleted file mode 100644 index e63c25d3..00000000 Binary files a/Scripts/Scale125/UserProfile.png and /dev/null differ diff --git a/Scripts/Scale125/WPMission.png b/Scripts/Scale125/WPMission.png deleted file mode 100644 index 33b200eb..00000000 Binary files a/Scripts/Scale125/WPMission.png and /dev/null differ diff --git a/Scripts/Scale125/Welcome.png b/Scripts/Scale125/Welcome.png deleted file mode 100644 index 57120d58..00000000 Binary files a/Scripts/Scale125/Welcome.png and /dev/null differ diff --git a/Scripts/Scale125/Withdraw.png b/Scripts/Scale125/Withdraw.png deleted file mode 100644 index 22c04ce9..00000000 Binary files a/Scripts/Scale125/Withdraw.png and /dev/null differ diff --git a/Scripts/Scale125/Wonder.png b/Scripts/Scale125/Wonder.png deleted file mode 100644 index 9c25013f..00000000 Binary files a/Scripts/Scale125/Wonder.png and /dev/null differ diff --git a/Scripts/Scale125/Wonder2.png b/Scripts/Scale125/Wonder2.png deleted file mode 100644 index dca6657e..00000000 Binary files a/Scripts/Scale125/Wonder2.png and /dev/null differ diff --git a/Scripts/Scale125/Wonder3.png b/Scripts/Scale125/Wonder3.png deleted file mode 100644 index 6daabada..00000000 Binary files a/Scripts/Scale125/Wonder3.png and /dev/null differ diff --git a/Scripts/Scale125/Wonder4.png b/Scripts/Scale125/Wonder4.png deleted file mode 100644 index 7cdbd6d8..00000000 Binary files a/Scripts/Scale125/Wonder4.png and /dev/null differ diff --git a/Scripts/Scale125/WonderPick.png b/Scripts/Scale125/WonderPick.png deleted file mode 100644 index 2c3e0824..00000000 Binary files a/Scripts/Scale125/WonderPick.png and /dev/null differ diff --git a/Scripts/Scale125/WonderPickRaminItems.png b/Scripts/Scale125/WonderPickRaminItems.png new file mode 100644 index 00000000..83712a1a Binary files /dev/null and b/Scripts/Scale125/WonderPickRaminItems.png differ diff --git a/Scripts/Scale125/Year.png b/Scripts/Scale125/Year.png deleted file mode 100644 index 02ec4f62..00000000 Binary files a/Scripts/Scale125/Year.png and /dev/null differ diff --git a/Scripts/Scale125/__shiny2star1.png b/Scripts/Scale125/__shiny2star1.png deleted file mode 100644 index 83ee5347..00000000 Binary files a/Scripts/Scale125/__shiny2star1.png and /dev/null differ diff --git a/Scripts/Scale125/bonusWeek.png b/Scripts/Scale125/bonusWeek.png deleted file mode 100644 index 4ad89e8c..00000000 Binary files a/Scripts/Scale125/bonusWeek.png and /dev/null differ diff --git a/Scripts/Scale125/clearAll.png b/Scripts/Scale125/clearAll.png deleted file mode 100644 index eed5f740..00000000 Binary files a/Scripts/Scale125/clearAll.png and /dev/null differ diff --git a/Scripts/Scale125/closeduringpack.png b/Scripts/Scale125/closeduringpack.png deleted file mode 100644 index 4a549408..00000000 Binary files a/Scripts/Scale125/closeduringpack.png and /dev/null differ diff --git a/Scripts/Scale125/deluxe1star1.png b/Scripts/Scale125/deluxe1star1.png deleted file mode 100644 index 9d15dfca..00000000 Binary files a/Scripts/Scale125/deluxe1star1.png and /dev/null differ diff --git a/Scripts/Scale125/deluxe1star2.png b/Scripts/Scale125/deluxe1star2.png deleted file mode 100644 index c1e19933..00000000 Binary files a/Scripts/Scale125/deluxe1star2.png and /dev/null differ diff --git a/Scripts/Scale125/deluxe3diamond1.png b/Scripts/Scale125/deluxe3diamond1.png deleted file mode 100644 index 4953450a..00000000 Binary files a/Scripts/Scale125/deluxe3diamond1.png and /dev/null differ diff --git a/Scripts/Scale125/deluxe3diamond2.png b/Scripts/Scale125/deluxe3diamond2.png deleted file mode 100644 index 5a1770ea..00000000 Binary files a/Scripts/Scale125/deluxe3diamond2.png and /dev/null differ diff --git a/Scripts/Scale125/deluxefullart1.png b/Scripts/Scale125/deluxefullart1.png deleted file mode 100644 index 5c2db67a..00000000 Binary files a/Scripts/Scale125/deluxefullart1.png and /dev/null differ diff --git a/Scripts/Scale125/deluxefullart2.png b/Scripts/Scale125/deluxefullart2.png deleted file mode 100644 index af0bdeae..00000000 Binary files a/Scripts/Scale125/deluxefullart2.png and /dev/null differ diff --git a/Scripts/Scale125/deluxeimmersive1.png b/Scripts/Scale125/deluxeimmersive1.png deleted file mode 100644 index 851c6854..00000000 Binary files a/Scripts/Scale125/deluxeimmersive1.png and /dev/null differ diff --git a/Scripts/Scale125/deluxeimmersive2.png b/Scripts/Scale125/deluxeimmersive2.png deleted file mode 100644 index 2e4313dd..00000000 Binary files a/Scripts/Scale125/deluxeimmersive2.png and /dev/null differ diff --git a/Scripts/Scale125/deluxeshiny2star2.png b/Scripts/Scale125/deluxeshiny2star2.png deleted file mode 100644 index 3a2fc8b1..00000000 Binary files a/Scripts/Scale125/deluxeshiny2star2.png and /dev/null differ diff --git a/Scripts/Scale125/deluxetrainer1.png b/Scripts/Scale125/deluxetrainer1.png deleted file mode 100644 index 60842e39..00000000 Binary files a/Scripts/Scale125/deluxetrainer1.png and /dev/null differ diff --git a/Scripts/Scale125/deluxetrainer2.png b/Scripts/Scale125/deluxetrainer2.png deleted file mode 100644 index af007609..00000000 Binary files a/Scripts/Scale125/deluxetrainer2.png and /dev/null differ diff --git a/Scripts/Scale125/empty.png b/Scripts/Scale125/empty.png deleted file mode 100644 index b1ed451c..00000000 Binary files a/Scripts/Scale125/empty.png and /dev/null differ diff --git a/Scripts/Scale125/fullart-megashine1.png b/Scripts/Scale125/fullart-megashine1.png deleted file mode 100644 index 7c63aace..00000000 Binary files a/Scripts/Scale125/fullart-megashine1.png and /dev/null differ diff --git a/Scripts/Scale125/fullart-megashine2.png b/Scripts/Scale125/fullart-megashine2.png deleted file mode 100644 index 7dee6d4c..00000000 Binary files a/Scripts/Scale125/fullart-megashine2.png and /dev/null differ diff --git a/Scripts/Scale125/fullart1.png b/Scripts/Scale125/fullart1.png deleted file mode 100644 index 9eaecdfa..00000000 Binary files a/Scripts/Scale125/fullart1.png and /dev/null differ diff --git a/Scripts/Scale125/fullart2.png b/Scripts/Scale125/fullart2.png deleted file mode 100644 index 18a2b4da..00000000 Binary files a/Scripts/Scale125/fullart2.png and /dev/null differ diff --git a/Scripts/Scale125/fullart3.png b/Scripts/Scale125/fullart3.png deleted file mode 100644 index 1e338e9b..00000000 Binary files a/Scripts/Scale125/fullart3.png and /dev/null differ diff --git a/Scripts/Scale125/fullart4.png b/Scripts/Scale125/fullart4.png deleted file mode 100644 index 712ec6b4..00000000 Binary files a/Scripts/Scale125/fullart4.png and /dev/null differ diff --git a/Scripts/Scale125/fullart5.png b/Scripts/Scale125/fullart5.png deleted file mode 100644 index 9cb65b1b..00000000 Binary files a/Scripts/Scale125/fullart5.png and /dev/null differ diff --git a/Scripts/Scale125/gimmighoul1.png b/Scripts/Scale125/gimmighoul1.png deleted file mode 100644 index d10d666f..00000000 Binary files a/Scripts/Scale125/gimmighoul1.png and /dev/null differ diff --git a/Scripts/Scale125/gimmighoul2.png b/Scripts/Scale125/gimmighoul2.png deleted file mode 100644 index def5936f..00000000 Binary files a/Scripts/Scale125/gimmighoul2.png and /dev/null differ diff --git a/Scripts/Scale125/gimmighoul3.png b/Scripts/Scale125/gimmighoul3.png deleted file mode 100644 index 34acd47f..00000000 Binary files a/Scripts/Scale125/gimmighoul3.png and /dev/null differ diff --git a/Scripts/Scale125/gimmighoul4.png b/Scripts/Scale125/gimmighoul4.png deleted file mode 100644 index 839cd600..00000000 Binary files a/Scripts/Scale125/gimmighoul4.png and /dev/null differ diff --git a/Scripts/Scale125/immersive-megashine6-1.png b/Scripts/Scale125/immersive-megashine6-1.png deleted file mode 100644 index 031e9aa2..00000000 Binary files a/Scripts/Scale125/immersive-megashine6-1.png and /dev/null differ diff --git a/Scripts/Scale125/immersive-megashine6.png b/Scripts/Scale125/immersive-megashine6.png deleted file mode 100644 index 85fa5c5b..00000000 Binary files a/Scripts/Scale125/immersive-megashine6.png and /dev/null differ diff --git a/Scripts/Scale125/inHamburgerMenu.png b/Scripts/Scale125/inHamburgerMenu.png deleted file mode 100644 index 4e277dd6..00000000 Binary files a/Scripts/Scale125/inHamburgerMenu.png and /dev/null differ diff --git a/Scripts/Scale125/insideTrade.png b/Scripts/Scale125/insideTrade.png deleted file mode 100644 index fb5cc391..00000000 Binary files a/Scripts/Scale125/insideTrade.png and /dev/null differ diff --git a/Scripts/Scale125/lag1.png b/Scripts/Scale125/lag1.png deleted file mode 100644 index 50510c8e..00000000 Binary files a/Scripts/Scale125/lag1.png and /dev/null differ diff --git a/Scripts/Scale125/lag2.png b/Scripts/Scale125/lag2.png deleted file mode 100644 index ce17bc8e..00000000 Binary files a/Scripts/Scale125/lag2.png and /dev/null differ diff --git a/Scripts/Scale125/lag3.png b/Scripts/Scale125/lag3.png deleted file mode 100644 index 278cec84..00000000 Binary files a/Scripts/Scale125/lag3.png and /dev/null differ diff --git a/Scripts/Scale125/lag4.png b/Scripts/Scale125/lag4.png deleted file mode 100644 index 92c1f2f6..00000000 Binary files a/Scripts/Scale125/lag4.png and /dev/null differ diff --git a/Scripts/Scale125/lag5.png b/Scripts/Scale125/lag5.png deleted file mode 100644 index 4d723dd8..00000000 Binary files a/Scripts/Scale125/lag5.png and /dev/null differ diff --git a/Scripts/Scale125/missionwonder.png b/Scripts/Scale125/missionwonder.png deleted file mode 100644 index 10d71b17..00000000 Binary files a/Scripts/Scale125/missionwonder.png and /dev/null differ diff --git a/Scripts/Scale125/newPrivacyTOSpopup.png b/Scripts/Scale125/newPrivacyTOSpopup.png deleted file mode 100644 index e454d4da..00000000 Binary files a/Scripts/Scale125/newPrivacyTOSpopup.png and /dev/null differ diff --git a/Scripts/Scale125/normal6card4.png b/Scripts/Scale125/normal6card4.png deleted file mode 100644 index 38f9b0b0..00000000 Binary files a/Scripts/Scale125/normal6card4.png and /dev/null differ diff --git a/Scripts/Scale125/normal6card5.png b/Scripts/Scale125/normal6card5.png deleted file mode 100644 index a400a35e..00000000 Binary files a/Scripts/Scale125/normal6card5.png and /dev/null differ diff --git a/Scripts/Scale125/normal6card6.png b/Scripts/Scale125/normal6card6.png deleted file mode 100644 index f0671aa7..00000000 Binary files a/Scripts/Scale125/normal6card6.png and /dev/null differ diff --git a/Scripts/Scale125/notenoughitems.png b/Scripts/Scale125/notenoughitems.png deleted file mode 100644 index 604238bf..00000000 Binary files a/Scripts/Scale125/notenoughitems.png and /dev/null differ diff --git a/Scripts/Scale125/player.png b/Scripts/Scale125/player.png deleted file mode 100644 index 1e0d8705..00000000 Binary files a/Scripts/Scale125/player.png and /dev/null differ diff --git a/Scripts/Scale125/requests.png b/Scripts/Scale125/requests.png deleted file mode 100644 index a9657679..00000000 Binary files a/Scripts/Scale125/requests.png and /dev/null differ diff --git a/Scripts/Scale125/shinedustItems.png b/Scripts/Scale125/shinedustItems.png deleted file mode 100644 index 04e43c2a..00000000 Binary files a/Scripts/Scale125/shinedustItems.png and /dev/null differ diff --git a/Scripts/Scale125/shiny2star6card-megashine3.png b/Scripts/Scale125/shiny1star10.png similarity index 100% rename from Scripts/Scale125/shiny2star6card-megashine3.png rename to Scripts/Scale125/shiny1star10.png diff --git a/Scripts/Scale125/shiny2star6card-megashine4.png b/Scripts/Scale125/shiny1star11.png similarity index 100% rename from Scripts/Scale125/shiny2star6card-megashine4.png rename to Scripts/Scale125/shiny1star11.png diff --git a/Scripts/Scale125/shiny1star12.png b/Scripts/Scale125/shiny1star12.png new file mode 100644 index 00000000..510b9fb2 Binary files /dev/null and b/Scripts/Scale125/shiny1star12.png differ diff --git a/Scripts/Scale125/shiny1star6card6.png b/Scripts/Scale125/shiny1star6.png similarity index 100% rename from Scripts/Scale125/shiny1star6card6.png rename to Scripts/Scale125/shiny1star6.png diff --git a/Scripts/Scale125/shiny2star6card6.png b/Scripts/Scale125/shiny1star7.png similarity index 100% rename from Scripts/Scale125/shiny2star6card6.png rename to Scripts/Scale125/shiny1star7.png diff --git a/Scripts/Scale125/shiny2star6card-megashine1.png b/Scripts/Scale125/shiny1star8.png similarity index 100% rename from Scripts/Scale125/shiny2star6card-megashine1.png rename to Scripts/Scale125/shiny1star8.png diff --git a/Scripts/Scale125/shiny2star6card-megashine2.png b/Scripts/Scale125/shiny1star9.png similarity index 100% rename from Scripts/Scale125/shiny2star6card-megashine2.png rename to Scripts/Scale125/shiny1star9.png diff --git a/Scripts/Scale125/shiny2star2.png b/Scripts/Scale125/shiny2star2.png deleted file mode 100644 index a5a48525..00000000 Binary files a/Scripts/Scale125/shiny2star2.png and /dev/null differ diff --git a/Scripts/Scale125/shiny2star3.png b/Scripts/Scale125/shiny2star3.png deleted file mode 100644 index a5a48525..00000000 Binary files a/Scripts/Scale125/shiny2star3.png and /dev/null differ diff --git a/Scripts/Scale125/shiny2star4.png b/Scripts/Scale125/shiny2star4.png deleted file mode 100644 index a5a48525..00000000 Binary files a/Scripts/Scale125/shiny2star4.png and /dev/null differ diff --git a/Scripts/Scale125/shiny2star5.png b/Scripts/Scale125/shiny2star5.png deleted file mode 100644 index a5a48525..00000000 Binary files a/Scripts/Scale125/shiny2star5.png and /dev/null differ diff --git a/Scripts/Scale125/trophy.png b/Scripts/Scale125/trophy.png deleted file mode 100644 index a31a747c..00000000 Binary files a/Scripts/Scale125/trophy.png and /dev/null differ diff --git a/Scripts/Scale125/trophyPage.png b/Scripts/Scale125/trophyPage.png deleted file mode 100644 index 265bf4fa..00000000 Binary files a/Scripts/Scale125/trophyPage.png and /dev/null differ diff --git a/Scripts/Scale125/wrongItem.png b/Scripts/Scale125/wrongItem.png deleted file mode 100644 index 7f4b5a1c..00000000 Binary files a/Scripts/Scale125/wrongItem.png and /dev/null differ