mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-15 22:19:18 +00:00
Add: Task Echo of War
This commit is contained in:
parent
05096c9105
commit
96b6bdadf0
BIN
assets/cn/combat/finish/COMBAT_AGAIN.SEARCH.png
Normal file
BIN
assets/cn/combat/finish/COMBAT_AGAIN.SEARCH.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
assets/cn/combat/prepare/COMBAT_PREPARE.SEARCH.png
Normal file
BIN
assets/cn/combat/prepare/COMBAT_PREPARE.SEARCH.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
assets/en/combat/finish/COMBAT_AGAIN.SEARCH.png
Normal file
BIN
assets/en/combat/finish/COMBAT_AGAIN.SEARCH.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
assets/en/combat/prepare/COMBAT_PREPARE.SEARCH.png
Normal file
BIN
assets/en/combat/prepare/COMBAT_PREPARE.SEARCH.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
assets/share/dungeon/ui/OCR_WEEKLY_LIMIT.png
Normal file
BIN
assets/share/dungeon/ui/OCR_WEEKLY_LIMIT.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.7 KiB |
4
src.py
4
src.py
@ -26,6 +26,10 @@ class StarRailCopilot(AzurLaneAutoScript):
|
||||
from tasks.dungeon.dungeon import Dungeon
|
||||
Dungeon(config=self.config, device=self.device).run()
|
||||
|
||||
def weekly(self):
|
||||
from tasks.dungeon.weekly import WeeklyDungeon
|
||||
WeeklyDungeon(config=self.config, device=self.device).run()
|
||||
|
||||
def daily_quest(self):
|
||||
from tasks.daily.daily_quest import DailyQuestUI
|
||||
DailyQuestUI(config=self.config, device=self.device).run()
|
||||
|
@ -8,14 +8,14 @@ COMBAT_AGAIN = ButtonWrapper(
|
||||
cn=Button(
|
||||
file='./assets/cn/combat/finish/COMBAT_AGAIN.png',
|
||||
area=(846, 601, 924, 619),
|
||||
search=(826, 581, 944, 639),
|
||||
search=(709, 592, 979, 628),
|
||||
color=(162, 162, 162),
|
||||
button=(709, 592, 979, 628),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/combat/finish/COMBAT_AGAIN.png',
|
||||
area=(809, 602, 902, 618),
|
||||
search=(789, 582, 922, 638),
|
||||
search=(709, 591, 981, 628),
|
||||
color=(159, 159, 159),
|
||||
button=(709, 591, 981, 628),
|
||||
),
|
||||
|
@ -8,14 +8,14 @@ COMBAT_PREPARE = ButtonWrapper(
|
||||
cn=Button(
|
||||
file='./assets/cn/combat/prepare/COMBAT_PREPARE.png',
|
||||
area=(1071, 649, 1110, 667),
|
||||
search=(1051, 629, 1130, 687),
|
||||
search=(836, 640, 1225, 677),
|
||||
color=(141, 140, 141),
|
||||
button=(956, 640, 1224, 676),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/combat/prepare/COMBAT_PREPARE.png',
|
||||
area=(1043, 650, 1137, 666),
|
||||
search=(1023, 630, 1157, 686),
|
||||
search=(836, 640, 1225, 677),
|
||||
color=(153, 154, 155),
|
||||
button=(956, 640, 1225, 676),
|
||||
),
|
||||
|
@ -118,6 +118,8 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo
|
||||
continue
|
||||
if self.handle_ascension_dungeon_prepare():
|
||||
continue
|
||||
if self.handle_popup_confirm():
|
||||
continue
|
||||
|
||||
def combat_execute(self, expected_end=None):
|
||||
"""
|
||||
@ -165,7 +167,7 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo
|
||||
Pages:
|
||||
in: COMBAT_AGAIN
|
||||
"""
|
||||
current = self.combat_get_trailblaze_power(expect_reduce=True)
|
||||
current = self.combat_get_trailblaze_power(expect_reduce=self.combat_wave_cost > 0)
|
||||
# Wave limit
|
||||
if self.combat_wave_limit:
|
||||
if self.combat_wave_done + self.combat_waves > self.combat_wave_limit:
|
||||
@ -181,6 +183,9 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo
|
||||
else:
|
||||
logger.info(f'Current has {current}, combat costs {self.combat_wave_cost}, can not run again')
|
||||
return False
|
||||
elif self.combat_wave_cost <= 0:
|
||||
logger.info(f'Free combat, combat costs {self.combat_wave_cost}, can not run again')
|
||||
return False
|
||||
else:
|
||||
if current >= self.combat_wave_cost:
|
||||
logger.info(f'Current has {current}, combat costs {self.combat_wave_cost}, can run again')
|
||||
|
@ -2,6 +2,7 @@ import re
|
||||
|
||||
import module.config.server as server
|
||||
from module.base.timer import Timer
|
||||
from module.base.utils import color_similar, get_color
|
||||
from module.logger import logger
|
||||
from module.ocr.ocr import Digit, DigitCounter
|
||||
from tasks.base.ui import UI
|
||||
@ -75,7 +76,7 @@ class CombatPrepare(UI):
|
||||
# Empty result
|
||||
if total == 0:
|
||||
continue
|
||||
# Confirm if it is > 180, sometimes just OCR errors
|
||||
# Confirm if it is > 240, sometimes just OCR errors
|
||||
if current > 240 and timeout.reached():
|
||||
break
|
||||
if expect_reduce and current >= self.config.stored.TrailblazePower.value:
|
||||
@ -106,6 +107,12 @@ class CombatPrepare(UI):
|
||||
else:
|
||||
self.device.screenshot()
|
||||
|
||||
color = get_color(self.device.image, OCR_WAVE_COST.area)
|
||||
if color_similar(color, (229, 231, 223), threshold=30):
|
||||
logger.info(f'Combat is trailblaze power free')
|
||||
self.combat_wave_cost = 0
|
||||
return 0
|
||||
|
||||
cost = Digit(OCR_WAVE_COST).ocr_single_line(self.device.image)
|
||||
if cost == 10:
|
||||
if multi:
|
||||
|
@ -73,6 +73,16 @@ OCR_SIMUNI_POINT_OFFSET = ButtonWrapper(
|
||||
button=(685, 250, 717, 273),
|
||||
),
|
||||
)
|
||||
OCR_WEEKLY_LIMIT = ButtonWrapper(
|
||||
name='OCR_WEEKLY_LIMIT',
|
||||
share=Button(
|
||||
file='./assets/share/dungeon/ui/OCR_WEEKLY_LIMIT.png',
|
||||
area=(580, 225, 680, 257),
|
||||
search=(560, 205, 700, 277),
|
||||
color=(132, 192, 247),
|
||||
button=(580, 225, 680, 257),
|
||||
),
|
||||
)
|
||||
OPERATION_BRIEFING_CHECK = ButtonWrapper(
|
||||
name='OPERATION_BRIEFING_CHECK',
|
||||
share=Button(
|
||||
|
@ -1,4 +1,8 @@
|
||||
from datetime import timedelta
|
||||
|
||||
from module.base.utils import area_offset
|
||||
from module.config.stored.classes import now
|
||||
from module.config.utils import DEFAULT_TIME
|
||||
from module.logger import logger
|
||||
from tasks.combat.combat import Combat
|
||||
from tasks.daily.keywords import KEYWORDS_DAILY_QUEST
|
||||
@ -7,6 +11,7 @@ from tasks.dungeon.keywords import DungeonList, KEYWORDS_DUNGEON_LIST, KEYWORDS_
|
||||
from tasks.dungeon.ui import DungeonUI
|
||||
from tasks.battle_pass.keywords import KEYWORD_BATTLE_PASS_QUEST
|
||||
|
||||
|
||||
class Dungeon(DungeonUI, DungeonEvent, Combat):
|
||||
called_daily_support = False
|
||||
achieved_daily_quest = False
|
||||
@ -210,6 +215,8 @@ class Dungeon(DungeonUI, DungeonEvent, Combat):
|
||||
def delay_dungeon_task(self, dungeon):
|
||||
if dungeon.is_Cavern_of_Corrosion:
|
||||
limit = 80
|
||||
elif dungeon.is_Echo_of_War:
|
||||
limit = 30
|
||||
else:
|
||||
limit = 60
|
||||
# Recover 1 trailbaze power each 6 minutes
|
||||
@ -226,8 +233,14 @@ class Dungeon(DungeonUI, DungeonEvent, Combat):
|
||||
# Check daily
|
||||
if self.achieved_daily_quest:
|
||||
self.config.task_call('DailyQuest')
|
||||
# Delay self
|
||||
self.config.task_delay(minute=cover)
|
||||
# Delay tasks
|
||||
future = now() + timedelta(minutes=cover)
|
||||
for task in ['Dungeon', 'Weekly']:
|
||||
next_run = self.config.cross_get(keys=f'{task}.Scheduler.NextRun', default=DEFAULT_TIME)
|
||||
if future > next_run:
|
||||
logger.info(f"Delay task `{task}` to {future}")
|
||||
self.config.cross_set(keys=f'{task}.Scheduler.NextRun', value=future)
|
||||
|
||||
self.config.task_stop()
|
||||
|
||||
def handle_destructible_around_blaze(self):
|
||||
|
@ -428,7 +428,8 @@ class DungeonUI(UI):
|
||||
if dungeon.is_Calyx_Golden \
|
||||
or dungeon.is_Calyx_Crimson \
|
||||
or dungeon.is_Stagnant_Shadow \
|
||||
or dungeon.is_Cavern_of_Corrosion:
|
||||
or dungeon.is_Cavern_of_Corrosion \
|
||||
or dungeon.is_Echo_of_War:
|
||||
self._dungeon_nav_goto(dungeon)
|
||||
self._dungeon_insight(dungeon)
|
||||
self._dungeon_enter(dungeon)
|
||||
|
88
tasks/dungeon/weekly.py
Normal file
88
tasks/dungeon/weekly.py
Normal file
@ -0,0 +1,88 @@
|
||||
from module.logger import logger
|
||||
from module.ocr.ocr import DigitCounter
|
||||
from tasks.daily.keywords import KEYWORDS_DAILY_QUEST
|
||||
from tasks.dungeon.assets.assets_dungeon_ui import OCR_DUNGEON_LIST, OCR_WEEKLY_LIMIT
|
||||
from tasks.dungeon.dungeon import Dungeon
|
||||
from tasks.dungeon.keywords import DungeonList, KEYWORDS_DUNGEON_TAB
|
||||
from tasks.dungeon.ui import DUNGEON_LIST
|
||||
|
||||
|
||||
class WeeklyDungeon(Dungeon):
|
||||
def require_compulsory_support(self) -> bool:
|
||||
return False
|
||||
|
||||
def _dungeon_run(self, dungeon: DungeonList, team: int = None, wave_limit: int = 0, support_character: str = None,
|
||||
skip_ui_switch: bool = False):
|
||||
if team is None:
|
||||
team = self.config.Weekly_Team
|
||||
# No support
|
||||
support_character = ''
|
||||
skip_ui_switch = True
|
||||
return super()._dungeon_run(
|
||||
dungeon=dungeon, team=team, wave_limit=wave_limit,
|
||||
support_character=support_character, skip_ui_switch=skip_ui_switch)
|
||||
|
||||
def get_weekly_remain(self) -> int:
|
||||
"""
|
||||
Pages:
|
||||
in: page_guide, Survival_Index, KEYWORDS_DUNGEON_NAV.Echo_of_War
|
||||
"""
|
||||
ocr = DigitCounter(OCR_WEEKLY_LIMIT)
|
||||
current, _, _ = ocr.ocr_single_line(self.device.image)
|
||||
total = self.config.stored.EchoOfWar.FIXED_TOTAL
|
||||
remain = total - current
|
||||
if current <= total:
|
||||
logger.attr('EchoOfWar', f'{current}/{total}')
|
||||
self.config.stored.EchoOfWar.value = current
|
||||
return current
|
||||
else:
|
||||
logger.warning(f'Invalid EchoOfWar limit: {current}/{total}')
|
||||
return 0
|
||||
|
||||
def run(self):
|
||||
# self.config.update_battle_pass_quests()
|
||||
self.config.update_daily_quests()
|
||||
self.called_daily_support = False
|
||||
self.achieved_daily_quest = False
|
||||
self.daily_quests = self.config.stored.DailyQuest.load_quests()
|
||||
|
||||
dungeon = DungeonList.find(self.config.Weekly_Name)
|
||||
|
||||
# UI switches
|
||||
self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index)
|
||||
# Equivalent to self.dungeon_goto(dungeon), but check limit remains
|
||||
DUNGEON_LIST.search_button = OCR_DUNGEON_LIST
|
||||
self._dungeon_nav_goto(dungeon)
|
||||
|
||||
# Check limit
|
||||
remain = self.get_weekly_remain()
|
||||
if remain <= 0:
|
||||
if KEYWORDS_DAILY_QUEST.Complete_Echo_of_War_1_times in self.daily_quests:
|
||||
logger.info('Reached the limit to get Echo_of_War rewards, continue cause daily quests require it')
|
||||
remain = 1
|
||||
else:
|
||||
logger.info('Reached the limit to get Echo_of_War rewards, stop')
|
||||
self.config.task_delay(server_update=True)
|
||||
self.config.task_stop()
|
||||
|
||||
self._dungeon_insight(dungeon)
|
||||
self._dungeon_enter(dungeon)
|
||||
|
||||
# Combat
|
||||
count = self.dungeon_run(dungeon, wave_limit=min(remain, 3))
|
||||
|
||||
with self.config.multi_set():
|
||||
# Check daily quests
|
||||
if count:
|
||||
if KEYWORDS_DAILY_QUEST.Complete_Echo_of_War_1_times in self.daily_quests:
|
||||
logger.info('Achieve daily quest Complete_Echo_of_War_1_times')
|
||||
self.config.task_call('DailyQuest')
|
||||
# Finished all remains
|
||||
if count >= remain:
|
||||
logger.info('All Echo_of_War rewards got')
|
||||
self.config.task_delay(server_update=True)
|
||||
self.config.task_stop()
|
||||
|
||||
logger.warning(f'Unexpected Echo_of_War case, count={count}, remain={remain}')
|
||||
self.config.task_delay(server_update=True)
|
||||
self.config.task_stop()
|
Loading…
Reference in New Issue
Block a user