diff --git a/assets/cn/gg_handler/BUTTON_GEM.png b/assets/cn/gg_handler/BUTTON_GEM.png new file mode 100644 index 000000000..4dec46f66 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GEM.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_APP_CHOOSE.png b/assets/cn/gg_handler/BUTTON_GG_APP_CHOOSE.png new file mode 100644 index 000000000..6dba26d22 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_APP_CHOOSE.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_CONFIRM.png b/assets/cn/gg_handler/BUTTON_GG_CONFIRM.png new file mode 100644 index 000000000..8986d50fb Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_CONFIRM.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_CONFIRM_POS.png b/assets/cn/gg_handler/BUTTON_GG_CONFIRM_POS.png new file mode 100644 index 000000000..ecf5d4552 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_CONFIRM_POS.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_ENTER_POS.png b/assets/cn/gg_handler/BUTTON_GG_ENTER_POS.png new file mode 100644 index 000000000..eec034768 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_ENTER_POS.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_EXIT_POS.png b/assets/cn/gg_handler/BUTTON_GG_EXIT_POS.png new file mode 100644 index 000000000..b6c82239b Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_EXIT_POS.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_RESTART_ERROR.png b/assets/cn/gg_handler/BUTTON_GG_RESTART_ERROR.png new file mode 100644 index 000000000..3771b69ca Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_RESTART_ERROR.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_END.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_END.png new file mode 100644 index 000000000..d2a6afe27 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_END.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_ENTER_CONFIRM.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_ENTER_CONFIRM.png new file mode 100644 index 000000000..313f30117 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_ENTER_CONFIRM.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_ENTER_POS.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_ENTER_POS.png new file mode 100644 index 000000000..673c81d84 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_ENTER_POS.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_FATAL.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_FATAL.png new file mode 100644 index 000000000..ca9c33ad0 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_FATAL.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_MENU_A.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_MENU_A.png new file mode 100644 index 000000000..5bdbfb5ae Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_MENU_A.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_MENU_B.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_MENU_B.png new file mode 100644 index 000000000..a5fdd27ea Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_MENU_B.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_MODE_A_CONFIRM.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_MODE_A_CONFIRM.png new file mode 100644 index 000000000..91ca02a3f Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_MODE_A_CONFIRM.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_MODE_B_CONFIRM.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_MODE_B_CONFIRM.png new file mode 100644 index 000000000..0a426b471 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_MODE_B_CONFIRM.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM0.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM0.png new file mode 100644 index 000000000..d760c04a7 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM0.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM1.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM1.png new file mode 100644 index 000000000..38b4a2e97 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM1.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM2.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM2.png new file mode 100644 index 000000000..dc124187c Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM2.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM3.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM3.png new file mode 100644 index 000000000..ef888d593 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM3.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM4.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM4.png new file mode 100644 index 000000000..c50057a1b Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM4.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM5.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM5.png new file mode 100644 index 000000000..1ebd0d12c Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM5.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM6.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM6.png new file mode 100644 index 000000000..218799dc1 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM6.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM7.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM7.png new file mode 100644 index 000000000..2ac5b6390 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM7.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM8.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM8.png new file mode 100644 index 000000000..ce192d615 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM8.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM9.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM9.png new file mode 100644 index 000000000..289b54aad Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM9.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_START.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_START.png new file mode 100644 index 000000000..5a0b74550 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_START.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SCRIPT_START_PROCESS.png b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_START_PROCESS.png new file mode 100644 index 000000000..74a7cc576 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SCRIPT_START_PROCESS.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_SEARCH_MODE_CONFIRM.png b/assets/cn/gg_handler/BUTTON_GG_SEARCH_MODE_CONFIRM.png new file mode 100644 index 000000000..82e6cd9c8 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_SEARCH_MODE_CONFIRM.png differ diff --git a/assets/cn/gg_handler/BUTTON_GG_TAB_SEARCH_POS.png b/assets/cn/gg_handler/BUTTON_GG_TAB_SEARCH_POS.png new file mode 100644 index 000000000..50d170737 Binary files /dev/null and b/assets/cn/gg_handler/BUTTON_GG_TAB_SEARCH_POS.png differ diff --git a/assets/cn/gg_handler/OCR_PRE_BATTLE_CHECK.png b/assets/cn/gg_handler/OCR_PRE_BATTLE_CHECK.png new file mode 100644 index 000000000..f4f719aa2 Binary files /dev/null and b/assets/cn/gg_handler/OCR_PRE_BATTLE_CHECK.png differ diff --git a/config/template.json b/config/template.json index 92cf25714..e0f98d747 100644 --- a/config/template.json +++ b/config/template.json @@ -93,6 +93,7 @@ }, "PowerLimit": { "PowerLimit": { + "Enable": true, "Exercise": 25000, "Raid": 25000, "Ash": 25000 @@ -2069,6 +2070,7 @@ "ServerUpdate": "00:00, 12:00, 18:00" }, "Exercise": { + "DelayUntilHoursBeforeNextUpdate": 12, "OpponentChooseMode": "max_exp", "OpponentTrial": 1, "ExerciseStrategy": "aggressive", diff --git a/module/base/timer.py b/module/base/timer.py index a36182de0..66370bbdc 100644 --- a/module/base/timer.py +++ b/module/base/timer.py @@ -157,3 +157,28 @@ class Timer: return f'Timer(limit={round(self.current(), 3)}/{self.limit}, count={self._reach_count}/{self.count})' __repr__ = __str__ + + +def timeout(_function, timeout_sec=30.0, *args, **kwargs): + """Won't kill that task until it finishes""" + from threading import Thread + from module.logger import logger + + def function_timeout(_func): + t0 = time.time() + success = True + p = Thread(target=_func, args=args, kwargs=kwargs) + p.start() + p.join(timeout_sec) + if p.is_alive(): + success = False + t1 = time.time() + if t1 - t0 < 10: + success = False + _success = 'Done' if success else 'Failed' + logger.hr(f'{_func.__name__}: {_success} in {str(round(t1 - t0, 1))}s', 1) + if not success: + return True + return False + + return function_timeout(_function) diff --git a/module/config/argument/args.json b/module/config/argument/args.json index c97016eba..fc9f4a570 100644 --- a/module/config/argument/args.json +++ b/module/config/argument/args.json @@ -462,6 +462,10 @@ }, "PowerLimit": { "PowerLimit": { + "Enable": { + "type": "checkbox", + "value": true + }, "Exercise": { "type": "input", "value": 25000 @@ -14686,6 +14690,18 @@ } }, "Exercise": { + "DelayUntilHoursBeforeNextUpdate": { + "type": "select", + "value": 12, + "option": [ + 1, + 2, + 3, + 4, + 5, + 12 + ] + }, "OpponentChooseMode": { "type": "select", "value": "max_exp", diff --git a/module/config/argument/argument.yaml b/module/config/argument/argument.yaml index 61116fb8d..06c75dfdd 100644 --- a/module/config/argument/argument.yaml +++ b/module/config/argument/argument.yaml @@ -650,6 +650,9 @@ Hard: value: 1 option: [ 1, 2 ] Exercise: + DelayUntilHoursBeforeNextUpdate: + value: 12 + option: [ 1, 2, 3, 4, 5, 12] OpponentChooseMode: value: max_exp option: [ max_exp, easiest, leftmost, easiest_else_exp ] @@ -879,6 +882,7 @@ Misc: # ==================== Cheat ==================== PowerLimit: + Enable: true Exercise: 25000 Raid: 25000 Ash: 25000 diff --git a/module/config/config_generated.py b/module/config/config_generated.py index 9ac6b7bd0..d1d8b1c70 100644 --- a/module/config/config_generated.py +++ b/module/config/config_generated.py @@ -371,6 +371,7 @@ class GeneratedConfig: Hard_HardFleet = 1 # 1, 2 # Group `Exercise` + Exercise_DelayUntilHoursBeforeNextUpdate = 12 # 1, 2, 3, 4, 5, 12 Exercise_OpponentChooseMode = 'max_exp' # max_exp, easiest, leftmost, easiest_else_exp Exercise_OpponentTrial = 1 Exercise_ExerciseStrategy = 'aggressive' # aggressive, fri18, sat0, sat12, sat18, sun0, sun12, sun18 @@ -535,6 +536,7 @@ class GeneratedConfig: Misc_SkipBattleCelebrate = False # Group `PowerLimit` + PowerLimit_Enable = True PowerLimit_Exercise = 25000 PowerLimit_Raid = 25000 PowerLimit_Ash = 25000 diff --git a/module/config/full_config_generated.py b/module/config/full_config_generated.py index 4cb8a5436..d442739af 100644 --- a/module/config/full_config_generated.py +++ b/module/config/full_config_generated.py @@ -68,6 +68,7 @@ class FullGeneratedConfig: Restart_Storage_Storage = None # Task `PowerLimit` + PowerLimit_PowerLimit_Enable = None PowerLimit_PowerLimit_Exercise = None PowerLimit_PowerLimit_Raid = None PowerLimit_PowerLimit_Ash = None @@ -1540,6 +1541,7 @@ class FullGeneratedConfig: Exercise_Scheduler_SuccessInterval = None Exercise_Scheduler_FailureInterval = None Exercise_Scheduler_ServerUpdate = None + Exercise_Exercise_DelayUntilHoursBeforeNextUpdate = None Exercise_Exercise_OpponentChooseMode = None Exercise_Exercise_OpponentTrial = None Exercise_Exercise_ExerciseStrategy = None diff --git a/module/config/i18n/en-US.json b/module/config/i18n/en-US.json index ee73d37e8..00792c3c6 100644 --- a/module/config/i18n/en-US.json +++ b/module/config/i18n/en-US.json @@ -2303,6 +2303,16 @@ "name": "Exercise Settings", "help": "Runs exercise and automatically retreats when sum HP volume is low" }, + "DelayUntilHoursBeforeNextUpdate": { + "name": "Exercise.DelayUntilHoursBeforeNextUpdate.name", + "help": "Exercise.DelayUntilHoursBeforeNextUpdate.help", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "12": "12" + }, "OpponentChooseMode": { "name": "Opponent Choose Mode", "help": "", @@ -3077,6 +3087,10 @@ "name": "PowerLimit._info.name", "help": "PowerLimit._info.help" }, + "Enable": { + "name": "PowerLimit.Enable.name", + "help": "PowerLimit.Enable.help" + }, "Exercise": { "name": "PowerLimit.Exercise.name", "help": "PowerLimit.Exercise.help" diff --git a/module/config/i18n/ja-JP.json b/module/config/i18n/ja-JP.json index 5e8223dee..cd616063a 100644 --- a/module/config/i18n/ja-JP.json +++ b/module/config/i18n/ja-JP.json @@ -2303,6 +2303,16 @@ "name": "Exercise._info.name", "help": "Exercise._info.help" }, + "DelayUntilHoursBeforeNextUpdate": { + "name": "Exercise.DelayUntilHoursBeforeNextUpdate.name", + "help": "Exercise.DelayUntilHoursBeforeNextUpdate.help", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "12": "12" + }, "OpponentChooseMode": { "name": "Exercise.OpponentChooseMode.name", "help": "Exercise.OpponentChooseMode.help", @@ -3077,6 +3087,10 @@ "name": "PowerLimit._info.name", "help": "PowerLimit._info.help" }, + "Enable": { + "name": "PowerLimit.Enable.name", + "help": "PowerLimit.Enable.help" + }, "Exercise": { "name": "PowerLimit.Exercise.name", "help": "PowerLimit.Exercise.help" diff --git a/module/config/i18n/zh-CN.json b/module/config/i18n/zh-CN.json index 4ad0cb100..67e6d1f9d 100644 --- a/module/config/i18n/zh-CN.json +++ b/module/config/i18n/zh-CN.json @@ -2303,6 +2303,16 @@ "name": "演习", "help": "打演习,血量过低时自动撤退" }, + "DelayUntilHoursBeforeNextUpdate": { + "name": "推迟演习至下次更新次数前 X 小时", + "help": "", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "12": "不推迟" + }, "OpponentChooseMode": { "name": "对手选择模式", "help": "", @@ -3077,6 +3087,10 @@ "name": "战力限制", "help": "敏感项目前的最后一道保险\n若前排战力高于此值强制重启,并视为需要使用GG(打开GG开关以及GG自动重启倍率开关)" }, + "Enable": { + "name": "启用", + "help": "" + }, "Exercise": { "name": "演习", "help": "" diff --git a/module/config/i18n/zh-TW.json b/module/config/i18n/zh-TW.json index ef168b8b9..2044de16f 100644 --- a/module/config/i18n/zh-TW.json +++ b/module/config/i18n/zh-TW.json @@ -2303,6 +2303,16 @@ "name": "演習", "help": "打演習,血量過低時自動撤退" }, + "DelayUntilHoursBeforeNextUpdate": { + "name": "Exercise.DelayUntilHoursBeforeNextUpdate.name", + "help": "Exercise.DelayUntilHoursBeforeNextUpdate.help", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "12": "12" + }, "OpponentChooseMode": { "name": "對手選擇模式", "help": "", @@ -3077,6 +3087,10 @@ "name": "PowerLimit._info.name", "help": "PowerLimit._info.help" }, + "Enable": { + "name": "PowerLimit.Enable.name", + "help": "PowerLimit.Enable.help" + }, "Exercise": { "name": "PowerLimit.Exercise.name", "help": "PowerLimit.Exercise.help" diff --git a/module/gg_handler/assets.py b/module/gg_handler/assets.py new file mode 100644 index 000000000..410251e50 --- /dev/null +++ b/module/gg_handler/assets.py @@ -0,0 +1,36 @@ +from module.base.button import Button +from module.base.template import Template + +# This file was automatically generated by dev_tools/button_extract.py. +# Don't modify it manually. + +BUTTON_GEM = Button(area={'cn': (991, 26, 1013, 45), 'en': (991, 26, 1013, 45), 'jp': (991, 26, 1013, 45), 'tw': (991, 26, 1013, 45)}, color={'cn': (239, 72, 110), 'en': (239, 72, 110), 'jp': (239, 72, 110), 'tw': (239, 72, 110)}, button={'cn': (991, 26, 1013, 45), 'en': (991, 26, 1013, 45), 'jp': (991, 26, 1013, 45), 'tw': (991, 26, 1013, 45)}, file={'cn': './assets/cn/gg_handler/BUTTON_GEM.png', 'en': './assets/cn/gg_handler/BUTTON_GEM.png', 'jp': './assets/cn/gg_handler/BUTTON_GEM.png', 'tw': './assets/cn/gg_handler/BUTTON_GEM.png'}) +BUTTON_GG_APP_CHOOSE = Button(area={'cn': (338, 114, 381, 152), 'en': (338, 114, 381, 152), 'jp': (338, 114, 381, 152), 'tw': (338, 114, 381, 152)}, color={'cn': (211, 168, 176), 'en': (211, 168, 176), 'jp': (211, 168, 176), 'tw': (211, 168, 176)}, button={'cn': (338, 114, 381, 152), 'en': (338, 114, 381, 152), 'jp': (338, 114, 381, 152), 'tw': (338, 114, 381, 152)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_APP_CHOOSE.png', 'en': './assets/cn/gg_handler/BUTTON_GG_APP_CHOOSE.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_APP_CHOOSE.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_APP_CHOOSE.png'}) +BUTTON_GG_CONFIRM = Button(area={'cn': (1222, 695, 1249, 715), 'en': (1222, 695, 1249, 715), 'jp': (1222, 695, 1249, 715), 'tw': (1222, 695, 1249, 715)}, color={'cn': (125, 125, 125), 'en': (125, 125, 125), 'jp': (125, 125, 125), 'tw': (125, 125, 125)}, button={'cn': (1222, 695, 1249, 715), 'en': (1222, 695, 1249, 715), 'jp': (1222, 695, 1249, 715), 'tw': (1222, 695, 1249, 715)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_CONFIRM.png', 'en': './assets/cn/gg_handler/BUTTON_GG_CONFIRM.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_CONFIRM.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_CONFIRM.png'}) +BUTTON_GG_CONFIRM_POS = Button(area={'cn': (1220, 693, 1250, 717), 'en': (1220, 693, 1250, 717), 'jp': (1220, 693, 1250, 717), 'tw': (1220, 693, 1250, 717)}, color={'cn': (255, 255, 255), 'en': (255, 255, 255), 'jp': (255, 255, 255), 'tw': (255, 255, 255)}, button={'cn': (1220, 693, 1250, 717), 'en': (1220, 693, 1250, 717), 'jp': (1220, 693, 1250, 717), 'tw': (1220, 693, 1250, 717)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_CONFIRM_POS.png', 'en': './assets/cn/gg_handler/BUTTON_GG_CONFIRM_POS.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_CONFIRM_POS.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_CONFIRM_POS.png'}) +BUTTON_GG_ENTER_POS = Button(area={'cn': (558, 15, 603, 61), 'en': (558, 15, 603, 61), 'jp': (558, 15, 603, 61), 'tw': (558, 15, 603, 61)}, color={'cn': (255, 255, 255), 'en': (255, 255, 255), 'jp': (255, 255, 255), 'tw': (255, 255, 255)}, button={'cn': (558, 15, 603, 61), 'en': (558, 15, 603, 61), 'jp': (558, 15, 603, 61), 'tw': (558, 15, 603, 61)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_ENTER_POS.png', 'en': './assets/cn/gg_handler/BUTTON_GG_ENTER_POS.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_ENTER_POS.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_ENTER_POS.png'}) +BUTTON_GG_EXIT_POS = Button(area={'cn': (1224, 18, 1264, 56), 'en': (1224, 18, 1264, 56), 'jp': (1224, 18, 1264, 56), 'tw': (1224, 18, 1264, 56)}, color={'cn': (255, 255, 255), 'en': (255, 255, 255), 'jp': (255, 255, 255), 'tw': (255, 255, 255)}, button={'cn': (1224, 18, 1264, 56), 'en': (1224, 18, 1264, 56), 'jp': (1224, 18, 1264, 56), 'tw': (1224, 18, 1264, 56)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_EXIT_POS.png', 'en': './assets/cn/gg_handler/BUTTON_GG_EXIT_POS.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_EXIT_POS.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_EXIT_POS.png'}) +BUTTON_GG_RESTART_ERROR = Button(area={'cn': (337, 310, 459, 351), 'en': (337, 310, 459, 351), 'jp': (337, 310, 459, 351), 'tw': (337, 310, 459, 351)}, color={'cn': (96, 96, 96), 'en': (96, 96, 96), 'jp': (96, 96, 96), 'tw': (96, 96, 96)}, button={'cn': (337, 310, 459, 351), 'en': (337, 310, 459, 351), 'jp': (337, 310, 459, 351), 'tw': (337, 310, 459, 351)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_RESTART_ERROR.png', 'en': './assets/cn/gg_handler/BUTTON_GG_RESTART_ERROR.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_RESTART_ERROR.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_RESTART_ERROR.png'}) +BUTTON_GG_SCRIPT_END = Button(area={'cn': (1155, 375, 1227, 420), 'en': (1155, 375, 1227, 420), 'jp': (1155, 375, 1227, 420), 'tw': (1155, 375, 1227, 420)}, color={'cn': (85, 85, 85), 'en': (85, 85, 85), 'jp': (85, 85, 85), 'tw': (85, 85, 85)}, button={'cn': (1155, 375, 1227, 420), 'en': (1155, 375, 1227, 420), 'jp': (1155, 375, 1227, 420), 'tw': (1155, 375, 1227, 420)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_END.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_END.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_END.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_END.png'}) +BUTTON_GG_SCRIPT_ENTER_CONFIRM = Button(area={'cn': (284, 104, 395, 136), 'en': (284, 104, 395, 136), 'jp': (284, 104, 395, 136), 'tw': (284, 104, 395, 136)}, color={'cn': (112, 112, 112), 'en': (112, 112, 112), 'jp': (112, 112, 112), 'tw': (112, 112, 112)}, button={'cn': (284, 104, 395, 136), 'en': (284, 104, 395, 136), 'jp': (284, 104, 395, 136), 'tw': (284, 104, 395, 136)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_ENTER_CONFIRM.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_ENTER_CONFIRM.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_ENTER_CONFIRM.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_ENTER_CONFIRM.png'}) +BUTTON_GG_SCRIPT_ENTER_POS = Button(area={'cn': (1225, 127, 1269, 170), 'en': (1225, 127, 1269, 170), 'jp': (1225, 127, 1269, 170), 'tw': (1225, 127, 1269, 170)}, color={'cn': (255, 255, 255), 'en': (255, 255, 255), 'jp': (255, 255, 255), 'tw': (255, 255, 255)}, button={'cn': (1225, 127, 1269, 170), 'en': (1225, 127, 1269, 170), 'jp': (1225, 127, 1269, 170), 'tw': (1225, 127, 1269, 170)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_ENTER_POS.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_ENTER_POS.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_ENTER_POS.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_ENTER_POS.png'}) +BUTTON_GG_SCRIPT_FATAL = Button(area={'cn': (63, 622, 117, 655), 'en': (63, 622, 117, 655), 'jp': (63, 622, 117, 655), 'tw': (63, 622, 117, 655)}, color={'cn': (100, 100, 100), 'en': (100, 100, 100), 'jp': (100, 100, 100), 'tw': (100, 100, 100)}, button={'cn': (63, 622, 117, 655), 'en': (63, 622, 117, 655), 'jp': (63, 622, 117, 655), 'tw': (63, 622, 117, 655)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_FATAL.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_FATAL.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_FATAL.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_FATAL.png'}) +BUTTON_GG_SCRIPT_MENU_A = Button(area={'cn': (344, 289, 449, 320), 'en': (344, 289, 449, 320), 'jp': (344, 289, 449, 320), 'tw': (344, 289, 449, 320)}, color={'cn': (113, 113, 113), 'en': (113, 113, 113), 'jp': (113, 113, 113), 'tw': (113, 113, 113)}, button={'cn': (344, 289, 449, 320), 'en': (344, 289, 449, 320), 'jp': (344, 289, 449, 320), 'tw': (344, 289, 449, 320)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_MENU_A.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_MENU_A.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_MENU_A.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_MENU_A.png'}) +BUTTON_GG_SCRIPT_MENU_B = Button(area={'cn': (347, 358, 446, 393), 'en': (347, 358, 446, 393), 'jp': (347, 358, 446, 393), 'tw': (347, 358, 446, 393)}, color={'cn': (110, 110, 110), 'en': (110, 110, 110), 'jp': (110, 110, 110), 'tw': (110, 110, 110)}, button={'cn': (347, 358, 446, 393), 'en': (347, 358, 446, 393), 'jp': (347, 358, 446, 393), 'tw': (347, 358, 446, 393)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_MENU_B.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_MENU_B.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_MENU_B.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_MENU_B.png'}) +BUTTON_GG_SCRIPT_MODE_A_CONFIRM = Button(area={'cn': (100, 145, 189, 172), 'en': (100, 145, 189, 172), 'jp': (100, 145, 189, 172), 'tw': (100, 145, 189, 172)}, color={'cn': (114, 114, 114), 'en': (114, 114, 114), 'jp': (114, 114, 114), 'tw': (114, 114, 114)}, button={'cn': (100, 145, 189, 172), 'en': (100, 145, 189, 172), 'jp': (100, 145, 189, 172), 'tw': (100, 145, 189, 172)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_MODE_A_CONFIRM.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_MODE_A_CONFIRM.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_MODE_A_CONFIRM.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_MODE_A_CONFIRM.png'}) +BUTTON_GG_SCRIPT_MODE_B_CONFIRM = Button(area={'cn': (105, 146, 190, 168), 'en': (105, 146, 190, 168), 'jp': (105, 146, 190, 168), 'tw': (105, 146, 190, 168)}, color={'cn': (127, 127, 127), 'en': (127, 127, 127), 'jp': (127, 127, 127), 'tw': (127, 127, 127)}, button={'cn': (105, 146, 190, 168), 'en': (105, 146, 190, 168), 'jp': (105, 146, 190, 168), 'tw': (105, 146, 190, 168)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_MODE_B_CONFIRM.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_MODE_B_CONFIRM.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_MODE_B_CONFIRM.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_MODE_B_CONFIRM.png'}) +BUTTON_GG_SCRIPT_PANEL_NUM0 = Button(area={'cn': (916, 336, 947, 376), 'en': (916, 336, 947, 376), 'jp': (916, 336, 947, 376), 'tw': (916, 336, 947, 376)}, color={'cn': (59, 69, 74), 'en': (59, 69, 74), 'jp': (59, 69, 74), 'tw': (59, 69, 74)}, button={'cn': (916, 336, 947, 376), 'en': (916, 336, 947, 376), 'jp': (916, 336, 947, 376), 'tw': (916, 336, 947, 376)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM0.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM0.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM0.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM0.png'}) +BUTTON_GG_SCRIPT_PANEL_NUM1 = Button(area={'cn': (913, 119, 947, 158), 'en': (913, 119, 947, 158), 'jp': (913, 119, 947, 158), 'tw': (913, 119, 947, 158)}, color={'cn': (49, 60, 65), 'en': (49, 60, 65), 'jp': (49, 60, 65), 'tw': (49, 60, 65)}, button={'cn': (913, 119, 947, 158), 'en': (913, 119, 947, 158), 'jp': (913, 119, 947, 158), 'tw': (913, 119, 947, 158)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM1.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM1.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM1.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM1.png'}) +BUTTON_GG_SCRIPT_PANEL_NUM2 = Button(area={'cn': (986, 120, 1021, 158), 'en': (986, 120, 1021, 158), 'jp': (986, 120, 1021, 158), 'tw': (986, 120, 1021, 158)}, color={'cn': (55, 66, 71), 'en': (55, 66, 71), 'jp': (55, 66, 71), 'tw': (55, 66, 71)}, button={'cn': (986, 120, 1021, 158), 'en': (986, 120, 1021, 158), 'jp': (986, 120, 1021, 158), 'tw': (986, 120, 1021, 158)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM2.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM2.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM2.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM2.png'}) +BUTTON_GG_SCRIPT_PANEL_NUM3 = Button(area={'cn': (1056, 119, 1093, 158), 'en': (1056, 119, 1093, 158), 'jp': (1056, 119, 1093, 158), 'tw': (1056, 119, 1093, 158)}, color={'cn': (55, 65, 70), 'en': (55, 65, 70), 'jp': (55, 65, 70), 'tw': (55, 65, 70)}, button={'cn': (1056, 119, 1093, 158), 'en': (1056, 119, 1093, 158), 'jp': (1056, 119, 1093, 158), 'tw': (1056, 119, 1093, 158)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM3.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM3.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM3.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM3.png'}) +BUTTON_GG_SCRIPT_PANEL_NUM4 = Button(area={'cn': (914, 190, 950, 232), 'en': (914, 190, 950, 232), 'jp': (914, 190, 950, 232), 'tw': (914, 190, 950, 232)}, color={'cn': (54, 65, 70), 'en': (54, 65, 70), 'jp': (54, 65, 70), 'tw': (54, 65, 70)}, button={'cn': (914, 190, 950, 232), 'en': (914, 190, 950, 232), 'jp': (914, 190, 950, 232), 'tw': (914, 190, 950, 232)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM4.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM4.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM4.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM4.png'}) +BUTTON_GG_SCRIPT_PANEL_NUM5 = Button(area={'cn': (981, 192, 1025, 232), 'en': (981, 192, 1025, 232), 'jp': (981, 192, 1025, 232), 'tw': (981, 192, 1025, 232)}, color={'cn': (52, 63, 68), 'en': (52, 63, 68), 'jp': (52, 63, 68), 'tw': (52, 63, 68)}, button={'cn': (981, 192, 1025, 232), 'en': (981, 192, 1025, 232), 'jp': (981, 192, 1025, 232), 'tw': (981, 192, 1025, 232)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM5.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM5.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM5.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM5.png'}) +BUTTON_GG_SCRIPT_PANEL_NUM6 = Button(area={'cn': (1056, 191, 1097, 231), 'en': (1056, 191, 1097, 231), 'jp': (1056, 191, 1097, 231), 'tw': (1056, 191, 1097, 231)}, color={'cn': (53, 64, 69), 'en': (53, 64, 69), 'jp': (53, 64, 69), 'tw': (53, 64, 69)}, button={'cn': (1056, 191, 1097, 231), 'en': (1056, 191, 1097, 231), 'jp': (1056, 191, 1097, 231), 'tw': (1056, 191, 1097, 231)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM6.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM6.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM6.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM6.png'}) +BUTTON_GG_SCRIPT_PANEL_NUM7 = Button(area={'cn': (910, 262, 950, 303), 'en': (910, 262, 950, 303), 'jp': (910, 262, 950, 303), 'tw': (910, 262, 950, 303)}, color={'cn': (48, 59, 65), 'en': (48, 59, 65), 'jp': (48, 59, 65), 'tw': (48, 59, 65)}, button={'cn': (910, 262, 950, 303), 'en': (910, 262, 950, 303), 'jp': (910, 262, 950, 303), 'tw': (910, 262, 950, 303)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM7.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM7.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM7.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM7.png'}) +BUTTON_GG_SCRIPT_PANEL_NUM8 = Button(area={'cn': (987, 263, 1021, 304), 'en': (987, 263, 1021, 304), 'jp': (987, 263, 1021, 304), 'tw': (987, 263, 1021, 304)}, color={'cn': (59, 69, 74), 'en': (59, 69, 74), 'jp': (59, 69, 74), 'tw': (59, 69, 74)}, button={'cn': (987, 263, 1021, 304), 'en': (987, 263, 1021, 304), 'jp': (987, 263, 1021, 304), 'tw': (987, 263, 1021, 304)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM8.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM8.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM8.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM8.png'}) +BUTTON_GG_SCRIPT_PANEL_NUM9 = Button(area={'cn': (1053, 266, 1098, 301), 'en': (1053, 266, 1098, 301), 'jp': (1053, 266, 1098, 301), 'tw': (1053, 266, 1098, 301)}, color={'cn': (54, 65, 70), 'en': (54, 65, 70), 'jp': (54, 65, 70), 'tw': (54, 65, 70)}, button={'cn': (1053, 266, 1098, 301), 'en': (1053, 266, 1098, 301), 'jp': (1053, 266, 1098, 301), 'tw': (1053, 266, 1098, 301)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM9.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM9.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM9.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_PANEL_NUM9.png'}) +BUTTON_GG_SCRIPT_START = Button(area={'cn': (906, 557, 965, 596), 'en': (906, 557, 965, 596), 'jp': (906, 557, 965, 596), 'tw': (906, 557, 965, 596)}, color={'cn': (87, 87, 87), 'en': (87, 87, 87), 'jp': (87, 87, 87), 'tw': (87, 87, 87)}, button={'cn': (906, 557, 965, 596), 'en': (906, 557, 965, 596), 'jp': (906, 557, 965, 596), 'tw': (906, 557, 965, 596)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_START.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_START.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_START.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_START.png'}) +BUTTON_GG_SCRIPT_START_PROCESS = Button(area={'cn': (1088, 561, 1147, 599), 'en': (1088, 561, 1147, 599), 'jp': (1088, 561, 1147, 599), 'tw': (1088, 561, 1147, 599)}, color={'cn': (93, 93, 93), 'en': (93, 93, 93), 'jp': (93, 93, 93), 'tw': (93, 93, 93)}, button={'cn': (1088, 561, 1147, 599), 'en': (1088, 561, 1147, 599), 'jp': (1088, 561, 1147, 599), 'tw': (1088, 561, 1147, 599)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_START_PROCESS.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_START_PROCESS.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_START_PROCESS.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SCRIPT_START_PROCESS.png'}) +BUTTON_GG_SEARCH_MODE_CONFIRM = Button(area={'cn': (337, 68, 605, 73), 'en': (337, 68, 605, 73), 'jp': (337, 68, 605, 73), 'tw': (337, 68, 605, 73)}, color={'cn': (77, 122, 119), 'en': (77, 122, 119), 'jp': (77, 122, 119), 'tw': (77, 122, 119)}, button={'cn': (337, 68, 605, 73), 'en': (337, 68, 605, 73), 'jp': (337, 68, 605, 73), 'tw': (337, 68, 605, 73)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_SEARCH_MODE_CONFIRM.png', 'en': './assets/cn/gg_handler/BUTTON_GG_SEARCH_MODE_CONFIRM.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_SEARCH_MODE_CONFIRM.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_SEARCH_MODE_CONFIRM.png'}) +BUTTON_GG_TAB_SEARCH_POS = Button(area={'cn': (445, 11, 491, 59), 'en': (445, 11, 491, 59), 'jp': (445, 11, 491, 59), 'tw': (445, 11, 491, 59)}, color={'cn': (255, 255, 255), 'en': (255, 255, 255), 'jp': (255, 255, 255), 'tw': (255, 255, 255)}, button={'cn': (445, 11, 491, 59), 'en': (445, 11, 491, 59), 'jp': (445, 11, 491, 59), 'tw': (445, 11, 491, 59)}, file={'cn': './assets/cn/gg_handler/BUTTON_GG_TAB_SEARCH_POS.png', 'en': './assets/cn/gg_handler/BUTTON_GG_TAB_SEARCH_POS.png', 'jp': './assets/cn/gg_handler/BUTTON_GG_TAB_SEARCH_POS.png', 'tw': './assets/cn/gg_handler/BUTTON_GG_TAB_SEARCH_POS.png'}) +OCR_PRE_BATTLE_CHECK = Button(area={'cn': (736, 518, 979, 582), 'en': (736, 518, 979, 582), 'jp': (736, 518, 979, 582), 'tw': (736, 518, 979, 582)}, color={'cn': (90, 100, 119), 'en': (90, 100, 119), 'jp': (90, 100, 119), 'tw': (90, 100, 119)}, button={'cn': (736, 518, 979, 582), 'en': (736, 518, 979, 582), 'jp': (736, 518, 979, 582), 'tw': (736, 518, 979, 582)}, file={'cn': './assets/cn/gg_handler/OCR_PRE_BATTLE_CHECK.png', 'en': './assets/cn/gg_handler/OCR_PRE_BATTLE_CHECK.png', 'jp': './assets/cn/gg_handler/OCR_PRE_BATTLE_CHECK.png', 'tw': './assets/cn/gg_handler/OCR_PRE_BATTLE_CHECK.png'}) diff --git a/module/gg_handler/change_attribute.py b/module/gg_handler/change_attribute.py new file mode 100644 index 000000000..fecd077c4 --- /dev/null +++ b/module/gg_handler/change_attribute.py @@ -0,0 +1,80 @@ +from module.logger import logger +from module.config.config import deep_get +from module.base.base import ModuleBase +import uiautomator2 as u2 + +class ChangeAttribute(ModuleBase): + + def __init__(self, config, device): + super().__init__(config, device) + self.d = u2.connect(self.device.serial) + self.gg_package_name = deep_get(self.config.data, keys='GameManager.GGHandler.GGPackageName') + + def GetShipData(self): + DataList: str = deep_get(self.config.data, "GameManager.ChangeAttribute.ShipData").split("\n") + DataString = "|".join(DataList) + return DataString + + def PushLua(self): + IsPush = deep_get(self.config.data, keys='GameManager.ChangeAttribute.PushLua') + if IsPush: + self.device.adb_shell("mkdir /sdcard/Notes") + self.device.sleep(0.5) + self.device.adb_shell("rm /sdcard/Notes/ShipFucker.lua") + self.device.sleep(0.5) + self.device.adb_push("bin/Lua/ShipFucker.lua", "/sdcard/Notes/ShipFucker.lua") + self.device.sleep(0.5) + logger.info('Lua Pushed') + + def ChangeAttribute(self): + if not deep_get(self.config.data, "GameManager.ChangeAttribute.Enable"): + return 0 + _set = False + _confirmed = False + while 1: + if self.d(resourceId=f"{self.gg_package_name}:id/search_toolbar").exists: + self.d.xpath( + f'//*[@resource-id="{self.gg_package_name}' + f':id/search_toolbar"]/android.widget.ImageView[last()]' + ).click() + self.device.sleep(1) + if self.d(resourceId=f"{self.gg_package_name}:id/file").exists: + self.d(resourceId=f"{self.gg_package_name}:id/file").send_keys("/sdcard/Notes/ShipFucker.lua") + logger.info('Lua path set') + if self.d.xpath('//*[@text="执行"]').exists: + self.d.xpath('//*[@text="执行"]').click() + logger.info('Click Run') + self.device.sleep(0.5) + if self.d.xpath('//*[contains(@text,"改属性")]').exists: + self.d.xpath('//*[contains(@text,"改属性")]').click() + logger.info('Click Change Statistic') + self.device.sleep(0.5) + if self.d(resourceId=f"{self.gg_package_name}:id/edit").exists: + ShipDataString = self.GetShipData() + self.d(resourceId=f"{self.gg_package_name}:id/edit")[0].send_keys(ShipDataString) + self.device.sleep(0.5) + _set = True + if _set and self.d.xpath('//*[@text="确定"]').exists: + self.d.xpath('//*[@text="确定"]').click() + logger.info("Click confirm") + self.device.sleep(0.5) + _confirmed = True + if _confirmed: + self.d.wait_timeout = deep_get(self.config.data, "GameManager.ChangeAttribute.Timeout") + logger.info(f'Xpath timeout set to {self.d.wait_timeout} seconds') + + if _set and _confirmed: + try: + self.d.xpath('//*[@text="确定"]').click() + logger.info("Click confirm") + self.device.sleep(0.5) + self.d.xpath('//*[@text="确定"]').click() + logger.info("Click confirm") + except Exception as e: + pass + self.d.wait_timeout = 3 + logger.info(f'Xpath timeout set to {self.d.wait_timeout} seconds') + if _set and _confirmed: + break + else: + return 0 \ No newline at end of file diff --git a/module/gg_handler/change_ship.py b/module/gg_handler/change_ship.py new file mode 100644 index 000000000..b22c00fb0 --- /dev/null +++ b/module/gg_handler/change_ship.py @@ -0,0 +1,138 @@ +from enum import Enum + +from uiautomator2 import UiObjectNotFoundError + +from module.logger import logger +from module.gg_handler.gg_data import GGData +from module.config.config import deep_get +from module.base.base import ModuleBase +import uiautomator2 as u2 + + +class ShipData: + def __init__(self, DataStr: str): + DataList = DataStr.split(";") + self.ShipId = DataList[0] + self.Rarity = DataList[1] + self.Star = DataList[2] + self.ShipType = DataList[3] + self.TargetType = DataList[4] + + +class ChangeShip(ModuleBase): + + def __init__(self, config, device): + super().__init__(config, device) + self.d = u2.connect(self.device.serial) + self.gg_package_name = deep_get(self.config.data, keys='GameManager.GGHandler.GGPackageName') + + def GetShipData(self): + DataList = list() + vanguard_setting = deep_get(self.config.data, keys='GameManager.ChangeShip.Vanguard') + capitalship_setting = deep_get(self.config.data, keys='GameManager.ChangeShip.CapitalShip') + _to_split = "" + if vanguard_setting == "downes_and_cassin_to_ca": + _to_split = "\n101041;2;1;1;3\n101031;2;1;1;3\n" + elif vanguard_setting == "downes_and_cassin_to_cl": + _to_split = "\n101041;2;1;1;2\n101031;2;1;1;2\n" + elif vanguard_setting == "custom" and capitalship_setting != "custom": + _to_split = deep_get(self.config.data, "GameManager.ChangeShip.ShipData") + if capitalship_setting == "cvl_to_bc": + _to_split += "\n106021;2;1;6;4\n107041;2;1;6;4\n206011;2;1;6;4\n107011;2;1;6;4\n\n105011;2;1;5;19\n105021;2;1;5;19\n" + elif capitalship_setting == "cvl_to_bb": + _to_split += "\n106021;2;1;6;5\n107041;2;1;6;5\n206011;2;1;6;5\n107011;2;1;6;5\n\n105011;2;1;5;19\n105021;2;1;5;19\n" + elif capitalship_setting == "cvl_to_cv": + _to_split += "\n106021;2;1;6;7\n107041;2;1;6;7\n206011;2;1;6;7\n107011;2;1;6;7\n" + elif capitalship_setting == "custom": + _to_split += deep_get(self.config.data, "GameManager.ChangeShip.ShipData") + + for i in _to_split.split("\n"): + if i: + DataList.append(ShipData(i)) + return DataList + + def PushLua(self): + IsPush = deep_get(self.config.data, keys='GameManager.ChangeShip.PushLua') + if IsPush: + self.device.adb_shell("mkdir /sdcard/Notes") + self.device.sleep(0.5) + self.device.adb_shell("rm /sdcard/Notes/ShipChanger.lua") + self.device.sleep(0.5) + self.device.adb_push("bin/Lua/ShipChanger.lua", "/sdcard/Notes/ShipChanger.lua") + self.device.sleep(0.5) + logger.info('Lua Pushed') + + def ChangeShipType(self): + if not deep_get(self.config.data, "GameManager.ChangeShip.Enable"): + return 0 + HARDMODEMAPS = [ + 'd1', 'd2', 'd3', + 'ht4', 'ht5', 'ht6', + ] + if not self.config.is_task_enabled("GemsFarming") or deep_get(self.config.data, + "GemsFarming.Campaign.Name").lower() not in HARDMODEMAPS: + return 0 + _set = False + _confirmed = False + while 1: + if self.d(resourceId=f"{self.gg_package_name}:id/search_toolbar").exists: + self.d.xpath( + f'//*[@resource-id="{self.gg_package_name}' + f':id/search_toolbar"]/android.widget.ImageView[last()]' + ).click() + self.device.sleep(1) + if self.d(resourceId=f"{self.gg_package_name}:id/file").exists: + self.d(resourceId=f"{self.gg_package_name}:id/file").send_keys("/sdcard/Notes/ShipChanger.lua") + logger.info('Lua path set') + if self.d.xpath('//*[@text="执行"]').exists: + self.d.xpath('//*[@text="执行"]').click() + logger.info('Click Run') + self.device.sleep(0.5) + if self.d.xpath('//*[contains(@text,"改船")]').exists: + self.d.xpath('//*[contains(@text,"改船")]').click() + logger.info('Click Change Statistic') + self.device.sleep(0.5) + if self.d(resourceId=f"{self.gg_package_name}:id/edit").exists: + ShipDataList = self.GetShipData() + ShipIdStr = ";".join([str(i.ShipId) for i in ShipDataList]) + ShipRarityStr = ";".join([str(i.Rarity) for i in ShipDataList]) + ShipStarStr = ";".join([str(i.Star) for i in ShipDataList]) + CurrentShipTypeStr = ";".join([str(i.ShipType) for i in ShipDataList]) + TargetShipTypeStr = ";".join([str(i.TargetType) for i in ShipDataList]) + while 1: + try: + self.d(resourceId=f"{self.gg_package_name}:id/edit")[0].send_keys(ShipIdStr) + self.d(resourceId=f"{self.gg_package_name}:id/edit")[1].send_keys(ShipRarityStr) + self.d(resourceId=f"{self.gg_package_name}:id/edit")[2].send_keys(ShipStarStr) + self.d(resourceId=f"{self.gg_package_name}:id/edit")[3].send_keys(CurrentShipTypeStr) + self.d(resourceId=f"{self.gg_package_name}:id/edit")[4].send_keys(TargetShipTypeStr) + break + except UiObjectNotFoundError: + self.d(className="android.widget.ScrollView")[0].scroll.toEnd() + + self.device.sleep(0.5) + _set = True + if _set and self.d.xpath('//*[@text="确定"]').exists: + self.d.xpath('//*[@text="确定"]').click() + logger.info("Click confirm") + self.device.sleep(0.5) + _confirmed = True + if _confirmed: + self.d.wait_timeout = deep_get(self.config.data, "GameManager.ChangeShip.Timeout") + logger.info(f'Xpath timeout set to {self.d.wait_timeout} seconds') + + if _set and _confirmed: + try: + self.d.xpath('//*[@text="确定"]').click() + logger.info("Click confirm") + self.device.sleep(0.5) + self.d.xpath('//*[@text="确定"]').click() + logger.info("Click confirm") + except Exception as e: + pass + self.d.wait_timeout = 3 + logger.info(f'Xpath timeout set to {self.d.wait_timeout} seconds') + if _set and _confirmed: + break + else: + return 0 diff --git a/module/gg_handler/gg_adb.py b/module/gg_handler/gg_adb.py new file mode 100644 index 000000000..1b0d3bbf8 --- /dev/null +++ b/module/gg_handler/gg_adb.py @@ -0,0 +1,172 @@ +# import subprocess +# +# from module.logger import logger +# from module.gg_handler.gg_data import GGData +# from module.config.config import deep_get +# from module.base.base import ModuleBase as Base +# from module.base.utils import point2str, random_rectangle_point +# from module.device.method.adb import Adb +# from module.device.method.utils import (RETRY_TRIES, retry_sleep, +# HierarchyButton, handle_adb_error) +# from module.exception import GameStuckError +# +# class GGADB(Adb): +# +# def __init__(self, config): +# super().__init__(config) +# self.factor = 200 +# self.config = config +# self.adb_reconnect() +# self.gg_package_name = deep_get(self.config.data, keys='GameManager.GGHandler.GGPackageName') +# +# def appear(self, xpath): +# return bool(HierarchyButton(self.h, xpath)) +# +# def appear_then_click(self, xpath): +# b = HierarchyButton(self.h, xpath) +# if b: +# point = random_rectangle_point(b.button) +# logger.info(f'Click {point2str(*point)} @ {b}') +# self.click_adb(*point) +# return True +# else: +# return False +# +# def exit(self): +# self.app_stop_adb(f'{self.gg_package_name}') +# logger.attr('GG', 'Killed') +# +# def skip_error(self): +# _skipped = 0 +# self.h = self.dump_hierarchy_adb() +# if self.appear('//*[@text="重启游戏"]'): +# _skipped = 1 +# logger.hr('Game died with GG panel') +# logger.info('No matter GG panel exists or not, Kill GG') +# self.exit() +# return _skipped +# +# def set_on(self, factor=200): +# self.factor = factor +# ggdata = GGData(self.config).get_data() +# for _i in range(1): +# try: +# if ggdata['gg_on']: +# logger.attr('GG', 'Enabled') +# pass +# else: +# chosen = False +# self.h = self.dump_hierarchy_adb() +# if self.appear_then_click(f'//*[@resource-id="com.ucr.tx:id/hot_frame"]'): +# logger.info('Open GG panel') +# Base.device.sleep(0.5) +# else: +# self.app_start_adb(self.gg_package_name) +# logger.info('Starting GG') +# logger.info('In GG overview') +# Base.device.sleep(3) +# while 1: +# Base.device.sleep(0.5) +# self.h = self.dump_hierarchy_adb() +# if self.appear_then_click('//*[@text="忽略"]'): +# logger.info("Click ignore") +# continue +# if self.appear_then_click(f'//*[@resource-id="{self.gg_package_name}:id/btn_start_usage"]'): +# logger.info('Click GG start button') +# logger.attr('GG', 'Started') +# continue +# if self.appear_then_click(f'//*[@resource-id="{self.gg_package_name}:id/hot_point_icon"]'): +# logger.info('Open GG panel') +# continue +# if self.appear(f'//*[@resource-id="{self.gg_package_name}:id/search_tab"]') \ +# and not self.appear(f'//*[@resource-id="{self.gg_package_name}:id/search_toolbar"]'): +# self.appear_then_click(f'//*[@resource-id="{self.gg_package_name}:id/search_tab"]') +# logger.info('Switch to search tab') +# continue +# if self.appear_then_click( +# f'//*[@package="{self.gg_package_name}" ' +# f'and @resource-id="android:id/text1" ' +# f'and contains(@text,"碧蓝航线")]' +# ): +# logger.info('Choose APP: AzurLane') +# chosen = True +# continue +# if not chosen and self.appear(f'//*[@resource-id="{self.gg_package_name}:id/app_icon"]'): +# self.appear_then_click(f'//*[@resource-id="{self.gg_package_name}:id/app_icon"]') +# logger.info('Click APP choosing tag') +# continue +# if self.appear(f'//*[@resource-id="{self.gg_package_name}:id/search_toolbar"]'): +# self.appear_then_click(f'//*[@resource-id="{self.gg_package_name}:id/search_toolbar"]/' +# f'android.widget.ImageView[last()]' +# ) +# logger.info('Click run Scripts') +# if self._run(): +# return 1 +# if self.appear_then_click('//*[@text="取消"]'): +# logger.info("Cancel exists but not running script, click cancel") +# continue +# if self.appear_then_click('//*[@text="确定"]'): +# # and self.d.xpath('//*[contains(@text,"脚本已结束")]').exists: +# logger.info("Confirm exists but script crashed, click confirm") +# continue +# if self.appear_then_click('//*[@text="重启游戏"]'): +# logger.info('GG Panel after game died exists, restart the game') +# logger.info('Click Restart') +# continue +# finally: +# pass +# +# def _run(self): +# _run = 0 +# _set = 0 +# _confirmed = 0 +# while 1: +# self.h = self.dump_hierarchy_adb() +# if self.appear(f'//*[@resource-id="{self.gg_package_name}:id/file"]'): +# self.adb_shell(['input', 'text', "/sdcard/Notes/Multiplier.lua"]) +# logger.info('Lua path set') +# import os +# _pop = os.popen(f'"toolkit/Lib/site-packages/adbutils/binaries/adb.exe" ' +# f'-s {self.device.serial} shell mkdir /sdcard/Notes') +# _pop = os.popen(f'"toolkit/Lib/site-packages/adbutils/binaries/adb.exe" ' +# f'-s {self.device.serial} shell rm /sdcard/Notes/Multiplier.lua') +# _pop = os.popen(f'"toolkit/Lib/site-packages/adbutils/binaries/adb.exe" ' +# f'-s {self.device.serial} push "Multiplier.lua" /sdcard/Notes/Multiplier.lua') +# Base.device.sleep(0.5) +# if self.appear_then_click('//*[@text="执行"]'): +# logger.info('Click Run') +# Base.device.sleep(0.5) +# if self.appear_then_click('//*[contains(@text,"修改面板")]'): +# logger.info('Click Change Statistic') +# if self.appear_then_click(f'//*[@resource-id="{self.gg_package_name}:id/edit"]'): +# logger.info('Factor Set') +# Base.device.sleep(0.5) +# _set = 1 +# if _set and self.appear('//*[@text="确定"]'): +# self.appear_then_click('//*[@text="确定"]') +# logger.info("Click confirm") +# Base.device.sleep(0.5) +# _confirmed = 1 +# +# from module.base.timer import Timer +# timeout = Timer(90, count=90).start() +# if _set and _confirmed: +# try: +# while 1: +# if self.appear_then_click('//*[@text="确定"]'): +# GGData(self.config).set_data(target='gg_on', value=True) +# break +# if timeout.reached(): +# raise GameStuckError +# finally: +# pass +# GGData(self.config).set_data(target='gg_on', value='True') +# logger.attr('GG', 'Enabled') +# logger.info("Close the script") +# if _set and _confirmed: +# break +# else: +# return 0 +# logger.hr('GG Enabled', level=2) +# self.app_stop_adb(self.gg_package_name) +# return 1 diff --git a/module/gg_handler/gg_data.py b/module/gg_handler/gg_data.py new file mode 100644 index 000000000..596fa6346 --- /dev/null +++ b/module/gg_handler/gg_data.py @@ -0,0 +1,85 @@ +from module.config.config import deep_get +from module.base.base import ModuleBase + + +class GGData(ModuleBase): + gg_on = False + gg_enable = False + gg_auto = False + gg_type = False + ggdata = {} + + def __init__(self, config=None): + self.config = config + import os + if not os.path.exists('./config/gg_handler'): + os.mkdir('./config/gg_handler') + with open(file=f'./config/gg_handler/gg_data_{self.config.config_name}.tmp', + mode='a+', + encoding='utf-8') as tmp: + tmp.close() + tmp = open(file=f'./config/gg_handler/gg_data_{self.config.config_name}.tmp', + mode='r', + encoding='utf-8') + line = tmp.readline() + if line[:-1] != self.config.config_name: + tmp.close() + tmp = open(file=f'./config/gg_handler/gg_data_{self.config.config_name}.tmp', + mode='w', + encoding='utf-8') + tmp.write(f'{self.config.config_name}\n') + tmp.write('gg_on=False\n') + self.ggdata['gg_on'] = False + self.ggdata['gg_type'] = False + self.ggdata['gg_enable'] = deep_get(d=self.config.data, + keys='GameManager.GGHandler.Enabled', + default=False) + self.ggdata['gg_auto'] = deep_get(d=self.config.data, + keys='GameManager.GGHandler.AutoRestartGG', + default=False) + tmp.write('gg_enable=' + str(self.ggdata['gg_enable']) + '\n') + tmp.write('gg_auto=' + str(self.ggdata['gg_auto']) + '\n') + tmp.write('gg_type=' + str(self.ggdata['gg_type']) + '\n') + tmp.close() + else: + for i in range(4): + line = tmp.readline() + if i == 3 and line == '': + line = 'gg_type=False\n' + line1, line2 = line.split('=') + self.ggdata[line1] = True if line2[:-1] == 'True' else False + tmp.close() + + def get_data(self): + # Return a dict of data + return self.ggdata + + def set_data(self, target=None, value=None): + self.target = target + self.value = value + self.ggdata[self.target] = self.value + self.update_data() + + def update_data(self): + with open(file=f'./config/gg_handler/gg_data_{self.config.config_name}.tmp', + mode='w', + encoding='utf-8') as tmp: + tmp.write(f'{self.config.config_name}\n') + for t in self.ggdata: + tmp.write(t + '=' + str(self.ggdata[t]) + '\n') + tmp.close() + + def dele(self): + with open(file=f'./config/gg_handler/gg_data_{self.config.config_name}.tmp', + mode='w', + encoding='utf-8') as tmp: + tmp.write('啊吧啊吧') + tmp.close() + + +# if __name__ == '__main__': +# config = AzurLaneConfig(config_name='alas') +# print(gg_data(config).get_data()) +# gg_data(config=config, target='gg_on', value=True).set_data() +# print(gg_data(config).get_data()) +# gg_data().dele() \ No newline at end of file diff --git a/module/gg_handler/gg_handler.py b/module/gg_handler/gg_handler.py new file mode 100644 index 000000000..2fcbd6b2f --- /dev/null +++ b/module/gg_handler/gg_handler.py @@ -0,0 +1,393 @@ +from module.gg_handler.gg_data import GGData +from module.gg_handler.gg_u2 import GGU2 +# from module.gg_handler.gg_screenshot import GGScreenshot +from module.config.deep import deep_get, deep_set +from module.logger import logger +from module.base.timer import timeout +from module.config.full_config import AzurLaneFullConfig + + +class GGHandler: + """ + A module to handle needs of cheaters + Args: + config: AzurlaneConfig + device: Device + """ + + def __init__(self, config=None, device=None): + self.task = '' + self.config = config + self.device = device + self.factor = deep_get(self.config.data, + 'GameManager.GGHandler.GGMultiplyingFactor', + default=200) + self.method = deep_get(self.config.data, + 'GameManager.GGHandler.GGMethod', + default='screenshot') + ggu2 = GGU2(config=self.config, device=self.device) + self.GGData = GGData(config=self.config) + self.gg = ggu2 + lua_enable = deep_get(d=self.config.data, keys='Hook.HookGeneral.Enable', default=False) + if lua_enable: + self.GGData.set_data('gg_enable', False) + logger.info('LuaHook enabled, ignoring GG') + + def restart(self, crashed=False): + from module.handler.login import LoginHandler + from module.exception import GameStuckError + _crashed = crashed + for _ in range(2): + try: + if _crashed: + timeout(self.handle_u2_restart, timeout_sec=60) + if not timeout(LoginHandler(config=self.config, device=self.device).app_restart, timeout_sec=600): + break + raise RuntimeError + except GameStuckError as e: + pass + except Exception as e: + logger.exception(e) + if _crashed: + logger.critical('Maybe your emulator died, trying to restart it') + self.device.emulator_start() + _crashed = True + + def set(self, mode=True): + """ + Set the GG status to True/False. + Args: + mode: bool + """ + gg_package_name = deep_get(self.config.data, keys='GameManager.GGHandler.GGPackageName') + if mode: + logger.hr('Enabling GG') + # if self.method == 'screenshot' or gg_package_name == 'com.': + # GGScreenshot(config=self.config, device=self.device) \ + # .gg_set(mode=True, factor=self.factor) + # elif self.method == 'u2': + # GGU2(config=self.config, device=self.device) \ + # .set_on(factor=self.factor) + self.handle_u2_restart() + success = self.change_attribute() + success = self.multiplier() and success + success = self.speed_up() and success + # if not success: + # from module.exception import GameStuckError + # raise GameStuckError + # Not support screenshot anymore + else: + self.gg_reset() + + def skip_error(self) -> bool: + """ + Close all the windows of GG. + Often to be used when game restarts with GG enabled. + Returns: + bool: Whether GG error panel occurs + """ + gg_package_name = deep_get(self.config.data, keys='GameManager.GGHandler.GGPackageName') + # if self.method == 'screenshot' or gg_package_name == 'com.': + # return \ + # GGScreenshot(config=self.config, device=self.device).skip_error() + # elif self.method == 'u2': + # return \ + # GGU2(config=self.config, device=self.device).skip_error() + return self.gg.skip_error() # Not support screenshot anymore + + def check_config(self) -> dict: + """ + Reset GG config to the user's config and return gg_data. + Returns: + gg_data: dict = { + 'gg_enable' : bool = Whether GG manager enabled, + 'gg_auto' : bool = Whether to start GG before tasks, + 'gg_on' : bool = Whether multiplier is on now} + """ + gg_enable = deep_get(d=self.config.data, keys='GameManager.GGHandler.Enabled', default=False) + gg_auto = deep_get(d=self.config.data, keys='GameManager.GGHandler.AutoRestartGG', default=False) + lua_enable = deep_get(d=self.config.data, keys='Hook.HookGeneral.Enable', default=False) + if lua_enable: + gg_enable = False + logger.info('LuaHook enabled, ignoring GG') + self.GGData.set_data(target='gg_enable', value=gg_enable) + self.GGData.set_data(target='gg_auto', value=gg_auto) + gg_data = self.GGData.get_data() + logger.info(f'GG status:') + logger.info( + f'Enabled={gg_data["gg_enable"]} AutoRestart={gg_data["gg_auto"]} Current stage={gg_data["gg_on"]} Type Changed={gg_data["gg_type"]}') + return gg_data + + def handle_u2_restart(self): + _need_restart_atx = deep_get(d=self.config.data, keys='GameManager.GGHandler.RestartATX') + if _need_restart_atx: + try: + timeout(self.device.restart_atx, 60) + except Exception: + logger.critical('Maybe your emulator died, trying to restart it') + self.device.emulator_start() + import uiautomator2 as u2 + logger.info('Reset UiAutomator') + try: + u2.connect(self.device.serial).reset_uiautomator() + except Exception: + logger.critical('Maybe your emulator died, trying to restart it') + self.device.emulator_start() + + def handle_restart(self): + """ + Handle the restart errors of GG. + """ + gg_data = self.GGData.get_data() + gg_enable = gg_data['gg_enable'] + if gg_enable: + self.GGData.set_data(target='gg_on', value=False) + self.GGData.set_data(target='gg_type', value=False) + logger.info(f'GG status:') + logger.info( + f'Enabled={gg_data["gg_enable"]} AutoRestart={gg_data["gg_auto"]} Current stage={gg_data["gg_on"]} Type Changed={gg_data["gg_type"]}') + if not self.skip_error(): + logger.hr('Assume game died without GG panel') + + def gg_reset(self): + """ + Force restart the game to reset GG status to False + """ + gg_data = self.GGData.get_data() + if gg_data['gg_enable'] and gg_data['gg_on']: + logger.hr('Disabling GG') + self.restart() + logger.attr('GG', 'Disabled') + + def check_status(self, mode=True): + """ + A check before a task begins to decide whether to enable GG and set it. + Args: + mode: The multiplier status when finish the check. + """ + gg_data = self.GGData.get_data() + if gg_data['gg_enable']: + gg_auto = mode if deep_get(d=self.config.data, + keys='GameManager.GGHandler.AutoRestartGG', + default=False) else False + logger.info(f'Check GG status:') + logger.info( + f'Enabled={gg_data["gg_enable"]} AutoRestart={gg_data["gg_auto"]} Current stage={gg_data["gg_on"]} ' + f'Type Changed={gg_data["gg_type"]}') + if gg_auto: + if not gg_data['gg_on']: + self.set(True) + if not gg_data['gg_type']: + self.change_ship_type(task=self.task) + self.gg.exit() + elif gg_data['gg_on']: + self.gg_reset() + + def power_limit(self, task=''): + """ + Forced final check before some dangerous tasks for cheaters. + If power is too high, disable the multiplier and assume the user need GG to be Enabled before the other tasks. + Args: + task: str = What task it is to limit power, default limit is 17000 for front ships. + """ + full_config: AzurLaneFullConfig = self.config.full_config + if not full_config.PowerLimit_PowerLimit_Enable: + return + + from module.gg_handler.assets import OCR_PRE_BATTLE_CHECK + from module.ocr.ocr import Digit + self.device.screenshot() + OCR_CHECK = Digit(OCR_PRE_BATTLE_CHECK, letter=(255, 255, 255), threshold=128) + ocr = OCR_CHECK.ocr(self.device.image) + from module.config.deep import deep_get + limit = deep_get(self.config.data, keys=f'PowerLimit.PowerLimit.{task}', default=25000) + logger.attr('Power Limit', limit) + if ocr >= limit: + logger.critical('There''s high chance that GG is on, restart to disable it') + from module.gg_handler.gg_data import GGData + self.GGData.set_data(target='gg_on', value=False) + self.GGData.set_data(target='gg_enable', value=True) + deep_set(d=self.config.data, keys='GameManager.GGHandler.Enabled', value=True) + deep_set(d=self.config.data, keys='GameManager.GGHandler.AutoRestartGG', value=True) + self.config.task_call('Restart') + self.config.task_delay(minute=0.5) + self.config.task_stop('Restart for sake of safty') + + def handle_restart_before_tasks(self) -> bool: + """ + Check if user need to restart everytime alas starts before tasks, and handle it. + Returns: + bool: If it needs restart first + """ + gg_data = self.GGData.get_data() + if (deep_get(d=self.config.data, + keys='GameManager.GGHandler.RestartEverytime', + default=True) + and gg_data['gg_enable']): + logger.info('Restart to reset GG status.') + self.restart() + return True + return False + + def check_then_set_gg_status(self, task=''): + """ + If task is in list _disabled or _group_enabled defined in this function, + set gg to the defined status + Args: + task : str = the next task to run + """ + self.task = task + _disabled_task = deep_get(self.config.data, 'GameManager.GGHandler.DisabledTask') + """ + 'disable_all_dangerous_task' + 'disable_meta_and_exercise' + 'disable_exercise' + 'enable_all' + """ + _disabled = [ + 'minigame' + ] + _group_exercise = [ + 'exercise' + ] + _group_meta = [ + 'opsi_ash_assist', + 'opsi_ash_beacon' + ] + _group_raid = [ + 'raid', + 'raid_daily', + 'coalition', + 'coalition_sp' + ] + _group_personal_choice = [ + 'guild' + ] + _group_enabled = [ + 'hard', + 'sos', + 'war_archives', + 'event_a', + 'event_b', + 'event_c', + 'event_d', + 'event_sp', + 'maritime_escort', + 'opsi_explore', + 'opsi_daily', + 'opsi_obscure', + 'opsi_month_boss', + 'opsi_abyssal', + 'opsi_archive', + 'opsi_stronghold', + 'opsi_meowfficer_farming', + 'opsi_hazard1_leveling', + 'opsi_cross_month', + 'research_farm', + 'research_farm2', + 'research_farm3', + 'research_farm4', + 'research_farm5', + 'research_farm6', + 'main', + 'main2', + 'main3', + 'main4', + 'main5', + 'main6', + 'event', + 'event2', + 'event3', + 'event4', + 'event5', + 'event6', + 'gems_farming', + 'c72_mystery_farming', + 'c122_medium_leveling', + 'c124_large_leveling', + 'hospital' + ] + + # Handle ignorance + + if _disabled_task == 'disable_meta_and_exercise': + _disabled += _group_exercise + _group_meta + _enabled = _group_enabled + _group_raid + _group_personal_choice + elif _disabled_task == 'disable_exercise': + _disabled += _group_exercise + _enabled = _group_enabled + _group_personal_choice + _group_raid + _group_meta + elif _disabled_task == 'enable_all': + _enabled = _group_enabled + _group_personal_choice + _group_raid + _group_meta + _group_exercise + # _disabled = [] + elif _disabled_task == 'disable_guild_and_dangerous': + _disabled += _group_exercise + _group_meta + _group_raid + _group_personal_choice + _enabled = _group_enabled + else: # _disabled_task == 'disable_all_dangerous_task': + _disabled += _group_exercise + _group_meta + _group_raid + _enabled = _group_enabled + _group_personal_choice + + if task in _disabled: + self.check_status(False) + elif task in _enabled: + self.check_status(True) + + def change_ship_type(self, task): + if task == 'gems_farming': + if not deep_get(self.config.data, "GameManager.ChangeShip.Enable"): + return True + HARDMODEMAPS = [ + 'd1', 'd2', 'd3', + 'ht4', 'ht5', 'ht6', + ] + if not self.config.is_task_enabled("GemsFarming") or deep_get(self.config.data, + "GemsFarming.Campaign.Name").lower() not in HARDMODEMAPS: + return 0 + self._change_ship_type() + return True + return False + + def _change_ship_type(self): + logger.hr('GG Ship Type', level=2) + success = timeout(self.gg.set_on, + timeout_sec=deep_get(self.config.data, "GameManager.GGHandler.Timeout"), + func='change_type', + factor=self.factor) + self.GGData.set_data(target='gg_on', value=True) + self.GGData.set_data(target='gg_type', value=True) + + # success = self.gg.set_on('change_type') + + def change_attribute(self): + if not deep_get(self.config.data, "GameManager.ChangeAttribute.Enable"): + return False + logger.hr('GG Attribute', level=2) + success = timeout(self.gg.set_on, + timeout_sec=deep_get(self.config.data, "GameManager.GGHandler.Timeout"), + func='change_attribute', + factor=self.factor) + self.GGData.set_data(target='gg_on', value=True) + # self.gg.set_on('change_attribute') + return True + + def speed_up(self): + if not deep_get(self.config.data, "GameManager.SpeedUp.Enable"): + return False + success = timeout(self.gg.set_on, + timeout_sec=deep_get(self.config.data, "GameManager.GGHandler.Timeout"), + func='speedup', + factor=self.factor) + self.GGData.set_data(target='gg_on', value=True) + + # success = self.gg.set_on(factor=self.factor) + return True + + def multiplier(self): + logger.hr('GG Multiplier', level=2) + success = timeout(self.gg.set_on, + timeout_sec=deep_get(self.config.data, "GameManager.GGHandler.Timeout"), + func='multiplier', + factor=self.factor) + self.GGData.set_data(target='gg_on', value=True) + + # success = self.gg.set_on(factor=self.factor) + return True diff --git a/module/gg_handler/gg_screenshot.py b/module/gg_handler/gg_screenshot.py new file mode 100644 index 000000000..ebca71f6d --- /dev/null +++ b/module/gg_handler/gg_screenshot.py @@ -0,0 +1,263 @@ +from module.config.deep import deep_get +from module.logger import logger +from module.gg_handler.assets import * +from module.base.base import ModuleBase as Base +from module.gg_handler.gg_data import GGData + + +class GGScreenshot(Base): + + def __init__(self, config, device): + super().__init__(config, device) + self.device = device + self.config = config + self.gg_panel_confirm_time = 5 + # self.gg_panel_confirm_time = deep_get(self.config.data, 'GameManager.GGHandler.GGPanelConfirmTime') + + def skip_error(self): + """ + Page: + in: Game down error + out: restart + """ + skip_first_screenshot = False + count = 0 + logger.attr('Confirm Time', f'{self.gg_panel_confirm_time}S') + times = self.gg_panel_confirm_time * 2 + for i in range(times): + skipped = 0 + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.sleep(0.5) + self.device.screenshot() + if self.appear(button=BUTTON_GG_RESTART_ERROR, offset=(50, 50)): + logger.hr('Game died with GG panel') + logger.info('Close GG restart error') + self.device.click(BUTTON_GG_RESTART_ERROR) + skipped = 1 + count += 1 + if count >= 2: + break + skip_first_screenshot = False + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.sleep(0.3) + self.device.screenshot() + if self.appear(button=BUTTON_GG_RESTART_ERROR, offset=(50, 50)): + logger.hr('Game died with GG panel') + logger.info('Close GG restart error') + skipped = 1 + self.device.click(BUTTON_GG_RESTART_ERROR) + elif self.appear(button=BUTTON_GG_SCRIPT_END, offset=(50, 50)): + logger.info('Close previous script') + skipped = 1 + self.device.click(BUTTON_GG_SCRIPT_END) + elif self.appear(button=BUTTON_GG_SCRIPT_FATAL, offset=(50, 50)): + logger.info('Restart previous script') + skipped = 1 + self.device.click(BUTTON_GG_SCRIPT_FATAL) + elif self.appear(button=BUTTON_GG_APP_CHOOSE, offset=(150, 500)): + logger.info('APP choose') + skipped = 1 + self.device.click(BUTTON_GG_APP_CHOOSE) + elif self.appear(button=BUTTON_GG_SCRIPT_MENU_A, offset=(50, 50)): + skipped = 1 + logger.info('Close previous script') + self.device.click(BUTTON_GG_EXIT_POS) + elif not self.appear(button=BUTTON_GG_CONFIRM, offset=(50, 50)): + logger.hr('GG Panel Disappearance Confirmed') + break + elif self.appear(button=BUTTON_GG_SEARCH_MODE_CONFIRM, offset=(10, 10), threshold=0.999): + logger.info('At GG main panel, click GG exit') + skipped = 1 + self.device.click(BUTTON_GG_EXIT_POS) + elif self.appear(button=BUTTON_GG_CONFIRM, offset=(50, 50)) and \ + not self.appear(button=BUTTON_GG_CONFIRM, offset=10): + self.device.click(BUTTON_GG_TAB_SEARCH_POS) + skipped = 1 + logger.info('Enter search mode') + elif self.appear(button=BUTTON_GG_CONFIRM, offset=10): + logger.info('Unexpected GG page, Try GG exit') + self.device.click(BUTTON_GG_EXIT_POS) + skipped = 1 + return skipped + + def _enter_gg(self): + """ + Page: + in: any + out: any GG + """ + self.device.click(BUTTON_GG_ENTER_POS) + skip_first_screenshot = False + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.sleep(0.3) + self.device.screenshot() + if self.appear(button=BUTTON_GG_CONFIRM, offset=(50, 50)): + logger.info('Entered GG') + break + self.device.click(BUTTON_GG_ENTER_POS) + skip_first_screenshot = False + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.sleep(0.3) + self.device.screenshot() + if not self.appear(button=BUTTON_GG_APP_CHOOSE, offset=(150, 500)): + from module.ui.assets import BACK_ARROW + self.device.click(BACK_ARROW) + logger.info('Actually APP choosing button') + else: + self.appear_then_click(button=BUTTON_GG_APP_CHOOSE, offset=(150, 500)) + logger.info('APP Choose') + break + + def _gg_enter_script(self): + """ + Page: + in: any GG + out: GG ready to start script + """ + skip_first_screenshot = False + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.sleep(0.5) + self.device.screenshot() + if self.appear(button=BUTTON_GG_SCRIPT_ENTER_CONFIRM, offset=(50, 50)): + logger.info('GG script ready to start') + break + elif self.appear(button=BUTTON_GG_SCRIPT_END, offset=(50, 50)): + logger.info('Close previous script') + self.device.click(BUTTON_GG_SCRIPT_END) + elif self.appear(button=BUTTON_GG_SCRIPT_FATAL, offset=(50, 50)): + logger.info('Stop previous script') + self.device.click(BUTTON_GG_SCRIPT_FATAL) + elif self.appear(button=BUTTON_GG_APP_CHOOSE, offset=(150, 500)): + logger.info('APP choose') + self.device.click(BUTTON_GG_APP_CHOOSE) + elif self.appear(button=BUTTON_GG_SEARCH_MODE_CONFIRM, offset=(10, 10), threshold=0.95): + self.device.click(BUTTON_GG_SCRIPT_ENTER_POS) + logger.info('Enter script choose') + else: + self.device.click(BUTTON_GG_TAB_SEARCH_POS) + logger.info('Enter search mode') + skip_first_screenshot = False + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.sleep(0.5) + self.device.screenshot() + if self.appear(button=BUTTON_GG_SCRIPT_START, offset=(50, 50)): + self.device.click(BUTTON_GG_SCRIPT_START) + return 1 + + def _gg_mode(self): + """ + Page: + in: GG Script Menu + out: GG GG input panel + """ + skip_first_screenshot = False + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.sleep(0.5) + self.device.screenshot() + if self.appear(button=BUTTON_GG_SCRIPT_MENU_A, offset=(50, 50), threshold=0.8): + method = [BUTTON_GG_SCRIPT_MENU_B, BUTTON_GG_SCRIPT_MENU_A] + self.device.click(method[int(self._mode)]) + break + + def _gg_handle_factor(self): + """ + Page: + in: GG input panel + out:factor set(Not ensured yet) + """ + self.wait_until_appear(button=BUTTON_GG_SCRIPT_START_PROCESS, skip_first_screenshot=True) + logger.info(f'Factor={self._factor}') + if self._factor == 200: + logger.info('Skip factor input') + return 0 + method = [ + BUTTON_GG_SCRIPT_PANEL_NUM0, + BUTTON_GG_SCRIPT_PANEL_NUM1, + BUTTON_GG_SCRIPT_PANEL_NUM2, + BUTTON_GG_SCRIPT_PANEL_NUM3, + BUTTON_GG_SCRIPT_PANEL_NUM4, + BUTTON_GG_SCRIPT_PANEL_NUM5, + BUTTON_GG_SCRIPT_PANEL_NUM6, + BUTTON_GG_SCRIPT_PANEL_NUM7, + BUTTON_GG_SCRIPT_PANEL_NUM8, + BUTTON_GG_SCRIPT_PANEL_NUM9, + ] + for i in str(self._factor): + self.appear_then_click(button=method[int(i)], offset=(50, 50)) + self.device.sleep(0.5) + logger.info('Input success') + + def _gg_script_run(self): + """ + Page: + in: GG factor set + out: GG Menu + """ + skip_first_screenshot = False + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.sleep(0.5) + self.device.screenshot() + if self.appear_then_click(button=BUTTON_GG_SCRIPT_START_PROCESS, offset=(50, 50), threshold=0.9): + break + + logger.info('Waiting for end') + skip_first_screenshot = False + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.sleep(0.5) + self.device.screenshot() + if self.appear_then_click(button=BUTTON_GG_SCRIPT_END, offset=(50, 50), threshold=0.9): + return 1 + + def gg_set(self, mode=True, factor=200): + import os + os.popen(f'"toolkit/Lib/site-packages/adbutils/binaries/adb.exe" -s' + f' {self.device.serial} shell mkdir /sdcard/Notes') + self.device.sleep(0.5) + os.popen(f'"toolkit/Lib/site-packages/adbutils/binaries/adb.exe" -s' + f' {self.device.serial} shell rm /sdcard/Notes/Multiplier.lua') + self.device.sleep(0.5) + os.popen(f'"toolkit/Lib/site-packages/adbutils/binaries/adb.exe" -s' + f' {self.device.serial} push "bin/Lua/Multiplier.lua" /sdcard/Notes/Multiplier.lua') + self.device.sleep(0.5) + logger.info('Lua Pushed') + + # self._gg_package_name = deep_get(self.config.data, keys='GameManager.GGHandler.GGPackageName') + # if self._gg_package_name != 'com.': + # os.popen(f'"toolkit/Lib/site-packages/adbutils/binaries/adb.exe" -s' + # f' {self.device.serial} shell am start -n {self._gg_package_name}') + self._mode = mode + self._factor = factor + self._enter_gg() + self._gg_enter_script() + self._gg_mode() + self._gg_handle_factor() + self._gg_script_run() + GGData(self.config).set_data(target='gg_on', value=self._mode) + self.skip_error() + logger.attr('GG', 'Enabled') \ No newline at end of file diff --git a/module/gg_handler/gg_u2.py b/module/gg_handler/gg_u2.py new file mode 100644 index 000000000..f971d4aca --- /dev/null +++ b/module/gg_handler/gg_u2.py @@ -0,0 +1,258 @@ +from module.gg_handler.speedup import SpeedUp +from module.logger import logger +from module.gg_handler.gg_data import GGData +from module.config.config import deep_get +from module.base.base import ModuleBase as Base +import uiautomator2 as u2 +from module.gg_handler.change_ship import ChangeShip +from module.gg_handler.change_attribute import ChangeAttribute + + +class GGU2(Base): + + def __init__(self, config, device): + super().__init__(config, device) + self.factor = 200 + self.config = config + self.device = device + self.d = u2.connect(self.device.serial) + self.gg_package_name = deep_get(self.config.data, keys='GameManager.GGHandler.GGPackageName') + self.d.wait_timeout = 10.0 + logger.info(f'Xpath timeout set to {self.d.wait_timeout} seconds') + + def exit(self): + self.d.app_stop(f'{self.gg_package_name}') + logger.attr('GG', 'Killed') + + def skip_error(self): + _skipped = 0 + if self.d.xpath('//*[@text="重启游戏"]').exists: + _skipped = 1 + logger.hr('Game died with GG panel') + logger.info('No matter GG panel exists or not, Kill GG') + self.exit() + return _skipped + + def set_on(self, func='multiplier', factor=200): + """ + func : 'multiplier' or 'change_type' or 'change_attribute' or 'speedup' + factor : factor used in multiplier + """ + _name_dict = { + 'en': 'Azur Lane', + 'cn': '碧蓝航线', + 'jp': 'アズールレーン', + 'tw': '碧藍航線' + } + _server = self.config.SERVER + _name = _name_dict[_server] + self.factor = factor + ggdata = GGData(self.config).get_data() + for _i in range(1): + try: + if ggdata['gg_on'] and func == 'multiplier': + logger.attr('GG', 'Enabled') + pass + elif ggdata['gg_type'] and func == 'change_type': + logger.attr('Type', 'Changed') + pass + else: + chosen = False + if self.d(resourceId=f"{self.gg_package_name}:id/hot_point_icon").exists: + self.d(resourceId=f"{self.gg_package_name}:id/hot_point_icon").click() + logger.info('Open GG panel') + self.device.sleep(0.5) + else: + self.d.app_start(self.gg_package_name) + logger.info('Starting GG') + logger.info('In GG overview') + self.device.sleep(3) + while 1: + self.device.sleep(0.5) + if self.d.xpath('//*[@text="忽略"]').exists: + self.d.xpath('//*[@text="忽略"]').click() + logger.info("Click ignore") + self.device.sleep(0.3) + continue + if self.d(resourceId=f"{self.gg_package_name}:id/btn_start_usage").exists: + self.d(resourceId=f"{self.gg_package_name}:id/btn_start_usage").click() + logger.info('Click GG start button') + logger.attr('GG', 'Started') + self.device.sleep(0.3) + continue + if self.d(resourceId=f"{self.gg_package_name}:id/hot_point_icon").exists: + self.d(resourceId=f"{self.gg_package_name}:id/hot_point_icon").click() + logger.info('Open GG panel') + self.device.sleep(0.3) + continue + if self.d(resourceId=f"{self.gg_package_name}:id/search_tab").exists \ + and not self.d(resourceId=f"{self.gg_package_name}:id/search_toolbar").exists: + self.d(resourceId=f"{self.gg_package_name}:id/search_tab").click() + logger.info('Switch to search tab') + self.device.sleep(0.3) + continue + if self.d.xpath( + f'//*[@package="{self.gg_package_name}" ' + f'and @resource-id="android:id/text1" ' + f'and contains(@text,"{_name}")]' + ).exists: + self.d.xpath(f'//*[contains(@text,"{_name}")]').click() + logger.info('Choose APP: AzurLane') + self.device.sleep(0.3) + chosen = True + continue + if not chosen and self.d(resourceId=f"{self.gg_package_name}:id/app_icon").exists: + self.d(resourceId=f"{self.gg_package_name}:id/app_icon").click() + logger.info('Click APP choosing tag') + self.device.sleep(0.3) + continue + if self.d(resourceId=f"{self.gg_package_name}:id/search_toolbar").exists: + self.d.xpath( + f'//*[@resource-id="{self.gg_package_name}' + f':id/search_toolbar"]/android.widget.ImageView[last()]' + ).click() + logger.info('Click run Scripts') + self.device.sleep(0.3) + self.__getattribute__(func)() + return 1 + if self.d.xpath('//*[@text="取消"]').exists: + self.d.xpath('//*[@text="取消"]').click() + logger.info("Cancel exists but not running script, click cancel") + self.device.sleep(0.3) + continue + if self.d.xpath('//*[@text="确定"]').exists: + self.d.xpath('//*[@text="确定"]').click() + logger.info("Confirm exists but script crashed, click confirm") + self.device.sleep(0.3) + continue + if self.d.xpath('//*[@text="重启游戏"]').exists: + self.d.xpath('//*[@text="重启游戏"]').click() + logger.info('GG Panel after game died exists, restart the game') + logger.info('Click Restart') + self.device.sleep(0.3) + continue + + except Exception as e: + pass + + def change_type(self): + ShipChanger = ChangeShip(self.config, self.device) + ShipChanger.PushLua() + ShipChanger.ChangeShipType() + try: + GGData(self.config).set_data(target='gg_on', value=True) + self.d.xpath('//*[@text="确定"]').click() + except Exception as e: + pass + GGData(self.config).set_data(target='gg_type', value=True) + # self.d.app_stop(self.gg_package_name) + logger.hr('GG Enabled: Type Changed', level=2) + return 1 + + def change_attribute(self): + AttributeChanger = ChangeAttribute(self.config, self.device) + AttributeChanger.PushLua() + AttributeChanger.ChangeAttribute() + try: + GGData(self.config).set_data(target='gg_on', value=True) + self.d.xpath('//*[@text="确定"]').click() + except Exception as e: + pass + # self.d.app_stop(self.gg_package_name) + return 1 + + def speedup(self): + speedup = SpeedUp(self.config, self.device) + speedup.Run() + + def multiplier(self): + _run = False + _set = False + _confirmed = False + import os + _repush = deep_get(self.config.data, keys='GameManager.GGHandler.RepushLua') + if _repush: + # os.popen(f'"toolkit/Lib/site-packages/adbutils/binaries/adb.exe" -s' + # f' {self.device.serial} shell mkdir /sdcard/Notes') + # self.device.sleep(0.5) + # os.popen(f'"toolkit/Lib/site-packages/adbutils/binaries/adb.exe" -s' + # f' {self.device.serial} shell rm /sdcard/Notes/Multiplier.lua') + # self.device.sleep(0.5) + # os.popen(f'"toolkit/Lib/site-packages/adbutils/binaries/adb.exe" -s' + # f' {self.device.serial} push "bin/Lua/Multiplier.lua" /sdcard/Notes/Multiplier.lua') + # self.device.sleep(0.5) + self.device.adb_shell("mkdir /sdcard/Notes") + self.device.sleep(0.5) + self.device.adb_shell("rm /sdcard/Notes/Multiplier.lua") + self.device.sleep(0.5) + self.device.adb_push("bin/Lua/Multiplier.lua", "/sdcard/Notes/Multiplier.lua") + self.device.sleep(0.5) + logger.info('Lua Pushed') + while 1: + self.device.sleep(1) + if self.d(resourceId=f"{self.gg_package_name}:id/search_toolbar").exists: + self.d.xpath( + f'//*[@resource-id="{self.gg_package_name}' + f':id/search_toolbar"]/android.widget.ImageView[last()]' + ).click() + logger.info('Click run Scripts') + self.device.sleep(0.3) + if self.d(resourceId=f"{self.gg_package_name}:id/file").exists: + self.d(resourceId=f"{self.gg_package_name}:id/file").send_keys("/sdcard/Notes/Multiplier.lua") + logger.info('Lua path set') + if self.d.xpath('//*[@text="执行"]').exists: + self.d.xpath('//*[@text="执行"]').click() + logger.info('Click Run') + self.device.sleep(0.5) + if self.d.xpath('//*[contains(@text,"修改面板")]').exists: + self.d.xpath('//*[contains(@text,"修改面板")]').click() + logger.info('Click Change Statistic') + self.device.sleep(0.5) + if self.d(resourceId=f"{self.gg_package_name}:id/edit").exists: + self.d(resourceId=f"{self.gg_package_name}:id/edit").send_keys(f"{self.factor}") + logger.info(f'Factor Set: {self.factor}') + self.device.sleep(0.5) + _set = True + if _set and self.d.xpath('//*[@text="确定"]').exists: + self.d.xpath('//*[@text="确定"]').click() + logger.info("Click confirm") + self.device.sleep(0.5) + _confirmed = True + if _confirmed: + self.d.wait_timeout = deep_get(self.config.data, "GameManager.GGHandler.Timeout") + logger.info(f'Xpath timeout set to {self.d.wait_timeout} seconds') + + if _set and _confirmed: + try: + GGData(self.config).set_data(target='gg_on', value=True) + self.d.xpath('//*[@text="确定"]').click() + except Exception as e: + pass + GGData(self.config).set_data(target='gg_on', value=True) + logger.attr('GG', 'Enabled') + logger.info("Close the script") + self.d.wait_timeout = 3 + logger.info(f'Xpath timeout set to {self.d.wait_timeout} seconds') + if _set and _confirmed: + break + else: + return 0 + logger.hr('GG Enabled: Multiplied', level=2) + # self.d.app_stop(self.gg_package_name) + return 1 + + +if __name__ == '__main__': + from module.config.config import AzurLaneConfig + from module.device.device import Device + + config = AzurLaneConfig('主号') + device = Device(config) + ggu2 = GGU2(config, device) + try: + ggu2.set_on(func='change_type') + except Exception as e: + pass + print(GGData(config).get_data()) + + diff --git a/module/gg_handler/speedup.py b/module/gg_handler/speedup.py new file mode 100644 index 000000000..4828ccc94 --- /dev/null +++ b/module/gg_handler/speedup.py @@ -0,0 +1,81 @@ +from module.gg_handler.gg_data import GGData +from module.logger import logger +from module.config.deep import deep_get, deep_set +from module.base.base import ModuleBase +import uiautomator2 as u2 + + +class SpeedUp(ModuleBase): + + def __init__(self, config, device): + super().__init__(config, device) + self.d = u2.connect(self.device.serial) + self.gg_package_name = deep_get(self.config.data, keys='GameManager.GGHandler.GGPackageName') + + def Run(self): + _run = False + _set = False + _confirmed = False + import os + rate = float(deep_get(self.config.data, keys='GameManager.SpeedUp.Rate', default=5.0)) + _repush = deep_get(self.config.data, keys='GameManager.SpeedUp.PushLua') + if _repush: + self.device.adb_shell("mkdir /sdcard/Notes") + self.device.sleep(0.5) + self.device.adb_shell("rm /sdcard/Notes/SpeedUp.lua") + self.device.sleep(0.5) + self.device.adb_push("bin/Lua/SpeedUp.lua", "/sdcard/Notes/SpeedUp.lua") + self.device.sleep(0.5) + logger.info('Lua Pushed') + while 1: + self.device.sleep(1) + if self.d(resourceId=f"{self.gg_package_name}:id/search_toolbar").exists: + self.d.xpath( + f'//*[@resource-id="{self.gg_package_name}' + f':id/search_toolbar"]/android.widget.ImageView[last()]' + ).click() + logger.info('Click run Scripts') + self.device.sleep(0.3) + if self.d(resourceId=f"{self.gg_package_name}:id/file").exists: + self.d(resourceId=f"{self.gg_package_name}:id/file").send_keys("/sdcard/Notes/SpeedUp.lua") + logger.info('Lua path set') + if self.d.xpath('//*[@text="执行"]').exists: + self.d.xpath('//*[@text="执行"]').click() + logger.info('Click Run') + self.device.sleep(0.5) + if self.d.xpath('//*[contains(@text,"设置倍速")]').exists: + self.d.xpath('//*[contains(@text,"设置倍速")]').click() + logger.info('Click Change Statistic') + self.device.sleep(0.5) + if self.d(resourceId=f"{self.gg_package_name}:id/edit").exists: + self.d(resourceId=f"{self.gg_package_name}:id/edit").send_keys(f"{rate}") + logger.info(f'Factor Set: {rate}') + self.device.sleep(0.5) + _set = True + if _set and self.d.xpath('//*[@text="确定"]').exists: + self.d.xpath('//*[@text="确定"]').click() + logger.info("Click confirm") + self.device.sleep(0.5) + _confirmed = True + if _confirmed: + self.d.wait_timeout = deep_get(self.config.data, "GameManager.SpeedUp.Timeout") + logger.info(f'Xpath timeout set to {self.d.wait_timeout} seconds') + + if _set and _confirmed: + try: + # GGData(self.config).set_data(target='gg_on', value=True) + self.d.xpath('//*[@text="确定"]').click() + except Exception as e: + pass + # GGData(self.config).set_data(target='gg_on', value=True) + logger.attr('GG', 'Enabled') + logger.info("Close the script") + self.d.wait_timeout = 3 + logger.info(f'Xpath timeout set to {self.d.wait_timeout} seconds') + if _set and _confirmed: + break + else: + return 0 + logger.hr('GG Enabled: SpeedUp', level=2) + # self.d.app_stop(self.gg_package_name) + return 1 diff --git a/module/os_ash/ash.py b/module/os_ash/ash.py index 0d54085a5..89338acb2 100644 --- a/module/os_ash/ash.py +++ b/module/os_ash/ash.py @@ -82,6 +82,17 @@ class AshCombat(Combat): pass +class AshCombat(AshCombat): + def handle_battle_preparation(self): + if self.appear(BATTLE_PREPARATION, offset=(20, 20)): + self.device.sleep(0.5) + self.device.screenshot() + # Power limit check + from module.gg_handler.gg_handler import GGHandler + GGHandler(config=self.config, device=self.device).power_limit('Ash') + super().handle_battle_preparation() + + class OSAsh(UI, MapEventHandler): _ash_fully_collected = False diff --git a/module/raid/raid.py b/module/raid/raid.py index 3a4b0a02f..a7be35ae7 100644 --- a/module/raid/raid.py +++ b/module/raid/raid.py @@ -395,3 +395,9 @@ class Raid(MapOperation, RaidCombat, CampaignEvent): self.device.swipe_vector((-900, 0), box=(0, 130, 1280, 440)) interval.reset() continue + +class Raid(Raid): + def combat_preparation(self, *args, **kwargs): + from module.gg_handler.gg_handler import GGHandler + GGHandler(config=self.config, device=self.device).power_limit('Raid') + super().combat_preparation(*args, **kwargs) \ No newline at end of file