From 1789952e9458f297bcbd67c35c0cd231ef65eb7b Mon Sep 17 00:00:00 2001 From: guoh064 <50830808+guoh064@users.noreply.github.com> Date: Sun, 16 Aug 2026 14:19:00 +0800 Subject: [PATCH 1/3] Fix: ensure dock top before finding island character (#5890) --- module/island/production.py | 2 ++ module/island_handler/dock.py | 32 +++++++++++++++++++++-------- module/island_handler/restaurant.py | 14 +++++++------ 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/module/island/production.py b/module/island/production.py index 3176c8014..4129a904b 100644 --- a/module/island/production.py +++ b/module/island/production.py @@ -229,6 +229,8 @@ class IslandProduction(IslandRecipe, IslandDock): logger.warning(f'Failed to select character {worker} for slot {slot_id}, try to select manjuu instead') worker = 'manjuu' self.ensure_dock_page_at_top() + else: + self.island_dock_select_one(character.button) if worker == 'manjuu': self.island_dock_select_manjuu() self.island_dock_select_confirm(self.is_in_recipe_menu) diff --git a/module/island_handler/dock.py b/module/island_handler/dock.py index 51ba2d5cc..9a92185a7 100644 --- a/module/island_handler/dock.py +++ b/module/island_handler/dock.py @@ -97,13 +97,17 @@ class IslandDock(IslandUI): def ensure_dock_page_at_top(self): ISLAND_DOCK_DETECT.load_color(self.device.image) ISLAND_DOCK_DETECT._match_init = True + drag_count = 0 for _ in self.loop(timeout=10): self.prev_dock_page() + drag_count += 1 if self.appear(ISLAND_DOCK_DETECT, offset=(20, 20)): - logger.warning('Reached top of dock page') - return True + if drag_count >= 2: + logger.info('Reached top of dock page') + return True else: ISLAND_DOCK_DETECT.load_color(self.device.image) + drag_count = 0 return False def island_dock_select_one(self, button, skip_first=False): @@ -137,6 +141,7 @@ class IslandDock(IslandUI): def island_dock_select_manjuu(self): self.island_dock_sort_method_dsc_set(enable=False, wait_loading=True) + # self.ensure_dock_page_at_top() # not necessary for now since usually Manjuu is searched first scanner = CharacterScanner(self.dock_grid, identity=['Manjuu'], status='free') candidates = scanner.scan(self.device.image) if candidates: @@ -147,9 +152,11 @@ class IslandDock(IslandUI): return False def island_dock_find_character(self, identity): + self.ensure_dock_page_at_top() self.island_dock_sort_method_dsc_set(enable=True) ISLAND_DOCK_DETECT.load_color(self.device.image) ISLAND_DOCK_DETECT._match_init = True + drag_count = 0 for _ in self.loop(timeout=40, skip_first=False): # dock_grid needs refresh after each page swipe, so we need to get a new scanner each time scanner = CharacterScanner(self.dock_grid, identity=identity, status=None) @@ -159,19 +166,24 @@ class IslandDock(IslandUI): continue return candidate self.next_dock_page() + drag_count += 1 if self.appear(ISLAND_DOCK_DETECT, offset=(20, 20)): - logger.warning('Reached end of dock page') - break + if drag_count >= 2: + logger.warning('Reached end of dock page') + break else: ISLAND_DOCK_DETECT.load_color(self.device.image) + drag_count = 0 else: logger.warning('Failed to find all requested characters') return None - def island_dock_select_character_with_blacklist(self, blacklist): + def island_dock_find_character_with_blacklist(self, blacklist): + self.ensure_dock_page_at_top() self.island_dock_sort_method_dsc_set(enable=True) ISLAND_DOCK_DETECT.load_color(self.device.image) ISLAND_DOCK_DETECT._match_init = True + drag_count = 0 for _ in self.loop(timeout=40, skip_first=False): # dock_grid needs refresh after each page swipe, so we need to get a new scanner each time scanner = CharacterScanner(self.dock_grid, identity='any', status='free') @@ -191,13 +203,15 @@ class IslandDock(IslandUI): elif self.is_button_selected(candidate.button, color=(19, 181, 231)): continue else: - self.island_dock_select_one(candidate.button) - return candidate.identity + return candidate self.next_dock_page() + drag_count += 1 if self.appear(ISLAND_DOCK_DETECT, offset=(20, 20)): - logger.warning('Reached end of dock page') - break + if drag_count >= 2: + logger.warning('Reached end of dock page') + break else: ISLAND_DOCK_DETECT.load_color(self.device.image) + drag_count = 0 logger.warning('Failed to find any character not in blacklist') return None diff --git a/module/island_handler/restaurant.py b/module/island_handler/restaurant.py index 44fbfe6ab..f4507a676 100644 --- a/module/island_handler/restaurant.py +++ b/module/island_handler/restaurant.py @@ -397,19 +397,21 @@ class IslandRestaurant(IslandDock): | selected_waitresses | all_named_waitresses ) - selected = self.island_dock_select_character_with_blacklist(fallback_blacklist) - if selected is None: + candidate = self.island_dock_find_character_with_blacklist(fallback_blacklist) + if candidate is None: success = False else: - selected_waitresses.add(selected) + self.island_dock_select_one(candidate.button) + selected_waitresses.add(candidate.identity) for _ in range(active_waitresses.count(WAITRESS_ANY)): blacklist = unavailable_waitress_list | selected_waitresses | all_named_waitresses - selected = self.island_dock_select_character_with_blacklist(blacklist) - if selected is None: + candidate = self.island_dock_find_character_with_blacklist(blacklist) + if candidate is None: success = False else: - selected_waitresses.add(selected) + self.island_dock_select_one(candidate.button) + selected_waitresses.add(candidate.identity) if not success: logger.warning("Failed to choose waitress") self.ui_back(check_button=self.is_in_island_restaurant) From 8a3710094a1fd3c8a49389a9d8719cdcea90245a Mon Sep 17 00:00:00 2001 From: guoh064 <50830808+guoh064@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:25:21 +0800 Subject: [PATCH 2/3] Fix: island production and restaurant should keep task target items --- module/island/utils.py | 8 ++++ module/island_handler/recipe.py | 66 ++++++++++++++++++----------- module/island_handler/restaurant.py | 20 ++++++--- 3 files changed, 64 insertions(+), 30 deletions(-) diff --git a/module/island/utils.py b/module/island/utils.py index 993d3df7e..60361df55 100644 --- a/module/island/utils.py +++ b/module/island/utils.py @@ -300,6 +300,14 @@ def get_stuck_season_order_requirements(stuck_order_id): return dict(requirements) +def merge_task_target_stuck_order_items(task_target_items, stuck_order_items): + """Normalize and merge configured tasks with remaining stuck-order needs.""" + return merge_item_needs( + normalize_item_needs(task_target_items, default_period=10), + normalize_item_needs(stuck_order_items, default_period=10), + ) + + def normalize_stuck_season_order_id(stuck_order_id): try: stuck_order_id = int(stuck_order_id) diff --git a/module/island_handler/recipe.py b/module/island_handler/recipe.py index 895730b18..71d810335 100644 --- a/module/island_handler/recipe.py +++ b/module/island_handler/recipe.py @@ -21,9 +21,8 @@ from module.island.utils import ( load_hard_floor_items, load_item_mapping, load_reserve_items, - merge_item_needs, + merge_task_target_stuck_order_items, normalize_item_keys, - normalize_item_needs, parse_item_need_deadlines, ) from module.island_handler.assets import * @@ -122,6 +121,16 @@ def get_recipe_product_id(recipe_id): return next(iter(DIC_ISLAND_RECIPE[recipe_id]['commission_product'])) +def get_ingredient_available_stock(stock, hard_floor, reserve, task_target_reserve): + return max( + stock + - max(hard_floor, 0) + - max(reserve, 0) + - max(task_target_reserve, 0), + 0, + ) + + def get_target_stock_weight(stock, target_stock, hard_floor, reserve): if stock >= target_stock or target_stock <= 0: return 0 @@ -349,6 +358,20 @@ class IslandRecipe(IslandExchange, IslandShop): yaml_text = self.config.cross_get("IslandProduction.IslandProduction.ReserveItems", "") return normalize_item_keys(load_reserve_items(yaml_text)) + def get_task_target_items(self, task_target_items=None): + if task_target_items is None: + task_target_items = load_item_mapping( + self.config.cross_get("IslandSeasonTask.IslandSeasonTask.TaskTarget", "{}"), + config_name='TaskTarget', + ) + stuck_season_order_id = self.config.cross_get( + "IslandOrder.IslandOrder.StuckSeasonOrderId", 0 + ) + return merge_task_target_stuck_order_items( + task_target_items, + get_stuck_season_order_requirements(stuck_season_order_id), + ) + def get_recipe_id_sequence_to_run( self, daily_buffer_items_dict=None, @@ -372,21 +395,8 @@ class IslandRecipe(IslandExchange, IslandShop): reserve_items_dict = self.reserve_items else: reserve_items_dict = normalize_item_keys(reserve_items_dict) - if task_target_items_dict is None: - yaml_text = self.config.cross_get("IslandSeasonTask.IslandSeasonTask.TaskTarget", "{}") - task_target_items_dict = load_item_mapping(yaml_text, config_name='TaskTarget') - task_target_items_dict = normalize_item_needs(task_target_items_dict, default_period=10) - stuck_season_order_id = self.config.cross_get( - "IslandOrder.IslandOrder.StuckSeasonOrderId", 0 - ) - stuck_season_order_items = normalize_item_needs( - get_stuck_season_order_requirements(stuck_season_order_id), - default_period=10, - ) - task_target_items_dict = merge_item_needs( - task_target_items_dict, - stuck_season_order_items, - ) + task_target_items_dict = self.get_task_target_items(task_target_items_dict) + self.task_target_items = task_target_items_dict if idle_accumulating_items_dict is None: yaml_text = self.config.cross_get("IslandProduction.IslandProduction.IdleAccumulatingItems", "") if yaml_text is None: @@ -556,6 +566,9 @@ class IslandRecipe(IslandExchange, IslandShop): # since ranch recipes may have boosted ingredient requirement for higher batch production. counters = self.get_recipe_ingredient_counters() recipe_cost = DIC_ISLAND_RECIPE[recipe_id]['commission_cost'] + task_target_items = getattr(self, 'task_target_items', None) + if task_target_items is None: + task_target_items = self.get_task_target_items() if counters is None: logger.warning(f'Unable to read ingredient counters for recipe {recipe_id}') return False, 0 @@ -564,11 +577,12 @@ class IslandRecipe(IslandExchange, IslandShop): for ingredient_key, counter in zip(recipe_cost, counters): if ingredient_key in DIC_ISLAND_SHOP_ITEM_TO_RECIPE or ingredient_key in (2521, 2522): continue - available_stock = max( - counter[0] - - self.hard_floor_items.get(ingredient_key, 0) - - self.reserve_items.get(ingredient_key, 0), - 0, + task_target_reserve = task_target_items.get(ingredient_key, {}).get('total_need_count', 0) + available_stock = get_ingredient_available_stock( + counter[0], + self.hard_floor_items.get(ingredient_key, 0), + self.reserve_items.get(ingredient_key, 0), + task_target_reserve, ) count = available_stock // counter[1] if counter[1] > 0 else float('inf') if count < max_count: @@ -586,7 +600,10 @@ class IslandRecipe(IslandExchange, IslandShop): for ingredient_key, counter, button in zip(recipe_cost, counters, ingredient_buttons): hard_floor = self.hard_floor_items.get(ingredient_key, 0) reserve = self.reserve_items.get(ingredient_key, 0) - available_stock = max(counter[0] - hard_floor - reserve, 0) + task_target_reserve = task_target_items.get(ingredient_key, {}).get('total_need_count', 0) + available_stock = get_ingredient_available_stock( + counter[0], hard_floor, reserve, task_target_reserve + ) if available_stock < real_count * counter[1]: if ingredient_key in (2521, 2522): if ingredient_key in failed_buy_items: @@ -639,7 +656,8 @@ class IslandRecipe(IslandExchange, IslandShop): else: logger.warning( f'Ingredient {ingredient_key} cannot be bought from shop, ' - f'insufficient ingredient for recipe production after hard floor {hard_floor} and reserve {reserve}' + f'insufficient ingredient for recipe production after hard floor {hard_floor}, ' + f'reserve {reserve}, and task target {task_target_reserve}' ) real_count = min(real_count, available_stock // counter[1]) if counter[1] > 0 else 0 success = False diff --git a/module/island_handler/restaurant.py b/module/island_handler/restaurant.py index f4507a676..af445b1d5 100644 --- a/module/island_handler/restaurant.py +++ b/module/island_handler/restaurant.py @@ -15,6 +15,8 @@ from module.island.data import DIC_ISLAND_ITEM, DIC_ISLAND_RESTAURANT_MENU_TO_RE from module.island.utils import ( get_stuck_season_order_requirements, load_hard_floor_items, + load_item_mapping, + merge_task_target_stuck_order_items, normalize_item_keys, ) from module.island_handler.assets import * @@ -277,8 +279,9 @@ class IslandRestaurant(IslandDock): item for item in items if item.id in menu # Sell one full waitress-capacity tranche while preserving manual - # hard floors and remaining season-order requirements. Reserves and - # daily buffers are soft and may be consumed by restaurants. + # hard floors, task targets, and remaining season-order + # requirements. Reserves and daily buffers are soft and may be + # consumed by restaurants. and has_sellable_capacity(item) ] surplus_items = [ @@ -303,13 +306,18 @@ class IslandRestaurant(IslandDock): stuck_season_order_id = self.config.cross_get( "IslandOrder.IslandOrder.StuckSeasonOrderId", 0 ) - season_order_items = normalize_item_keys( - get_stuck_season_order_requirements(stuck_season_order_id) + task_target_items = load_item_mapping( + self.config.cross_get("IslandSeasonTask.IslandSeasonTask.TaskTarget", "{}"), + config_name='TaskTarget', ) - item_ids = set(hard_floor_items) | set(season_order_items) + protected_target_items = merge_task_target_stuck_order_items( + task_target_items, + get_stuck_season_order_requirements(stuck_season_order_id), + ) + item_ids = set(hard_floor_items) | set(protected_target_items) return { item_id: max(hard_floor_items.get(item_id, 0), 0) - + max(season_order_items.get(item_id, 0), 0) + + max(protected_target_items.get(item_id, {}).get('total_need_count', 0), 0) for item_id in item_ids } From 1d2d974f438b078fdd3e0676410a264582c2aafc Mon Sep 17 00:00:00 2001 From: guoh064 <50830808+guoh064@users.noreply.github.com> Date: Mon, 17 Aug 2026 01:37:53 +0800 Subject: [PATCH 3/3] Upd: [TW] asset HORROR_COALITION_CHECK (#5867) --- .../tw/coalition/HORROR_COALITION_CHECK.png | Bin 6594 -> 14001 bytes module/coalition/assets.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/tw/coalition/HORROR_COALITION_CHECK.png b/assets/tw/coalition/HORROR_COALITION_CHECK.png index b758551d2d2c410360100e0c3f7e8826cdc74c71..09c1b742e999ca1e9a990f2da65e4b158b2e4d9b 100644 GIT binary patch literal 14001 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 literal 6594 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 diff --git a/module/coalition/assets.py b/module/coalition/assets.py index 6934be5e4..04c646855 100644 --- a/module/coalition/assets.py +++ b/module/coalition/assets.py @@ -60,7 +60,7 @@ FROSTFALL_SWITCH_SINGLE = Button(area={'cn': (968, 449, 1098, 478), 'en': (968, FROSTFALL_TC1 = Button(area={'cn': (304, 320, 330, 332), 'en': (304, 320, 330, 332), 'jp': (304, 320, 330, 332), 'tw': (304, 320, 330, 332)}, color={'cn': (204, 162, 254), 'en': (204, 162, 254), 'jp': (204, 162, 254), 'tw': (188, 137, 254)}, button={'cn': (304, 320, 330, 332), 'en': (304, 320, 330, 332), 'jp': (304, 320, 330, 332), 'tw': (304, 320, 330, 332)}, file={'cn': './assets/cn/coalition/FROSTFALL_TC1.png', 'en': './assets/en/coalition/FROSTFALL_TC1.png', 'jp': './assets/jp/coalition/FROSTFALL_TC1.png', 'tw': './assets/tw/coalition/FROSTFALL_TC1.png'}) FROSTFALL_TC2 = Button(area={'cn': (631, 160, 658, 173), 'en': (631, 160, 658, 173), 'jp': (631, 160, 658, 173), 'tw': (631, 160, 658, 173)}, color={'cn': (186, 136, 252), 'en': (186, 136, 252), 'jp': (186, 136, 252), 'tw': (186, 136, 252)}, button={'cn': (631, 160, 658, 173), 'en': (631, 160, 658, 173), 'jp': (631, 160, 658, 173), 'tw': (631, 160, 658, 173)}, file={'cn': './assets/cn/coalition/FROSTFALL_TC2.png', 'en': './assets/en/coalition/FROSTFALL_TC2.png', 'jp': './assets/jp/coalition/FROSTFALL_TC2.png', 'tw': './assets/tw/coalition/FROSTFALL_TC2.png'}) FROSTFALL_TC3 = Button(area={'cn': (810, 362, 835, 373), 'en': (810, 362, 835, 373), 'jp': (810, 362, 835, 373), 'tw': (810, 362, 835, 373)}, color={'cn': (197, 153, 255), 'en': (197, 153, 255), 'jp': (197, 153, 255), 'tw': (197, 153, 255)}, button={'cn': (810, 362, 835, 373), 'en': (810, 362, 835, 373), 'jp': (810, 362, 835, 373), 'tw': (810, 362, 835, 373)}, file={'cn': './assets/cn/coalition/FROSTFALL_TC3.png', 'en': './assets/en/coalition/FROSTFALL_TC3.png', 'jp': './assets/jp/coalition/FROSTFALL_TC3.png', 'tw': './assets/tw/coalition/FROSTFALL_TC3.png'}) -HORROR_COALITION_CHECK = Button(area={'cn': (204, 49, 250, 70), 'en': (182, 40, 238, 65), 'jp': (204, 50, 250, 67), 'tw': (186, 24, 223, 57)}, color={'cn': (142, 142, 164), 'en': (161, 158, 163), 'jp': (136, 137, 159), 'tw': (146, 146, 157)}, button={'cn': (204, 49, 250, 70), 'en': (182, 40, 238, 65), 'jp': (204, 50, 250, 67), 'tw': (186, 24, 223, 57)}, file={'cn': './assets/cn/coalition/HORROR_COALITION_CHECK.png', 'en': './assets/en/coalition/HORROR_COALITION_CHECK.png', 'jp': './assets/jp/coalition/HORROR_COALITION_CHECK.png', 'tw': './assets/tw/coalition/HORROR_COALITION_CHECK.png'}) +HORROR_COALITION_CHECK = Button(area={'cn': (204, 49, 250, 70), 'en': (182, 40, 238, 65), 'jp': (204, 50, 250, 67), 'tw': (186, 24, 222, 57)}, color={'cn': (142, 142, 164), 'en': (161, 158, 163), 'jp': (136, 137, 159), 'tw': (148, 147, 158)}, button={'cn': (204, 49, 250, 70), 'en': (182, 40, 238, 65), 'jp': (204, 50, 250, 67), 'tw': (186, 24, 222, 57)}, file={'cn': './assets/cn/coalition/HORROR_COALITION_CHECK.png', 'en': './assets/en/coalition/HORROR_COALITION_CHECK.png', 'jp': './assets/jp/coalition/HORROR_COALITION_CHECK.png', 'tw': './assets/tw/coalition/HORROR_COALITION_CHECK.png'}) HORROR_EASY = Button(area={'cn': (863, 425, 890, 464), 'en': (863, 425, 890, 464), 'jp': (863, 425, 890, 464), 'tw': (863, 425, 890, 464)}, color={'cn': (76, 76, 96), 'en': (76, 76, 96), 'jp': (76, 76, 96), 'tw': (76, 76, 96)}, button={'cn': (863, 425, 890, 464), 'en': (863, 425, 890, 464), 'jp': (863, 425, 890, 464), 'tw': (863, 425, 890, 464)}, file={'cn': './assets/cn/coalition/HORROR_EASY.png', 'en': './assets/cn/coalition/HORROR_EASY.png', 'jp': './assets/cn/coalition/HORROR_EASY.png', 'tw': './assets/cn/coalition/HORROR_EASY.png'}) HORROR_EX = Button(area={'cn': (172, 410, 200, 448), 'en': (172, 410, 200, 448), 'jp': (172, 410, 200, 448), 'tw': (172, 410, 200, 448)}, color={'cn': (150, 101, 105), 'en': (150, 101, 105), 'jp': (150, 101, 105), 'tw': (150, 101, 105)}, button={'cn': (172, 410, 200, 448), 'en': (172, 410, 200, 448), 'jp': (172, 410, 200, 448), 'tw': (172, 410, 200, 448)}, file={'cn': './assets/cn/coalition/HORROR_EX.png', 'en': './assets/cn/coalition/HORROR_EX.png', 'jp': './assets/cn/coalition/HORROR_EX.png', 'tw': './assets/cn/coalition/HORROR_EX.png'}) HORROR_FLEET_PREPARATION = Button(area={'cn': (1026, 514, 1139, 542), 'en': (1039, 516, 1125, 538), 'jp': (1042, 514, 1124, 542), 'tw': (1026, 514, 1139, 542)}, color={'cn': (146, 132, 183), 'en': (158, 149, 194), 'jp': (135, 117, 173), 'tw': (146, 132, 183)}, button={'cn': (1026, 514, 1139, 542), 'en': (1039, 516, 1125, 538), 'jp': (1042, 514, 1124, 542), 'tw': (1026, 514, 1139, 542)}, file={'cn': './assets/cn/coalition/HORROR_FLEET_PREPARATION.png', 'en': './assets/en/coalition/HORROR_FLEET_PREPARATION.png', 'jp': './assets/jp/coalition/HORROR_FLEET_PREPARATION.png', 'tw': './assets/cn/coalition/HORROR_FLEET_PREPARATION.png'})