mirror of
https://gitee.com/sui-feng-cb/AzurLaneAutoScript1
synced 2026-03-15 00:37:20 +08:00
223 lines
7.1 KiB
Python
223 lines
7.1 KiB
Python
from module.base.decorator import cached_property
|
||
from module.logger import logger
|
||
from module.shop.base import ShopItemGrid, ShopItemGrid_250814
|
||
from module.shop.clerk import ShopClerk
|
||
from module.shop.shop_status import ShopStatus
|
||
from module.shop.ui import ShopUI
|
||
|
||
import re
|
||
|
||
class GeneralShop_250814(ShopClerk, ShopUI, ShopStatus):
|
||
gems = 0
|
||
shop_template_folder = './assets/shop/general'
|
||
|
||
@cached_property
|
||
def shop_filter(self):
|
||
"""
|
||
Returns:
|
||
str:
|
||
"""
|
||
return self.config.GeneralShop_Filter.strip()
|
||
|
||
@cached_property
|
||
def skinbox_allowed_positions(self):
|
||
"""
|
||
The set of configured absolute grid positions (1-based),
|
||
or None if no restrictions are applied.
|
||
If all the input is invalid, returns an empty set which will block all purchases.
|
||
|
||
Returns:
|
||
set[int]:
|
||
"""
|
||
raw_filter = self.config.GeneralShop_SkinBoxPositionFilter.strip()
|
||
if not raw_filter:
|
||
return None
|
||
raw_filter = re.sub(r'[>﹥›˃ᐳ❯]', '>', raw_filter)
|
||
allowed = {int(pos) for pos in raw_filter.split('>') if pos.strip().isdigit()}
|
||
logger.attr('SkinBox_filter', ' > '.join([str(pos) for pos in allowed]))
|
||
|
||
# raw_filter = raw_filter.replace(',', ',')
|
||
# allowed = {int(pos) for pos in raw_filter.split(',') if pos.strip().isdigit()}
|
||
# logger.attr('SkinBox_filter', ', '.join([str(pos) for pos in allowed]))
|
||
|
||
# raw_filter = raw_filter.replace(',', ',')
|
||
# allowed = set()
|
||
# for item in raw_filter.split(','):
|
||
# pos_str = item.strip()
|
||
# if not pos_str:
|
||
# continue
|
||
# if pos_str.isdigit():
|
||
# allowed.add(int(pos_str))
|
||
# continue
|
||
# logger.warning(f"Invalid position index: {pos_str}")
|
||
# logger.attr('SkinBox_filter', ', '.join([str(pos) for pos in allowed]))
|
||
|
||
if not allowed:
|
||
logger.warning("No valid positions found")
|
||
|
||
return allowed
|
||
|
||
# New UI in 2025-08-14
|
||
@cached_property
|
||
def shop_general_items(self):
|
||
"""
|
||
Returns:
|
||
ShopItemGrid:
|
||
"""
|
||
shop_grid = self.shop_grid
|
||
|
||
shop_general_items = ShopItemGrid_250814(
|
||
shop_grid,
|
||
templates={},
|
||
template_area=(25, 20, 82, 72),
|
||
amount_area=(42, 50, 65, 65),
|
||
cost_area=(-12, 115, 60, 155),
|
||
price_area=(14, 121, 85, 150),
|
||
)
|
||
shop_general_items.load_template_folder(self.shop_template_folder)
|
||
shop_general_items.load_cost_template_folder('./assets/shop/cost')
|
||
return shop_general_items
|
||
|
||
def shop_items(self):
|
||
"""
|
||
Shared alias for all shops
|
||
If there are server-lang
|
||
differences, reference
|
||
shop_guild/medal for @Config
|
||
example
|
||
|
||
Returns:
|
||
ShopItemGrid:
|
||
"""
|
||
return self.shop_general_items
|
||
|
||
currency_rechecked = 0
|
||
|
||
def shop_currency(self):
|
||
"""
|
||
Ocr shop guild currency if needed
|
||
(gold coins and gems)
|
||
Then return gold coin count
|
||
|
||
Returns:
|
||
int: gold coin amount
|
||
"""
|
||
while 1:
|
||
self._currency = self.status_get_gold_coins()
|
||
self.gems = self.status_get_gems()
|
||
logger.info(f'Gold coins: {self._currency}, Gems: {self.gems}')
|
||
|
||
if self.currency_rechecked >= 3:
|
||
logger.warning('Failed to handle fix currency bug in general shop, skip')
|
||
break
|
||
|
||
# if self._currency == 0 and self.gems == 0:
|
||
# logger.info('Game bugged, coins and gems disappeared, switch between shops to reset')
|
||
# self.currency_rechecked += 1
|
||
#
|
||
# # 2022.06.01 General shop no longer at an expected location
|
||
# # NavBar 'get_active' (0 index-based) and swap with its left
|
||
# # adjacent neighbor then back (NavBar 'set' is 1 index-based)
|
||
# index = self._shop_bottom_navbar.get_active(self)
|
||
# self.shop_bottom_navbar_ensure(left=index)
|
||
# self.shop_bottom_navbar_ensure(left=index + 1)
|
||
# continue
|
||
# else:
|
||
# break
|
||
# 2023.07.13 Shop UI changed entirely, remove all these
|
||
break
|
||
|
||
return self._currency
|
||
|
||
def shop_check_item(self, item):
|
||
"""
|
||
Args:
|
||
item: Item to check
|
||
|
||
Returns:
|
||
bool: whether item can be bought
|
||
"""
|
||
if item.cost == 'Coins':
|
||
if item.price > self._currency:
|
||
return False
|
||
return True
|
||
|
||
if self.config.GeneralShop_UseGems:
|
||
if item.cost == 'Gems':
|
||
if item.price > self.gems:
|
||
return False
|
||
return True
|
||
|
||
return False
|
||
|
||
def _skinbox_position_check(self, item):
|
||
"""
|
||
Check if the skin box is at a designated purchase position.
|
||
|
||
Args:
|
||
item: Item to check
|
||
|
||
Returns:
|
||
bool: True if the skin box is targeted for purchase.
|
||
"""
|
||
allowed = self.skinbox_allowed_positions
|
||
if allowed is None:
|
||
return True
|
||
|
||
grids = self.shop_general_items.grids
|
||
abs_pos = round((item.button[0] - grids.origin[0]) / grids.delta[0]) + 1
|
||
return abs_pos in allowed
|
||
|
||
def shop_check_custom_item(self, item):
|
||
"""
|
||
Check a custom item that should be bought with specific option.
|
||
|
||
Args:
|
||
item: Item to check
|
||
|
||
Returns:
|
||
bool: whether item is custom
|
||
"""
|
||
if self.config.GeneralShop_ConsumeCoins and self._currency >= 550000:
|
||
if item.cost == 'Coins':
|
||
return True
|
||
|
||
mode = self.config.GeneralShop_BuySkinBox
|
||
if (
|
||
mode == 'unlimited'
|
||
or (mode == 'specified' and self.config.GeneralShop_BuySkinBoxAmount > 0)
|
||
):
|
||
if (not item.is_known_item() and item.amount == 1 and item.cost == 'Coins' and item.price == 7000):
|
||
# check a custom item that cannot be template matched as color
|
||
# and design constantly changes i.e. equip skin box
|
||
logger.info(f'Item {item} is considered to be an equip skin box')
|
||
if self._currency >= item.price and self._skinbox_position_check(item):
|
||
if mode == 'specified':
|
||
self.config.GeneralShop_BuySkinBoxAmount -= 1
|
||
return True
|
||
|
||
return False
|
||
|
||
def run(self):
|
||
"""
|
||
Run General Shop
|
||
"""
|
||
# Base case; exit run if filter empty
|
||
if not self.shop_filter:
|
||
return
|
||
|
||
# When called, expected to be in
|
||
# corrected General Shop interface
|
||
logger.hr('General Shop', level=1)
|
||
|
||
# Execute buy operations
|
||
# Refresh if enabled and available
|
||
refresh = self.config.GeneralShop_Refresh
|
||
for _ in range(2):
|
||
success = self.shop_buy()
|
||
if not success:
|
||
break
|
||
if refresh and self.shop_refresh():
|
||
continue
|
||
break
|