mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-22 00:35:34 +00:00
Add: claim immersifier rewards
This commit is contained in:
parent
fe39645e59
commit
9a113a7b9b
BIN
assets/share/rogue/reward/OCR_REMAIN.png
Normal file
BIN
assets/share/rogue/reward/OCR_REMAIN.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
BIN
assets/share/rogue/reward/REWARD_CLOSE.png
Normal file
BIN
assets/share/rogue/reward/REWARD_CLOSE.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.8 KiB |
BIN
assets/share/rogue/reward/USE_IMMERSIFIER.BUTTON.png
Normal file
BIN
assets/share/rogue/reward/USE_IMMERSIFIER.BUTTON.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
assets/share/rogue/reward/USE_IMMERSIFIER.png
Normal file
BIN
assets/share/rogue/reward/USE_IMMERSIFIER.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.8 KiB |
BIN
assets/share/rogue/reward/USE_STAMINA.BUTTON.png
Normal file
BIN
assets/share/rogue/reward/USE_STAMINA.BUTTON.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
assets/share/rogue/reward/USE_STAMINA.png
Normal file
BIN
assets/share/rogue/reward/USE_STAMINA.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.3 KiB |
@ -58,6 +58,7 @@
|
|||||||
},
|
},
|
||||||
"DungeonStorage": {
|
"DungeonStorage": {
|
||||||
"TrailblazePower": {},
|
"TrailblazePower": {},
|
||||||
|
"Immersifier": {},
|
||||||
"DungeonDouble": {},
|
"DungeonDouble": {},
|
||||||
"EchoOfWar": {},
|
"EchoOfWar": {},
|
||||||
"SimulatedUniverse": {}
|
"SimulatedUniverse": {}
|
||||||
|
@ -390,6 +390,12 @@
|
|||||||
"order": 1,
|
"order": 1,
|
||||||
"color": "#eb8efe"
|
"color": "#eb8efe"
|
||||||
},
|
},
|
||||||
|
"Immersifier": {
|
||||||
|
"type": "stored",
|
||||||
|
"value": {},
|
||||||
|
"display": "hide",
|
||||||
|
"stored": "StoredImmersifier"
|
||||||
|
},
|
||||||
"DungeonDouble": {
|
"DungeonDouble": {
|
||||||
"type": "stored",
|
"type": "stored",
|
||||||
"value": {},
|
"value": {},
|
||||||
|
@ -116,6 +116,8 @@ DungeonStorage:
|
|||||||
stored: StoredTrailblazePower
|
stored: StoredTrailblazePower
|
||||||
order: 1
|
order: 1
|
||||||
color: "#eb8efe"
|
color: "#eb8efe"
|
||||||
|
Immersifier:
|
||||||
|
stored: StoredImmersifier
|
||||||
DungeonDouble:
|
DungeonDouble:
|
||||||
stored: StoredDungeonDouble
|
stored: StoredDungeonDouble
|
||||||
EchoOfWar:
|
EchoOfWar:
|
||||||
|
@ -101,6 +101,19 @@
|
|||||||
"order": 8,
|
"order": 8,
|
||||||
"color": "#fc8f8b"
|
"color": "#fc8f8b"
|
||||||
},
|
},
|
||||||
|
"Immersifier": {
|
||||||
|
"name": "Immersifier",
|
||||||
|
"path": "Dungeon.DungeonStorage.Immersifier",
|
||||||
|
"i18n": "DungeonStorage.Immersifier.name",
|
||||||
|
"stored": "StoredImmersifier",
|
||||||
|
"attrs": {
|
||||||
|
"time": "2020-01-01 00:00:00",
|
||||||
|
"total": 8,
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
"order": 0,
|
||||||
|
"color": "#777777"
|
||||||
|
},
|
||||||
"DungeonDouble": {
|
"DungeonDouble": {
|
||||||
"name": "DungeonDouble",
|
"name": "DungeonDouble",
|
||||||
"path": "Dungeon.DungeonStorage.DungeonDouble",
|
"path": "Dungeon.DungeonStorage.DungeonDouble",
|
||||||
|
@ -57,6 +57,7 @@ class GeneratedConfig:
|
|||||||
|
|
||||||
# Group `DungeonStorage`
|
# Group `DungeonStorage`
|
||||||
DungeonStorage_TrailblazePower = {}
|
DungeonStorage_TrailblazePower = {}
|
||||||
|
DungeonStorage_Immersifier = {}
|
||||||
DungeonStorage_DungeonDouble = {}
|
DungeonStorage_DungeonDouble = {}
|
||||||
DungeonStorage_EchoOfWar = {}
|
DungeonStorage_EchoOfWar = {}
|
||||||
DungeonStorage_SimulatedUniverse = {}
|
DungeonStorage_SimulatedUniverse = {}
|
||||||
|
@ -401,6 +401,10 @@
|
|||||||
"name": "Power",
|
"name": "Power",
|
||||||
"help": ""
|
"help": ""
|
||||||
},
|
},
|
||||||
|
"Immersifier": {
|
||||||
|
"name": "Immersifier",
|
||||||
|
"help": ""
|
||||||
|
},
|
||||||
"DungeonDouble": {
|
"DungeonDouble": {
|
||||||
"name": "Dungeon Double",
|
"name": "Dungeon Double",
|
||||||
"help": ""
|
"help": ""
|
||||||
|
@ -401,6 +401,10 @@
|
|||||||
"name": "Poder",
|
"name": "Poder",
|
||||||
"help": ""
|
"help": ""
|
||||||
},
|
},
|
||||||
|
"Immersifier": {
|
||||||
|
"name": "Inmersor",
|
||||||
|
"help": ""
|
||||||
|
},
|
||||||
"DungeonDouble": {
|
"DungeonDouble": {
|
||||||
"name": "Mazmorra x2",
|
"name": "Mazmorra x2",
|
||||||
"help": ""
|
"help": ""
|
||||||
|
@ -401,6 +401,10 @@
|
|||||||
"name": "DungeonStorage.TrailblazePower.name",
|
"name": "DungeonStorage.TrailblazePower.name",
|
||||||
"help": "DungeonStorage.TrailblazePower.help"
|
"help": "DungeonStorage.TrailblazePower.help"
|
||||||
},
|
},
|
||||||
|
"Immersifier": {
|
||||||
|
"name": "DungeonStorage.Immersifier.name",
|
||||||
|
"help": "DungeonStorage.Immersifier.help"
|
||||||
|
},
|
||||||
"DungeonDouble": {
|
"DungeonDouble": {
|
||||||
"name": "DungeonStorage.DungeonDouble.name",
|
"name": "DungeonStorage.DungeonDouble.name",
|
||||||
"help": "DungeonStorage.DungeonDouble.help"
|
"help": "DungeonStorage.DungeonDouble.help"
|
||||||
|
@ -401,6 +401,10 @@
|
|||||||
"name": "开拓力",
|
"name": "开拓力",
|
||||||
"help": ""
|
"help": ""
|
||||||
},
|
},
|
||||||
|
"Immersifier": {
|
||||||
|
"name": "沉浸器",
|
||||||
|
"help": ""
|
||||||
|
},
|
||||||
"DungeonDouble": {
|
"DungeonDouble": {
|
||||||
"name": "副本双倍",
|
"name": "副本双倍",
|
||||||
"help": ""
|
"help": ""
|
||||||
|
@ -401,6 +401,10 @@
|
|||||||
"name": "開拓力",
|
"name": "開拓力",
|
||||||
"help": ""
|
"help": ""
|
||||||
},
|
},
|
||||||
|
"Immersifier": {
|
||||||
|
"name": "沉浸器",
|
||||||
|
"help": ""
|
||||||
|
},
|
||||||
"DungeonDouble": {
|
"DungeonDouble": {
|
||||||
"name": "副本雙倍",
|
"name": "副本雙倍",
|
||||||
"help": ""
|
"help": ""
|
||||||
@ -806,20 +810,20 @@
|
|||||||
"combat": "偏好戰鬥",
|
"combat": "偏好戰鬥",
|
||||||
"occurrence": "偏好事件"
|
"occurrence": "偏好事件"
|
||||||
},
|
},
|
||||||
"ImmersionReward": {
|
"ImmersionReward": {
|
||||||
"name": "领取浸器奖励",
|
"name": "領取浸器獎勵",
|
||||||
"help": "注意:选择 \"使用沉浸器和开拓力领取\" 时,每日副本任务不再打本,所有开拓力将优先被用于领取浸器奖励,双倍活动时除外",
|
"help": "注意:選擇 \"使用沉浸器和開拓力領取\" 時,每日副本任務不再打本,所有開拓力將優先被用於領取浸器獎勵,雙倍活動時除外",
|
||||||
"do_not_claim": "不领取",
|
"do_not_claim": "不領取",
|
||||||
"immersifier": "仅使用沉浸器领取",
|
"immersifier": "只使用沉浸器領取",
|
||||||
"immersifier_trailblaze_power": "使用沉浸器和开拓力领取"
|
"immersifier_trailblaze_power": "使用沉浸器和開拓力領取"
|
||||||
},
|
},
|
||||||
"StopCondition": {
|
"StopCondition": {
|
||||||
"name": "停止条件",
|
"name": "停止條件",
|
||||||
"help": "注意:\"每周100精英怪掉落奖励达到上限\" 时,模拟宇宙任务将运行数小时",
|
"help": "注意:\"每週100精英怪掉落獎勵達到上限\" 時,模擬宇宙任務將運行數小時",
|
||||||
"weekly_point_reward": "每周点数奖励达到上限",
|
"weekly_point_reward": "每週點數獎勵達到上限",
|
||||||
"100_elite_boss": "每周100精英怪掉落奖励达到上限",
|
"100_elite_boss": "每週100精英怪掉落獎勵達到上限",
|
||||||
"non_stop": "不停止 (仅用于除錯)"
|
"non_stop": "不停止 (只用於除錯)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"RoguePath": {
|
"RoguePath": {
|
||||||
"_info": {
|
"_info": {
|
||||||
|
@ -177,6 +177,29 @@ class StoredDailyActivity(StoredCounter, StoredExpiredAt0400):
|
|||||||
class StoredTrailblazePower(StoredCounter):
|
class StoredTrailblazePower(StoredCounter):
|
||||||
FIXED_TOTAL = 240
|
FIXED_TOTAL = 240
|
||||||
|
|
||||||
|
def predict_current(self) -> int:
|
||||||
|
"""
|
||||||
|
Predict current stamina from records
|
||||||
|
"""
|
||||||
|
# Overflowed
|
||||||
|
value = self.value
|
||||||
|
if value >= self.FIXED_TOTAL:
|
||||||
|
return value
|
||||||
|
# Invalid time, record in the future
|
||||||
|
record = self.time
|
||||||
|
now = datetime.now()
|
||||||
|
if record >= now:
|
||||||
|
return value
|
||||||
|
# Calculate
|
||||||
|
# Recover 1 trailbaze power each 6 minutes
|
||||||
|
diff = (now - record).total_seconds()
|
||||||
|
value += int(diff // 360)
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class StoredImmersifier(StoredCounter):
|
||||||
|
FIXED_TOTAL = 8
|
||||||
|
|
||||||
|
|
||||||
class StoredSimulatedUniverse(StoredCounter, StoredExpiredAtMonday0400):
|
class StoredSimulatedUniverse(StoredCounter, StoredExpiredAtMonday0400):
|
||||||
pass
|
pass
|
||||||
|
@ -10,6 +10,7 @@ from module.config.stored.classes import (
|
|||||||
StoredEchoOfWar,
|
StoredEchoOfWar,
|
||||||
StoredExpiredAt0400,
|
StoredExpiredAt0400,
|
||||||
StoredExpiredAtMonday0400,
|
StoredExpiredAtMonday0400,
|
||||||
|
StoredImmersifier,
|
||||||
StoredInt,
|
StoredInt,
|
||||||
StoredSimulatedUniverse,
|
StoredSimulatedUniverse,
|
||||||
StoredTrailblazePower,
|
StoredTrailblazePower,
|
||||||
@ -21,6 +22,7 @@ from module.config.stored.classes import (
|
|||||||
|
|
||||||
class StoredGenerated:
|
class StoredGenerated:
|
||||||
TrailblazePower = StoredTrailblazePower("Dungeon.DungeonStorage.TrailblazePower")
|
TrailblazePower = StoredTrailblazePower("Dungeon.DungeonStorage.TrailblazePower")
|
||||||
|
Immersifier = StoredImmersifier("Dungeon.DungeonStorage.Immersifier")
|
||||||
DungeonDouble = StoredDungeonDouble("Dungeon.DungeonStorage.DungeonDouble")
|
DungeonDouble = StoredDungeonDouble("Dungeon.DungeonStorage.DungeonDouble")
|
||||||
EchoOfWar = StoredEchoOfWar("Dungeon.DungeonStorage.EchoOfWar")
|
EchoOfWar = StoredEchoOfWar("Dungeon.DungeonStorage.EchoOfWar")
|
||||||
SimulatedUniverse = StoredSimulatedUniverse("Dungeon.DungeonStorage.SimulatedUniverse")
|
SimulatedUniverse = StoredSimulatedUniverse("Dungeon.DungeonStorage.SimulatedUniverse")
|
||||||
|
45
tasks/rogue/assets/assets_rogue_reward.py
Normal file
45
tasks/rogue/assets/assets_rogue_reward.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
from module.base.button import Button, ButtonWrapper
|
||||||
|
|
||||||
|
# This file was auto-generated, do not modify it manually. To generate:
|
||||||
|
# ``` python -m dev_tools.button_extract ```
|
||||||
|
|
||||||
|
OCR_REMAIN = ButtonWrapper(
|
||||||
|
name='OCR_REMAIN',
|
||||||
|
share=Button(
|
||||||
|
file='./assets/share/rogue/reward/OCR_REMAIN.png',
|
||||||
|
area=(675, 11, 1181, 64),
|
||||||
|
search=(655, 0, 1201, 84),
|
||||||
|
color=(75, 89, 125),
|
||||||
|
button=(675, 11, 1181, 64),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
REWARD_CLOSE = ButtonWrapper(
|
||||||
|
name='REWARD_CLOSE',
|
||||||
|
share=Button(
|
||||||
|
file='./assets/share/rogue/reward/REWARD_CLOSE.png',
|
||||||
|
area=(1043, 194, 1073, 224),
|
||||||
|
search=(1023, 174, 1093, 244),
|
||||||
|
color=(174, 175, 178),
|
||||||
|
button=(1043, 194, 1073, 224),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
USE_IMMERSIFIER = ButtonWrapper(
|
||||||
|
name='USE_IMMERSIFIER',
|
||||||
|
share=Button(
|
||||||
|
file='./assets/share/rogue/reward/USE_IMMERSIFIER.png',
|
||||||
|
area=(713, 509, 737, 523),
|
||||||
|
search=(693, 489, 757, 543),
|
||||||
|
color=(189, 189, 189),
|
||||||
|
button=(684, 499, 963, 535),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
USE_STAMINA = ButtonWrapper(
|
||||||
|
name='USE_STAMINA',
|
||||||
|
share=Button(
|
||||||
|
file='./assets/share/rogue/reward/USE_STAMINA.png',
|
||||||
|
area=(345, 509, 378, 524),
|
||||||
|
search=(325, 489, 398, 544),
|
||||||
|
color=(172, 172, 172),
|
||||||
|
button=(319, 499, 595, 535),
|
||||||
|
),
|
||||||
|
)
|
117
tasks/rogue/event/reward.py
Normal file
117
tasks/rogue/event/reward.py
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
from module.base.timer import Timer
|
||||||
|
from module.logger import logger
|
||||||
|
from module.ocr.ocr import DigitCounter
|
||||||
|
from tasks.base.assets.assets_base_popup import GET_REWARD
|
||||||
|
from tasks.combat.interact import CombatInteract
|
||||||
|
from tasks.rogue.assets.assets_rogue_reward import OCR_REMAIN, REWARD_CLOSE, USE_IMMERSIFIER, USE_STAMINA
|
||||||
|
from tasks.rogue.bleesing.ui import RogueUI
|
||||||
|
|
||||||
|
|
||||||
|
class RogueReward(RogueUI, CombatInteract):
|
||||||
|
def _reward_update_stamina(self, skip_first_screenshot=True):
|
||||||
|
ocr = DigitCounter(OCR_REMAIN)
|
||||||
|
timeout = Timer(1, count=2).start()
|
||||||
|
while 1:
|
||||||
|
if skip_first_screenshot:
|
||||||
|
skip_first_screenshot = False
|
||||||
|
else:
|
||||||
|
self.device.screenshot()
|
||||||
|
|
||||||
|
stamina = (0, 0, 0)
|
||||||
|
immersifier = (0, 0, 0)
|
||||||
|
|
||||||
|
if timeout.reached():
|
||||||
|
logger.warning('_reward_update_stamina() timeout')
|
||||||
|
break
|
||||||
|
|
||||||
|
for row in ocr.detect_and_ocr(self.device.image):
|
||||||
|
if row.ocr_text.isdigit():
|
||||||
|
continue
|
||||||
|
if row.ocr_text == '+':
|
||||||
|
continue
|
||||||
|
data = ocr.format_result(row.ocr_text)
|
||||||
|
if data[2] == self.config.stored.TrailblazePower.FIXED_TOTAL:
|
||||||
|
stamina = data
|
||||||
|
if data[2] == self.config.stored.Immersifier.FIXED_TOTAL:
|
||||||
|
immersifier = data
|
||||||
|
|
||||||
|
if stamina[2] > 0 and immersifier[2] > 0:
|
||||||
|
break
|
||||||
|
|
||||||
|
stamina = stamina[0]
|
||||||
|
immersifier = immersifier[0]
|
||||||
|
logger.attr('TrailblazePower', stamina)
|
||||||
|
logger.attr('Imersifier', immersifier)
|
||||||
|
with self.config.multi_set():
|
||||||
|
self.config.stored.TrailblazePower.value = stamina
|
||||||
|
self.config.stored.Immersifier.value = immersifier
|
||||||
|
|
||||||
|
def claim_domain_reward(
|
||||||
|
self,
|
||||||
|
use_trailblaze_power=False,
|
||||||
|
use_immersifier=True,
|
||||||
|
skip_first_screenshot=True
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Pages:
|
||||||
|
in: page_main, DUNGEON_COMBAT_INTERACT, near immersifier
|
||||||
|
"""
|
||||||
|
logger.hr('Claim domain reward', level=2)
|
||||||
|
logger.info(f'use_trailblaze_power={use_trailblaze_power}, use_immersifier={use_immersifier}')
|
||||||
|
if not use_trailblaze_power and not use_immersifier:
|
||||||
|
return
|
||||||
|
|
||||||
|
confirm = Timer(0.6, count=2).start()
|
||||||
|
while 1:
|
||||||
|
if skip_first_screenshot:
|
||||||
|
skip_first_screenshot = False
|
||||||
|
else:
|
||||||
|
self.device.screenshot()
|
||||||
|
|
||||||
|
if self.is_in_main():
|
||||||
|
if confirm.reached():
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
confirm.reset()
|
||||||
|
|
||||||
|
if self.handle_combat_interact():
|
||||||
|
self.interval_clear(USE_STAMINA)
|
||||||
|
confirm.reset()
|
||||||
|
continue
|
||||||
|
if self.handle_reward():
|
||||||
|
self.interval_clear(USE_STAMINA)
|
||||||
|
confirm.reset()
|
||||||
|
continue
|
||||||
|
if self.appear(REWARD_CLOSE, interval=2):
|
||||||
|
self._reward_update_stamina()
|
||||||
|
if use_immersifier and self.config.stored.Immersifier.value > 0:
|
||||||
|
self.device.click(USE_IMMERSIFIER)
|
||||||
|
self.interval_reset(USE_STAMINA)
|
||||||
|
self.interval_clear(GET_REWARD)
|
||||||
|
confirm.reset()
|
||||||
|
continue
|
||||||
|
elif use_trailblaze_power and self.config.stored.TrailblazePower.value >= 40:
|
||||||
|
self.device.click(USE_STAMINA)
|
||||||
|
self.interval_reset(USE_STAMINA)
|
||||||
|
self.interval_clear(GET_REWARD)
|
||||||
|
confirm.reset()
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
logger.info('Cannot claim more rewards')
|
||||||
|
self.device.click(REWARD_CLOSE)
|
||||||
|
self.interval_reset(USE_STAMINA)
|
||||||
|
confirm.reset()
|
||||||
|
continue
|
||||||
|
|
||||||
|
def can_claim_domain_reward(
|
||||||
|
self,
|
||||||
|
use_trailblaze_power=False,
|
||||||
|
use_immersifier=True
|
||||||
|
):
|
||||||
|
if not use_trailblaze_power and not use_immersifier:
|
||||||
|
return False
|
||||||
|
if use_immersifier and self.config.stored.Immersifier.value >= 0:
|
||||||
|
return True
|
||||||
|
if use_trailblaze_power and self.config.stored.TrailblazePower.predict_current() >= 40:
|
||||||
|
return True
|
||||||
|
return False
|
@ -11,10 +11,11 @@ from tasks.rogue.bleesing.blessing import RogueBlessingSelector
|
|||||||
from tasks.rogue.bleesing.bonus import RogueBonusSelector
|
from tasks.rogue.bleesing.bonus import RogueBonusSelector
|
||||||
from tasks.rogue.bleesing.curio import RogueCurioSelector
|
from tasks.rogue.bleesing.curio import RogueCurioSelector
|
||||||
from tasks.rogue.event.event import RogueEvent
|
from tasks.rogue.event.event import RogueEvent
|
||||||
|
from tasks.rogue.event.reward import RogueReward
|
||||||
from tasks.rogue.route.exit import RogueExit
|
from tasks.rogue.route.exit import RogueExit
|
||||||
|
|
||||||
|
|
||||||
class RouteBase(RouteBase_, RogueExit, RogueEvent):
|
class RouteBase(RouteBase_, RogueExit, RogueEvent, RogueReward):
|
||||||
registered_domain_exit = None
|
registered_domain_exit = None
|
||||||
|
|
||||||
def combat_expected_end(self):
|
def combat_expected_end(self):
|
||||||
@ -174,14 +175,16 @@ class RouteBase(RouteBase_, RogueExit, RogueEvent):
|
|||||||
Get reward of the DomainElite and DomainBoss
|
Get reward of the DomainElite and DomainBoss
|
||||||
"""
|
"""
|
||||||
logger.hr('Clear reward', level=1)
|
logger.hr('Clear reward', level=1)
|
||||||
|
use_trailblaze_power = 'trailblaze' in self.config.RogueWorld_ImmersionReward
|
||||||
|
use_immersifier = 'immersifier' in self.config.RogueWorld_ImmersionReward
|
||||||
|
|
||||||
# TODO: Skip if user don't want rewards or stamina exhausted
|
if self.can_claim_domain_reward(use_trailblaze_power=use_trailblaze_power, use_immersifier=use_immersifier):
|
||||||
return []
|
logger.info('Can claim domain reward')
|
||||||
|
result = self.goto(*waypoints)
|
||||||
result = self.goto(*waypoints)
|
self.claim_domain_reward(use_trailblaze_power=use_trailblaze_power, use_immersifier=use_immersifier)
|
||||||
|
else:
|
||||||
# TODO: Get reward
|
logger.info('Cannot claim more rewards')
|
||||||
pass
|
result = []
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user