Skip to content

Commit

Permalink
#425 体力计划 加入恶名狩猎 使用深度追猎
Browse files Browse the repository at this point in the history
DoctorReid committed Jan 24, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 9d884d4 commit cc928d4
Showing 8 changed files with 232 additions and 36 deletions.
76 changes: 76 additions & 0 deletions assets/game_data/screen_info/notorious_hunt.yml
Original file line number Diff line number Diff line change
@@ -226,3 +226,79 @@ area_list:
template_match_threshold: 0.7
color_range: null
goto_list: []
- area_name: 按钮-深度追猎-ON
id_mark: false
pc_rect:
- 0
- 0
- 0
- 0
text: 'ON'
lcs_percent: 0.5
template_sub_dir: ''
template_id: ''
template_match_threshold: 0.7
color_range:
- - 70
- 80
- 0
- - 255
- 255
- 255
goto_list: []
- area_name: 按钮-深度追猎-确认
id_mark: false
pc_rect:
- 0
- 0
- 0
- 0
text: 确认
lcs_percent: 0.5
template_sub_dir: ''
template_id: ''
template_match_threshold: 0.7
color_range: null
goto_list: []
- area_name: 文本-剩余电量
id_mark: false
pc_rect:
- 0
- 0
- 0
- 0
text: ''
lcs_percent: 0.5
template_sub_dir: ''
template_id: ''
template_match_threshold: 0.7
color_range: null
goto_list: []
- area_name: 文本-需要电量
id_mark: false
pc_rect:
- 0
- 0
- 0
- 0
text: ''
lcs_percent: 0.5
template_sub_dir: ''
template_id: ''
template_match_threshold: 0.7
color_range: null
goto_list: []
- area_name: 按钮-无报酬模式
id_mark: false
pc_rect:
- 0
- 0
- 0
- 0
text: 无报酬模式
lcs_percent: 0.5
template_sub_dir: ''
template_id: ''
template_match_threshold: 0.7
color_range: null
goto_list: []
14 changes: 14 additions & 0 deletions src/zzz_od/application/charge_plan/charge_plan_app.py
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@
from zzz_od.operation.back_to_normal_world import BackToNormalWorld
from zzz_od.operation.compendium.combat_simulation import CombatSimulation
from zzz_od.operation.compendium.expert_challenge import ExpertChallenge
from zzz_od.operation.compendium.notorious_hunt import NotoriousHunt
from zzz_od.operation.compendium.routine_cleanup import RoutineCleanup
from zzz_od.operation.compendium.tp_by_compendium import TransportByCompendium
from zzz_od.operation.goto.goto_menu import GotoMenu
@@ -37,6 +38,7 @@ def __init__(self, ctx: ZContext):
@node_from(from_name='实战模拟室')
@node_from(from_name='定期清剿')
@node_from(from_name='专业挑战室')
@node_from(from_name='恶名狩猎')
@operation_node(name='打开菜单', is_start_node=True)
def goto_menu(self) -> OperationRoundResult:
op = GotoMenu(self.ctx)
@@ -79,6 +81,8 @@ def transport(self) -> OperationRoundResult:
need_charge_power = 60
elif self.next_plan.category_name == '专业挑战室':
need_charge_power = 40
elif self.next_plan.category_name == '恶名狩猎':
need_charge_power = 60
else:
self.need_to_check_power_in_mission = True

@@ -126,11 +130,21 @@ def expert_challenge(self) -> OperationRoundResult:
can_run_times=None if self.need_to_check_power_in_mission else self.next_can_run_times)
return self.round_by_op_result(op.execute())

@node_from(from_name='识别副本分类', status='恶名狩猎')
@operation_node(name='专业挑战室')
def notorious_hunt(self) -> OperationRoundResult:
op = NotoriousHunt(self.ctx, self.next_plan,
use_charge_power=True,
need_check_power=self.need_to_check_power_in_mission,
can_run_times=None if self.need_to_check_power_in_mission else self.next_can_run_times)
return self.round_by_op_result(op.execute())

@node_from(from_name='传送', status=STATUS_ROUND_FINISHED)
@node_from(from_name='传送', success=False)
@node_from(from_name='实战模拟室', status=CombatSimulation.STATUS_CHARGE_NOT_ENOUGH)
@node_from(from_name='定期清剿', status=RoutineCleanup.STATUS_CHARGE_NOT_ENOUGH)
@node_from(from_name='专业挑战室', status=ExpertChallenge.STATUS_CHARGE_NOT_ENOUGH)
@node_from(from_name='恶名狩猎', status=ExpertChallenge.STATUS_CHARGE_NOT_ENOUGH)
@operation_node(name='返回大世界', is_start_node=True)
def back_to_world(self) -> OperationRoundResult:
op = BackToNormalWorld(self.ctx)
14 changes: 7 additions & 7 deletions src/zzz_od/application/charge_plan/charge_plan_config.py
Original file line number Diff line number Diff line change
@@ -8,11 +8,11 @@
class CardNumEnum(Enum):

DEFAULT = ConfigItem('默认数量')
NUM_1 = ConfigItem('1')
NUM_2 = ConfigItem('2')
NUM_3 = ConfigItem('3')
NUM_4 = ConfigItem('4')
NUM_5 = ConfigItem('5')
NUM_1 = ConfigItem('1张卡片', '1')
NUM_2 = ConfigItem('2张卡片', '2')
NUM_3 = ConfigItem('3张卡片', '3')
NUM_4 = ConfigItem('4张卡片', '4')
NUM_5 = ConfigItem('5张卡片', '5')


class ChargePlanItem:
@@ -29,7 +29,7 @@ def __init__(
plan_times: int = 1,
card_num: str = CardNumEnum.DEFAULT.value.value,
predefined_team_idx: int = -1,
notorious_hunt_buff_num: int = 1
notorious_hunt_buff_num: int = 1,
):
self.tab_name: str = tab_name
self.category_name: str = category_name
@@ -86,7 +86,7 @@ def save(self):
'plan_times': plan_item.plan_times,
'card_num': plan_item.card_num,
'predefined_team_idx': plan_item.predefined_team_idx,
'notorious_hunt_buff_num': plan_item.notorious_hunt_buff_num
'notorious_hunt_buff_num': plan_item.notorious_hunt_buff_num,
}

new_history_list.append(plan_data.copy())
Original file line number Diff line number Diff line change
@@ -55,7 +55,7 @@ def transport(self) -> OperationRoundResult:
@node_from(from_name='判断剩余次数')
@operation_node(name='恶名狩猎')
def notorious_hunt(self) -> OperationRoundResult:
op = NotoriousHunt(self.ctx, self.next_plan)
op = NotoriousHunt(self.ctx, self.next_plan, use_charge_power=False)
return self.round_by_op_result(op.execute())

@node_from(from_name='恶名狩猎')
Original file line number Diff line number Diff line change
@@ -77,7 +77,7 @@ def save(self):
'auto_battle_config': plan_item.auto_battle_config,
'run_times': plan_item.run_times,
'plan_times': plan_item.plan_times,
'notorious_hunt_buff_num': plan_item.notorious_hunt_buff_num
'notorious_hunt_buff_num': plan_item.notorious_hunt_buff_num,
})

YamlConfig.save(self)
15 changes: 13 additions & 2 deletions src/zzz_od/game_data/compendium.py
Original file line number Diff line number Diff line change
@@ -211,12 +211,22 @@ def get_charge_plan_category_list(self) -> List[ConfigItem]:
value=category_item.category_name
))

category_list = self.get_category_list_data('作战')
for category_item in category_list:
if category_item.category_name not in ['恶名狩猎']:
continue
category_config_list.append(ConfigItem(
label=category_item.category_name,
value=category_item.category_name
))

return category_config_list

def get_charge_plan_mission_type_list(self, category_name: str) -> List[ConfigItem]:
config_list: List[ConfigItem] = []

mission_type_list = self.get_mission_type_list_data('训练', category_name)
tab_name = '作战' if category_name == '恶名狩猎' else '训练'
mission_type_list = self.get_mission_type_list_data(tab_name, category_name)
for mission_type_item in mission_type_list:
config_list.append(ConfigItem(
label=mission_type_item.mission_type_name_display,
@@ -228,7 +238,8 @@ def get_charge_plan_mission_type_list(self, category_name: str) -> List[ConfigIt
def get_charge_plan_mission_list(self, category_name: str, mission_type: str) -> List[ConfigItem]:
config_list: List[ConfigItem] = []

mission_list = self.get_mission_list_data('训练', category_name, mission_type)
tab_name = '作战' if category_name == '恶名狩猎' else '训练'
mission_list = self.get_mission_list_data(tab_name, category_name, mission_type)
for mission_item in mission_list:
config_list.append(ConfigItem(
label=mission_item.mission_name_display,
21 changes: 21 additions & 0 deletions src/zzz_od/gui/view/one_dragon/charge_plan_interface.py
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
from one_dragon.gui.widgets.setting_card.switch_setting_card import SwitchSettingCard
from zzz_od.application.battle_assistant.auto_battle_config import get_auto_battle_op_config_list
from zzz_od.application.charge_plan.charge_plan_config import ChargePlanItem, CardNumEnum
from zzz_od.application.notorious_hunt.notorious_hunt_config import NotoriousHuntBuffEnum
from zzz_od.context.zzz_context import ZContext

from phosdeiz.gui.widgets import Column,ComboBox
@@ -37,6 +38,9 @@ def __init__(self, ctx: ZContext,
self.card_num_box = ComboBox()
self.card_num_box.currentIndexChanged.connect(self._on_card_num_changed)

self.notorious_hunt_buff_num_opt = ComboBox()
self.notorious_hunt_buff_num_opt.currentIndexChanged.connect(self.on_notorious_hunt_buff_num_changed)

self.predefined_team_opt = ComboBox()
self.predefined_team_opt.currentIndexChanged.connect(self.on_predefined_team_changed)

@@ -66,6 +70,7 @@ def __init__(self, ctx: ZContext,
self.mission_type_combo_box,
self.mission_combo_box,
self.card_num_box,
self.notorious_hunt_buff_num_opt,
self.predefined_team_opt,
self.auto_battle_combo_box,
],
@@ -100,6 +105,14 @@ def init_card_num_box(self) -> None:
self.card_num_box.set_items(config_list, self.plan.card_num)
self.card_num_box.setVisible(self.plan.category_name == '实战模拟室')

def init_notorious_hunt_buff_num_opt(self) -> None:
"""
初始化不透明度下拉框
"""
config_list = [config_enum.value for config_enum in NotoriousHuntBuffEnum]
self.notorious_hunt_buff_num_opt.set_items(config_list, self.plan.notorious_hunt_buff_num)
self.notorious_hunt_buff_num_opt.setVisible(self.plan.category_name == '恶名狩猎')

def init_predefined_team_opt(self) -> None:
"""
初始化预备编队的下拉框
@@ -134,6 +147,7 @@ def init_with_plan(self, plan: ChargePlanItem) -> None:
self.init_mission_combo_box()

self.init_card_num_box()
self.init_notorious_hunt_buff_num_opt()
self.init_predefined_team_opt()
self.init_auto_battle_box()

@@ -146,6 +160,7 @@ def _on_category_changed(self, idx: int) -> None:

self.init_mission_type_combo_box()
self.init_mission_combo_box()
self.init_notorious_hunt_buff_num_opt()

self.update_by_history()

@@ -171,6 +186,10 @@ def _on_card_num_changed(self, idx: int) -> None:
self.plan.card_num = self.card_num_box.itemData(idx)
self._emit_value()

def on_notorious_hunt_buff_num_changed(self, idx: int) -> None:
self.plan.notorious_hunt_buff_num = self.notorious_hunt_buff_num_opt.currentData()
self._emit_value()

def on_predefined_team_changed(self, idx: int) -> None:
self.plan.predefined_team_idx = self.predefined_team_opt.currentData()
self.init_auto_battle_box()
@@ -208,11 +227,13 @@ def update_by_history(self) -> None:
return

self.plan.card_num = history.card_num
self.plan.notorious_hunt_buff_num = history.notorious_hunt_buff_num
self.plan.predefined_team_idx = history.predefined_team_idx
self.plan.auto_battle_config = history.auto_battle_config
self.plan.plan_times = history.plan_times

self.init_card_num_box()
self.init_notorious_hunt_buff_num_opt()
self.init_predefined_team_opt()
self.init_auto_battle_box()
self.init_plan_times_input()
124 changes: 99 additions & 25 deletions src/zzz_od/operation/compendium/notorious_hunt.py
Original file line number Diff line number Diff line change
@@ -26,8 +26,14 @@
class NotoriousHunt(ZOperation):

STATUS_NO_LEFT_TIMES: ClassVar[str] = '没有剩余次数'

def __init__(self, ctx: ZContext, plan: ChargePlanItem):
STATUS_WITH_LEFT_TIMES: ClassVar[str] = '有剩余次数'
STATUS_CHARGE_NOT_ENOUGH: ClassVar[str] = '电量不足'
STATUS_CHARGE_ENOUGH: ClassVar[str] = '电量充足'

def __init__(self, ctx: ZContext, plan: ChargePlanItem,
use_charge_power: bool = False,
can_run_times: Optional[int] = None,
need_check_power: bool = False):
"""
使用快捷手册传送后
用这个进行挑战
@@ -42,6 +48,10 @@ def __init__(self, ctx: ZContext, plan: ChargePlanItem):
)

self.plan: ChargePlanItem = plan
self.use_charge_power: bool = use_charge_power # 是否使用电量 深度追猎
self.need_check_power: bool = need_check_power
self.can_run_times: int = can_run_times

self.auto_op: Optional[AutoBattleOperator] = None
self.charge_left: Optional[int] = None
self.charge_need: Optional[int] = None
@@ -62,26 +72,6 @@ def wait_entry_load(self) -> OperationRoundResult:
return self.round_retry(r1.status, wait=1)

@node_from(from_name='等待入口加载')
@operation_node(name='识别剩余次数')
def check_left_times(self) -> OperationRoundResult:
screen = self.screenshot()
area = self.ctx.screen_loader.get_area('恶名狩猎', '剩余次数')
part = cv2_utils.crop_image_only(screen, area.rect)

ocr_result = self.ctx.ocr.run_ocr_single_line(part)
left_times = str_utils.get_positive_digits(ocr_result, None)

if left_times is None:
return self.round_retry('未能识别剩余次数', wait_round_time=1)
elif left_times == 0:
self.ctx.notorious_hunt_record.left_times = 0
return self.round_success(NotoriousHunt.STATUS_NO_LEFT_TIMES)
else:
self.ctx.notorious_hunt_record.left_times = left_times
self.can_run_times = min(left_times, self.plan.plan_times - self.plan.run_times)
return self.round_success()

@node_from(from_name='识别剩余次数')
@operation_node(name='选择副本')
def choose_mission(self) -> OperationRoundResult:
screen = self.screenshot()
@@ -121,6 +111,84 @@ def choose_mission(self) -> OperationRoundResult:
return self.round_retry(f'未能识别{self.plan.mission_type_name}', wait_round_time=2)

@node_from(from_name='选择副本')
@operation_node(name='选择深度追猎')
def choose_by_use_power(self):
screen = self.screenshot()

result = self.round_by_find_area(screen, '恶名狩猎', '按钮-深度追猎-ON')
current_use_power = result.is_success # 当前在深度追猎模式

if self.use_charge_power == current_use_power:
return self.round_success()

# 选择深度追猎之后的对话框
result = self.round_by_find_and_click_area(screen, '恶名狩猎', '按钮-深度追猎-确认')
if result.is_success:
return self.round_wait(result.status, wait=1)

self.round_by_click_area('恶名狩猎', '按钮-深度追猎-ON')
return self.round_retry(wait=1)

@node_from(from_name='选择深度追猎')
@operation_node(name='识别可运行次数')
def check_can_run_times(self) -> OperationRoundResult:
screen = self.screenshot()

if self.use_charge_power: # 深度追猎
if self.need_check_power:
area = self.ctx.screen_loader.get_area('恶名狩猎', '文本-剩余电量')
part = cv2_utils.crop_image_only(screen, area.rect)
ocr_result = self.ctx.ocr.run_ocr_single_line(part)
self.charge_left = str_utils.get_positive_digits(ocr_result, None)
if self.charge_left is None:
return self.round_retry(status='识别 %s 失败' % '剩余电量', wait=1)

area = self.ctx.screen_loader.get_area('恶名狩猎', '文本-需要电量')
part = cv2_utils.crop_image_only(screen, area.rect)
ocr_result = self.ctx.ocr.run_ocr_single_line(part)
self.charge_need = str_utils.get_positive_digits(ocr_result, None)
if self.charge_need is None:
return self.round_retry(status='识别 %s 失败' % '需要电量', wait=1)

log.info('所需电量 %d 剩余电量 %d', self.charge_need, self.charge_left)
if self.charge_need > self.charge_left:
return self.round_success(NotoriousHunt.STATUS_CHARGE_NOT_ENOUGH)

self.can_run_times = self.charge_left // self.charge_need
max_need_run_times = self.plan.plan_times - self.plan.run_times

if self.can_run_times > max_need_run_times:
self.can_run_times = max_need_run_times

return self.round_success(NotoriousHunt.STATUS_CHARGE_ENOUGH)
else:
if self.can_run_times == 0:
return self.round_success(NotoriousHunt.STATUS_CHARGE_NOT_ENOUGH)
else:
return self.round_success(NotoriousHunt.STATUS_CHARGE_ENOUGH)
else:
result = self.round_by_find_area(screen, '恶名狩猎', '按钮-无报酬模式')
if result.is_success: # 可能是其他设备挑战了 没有剩余次数了
self.ctx.notorious_hunt_record.left_times = 0
return self.round_success(NotoriousHunt.STATUS_NO_LEFT_TIMES)

area = self.ctx.screen_loader.get_area('恶名狩猎', '剩余次数')
part = cv2_utils.crop_image_only(screen, area.rect)

ocr_result = self.ctx.ocr.run_ocr_single_line(part)
left_times = str_utils.get_positive_digits(ocr_result, None)
if left_times is None: # 识别不到时 使用记录中的数量
self.can_run_times = self.ctx.notorious_hunt_record.left_times

# 运行次数上限是计划剩余次数
need_run_times = self.plan.plan_times - self.plan.run_times
if self.can_run_times > need_run_times:
self.can_run_times = need_run_times

return self.round_success(NotoriousHunt.STATUS_WITH_LEFT_TIMES)

@node_from(from_name='识别可运行次数', status=STATUS_CHARGE_ENOUGH)
@node_from(from_name='识别可运行次数', status=STATUS_WITH_LEFT_TIMES)
@operation_node(name='选择难度')
def choose_level(self) -> OperationRoundResult:
if self.plan.level == NotoriousHuntLevelEnum.DEFAULT.value.value:
@@ -352,8 +420,11 @@ def battle_fail_exit(self) -> OperationRoundResult:
@operation_node(name='战斗结束')
def after_battle(self) -> OperationRoundResult:
self.can_run_times -= 1
self.ctx.notorious_hunt_record.left_times = self.ctx.notorious_hunt_record.left_times - 1
self.ctx.notorious_hunt_config.add_plan_run_times(self.plan)
if self.use_charge_power:
self.ctx.charge_plan_config.add_plan_run_times(self.plan)
else:
self.ctx.notorious_hunt_record.left_times = self.ctx.notorious_hunt_record.left_times - 1
self.ctx.notorious_hunt_config.add_plan_run_times(self.plan)
return self.round_success()

@node_from(from_name='战斗结束')
@@ -372,7 +443,10 @@ def check_next(self) -> OperationRoundResult:
def no_left_times(self) -> OperationRoundResult:
# 本地记录的剩余次数错误 找不到再来一次
# 可能在其它设备上完成了挑战 也可能是上面识别错了
self.ctx.notorious_hunt_record.left_times = 0
if self.use_charge_power:
pass
else:
self.ctx.notorious_hunt_record.left_times = 0
screen = self.screenshot()
return self.round_by_find_and_click_area(screen, '战斗画面', '战斗结果-完成',
success_wait=5, retry_wait_round=1)

0 comments on commit cc928d4

Please sign in to comment.