diff --git a/assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png b/assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png index a430a573c..9c6dcc97b 100644 Binary files a/assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png and b/assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png differ diff --git a/assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_VILLA.png b/assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_VILLA.png new file mode 100644 index 000000000..5ec10b965 Binary files /dev/null and b/assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_VILLA.png differ diff --git a/assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png b/assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png index 3257d80b8..cf7ba16c9 100644 Binary files a/assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png and b/assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png differ diff --git a/assets/cn/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3.png b/assets/cn/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3.png new file mode 100644 index 000000000..1a9d0869b Binary files /dev/null and b/assets/cn/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3.png differ diff --git a/assets/cn/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png b/assets/cn/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png index c9b20099f..86713e643 100644 Binary files a/assets/cn/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png and b/assets/cn/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png differ diff --git a/assets/cn/private_quarters/PRIVATE_QUARTERS_SHIP_NAKHIMOV.png b/assets/cn/private_quarters/PRIVATE_QUARTERS_SHIP_NAKHIMOV.png new file mode 100644 index 000000000..d7bfb8aa4 Binary files /dev/null and b/assets/cn/private_quarters/PRIVATE_QUARTERS_SHIP_NAKHIMOV.png differ diff --git a/assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png b/assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png index a430a573c..9c6dcc97b 100644 Binary files a/assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png and b/assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png differ diff --git a/assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_VILLA.png b/assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_VILLA.png new file mode 100644 index 000000000..5ec10b965 Binary files /dev/null and b/assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_VILLA.png differ diff --git a/assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png b/assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png index 3257d80b8..cf7ba16c9 100644 Binary files a/assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png and b/assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png differ diff --git a/assets/en/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3.png b/assets/en/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3.png new file mode 100644 index 000000000..1a9d0869b Binary files /dev/null and b/assets/en/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3.png differ diff --git a/assets/en/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png b/assets/en/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png index c9b20099f..86713e643 100644 Binary files a/assets/en/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png and b/assets/en/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png differ diff --git a/assets/en/private_quarters/PRIVATE_QUARTERS_SHIP_NAKHIMOV.png b/assets/en/private_quarters/PRIVATE_QUARTERS_SHIP_NAKHIMOV.png new file mode 100644 index 000000000..d7bfb8aa4 Binary files /dev/null and b/assets/en/private_quarters/PRIVATE_QUARTERS_SHIP_NAKHIMOV.png differ diff --git a/assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png b/assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png index a430a573c..9c6dcc97b 100644 Binary files a/assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png and b/assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png differ diff --git a/assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_VILLA.png b/assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_VILLA.png new file mode 100644 index 000000000..5ec10b965 Binary files /dev/null and b/assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_VILLA.png differ diff --git a/assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png b/assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png index 3257d80b8..cf7ba16c9 100644 Binary files a/assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png and b/assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png differ diff --git a/assets/jp/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3.png b/assets/jp/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3.png new file mode 100644 index 000000000..1a9d0869b Binary files /dev/null and b/assets/jp/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3.png differ diff --git a/assets/jp/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png b/assets/jp/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png index c9b20099f..86713e643 100644 Binary files a/assets/jp/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png and b/assets/jp/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png differ diff --git a/assets/jp/private_quarters/PRIVATE_QUARTERS_SHIP_NAKHIMOV.png b/assets/jp/private_quarters/PRIVATE_QUARTERS_SHIP_NAKHIMOV.png new file mode 100644 index 000000000..d7bfb8aa4 Binary files /dev/null and b/assets/jp/private_quarters/PRIVATE_QUARTERS_SHIP_NAKHIMOV.png differ diff --git a/assets/tw/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png b/assets/tw/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png index a430a573c..9c6dcc97b 100644 Binary files a/assets/tw/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png and b/assets/tw/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png differ diff --git a/assets/tw/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_VILLA.png b/assets/tw/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_VILLA.png new file mode 100644 index 000000000..5ec10b965 Binary files /dev/null and b/assets/tw/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_VILLA.png differ diff --git a/assets/tw/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3.png b/assets/tw/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3.png new file mode 100644 index 000000000..1a9d0869b Binary files /dev/null and b/assets/tw/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3.png differ diff --git a/assets/tw/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png b/assets/tw/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png index c9b20099f..86713e643 100644 Binary files a/assets/tw/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png and b/assets/tw/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png differ diff --git a/assets/tw/private_quarters/PRIVATE_QUARTERS_SHIP_NAKHIMOV.png b/assets/tw/private_quarters/PRIVATE_QUARTERS_SHIP_NAKHIMOV.png new file mode 100644 index 000000000..d7bfb8aa4 Binary files /dev/null and b/assets/tw/private_quarters/PRIVATE_QUARTERS_SHIP_NAKHIMOV.png differ diff --git a/dev_tools/map_extractor.py b/dev_tools/map_extractor.py index 2ba38afd4..3367b7d7f 100644 --- a/dev_tools/map_extractor.py +++ b/dev_tools/map_extractor.py @@ -322,11 +322,16 @@ DIC_SIREN_NAME_CHI_TO_ENG = { 'bulaimodun': 'Bremerton', 'fushun_g': 'FuShunG', 'lafeier': 'Raffaello', - 'huangjiafangzhou_g': 'ArkRoyal', + 'huangjiafangzhou_g': 'ArkRoyalG', 'chaijun': 'Cheshire', 'naximofu': 'Nakhimov', 'liekexingdunII': 'Lexington2', 'yuekechengII': 'Yorktown2', + + # Miracle by Midnight + 'youeryuan_boss03': 'MeowfficerBust_Playtime', + 'youeryuan_boss04': 'MeowfficerBust_Hobbies', + 'youeryuan_boss05': 'MeowfficerBust_Studying', } diff --git a/module/config/argument/args.json b/module/config/argument/args.json index 805fc8cef..fda46ecc2 100644 --- a/module/config/argument/args.json +++ b/module/config/argument/args.json @@ -7643,6 +7643,10 @@ "FortChoreMeowfficer": { "type": "checkbox", "value": true + }, + "OverflowCoins": { + "type": "input", + "value": -1 } }, "MeowfficerTrain": { @@ -12678,7 +12682,8 @@ "sirius", "new_jersey", "taihou", - "aegir" + "aegir", + "nakhimov" ] } }, diff --git a/module/config/argument/argument.yaml b/module/config/argument/argument.yaml index 4bf3b17e6..1e4df14bd 100644 --- a/module/config/argument/argument.yaml +++ b/module/config/argument/argument.yaml @@ -464,6 +464,7 @@ BuyFurniture: Meowfficer: BuyAmount: 1 FortChoreMeowfficer: true + OverflowCoins: -1 MeowfficerTrain: Enable: false Mode: @@ -870,7 +871,7 @@ PrivateQuarters: TargetInteract: true TargetShip: value: anchorage - option: [ anchorage, noshiro, sirius, new_jersey, taihou, aegir ] + option: [ anchorage, noshiro, sirius, new_jersey, taihou, aegir, nakhimov ] # ==================== Daily ==================== Daily: diff --git a/module/config/config_generated.py b/module/config/config_generated.py index 33184fe80..ad8797472 100644 --- a/module/config/config_generated.py +++ b/module/config/config_generated.py @@ -247,6 +247,7 @@ class GeneratedConfig: # Group `Meowfficer` Meowfficer_BuyAmount = 1 Meowfficer_FortChoreMeowfficer = True + Meowfficer_OverflowCoins = -1 # Group `MeowfficerTrain` MeowfficerTrain_Enable = False @@ -540,7 +541,7 @@ class GeneratedConfig: PrivateQuarters_BuyRoses = True PrivateQuarters_BuyCake = False PrivateQuarters_TargetInteract = True - PrivateQuarters_TargetShip = 'anchorage' # anchorage, noshiro, sirius, new_jersey, taihou, aegir + PrivateQuarters_TargetShip = 'anchorage' # anchorage, noshiro, sirius, new_jersey, taihou, aegir, nakhimov # Group `Daily` Daily_UseDailySkip = True diff --git a/module/config/i18n/en-US.json b/module/config/i18n/en-US.json index b82330041..2b233d124 100644 --- a/module/config/i18n/en-US.json +++ b/module/config/i18n/en-US.json @@ -1544,7 +1544,7 @@ "help": "" }, "Favorite": { - "name": "Use Favorite Filter", + "name": "Only Favorite Ships", "help": "During student selection apply the favorite filter\nThereby, giving priority to certain ship girls\nApply the favorite status to a ship girl in-game" }, "MinLevel": { @@ -1667,6 +1667,10 @@ "FortChoreMeowfficer": { "name": "Do Fort Chores", "help": "Completes all 3 chores; clean, feed, and play with meowfficer to get fort exp" + }, + "OverflowCoins": { + "name": "Buy Boxes On Coin Overflow", + "help": "When coins are above this value, keep buying boxes until coins drop to it or boxes run out; -1 to disable" } }, "MeowfficerTrain": { @@ -5682,7 +5686,8 @@ "sirius": "Sirius", "new_jersey": "New Jersey", "taihou": "Taihou", - "aegir": "Aegir" + "aegir": "Aegir", + "nakhimov": "Nakhimov" } }, "Daily": { diff --git a/module/config/i18n/ja-JP.json b/module/config/i18n/ja-JP.json index 08ae260c6..cf46e24d8 100644 --- a/module/config/i18n/ja-JP.json +++ b/module/config/i18n/ja-JP.json @@ -1544,7 +1544,7 @@ "help": "" }, "Favorite": { - "name": "好ましい選択", + "name": "お気に入りのみ選択", "help": "" }, "MinLevel": { @@ -1667,6 +1667,10 @@ "FortChoreMeowfficer": { "name": "Meowfficer.FortChoreMeowfficer.name", "help": "Meowfficer.FortChoreMeowfficer.help" + }, + "OverflowCoins": { + "name": "Meowfficer.OverflowCoins.name", + "help": "Meowfficer.OverflowCoins.help" } }, "MeowfficerTrain": { @@ -5682,7 +5686,8 @@ "sirius": "sirius", "new_jersey": "new_jersey", "taihou": "taihou", - "aegir": "aegir" + "aegir": "aegir", + "nakhimov": "nakhimov" } }, "Daily": { diff --git a/module/config/i18n/zh-CN.json b/module/config/i18n/zh-CN.json index 91d56f304..3dd215f03 100644 --- a/module/config/i18n/zh-CN.json +++ b/module/config/i18n/zh-CN.json @@ -1544,7 +1544,7 @@ "help": "" }, "Favorite": { - "name": "优先选择常用", + "name": "仅选择常用角色", "help": "" }, "MinLevel": { @@ -1667,6 +1667,10 @@ "FortChoreMeowfficer": { "name": "喵窝互动", "help": "清扫、喂食和逗猫" + }, + "OverflowCoins": { + "name": "金币溢出时购买猫箱", + "help": "当金币高于此值时,继续购买猫箱直至金币降至此值或猫箱售罄;-1 关闭" } }, "MeowfficerTrain": { @@ -5682,7 +5686,8 @@ "sirius": "天狼星", "new_jersey": "新泽西", "taihou": "大凤", - "aegir": "埃吉尔" + "aegir": "埃吉尔", + "nakhimov": "纳希莫夫" } }, "Daily": { diff --git a/module/config/i18n/zh-TW.json b/module/config/i18n/zh-TW.json index a365ad527..e703b46d9 100644 --- a/module/config/i18n/zh-TW.json +++ b/module/config/i18n/zh-TW.json @@ -1544,7 +1544,7 @@ "help": "" }, "Favorite": { - "name": "優先選擇常用", + "name": "僅選擇常用角色", "help": "" }, "MinLevel": { @@ -1667,6 +1667,10 @@ "FortChoreMeowfficer": { "name": "喵窩互動", "help": "清掃、餵食和逗貓" + }, + "OverflowCoins": { + "name": "金幣溢出時購買貓箱", + "help": "當金幣高於此值時,繼續購買貓箱直至金幣降至此值或貓箱售罄;-1 關閉" } }, "MeowfficerTrain": { @@ -5682,7 +5686,8 @@ "sirius": "天狼星", "new_jersey": "紐澤西", "taihou": "大鳳", - "aegir": "埃吉爾" + "aegir": "埃吉爾", + "nakhimov": "纳希莫夫" } }, "Daily": { diff --git a/module/device/platform/emulator_base.py b/module/device/platform/emulator_base.py index 522c6b51d..0f51963f5 100644 --- a/module/device/platform/emulator_base.py +++ b/module/device/platform/emulator_base.py @@ -100,12 +100,17 @@ class EmulatorInstanceBase: Convert MuMu 12 instance name to instance id. Example names: MuMuPlayer-12.0-3 + MuMuPlayerGlobal-12.0-0 + MuMuPlayer-15.0-0 YXArkNights-12.0-1 Returns: int: Instance ID, or None if this is not a MuMu 12 instance """ res = re.search(r'MuMuPlayer(?:Global)?-12.0-(\d+)', self.name) + if res: + return int(res.group(1)) + res = re.search(r'MuMuPlayer(?:Global)?-15.0-(\d+)', self.name) if res: return int(res.group(1)) res = re.search(r'YXArkNights-12.0-(\d+)', self.name) diff --git a/module/equipment/fleet_equipment.py b/module/equipment/fleet_equipment.py index f2a568e20..4f73c6536 100644 --- a/module/equipment/fleet_equipment.py +++ b/module/equipment/fleet_equipment.py @@ -1,3 +1,5 @@ +from module.logger import logger +from module.base.timer import Timer from module.equipment.assets import * from module.equipment.equipment_change import EquipmentChange from module.ocr.ocr import Digit @@ -10,8 +12,31 @@ OCR_FLEET_INDEX = Digit(OCR_FLEET_INDEX, letter=(90, 154, 255), threshold=128, a class FleetEquipment(EquipmentChange): def fleet_enter(self, fleet): self.ui_ensure(page_fleet) - self.ui_ensure_index(fleet, letter=OCR_FLEET_INDEX, - next_button=FLEET_NEXT, prev_button=FLEET_PREV, skip_first_screenshot=True) + + # ui_ensure_index, set fleet + letter = OCR_FLEET_INDEX + next_button = FLEET_NEXT + prev_button = FLEET_PREV + interval = (0.2, 0.3) + + retry = Timer(1, count=2) + for _ in self.loop(): + current = letter.ocr(self.device.image) + logger.attr("Index", current) + + # ui_ensure_index but ignore default value 0 + # otherwise we would have 1 extra click switching from 1 to 4 + if current == 0: + continue + + diff = fleet - current + if diff == 0: + break + + if retry.reached(): + button = next_button if diff > 0 else prev_button + self.device.multi_click(button, n=abs(diff), interval=interval) + retry.reset() def fleet_equipment_take_on_preset(self, preset_record, enter=FLEET_DETAIL_ENTER_FLAGSHIP, long_click=False, out=FLEET_DETAIL_CHECK): diff --git a/module/handler/info_handler.py b/module/handler/info_handler.py index b8de7a15e..81a1e3f9d 100644 --- a/module/handler/info_handler.py +++ b/module/handler/info_handler.py @@ -118,7 +118,7 @@ class InfoHandler(ModuleBase): return True if self.appear(POPUP_CANCEL_WHITE, offset=offset, interval=interval): POPUP_CANCEL_WHITE.name = POPUP_CANCEL_WHITE.name + '_' + name - self.device.click(POPUP_CONFIRM_WHITE) + self.device.click(POPUP_CANCEL_WHITE) POPUP_CANCEL_WHITE.name = POPUP_CANCEL_WHITE.name[:-len(name) - 1] return True return False diff --git a/module/logger.py b/module/logger.py index 4aad36209..b5bf64891 100644 --- a/module/logger.py +++ b/module/logger.py @@ -171,26 +171,7 @@ os.chdir(os.path.join(os.path.dirname(__file__), '../')) pyw_name = os.path.splitext(os.path.basename(sys.argv[0]))[0] -def _set_file_logger(name=pyw_name): - if '_' in name: - name = name.split('_', 1)[0] - log_file = f'./log/{datetime.date.today()}_{name}.txt' - try: - file = logging.FileHandler(log_file, encoding='utf-8') - except FileNotFoundError: - os.mkdir('./log') - file = logging.FileHandler(log_file, encoding='utf-8') - file.setFormatter(file_formatter) - - logger.handlers = [h for h in logger.handlers if not isinstance( - h, (logging.FileHandler, RichFileHandler))] - logger.addHandler(file) - logger.log_file = log_file - - def set_file_logger(name=pyw_name): - if '_' in name: - name = name.split('_', 1)[0] log_file = f'./log/{datetime.date.today()}_{name}.txt' try: file = open(log_file, mode='a', encoding='utf-8') diff --git a/module/map/map_operation.py b/module/map/map_operation.py index 765fd2678..36a31eb0e 100644 --- a/module/map/map_operation.py +++ b/module/map/map_operation.py @@ -312,7 +312,7 @@ class MapOperation(MysteryHandler, FleetPreparation, Retirement, FastForwardHand MAP_MODE_SWITCH_HARD5, MAP_MODE_SWITCH_HARD6, ]: - if self.appear(button, offset=(20, 20), threshold=0.7): + if self.appear(button, offset=(20, 20), similarity=0.7): if active: return self._is_mod_switch_hard_active(button) else: diff --git a/module/meowfficer/buy.py b/module/meowfficer/buy.py index c76abdba1..49e59b585 100644 --- a/module/meowfficer/buy.py +++ b/module/meowfficer/buy.py @@ -13,47 +13,118 @@ MEOWFFICER_COINS = Digit(OCR_MEOWFFICER_COINS, letter=(99, 69, 41), threshold=64 class MeowfficerBuy(MeowfficerBase): - def meow_choose(self, count) -> bool: + def meow_get_buy_count(self, buy_amount, overflow_th): """ + OCR remaining buys and coins, combine with user configs to decide + how many meowfficer boxes to buy this run. + + Args: + buy_amount (int): User configured purchase amount (Meowfficer_BuyAmount). + overflow_th (int): Coin overflow threshold (Meowfficer_OverflowCoins), + < 0 to disable overflow buy. + + Pages: + in: page_meowfficer + + Returns: + int: 0 to BUY_MAX, number of boxes to buy now. + """ + for _ in self.loop(timeout=2): + remain, bought, total = MEOWFFICER.ocr(self.device.image) + coins = MEOWFFICER_COINS.ocr(self.device.image) + if total > 0: + break + # else: retry if MEOWFFICER has ocr error + else: + logger.warning('Failed to get meowfficer buy status') + return 0 + + logger.attr('Meowfficer_remain', remain) + logger.attr('Meowfficer_coins', coins) + + if total != BUY_MAX: + logger.warning(f'Invalid meowfficer buy limit: {total}, revise to {BUY_MAX}') + total = BUY_MAX + bought = total - remain + + return self._meow_get_buy_count(bought, total, coins, buy_amount, overflow_th) + + @staticmethod + def _meow_get_buy_count(bought, total, coins, buy_amount, overflow_th): + """ + Calculate how many meowfficer boxes to buy. + + Baseline: buy up to Meowfficer_BuyAmount per day. + Overflow: when Meowfficer_OverflowCoins >= 0 and current coins + exceed it, keep buying extra boxes until coins drop to threshold or + today's quota runs out. The 1st box per day is free. + + Args: + bought (int): Number of boxes already bought today. + total (int): Total available boxes per day (typically BUY_MAX=15). + coins (int): Current coins. + buy_amount (int): User configured purchase amount (Meowfficer_BuyAmount). + overflow_th (int): Coin overflow threshold (Meowfficer_OverflowCoins), + < 0 to disable overflow buy. + + Returns: + int: 0 to BUY_MAX, number of boxes to buy now. + """ + today_left = max(0, total - bought) + if today_left <= 0: + logger.info(f'Already bought {bought}/{total} today, stopped') + return 0 + + # Baseline buy + baseline = min(max(0, buy_amount - bought), today_left) + + # Overflow buy + extra = 0 + if overflow_th >= 0 and coins > overflow_th: + if bought == 0: + # First box of the day is free, compensate so (extra-1)*BUY_PRIZE + # coins are spent, ensuring coins drop below overflow_th + extra = -(-(coins - overflow_th + BUY_PRIZE) // BUY_PRIZE) + else: + extra = -(-(coins - overflow_th) // BUY_PRIZE) + extra = min(extra, today_left - baseline) + extra = max(0, extra) + + count = baseline + extra + + # Cap by affordable coins, the 1st box per day is free + free = 1 if bought == 0 else 0 + affordable = coins // BUY_PRIZE + free + if count > affordable: + logger.info(f'Current coins only afford to buy {affordable}') + count = affordable + + logger.info( + f'Meowfficer buy plan: count={count}, baseline={baseline}, ' + f'overflow={extra}, bought={bought}/{total}, coins={coins}' + ) + return count + + def meow_choose(self, count) -> None: + """ + Navigate to MEOWFFICER_BUY and set buy index to `count`. + Pages: in: page_meowfficer out: MEOWFFICER_BUY Args: - count (int): 0 to 15. - - Returns: - bool: If success. + count (int): 1 to BUY_MAX. """ - remain, bought, total = MEOWFFICER.ocr(self.device.image) - logger.attr('Meowfficer_remain', remain) - - # Check buy status - if total != BUY_MAX: - logger.warning(f'Invalid meowfficer buy limit: {total}, revise to {BUY_MAX}') - total = BUY_MAX - bought = total - remain - if bought > 0: - if bought >= count: - logger.info(f'Already bought {bought} today, stopped') - return False - else: - count -= bought - logger.info(f'Already bought {bought} today, only need to buy {count} more') - - # Check coins - coins = MEOWFFICER_COINS.ocr(self.device.image) - if (coins < BUY_PRIZE) and (remain < total): - logger.info('Not enough coins to buy one, stopped') - return False - elif (count - int(remain == total)) * BUY_PRIZE > coins: - count = coins // BUY_PRIZE + int(remain == total) - logger.info(f'Current coins only enough to buy {count}') - self.meow_enter(MEOWFFICER_BUY_ENTER, check_button=MEOWFFICER_BUY) + + # info_bar may covers OCR_MEOWFFICER_CHOOSE, + # and OCR_MEOWFFICER_CHOOSE may detected as 0 causing extra clickings + # info_bar is usually from the previous Dorm task or meowfficer fort + self.handle_info_bar() + self.ui_ensure_index(count, letter=MEOWFFICER_CHOOSE, prev_button=MEOWFFICER_BUY_PREV, next_button=MEOWFFICER_BUY_NEXT, skip_first_screenshot=True) - return True def meow_confirm(self, skip_first_screenshot=True) -> None: """ @@ -62,7 +133,6 @@ class MeowfficerBuy(MeowfficerBase): out: page_meowfficer """ # Here uses a simple click, to avoid clicking MEOWFFICER_BUY multiple times. - # Retry logic is in meow_buy() logger.hr('Meow confirm') executed = False with self.stat.new( @@ -102,19 +172,24 @@ class MeowfficerBuy(MeowfficerBase): if self.match_template_color(MEOWFFICER_BUY_ENTER, offset=(20, 20)): break - def meow_buy(self) -> bool: + def meow_buy(self) -> None: """ + Buy meowfficer boxes according to baseline and optional overflow plan. + Pages: in: page_meowfficer out: page_meowfficer """ logger.hr('Meowfficer buy', level=1) - for _ in range(3): - if self.meow_choose(count=self.config.Meowfficer_BuyAmount): - self.meow_confirm() - else: - return True + buy_amount = self.config.Meowfficer_BuyAmount + buy_amount = max(min(buy_amount, 15), 1) + overflow_th = self.config.Meowfficer_OverflowCoins + + count = self.meow_get_buy_count(buy_amount, overflow_th) + if count <= 0: + return + self.meow_choose(count) + self.meow_confirm() logger.warning('Too many trial in meowfficer buy, stopped.') - return False diff --git a/module/meowfficer/meowfficer.py b/module/meowfficer/meowfficer.py index 8a29aa8f4..7154b18ad 100644 --- a/module/meowfficer/meowfficer.py +++ b/module/meowfficer/meowfficer.py @@ -34,6 +34,7 @@ class RewardMeowfficer(MeowfficerBuy, MeowfficerFort, MeowfficerTrain): out: page_meowfficer """ if self.config.Meowfficer_BuyAmount <= 0 \ + and self.config.Meowfficer_OverflowCoins < 0 \ and not self.config.Meowfficer_FortChoreMeowfficer \ and not self.config.MeowfficerTrain_Enable: self.config.Scheduler_Enable = False @@ -42,7 +43,8 @@ class RewardMeowfficer(MeowfficerBuy, MeowfficerFort, MeowfficerTrain): self.ui_ensure(page_meowfficer) self.wait_meowfficer_buttons() # Wait for the ui to load fully - if self.config.Meowfficer_BuyAmount > 0: + if self.config.Meowfficer_BuyAmount > 0 \ + or self.config.Meowfficer_OverflowCoins >= 0: self.meow_buy() if self.config.Meowfficer_FortChoreMeowfficer: self.meow_fort() diff --git a/module/os/globe_operation.py b/module/os/globe_operation.py index 7c1bfc00f..1a9a7895e 100644 --- a/module/os/globe_operation.py +++ b/module/os/globe_operation.py @@ -140,7 +140,7 @@ class GlobeOperation(ActionPointHandler): # Lower threshold to 0.75 # Don't know why buy but fonts are different sometimes return [select for select in ZONE_SELECT if - self.appear(select, offset=self._zone_select_offset, threshold=self._zone_select_similarity)] + self.appear(select, offset=self._zone_select_offset, similarity=self._zone_select_similarity)] def is_in_zone_select(self): """ @@ -190,7 +190,7 @@ class GlobeOperation(ActionPointHandler): if self.is_zone_pinned(): break if self.appear_then_click( - button, offset=self._zone_select_offset, threshold=self._zone_select_similarity, interval=5): + button, offset=self._zone_select_offset, similarity=self._zone_select_similarity, interval=5): continue def zone_type_select(self, types=('SAFE', 'DANGEROUS')): diff --git a/module/private_quarters/assets.py b/module/private_quarters/assets.py index f4a452f44..44ff56bd4 100644 --- a/module/private_quarters/assets.py +++ b/module/private_quarters/assets.py @@ -8,19 +8,22 @@ PRIVATE_QUARTERS_DAILY_COUNT = Button(area={'cn': (107, 129, 154, 154), 'en': (1 PRIVATE_QUARTERS_INTERACT = Button(area={'cn': (832, 446, 857, 471), 'en': (832, 446, 857, 471), 'jp': (832, 446, 857, 471), 'tw': (832, 446, 857, 471)}, color={'cn': (167, 165, 167), 'en': (167, 165, 167), 'jp': (167, 165, 167), 'tw': (167, 165, 167)}, button={'cn': (832, 446, 1107, 471), 'en': (832, 446, 1107, 471), 'jp': (832, 446, 1107, 471), 'tw': (832, 446, 1107, 471)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_INTERACT.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_INTERACT.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_INTERACT.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_INTERACT.png'}) PRIVATE_QUARTERS_INTERACT_CHECK = Button(area={'cn': (1223, 653, 1245, 675), 'en': (1223, 653, 1245, 675), 'jp': (1223, 653, 1245, 675), 'tw': (1223, 653, 1245, 675)}, color={'cn': (196, 192, 187), 'en': (196, 192, 187), 'jp': (196, 192, 187), 'tw': (196, 192, 187)}, button={'cn': (1223, 653, 1245, 675), 'en': (1223, 653, 1245, 675), 'jp': (1223, 653, 1245, 675), 'tw': (1223, 653, 1245, 675)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_INTERACT_CHECK.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_INTERACT_CHECK.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_INTERACT_CHECK.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_INTERACT_CHECK.png'}) PRIVATE_QUARTERS_LOADING_CHECK = Button(area={'cn': (582, 376, 702, 391), 'en': (582, 376, 702, 391), 'jp': (582, 376, 702, 391), 'tw': (582, 376, 702, 391)}, color={'cn': (200, 232, 255), 'en': (200, 232, 255), 'jp': (200, 232, 255), 'tw': (200, 232, 255)}, button={'cn': (582, 376, 702, 391), 'en': (582, 376, 702, 391), 'jp': (582, 376, 702, 391), 'tw': (582, 376, 702, 391)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_LOADING_CHECK.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_LOADING_CHECK.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_LOADING_CHECK.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_LOADING_CHECK.png'}) -PRIVATE_QUARTERS_PAGE_LEFT = Button(area={'cn': (20, 329, 40, 359), 'en': (20, 329, 40, 359), 'jp': (20, 329, 40, 359), 'tw': (20, 329, 40, 359)}, color={'cn': (231, 234, 238), 'en': (231, 234, 238), 'jp': (231, 234, 238), 'tw': (231, 234, 238)}, button={'cn': (20, 329, 40, 359), 'en': (20, 329, 40, 359), 'jp': (20, 329, 40, 359), 'tw': (20, 329, 40, 359)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png'}) +PRIVATE_QUARTERS_PAGE_LEFT = Button(area={'cn': (27, 332, 39, 356), 'en': (27, 332, 39, 356), 'jp': (27, 332, 39, 356), 'tw': (27, 332, 39, 356)}, color={'cn': (246, 248, 249), 'en': (246, 248, 249), 'jp': (246, 248, 249), 'tw': (246, 248, 249)}, button={'cn': (27, 332, 39, 356), 'en': (27, 332, 39, 356), 'jp': (27, 332, 39, 356), 'tw': (27, 332, 39, 356)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_PAGE_LEFT.png'}) PRIVATE_QUARTERS_PAGE_LOCALE_BEACH = Button(area={'cn': (24, 504, 99, 527), 'en': (38, 509, 86, 522), 'jp': (36, 506, 87, 525), 'tw': (25, 506, 93, 526)}, color={'cn': (198, 198, 198), 'en': (154, 154, 154), 'jp': (221, 221, 221), 'tw': (200, 200, 200)}, button={'cn': (24, 504, 99, 527), 'en': (38, 509, 86, 522), 'jp': (36, 506, 87, 525), 'tw': (25, 506, 93, 526)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_BEACH.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_BEACH.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_BEACH.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_BEACH.png'}) PRIVATE_QUARTERS_PAGE_LOCALE_LOFT = Button(area={'cn': (23, 502, 99, 528), 'en': (41, 505, 81, 525), 'jp': (35, 507, 86, 525), 'tw': (27, 506, 95, 526)}, color={'cn': (206, 206, 207), 'en': (196, 196, 197), 'jp': (211, 212, 212), 'tw': (204, 204, 205)}, button={'cn': (23, 502, 99, 528), 'en': (41, 505, 81, 525), 'jp': (35, 507, 86, 525), 'tw': (27, 506, 95, 526)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_LOFT.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_LOFT.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_LOFT.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_LOFT.png'}) -PRIVATE_QUARTERS_PAGE_RIGHT = Button(area={'cn': (1240, 329, 1260, 359), 'en': (1240, 329, 1260, 359), 'jp': (1240, 329, 1260, 359), 'tw': (1240, 344, 1260, 359)}, color={'cn': (232, 234, 237), 'en': (232, 234, 237), 'jp': (232, 234, 237), 'tw': (232, 233, 236)}, button={'cn': (1240, 329, 1260, 359), 'en': (1240, 329, 1260, 359), 'jp': (1240, 329, 1260, 359), 'tw': (1240, 344, 1260, 359)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png'}) +PRIVATE_QUARTERS_PAGE_LOCALE_VILLA = Button(area={'cn': (42, 508, 80, 523), 'en': (42, 508, 80, 523), 'jp': (42, 508, 80, 523), 'tw': (42, 508, 80, 523)}, color={'cn': (162, 162, 162), 'en': (162, 162, 162), 'jp': (162, 162, 162), 'tw': (162, 162, 162)}, button={'cn': (42, 508, 80, 523), 'en': (42, 508, 80, 523), 'jp': (42, 508, 80, 523), 'tw': (42, 508, 80, 523)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_VILLA.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_VILLA.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_VILLA.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_PAGE_LOCALE_VILLA.png'}) +PRIVATE_QUARTERS_PAGE_RIGHT = Button(area={'cn': (1241, 332, 1253, 356), 'en': (1241, 332, 1253, 356), 'jp': (1241, 332, 1253, 356), 'tw': (1240, 344, 1260, 359)}, color={'cn': (248, 248, 249), 'en': (248, 248, 249), 'jp': (248, 248, 249), 'tw': (232, 233, 236)}, button={'cn': (1241, 332, 1253, 356), 'en': (1241, 332, 1253, 356), 'jp': (1241, 332, 1253, 356), 'tw': (1240, 344, 1260, 359)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_PAGE_RIGHT.png'}) PRIVATE_QUARTERS_ROOM_BACK = Button(area={'cn': (28, 40, 43, 60), 'en': (28, 40, 43, 60), 'jp': (28, 40, 43, 60), 'tw': (28, 40, 43, 60)}, color={'cn': (185, 184, 186), 'en': (185, 184, 186), 'jp': (185, 184, 186), 'tw': (185, 184, 186)}, button={'cn': (16, 31, 139, 69), 'en': (27, 30, 147, 70), 'jp': (27, 30, 147, 70), 'tw': (21, 31, 126, 68)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_ROOM_BACK.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_ROOM_BACK.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_ROOM_BACK.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_ROOM_BACK.png'}) PRIVATE_QUARTERS_ROOM_CHECK = Button(area={'cn': (1218, 651, 1238, 666), 'en': (1218, 651, 1238, 666), 'jp': (1218, 651, 1238, 666), 'tw': (1218, 651, 1238, 666)}, color={'cn': (68, 98, 113), 'en': (68, 98, 113), 'jp': (68, 98, 113), 'tw': (68, 98, 113)}, button={'cn': (1218, 651, 1238, 666), 'en': (1218, 651, 1238, 666), 'jp': (1218, 651, 1238, 666), 'tw': (1218, 651, 1238, 666)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_ROOM_CHECK.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_ROOM_CHECK.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_ROOM_CHECK.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_ROOM_CHECK.png'}) PRIVATE_QUARTERS_ROOM_SAFE_CLICK_AREA = Button(area={'cn': (950, 95, 1275, 595), 'en': (950, 95, 1275, 595), 'jp': (950, 95, 1275, 595), 'tw': (950, 95, 1275, 595)}, color={'cn': (255, 255, 255), 'en': (255, 255, 255), 'jp': (255, 255, 255), 'tw': (255, 255, 255)}, button={'cn': (950, 95, 1275, 595), 'en': (950, 95, 1275, 595), 'jp': (950, 95, 1275, 595), 'tw': (950, 95, 1275, 595)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_ROOM_SAFE_CLICK_AREA.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_ROOM_SAFE_CLICK_AREA.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_ROOM_SAFE_CLICK_AREA.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_ROOM_SAFE_CLICK_AREA.png'}) PRIVATE_QUARTERS_ROOM_TARGET_CHECK_1 = Button(area={'cn': (721, 17, 781, 37), 'en': (721, 17, 781, 37), 'jp': (721, 17, 781, 37), 'tw': (721, 17, 781, 37)}, color={'cn': (206, 202, 201), 'en': (206, 202, 201), 'jp': (206, 202, 201), 'tw': (206, 202, 201)}, button={'cn': (721, 17, 781, 37), 'en': (721, 17, 781, 37), 'jp': (721, 17, 781, 37), 'tw': (721, 17, 781, 37)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_1.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_1.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_1.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_1.png'}) PRIVATE_QUARTERS_ROOM_TARGET_CHECK_2 = Button(area={'cn': (667, 71, 717, 86), 'en': (667, 71, 717, 86), 'jp': (667, 71, 717, 86), 'tw': (667, 71, 717, 86)}, color={'cn': (222, 213, 198), 'en': (222, 213, 198), 'jp': (222, 213, 198), 'tw': (222, 213, 198)}, button={'cn': (667, 71, 717, 86), 'en': (667, 71, 717, 86), 'jp': (667, 71, 717, 86), 'tw': (667, 71, 717, 86)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_2.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_2.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_2.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_2.png'}) -PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA = Button(area={'cn': (504, 45, 784, 625), 'en': (504, 45, 784, 625), 'jp': (504, 45, 784, 625), 'tw': (504, 45, 784, 625)}, color={'cn': (255, 255, 255), 'en': (255, 255, 255), 'jp': (255, 255, 255), 'tw': (255, 255, 255)}, button={'cn': (504, 45, 784, 625), 'en': (504, 45, 784, 625), 'jp': (504, 45, 784, 625), 'tw': (504, 45, 784, 625)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png'}) +PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3 = Button(area={'cn': (709, 185, 754, 200), 'en': (709, 185, 754, 200), 'jp': (709, 185, 754, 200), 'tw': (709, 185, 754, 200)}, color={'cn': (213, 206, 198), 'en': (213, 206, 198), 'jp': (213, 206, 198), 'tw': (213, 206, 198)}, button={'cn': (709, 185, 754, 200), 'en': (709, 185, 754, 200), 'jp': (709, 185, 754, 200), 'tw': (709, 185, 754, 200)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3.png'}) +PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA = Button(area={'cn': (504, 266, 784, 625), 'en': (504, 266, 784, 625), 'jp': (504, 266, 784, 625), 'tw': (504, 266, 784, 625)}, color={'cn': (255, 255, 255), 'en': (255, 255, 255), 'jp': (255, 255, 255), 'tw': (255, 255, 255)}, button={'cn': (504, 266, 784, 625), 'en': (504, 266, 784, 625), 'jp': (504, 266, 784, 625), 'tw': (504, 266, 784, 625)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_CLICK_AREA.png'}) PRIVATE_QUARTERS_ROOM_TARGET_INTIMACY_MAX = Button(area={'cn': (1157, 40, 1197, 60), 'en': (1157, 40, 1197, 60), 'jp': (1157, 40, 1197, 60), 'tw': (1157, 40, 1197, 60)}, color={'cn': (173, 161, 155), 'en': (173, 161, 155), 'jp': (173, 161, 155), 'tw': (173, 161, 155)}, button={'cn': (1157, 40, 1197, 60), 'en': (1157, 40, 1197, 60), 'jp': (1157, 40, 1197, 60), 'tw': (1157, 40, 1197, 60)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_INTIMACY_MAX.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_INTIMACY_MAX.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_INTIMACY_MAX.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_ROOM_TARGET_INTIMACY_MAX.png'}) PRIVATE_QUARTERS_SHIP_AEGIR = Button(area={'cn': (512, 526, 569, 568), 'en': (512, 526, 569, 568), 'jp': (512, 526, 569, 568), 'tw': (512, 526, 569, 568)}, color={'cn': (209, 191, 188), 'en': (209, 191, 188), 'jp': (209, 191, 188), 'tw': (209, 191, 188)}, button={'cn': (512, 526, 569, 568), 'en': (512, 526, 569, 568), 'jp': (512, 526, 569, 568), 'tw': (512, 526, 569, 568)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_SHIP_AEGIR.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_SHIP_AEGIR.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_SHIP_AEGIR.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_SHIP_AEGIR.png'}) PRIVATE_QUARTERS_SHIP_ANCHORAGE = Button(area={'cn': (713, 246, 778, 311), 'en': (713, 246, 778, 311), 'jp': (713, 246, 778, 311), 'tw': (713, 246, 778, 311)}, color={'cn': (214, 184, 176), 'en': (214, 184, 176), 'jp': (214, 184, 176), 'tw': (214, 184, 176)}, button={'cn': (713, 246, 778, 311), 'en': (713, 246, 778, 311), 'jp': (713, 246, 778, 311), 'tw': (713, 246, 778, 311)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_SHIP_ANCHORAGE.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_SHIP_ANCHORAGE.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_SHIP_ANCHORAGE.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_SHIP_ANCHORAGE.png'}) +PRIVATE_QUARTERS_SHIP_NAKHIMOV = Button(area={'cn': (944, 373, 994, 431), 'en': (944, 373, 994, 431), 'jp': (944, 373, 994, 431), 'tw': (944, 373, 994, 431)}, color={'cn': (181, 184, 166), 'en': (181, 184, 166), 'jp': (181, 184, 166), 'tw': (181, 184, 166)}, button={'cn': (944, 373, 994, 431), 'en': (944, 373, 994, 431), 'jp': (944, 373, 994, 431), 'tw': (944, 373, 994, 431)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_SHIP_NAKHIMOV.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_SHIP_NAKHIMOV.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_SHIP_NAKHIMOV.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_SHIP_NAKHIMOV.png'}) PRIVATE_QUARTERS_SHIP_NEW_JERSEY = Button(area={'cn': (973, 307, 1023, 347), 'en': (973, 307, 1023, 347), 'jp': (973, 307, 1023, 347), 'tw': (973, 307, 1023, 347)}, color={'cn': (149, 141, 173), 'en': (149, 141, 173), 'jp': (149, 141, 173), 'tw': (149, 141, 173)}, button={'cn': (973, 307, 1023, 347), 'en': (973, 307, 1023, 347), 'jp': (973, 307, 1023, 347), 'tw': (973, 307, 1023, 347)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_SHIP_NEW_JERSEY.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_SHIP_NEW_JERSEY.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_SHIP_NEW_JERSEY.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_SHIP_NEW_JERSEY.png'}) PRIVATE_QUARTERS_SHIP_NOSHIRO = Button(area={'cn': (965, 289, 1027, 362), 'en': (962, 295, 1027, 360), 'jp': (962, 295, 1027, 360), 'tw': (962, 295, 1027, 360)}, color={'cn': (143, 120, 127), 'en': (102, 93, 102), 'jp': (102, 93, 102), 'tw': (102, 93, 102)}, button={'cn': (965, 289, 1027, 362), 'en': (962, 295, 1027, 360), 'jp': (962, 295, 1027, 360), 'tw': (962, 295, 1027, 360)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_SHIP_NOSHIRO.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_SHIP_NOSHIRO.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_SHIP_NOSHIRO.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_SHIP_NOSHIRO.png'}) PRIVATE_QUARTERS_SHIP_SIRIUS = Button(area={'cn': (908, 411, 966, 478), 'en': (905, 414, 970, 479), 'jp': (905, 414, 970, 479), 'tw': (905, 414, 970, 479)}, color={'cn': (219, 207, 214), 'en': (156, 153, 165), 'jp': (156, 153, 165), 'tw': (156, 153, 165)}, button={'cn': (908, 411, 966, 478), 'en': (905, 414, 970, 479), 'jp': (905, 414, 970, 479), 'tw': (905, 414, 970, 479)}, file={'cn': './assets/cn/private_quarters/PRIVATE_QUARTERS_SHIP_SIRIUS.png', 'en': './assets/en/private_quarters/PRIVATE_QUARTERS_SHIP_SIRIUS.png', 'jp': './assets/jp/private_quarters/PRIVATE_QUARTERS_SHIP_SIRIUS.png', 'tw': './assets/tw/private_quarters/PRIVATE_QUARTERS_SHIP_SIRIUS.png'}) diff --git a/module/private_quarters/interact.py b/module/private_quarters/interact.py index 7fec47099..3415d343b 100644 --- a/module/private_quarters/interact.py +++ b/module/private_quarters/interact.py @@ -18,6 +18,7 @@ class PQInteract(UI): 'new_jersey': (PRIVATE_QUARTERS_SHIP_NEW_JERSEY, PRIVATE_QUARTERS_PAGE_LOCALE_LOFT), 'taihou': (PRIVATE_QUARTERS_SHIP_TAIHOU, PRIVATE_QUARTERS_PAGE_LOCALE_LOFT), 'aegir': (PRIVATE_QUARTERS_SHIP_AEGIR, PRIVATE_QUARTERS_PAGE_LOCALE_LOFT), + 'nakhimov': (PRIVATE_QUARTERS_SHIP_NAKHIMOV, PRIVATE_QUARTERS_PAGE_LOCALE_VILLA), } def _pq_handle_dialogue(self): @@ -70,6 +71,8 @@ class PQInteract(UI): return True if self.appear(PRIVATE_QUARTERS_ROOM_TARGET_CHECK_2, offset=(100, 100)): return True + if self.appear(PRIVATE_QUARTERS_ROOM_TARGET_CHECK_3, offset=(100, 100)): + return True # End, failed expired wait time if settle_timer.reached(): diff --git a/module/private_quarters/private_quarters.py b/module/private_quarters/private_quarters.py index 7dac27365..2105740a3 100644 --- a/module/private_quarters/private_quarters.py +++ b/module/private_quarters/private_quarters.py @@ -8,6 +8,15 @@ from module.ui.page import page_private_quarters, page_dormmenu class PrivateQuarters(PQInteract, PQShop): + # Key: str, server name + # Value: list[str] + not_supported_filter = { + 'cn': ('nakhimov'), + 'en': (), + 'jp': ('nakhimov'), + 'tw': ('taihou', 'nakhimov'), + } + def _pq_get_daily_count(self, retry=3): """ Wrapper func for status_get_daily_count @@ -144,14 +153,18 @@ class PrivateQuarters(PQInteract, PQShop): # Interact with target if enabled if target_interact: + # Ensure target is supported for server + # Update `not_supported_filter` to enable a target + if target_ship in self.not_supported_filter[server.server]: + logger.info(f'Target ship:{target_ship} not supported for {server.server} server.') + return + # Pull count here, exit run if = 0 count = self._pq_get_daily_count(retry=3) if count == 0: logger.info('Daily intimacy count exhausted, exit subtask') return - if server.server in ['tw'] and target_ship in ['taihou']: - logger.info(f'Target ship:{target_ship} not supported for {server.server} server.') - return + # Able to interact with target, execute self.pq_execute_interact(target_ship) @@ -161,7 +174,6 @@ class PrivateQuarters(PQInteract, PQShop): in: Any page out: page_main, may have info_bar """ - self.ui_ensure(page_dormmenu) self.ui_goto(page_private_quarters, get_ship=False) self.handle_info_bar() @@ -171,8 +183,5 @@ class PrivateQuarters(PQInteract, PQShop): target_interact=self.config.PrivateQuarters_TargetInteract, target_ship=self.config.PrivateQuarters_TargetShip ) - if server.server in ['tw']: - logger.info(f'Private Quarters task not presently supported for {server.server} server.') - logger.info('If want to address, review necessary assets, replace, update above condition, and test') self.config.task_delay(server_update=True)