Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions assets/i18n/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"exit_four_help": "支持打九退四,保证稳定57级,要求设置好战斗主题,即 脚本->全局配置->游戏装饰自定义->战斗主题",
"costume_main_15": "茨心乐园",
"costume_main_16": "狐栖归处",
"costume_main_17": "玉岚狐庭",
"check_true_orochi_enable": "是否在结束后检测真蛇",
"check_true_orochi_enable_help": "开启后会在任务结束后检测是否出现真蛇, 若出现则自动拉起真蛇",
"enable_book_auto": "自动选择",
Expand Down Expand Up @@ -137,5 +138,7 @@
"enable_ap100_anti_detect": "100体爬塔防检测",
"enable_ap100_anti_detect_help": "100体爬塔战斗过程是否随机点击或滑动",
"costume_battle_15": "灵狐寄愿",
"costume_shikigami_12": "拾光之窗"
}
"costume_shikigami_12": "拾光之窗",
"save_touch_fish": "惠比寿的摸鱼行动",
"save_touch_fish_help": "默认使用全部存储按钮,主要目的是为了配合真蛇每周打一次即可获得俩次奖励(并不会节省体力)"
}
37 changes: 34 additions & 3 deletions module/atom/gif.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# This Python file uses the following encoding: utf-8
# @author runhey
# github https://github.com/runhey
import types

import numpy as np

from module.atom.image import RuleImage
Expand All @@ -10,13 +12,39 @@
class RuleGif:
# 大部分实现同RuleImage 的接口

@staticmethod
def attach_to(image_obj: RuleImage, targets: list[RuleImage]) -> None:
"""
把GIF的多帧匹配行为原地挂载到一个RuleImage实例上

与replace_img的原地换属性同思路: 不换对象、不换引用,
持有该对象引用的Page/寻路会立即生效
:param image_obj: 被挂载的RuleImage实例
:param targets: 多帧RuleImage, 顺序即匹配优先级
"""
# GIF状态
image_obj.targets = targets
image_obj.roi_front = [0, 0, 0, 0]
image_obj.roi_back = targets[0].roi_back
image_obj.appear_target = targets[0]
image_obj.name = targets[0].name
image_obj._match_init = False
# 方法级替换: 把RuleGif的所有公开方法绑定到该实例上
for name, attr in RuleGif.__dict__.items():
if name.startswith('_'):
continue
if isinstance(attr, types.FunctionType):
setattr(image_obj, name, types.MethodType(attr, image_obj))

@property
def name(self) -> str:
return self.appear_target.name
return self.targets[0].name

def __init__(self, targets: list[RuleImage]):
self.targets = targets
self.roi_front: list = [0, 0, 0, 0]
self.roi_back: list = targets[0].roi_back
self._match_init = False
self.appear_target = targets[0]

def pre_process(self, image):
Expand Down Expand Up @@ -44,18 +72,21 @@ def search(self, image, roi: list = None, threshold: float = None) -> tuple:
return True, target
return False, None

def search_with_multi_scale(self, image, roi=None, threshold=None, scale_range=(0.8, 1.1, 0.05)):
def search_with_multi_scale(self, image, roi=None, threshold=None, scales=None, scale_range=(0.8, 1.1, 0.05)):
image = self.pre_process(image)
threshold = self.targets[0].threshold if threshold is None else threshold
roi = self.targets[0].roi_back if roi is None else roi
for target in self.targets:
target.roi_back = roi
if target.match_multi_scale(image, threshold=threshold, scale_range=scale_range):
if target.match_multi_scale(image, threshold=threshold, scales=scales, scale_range=scale_range):
self.roi_front = target.roi_front
self.appear_target = target
return True, target
return False, None

def match_multi_scale(self, image, threshold: float = None, scales: list = None, scale_range: tuple = None) -> bool:
return self.search_with_multi_scale(image, threshold=threshold, scales=scales, scale_range=scale_range)[0]

def match(self, image, threshold: float = None) -> bool:
return self.search(image, threshold=threshold)[0]

Expand Down
30 changes: 20 additions & 10 deletions tasks/ActivityShikigami/script_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
from module.logger import logger

from tasks.base_task import BaseTask
from tasks.Component.GeneralBattle.battle_wait import battle_wait_strategy
from tasks.Component.GeneralBattle.config_general_battle import GeneralBattleConfig
from tasks.Component.GeneralBattle.battle_wait import battle_wait_strategy, battle_wait_options
from tasks.Component.GeneralBattle.battle import Battle
from tasks.ActivityShikigami.assets import ActivityShikigamiAssets
from tasks.ActivityShikigami.config import SwitchSoulConfig, GeneralBattleConfig, ActivityShikigami
from tasks.Component.BaseActivity.base_activity import BaseActivity
Expand Down Expand Up @@ -137,13 +137,13 @@ def switch_next(self):
if self.run_idx >= len(self.conf.general_climb.run_sequence_v):
logger.info('All climbing activities have been completed')
return False
# 切换爬塔类型了, 恢复所有状态
self.current_count = 0
# 切换爬塔类型, count_map 按类型独立统计无需重置;但战斗框架状态需要清掉上一类型的残留
self.battle_state_reset()
logger.hr(f'Climb switch to {self.climb_type}', 2)
return True


class ScriptTask(StateMachine, GameUi, BaseActivity, SwitchSoul, ActivityShikigamiAssets):
class ScriptTask(StateMachine, GameUi, Battle, BaseActivity, SwitchSoul, ActivityShikigamiAssets):
"""
更新前请先看 ./README.md
"""
Expand Down Expand Up @@ -295,11 +295,21 @@ def start_battle(self):
logger.info(f'Try click fire, remain times[{max_times - click_times}]')
continue
# 运行战斗
self.run_general_battle(config=self.get_general_battle_conf())

@battle_wait_strategy(success='activity')
def battle_wait(self, *args, **kwargs):
return self.battle_wait_with_strategy(*args, **kwargs)
strategies, options = self.loadout_from_config(self.get_general_battle_conf())
strategies['success'] = 'activity'
self.loadout_show((strategies, options))
self.state_show()
with battle_wait_strategy(**strategies), battle_wait_options(**options):
win = self.battle_wait()
# 对齐历史语义: 战斗成功结束后记为一次
if win:
self.count_map[self.climb_type] += 1
logger.info(f'Count {self.climb_type}: {self.count_map[self.climb_type]}')
return win

# @battle_wait_strategy(success='activity')
# def battle_wait(self, *args, **kwargs):
# return self.battle_wait_with_strategy(*args, **kwargs)

def switch_soul(self, enter_button: RuleImage, cur_img: RuleImage):
conf = self.conf.switch_soul_config
Expand Down
44 changes: 39 additions & 5 deletions tasks/Component/Costume/assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,18 +102,51 @@ class CostumeAssets:


# Image Rule Assets
# 狐栖归处庭院判定
# 狐栖归处庭院判定
I_CHECK_MAIN_16 = RuleImage(roi_front=(260,168,80,54), roi_back=(180,100,240,180), threshold=0.8, method="Template matching", file="./tasks/Component/Costume/main16/main16_check_main_16.png")
# 探索
# 探索
I_MAIN_GOTO_EXPLORATION_16 = RuleImage(roi_front=(729,231,28,52), roi_back=(680,180,130,150), threshold=0.55, method="Template matching", file="./tasks/Component/Costume/main16/main16_main_goto_exploration_16.png")
# 召唤屋
# 召唤屋
I_MAIN_GOTO_SUMMON_16 = RuleImage(roi_front=(981,218,28,24), roi_back=(930,170,130,150), threshold=0.55, method="Template matching", file="./tasks/Component/Costume/main16/main16_main_goto_summon_16.png")
# 町中
# 町中
I_MAIN_GOTO_TOWN_16 = RuleImage(roi_front=(1014,346,14,34), roi_back=(960,300,100,120), threshold=0.8, method="Template matching", file="./tasks/Component/Costume/main16/main16_main_goto_town_16.png")
# 宠物屋
# 宠物屋
I_PET_HOUSE_16 = RuleImage(roi_front=(1256,402,20,58), roi_back=(1210,340,70,140), threshold=0.8, method="Template matching", file="./tasks/Component/Costume/main16/main16_pet_house_16.png")


# Image Rule Assets
# 庭院判定 a
I_CHECK_MAIN_17_A = RuleImage(roi_front=(260,168,80,54), roi_back=(180,100,240,180), threshold=0.8, method="Template matching", file="./tasks/Component/Costume/main17/main17_check_main_17_a.png")
# 庭院判定 b
I_CHECK_MAIN_17_B = RuleImage(roi_front=(260,168,80,54), roi_back=(180,100,240,180), threshold=0.8, method="Template matching", file="./tasks/Component/Costume/main17/main17_check_main_17_b.png")
# 庭院判定 c
I_CHECK_MAIN_17_C = RuleImage(roi_front=(260,168,80,54), roi_back=(180,100,240,180), threshold=0.8, method="Template matching", file="./tasks/Component/Costume/main17/main17_check_main_17_c.png")
# 探索 a
I_MAIN_GOTO_EXPLORATION_17_A = RuleImage(roi_front=(714,224,43,40), roi_back=(680,180,130,150), threshold=0.55, method="Template matching", file="./tasks/Component/Costume/main17/main17_main_goto_exploration_17_a.png")
# 探索 b
I_MAIN_GOTO_EXPLORATION_17_B = RuleImage(roi_front=(719,216,41,42), roi_back=(667,180,143,106), threshold=0.55, method="Template matching", file="./tasks/Component/Costume/main17/main17_main_goto_exploration_17_b.png")
# 探索 c
I_MAIN_GOTO_EXPLORATION_17_C = RuleImage(roi_front=(717,222,43,42), roi_back=(680,180,125,110), threshold=0.55, method="Template matching", file="./tasks/Component/Costume/main17/main17_main_goto_exploration_17_c.png")
# 召唤屋 a
I_MAIN_GOTO_SUMMON_17_A = RuleImage(roi_front=(981,218,40,41), roi_back=(930,170,130,150), threshold=0.55, method="Template matching", file="./tasks/Component/Costume/main17/main17_main_goto_summon_17_a.png")
# 召唤屋 b
I_MAIN_GOTO_SUMMON_17_B = RuleImage(roi_front=(981,218,39,38), roi_back=(930,170,130,150), threshold=0.55, method="Template matching", file="./tasks/Component/Costume/main17/main17_main_goto_summon_17_b.png")
# 召唤屋 c
I_MAIN_GOTO_SUMMON_17_C = RuleImage(roi_front=(981,218,39,37), roi_back=(930,170,130,150), threshold=0.55, method="Template matching", file="./tasks/Component/Costume/main17/main17_main_goto_summon_17_c.png")
# 町中 a
I_MAIN_GOTO_TOWN_17_A = RuleImage(roi_front=(1004,336,35,49), roi_back=(960,300,100,120), threshold=0.8, method="Template matching", file="./tasks/Component/Costume/main17/main17_main_goto_town_17_a.png")
# 町中 b
I_MAIN_GOTO_TOWN_17_B = RuleImage(roi_front=(1007,346,26,31), roi_back=(960,300,100,120), threshold=0.8, method="Template matching", file="./tasks/Component/Costume/main17/main17_main_goto_town_17_b.png")
# 町中 c
I_MAIN_GOTO_TOWN_17_C = RuleImage(roi_front=(1008,343,29,43), roi_back=(960,300,100,120), threshold=0.8, method="Template matching", file="./tasks/Component/Costume/main17/main17_main_goto_town_17_c.png")
# 宠物屋 a
I_PET_HOUSE_17_A = RuleImage(roi_front=(1249,404,23,56), roi_back=(1231,340,49,154), threshold=0.8, method="Template matching", file="./tasks/Component/Costume/main17/main17_pet_house_17_a.png")
# 宠物屋 b
I_PET_HOUSE_17_B = RuleImage(roi_front=(1251,417,19,45), roi_back=(1231,366,49,124), threshold=0.8, method="Template matching", file="./tasks/Component/Costume/main17/main17_pet_house_17_b.png")
# 宠物屋 c
I_PET_HOUSE_17_C = RuleImage(roi_front=(1248,406,19,59), roi_back=(1228,340,52,176), threshold=0.8, method="Template matching", file="./tasks/Component/Costume/main17/main17_pet_house_17_c.png")


# Image Rule Assets
# description
I_CHECK_MAIN_2 = RuleImage(roi_front=(1090,146,48,55), roi_back=(880,108,271,100), threshold=0.8, method="Template matching", file="./tasks/Component/Costume/main2/main2_check_main_2.png")
Expand Down Expand Up @@ -217,3 +250,4 @@ class CostumeAssets:
# description
I_PET_HOUSE_9 = RuleImage(roi_front=(888,327,40,35), roi_back=(730,316,440,57), threshold=0.8, method="Template matching", file="./tasks/Component/Costume/main9/main9_pet_house_9.png")


1 change: 1 addition & 0 deletions tasks/Component/Costume/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class MainType(str, Enum):
COSTUME_MAIN_14 = 'costume_main_14' # 雪月华庭
COSTUME_MAIN_15 = 'costume_main_15' # 茨心乐园
COSTUME_MAIN_16 = 'costume_main_16' # 狐栖归处
COSTUME_MAIN_17 = 'costume_main_17' # 玉岚狐庭

# 结界皮肤
class RealmType(str, Enum):
Expand Down
29 changes: 26 additions & 3 deletions tasks/Component/Costume/costume_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# github https://github.com/runhey

from module.atom.image import RuleImage
from module.atom.gif import RuleGif
from module.logger import logger

from tasks.Component.Costume.config import (MainType, CostumeConfig, RealmType,
Expand All @@ -23,6 +24,22 @@
'I_PET_HOUSE': f'I_PET_HOUSE_{i}'
} for i in range(1, 17)
}
# 玉岚狐庭(issue #1824)
main_costume_model[getattr(MainType, "COSTUME_MAIN_17")] = {
'I_CHECK_MAIN': ['I_CHECK_MAIN_17_A', 'I_CHECK_MAIN_17_B', 'I_CHECK_MAIN_17_C'],
'I_MAIN_GOTO_EXPLORATION': ['I_MAIN_GOTO_EXPLORATION_17_A', 'I_MAIN_GOTO_EXPLORATION_17_B', 'I_MAIN_GOTO_EXPLORATION_17_C'],
'I_MAIN_GOTO_SUMMON': ['I_MAIN_GOTO_SUMMON_17_A', 'I_MAIN_GOTO_SUMMON_17_B', 'I_MAIN_GOTO_SUMMON_17_C'],
'I_MAIN_GOTO_TOWN': ['I_MAIN_GOTO_TOWN_17_A', 'I_MAIN_GOTO_TOWN_17_B', 'I_MAIN_GOTO_TOWN_17_C'],
'I_PET_HOUSE': ['I_PET_HOUSE_17_A', 'I_PET_HOUSE_17_B', 'I_PET_HOUSE_17_C'],
}
main_costume_model[getattr(MainType, "COSTUME_MAIN_13")] = {
'I_CHECK_MAIN': ['I_CHECK_MAIN_13',],
'I_MAIN_GOTO_EXPLORATION': ['I_MAIN_GOTO_EXPLORATION_13', ],
'I_MAIN_GOTO_SUMMON': ['I_MAIN_GOTO_SUMMON_13',],
'I_MAIN_GOTO_TOWN': ['I_MAIN_GOTO_TOWN_13',],
'I_PET_HOUSE': ['I_PET_HOUSE_13',],
}



# 鲤鱼旗皮肤
Expand Down Expand Up @@ -101,8 +118,14 @@ def check_costume_main(self, main_type: MainType):
logger.info(f'Switch main costume to {main_type}')
costume_assets = CostumeAssets()
for key, value in main_costume_model[main_type].items():
assert_value: RuleImage = getattr(costume_assets, value)
self.replace_img(key, assert_value)
if isinstance(value, list):
if not hasattr(self, key):
continue
rules: list[RuleImage] = [getattr(costume_assets, item) for item in value]
RuleGif.attach_to(getattr(self, key), rules)
else:
assert_value: RuleImage = getattr(costume_assets, value)
self.replace_img(key, assert_value)

def check_costume_carpbanner(self, carpbanner_type: CarpBannerType):
if carpbanner_type == CarpBannerType.COSTUME_CARPBANNER_DEFAULT:
Expand Down Expand Up @@ -151,4 +174,4 @@ def check_costume_shikigami(self, shikigami_type: ShikigamiType):

if __name__ == '__main__':
c = CostumeBase()
c.check_costume_main(MainType.COSTUME_MAIN_2)
c.check_costume_main(MainType.COSTUME_MAIN_13)
2 changes: 1 addition & 1 deletion tasks/Component/Costume/costume_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def run(self):
self.ui_click(self.I_TOWN_GOTO_MAIN, self.I_CHECK_MAIN)
# 探索测试
self.ui_click(self.I_MAIN_GOTO_EXPLORATION, self.I_CHECK_EXPLORATION)
self.ui_click(self.I_UI_BACK_BLUE, self.I_CHECK_MAIN)
self.ui_click(self.I_UI_BACK_YELLOW, self.I_CHECK_MAIN)
# 召唤测试
self.ui_click(self.I_MAIN_GOTO_SUMMON, self.I_CHECK_SUMMON)
self.ui_click(self.I_SUMMON_GOTO_MAIN, self.I_CHECK_MAIN)
Expand Down
Loading
Loading