Add: Joint Battle Mystery Investigation (raid_20220127)

This commit is contained in:
LmeSzinc 2022-01-27 18:49:12 +08:00
parent 889836a40b
commit 7856c5eba5
20 changed files with 124 additions and 87 deletions

View File

@ -204,6 +204,10 @@ class AzurLaneAutoScript:
CampaignWarArchives(config=self.config, device=self.device).run(
name=self.config.Campaign_Name, folder=self.config.Campaign_Event, mode=self.config.Campaign_Mode)
def raid_daily(self):
from module.raid.daily import RaidDaily
RaidDaily(config=self.config, device=self.device).run()
def event_ab(self):
from module.event.campaign_ab import CampaignAB
CampaignAB(config=self.config, device=self.device).run()

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -78,4 +78,5 @@ To add a new event, add a new row in here, and run `python -m dev_tools.event_ex
| 20211130 | event 20211125 cn | World-spanning Arclight | - | - | - | 交匯世界的弧光 |
| 20211214 | event 20200603 cn | Stars of the Shimmering Fjord | - | - | - | 峽灣間的反擊 |
| 20211229 | event 20211229 cn | Tower of Transcendence | 逆转彩虹之塔 | Tower of Transcendence | 遡望せし虹彩の塔 | - |
| 20211230 | event 20201229 cn | Inverted Orthant | - | - | - | 負象限作戰 |
| 20211230 | event 20201229 cn | Inverted Orthant | - | - | - | 負象限作戰 |
| 20220127 | raid 20220127 | Joint Battle Mystery Investigation | 演习神秘事件调查 | Joint Battle Mystery Investigation | 秘密事件調査 | - |

View File

@ -241,9 +241,6 @@
"Fleet2Control": "prevent_yellow_face",
"Fleet2Recover": "not_in_dormitory",
"Fleet2Oath": false
},
"EnemyPriority": {
"EnemyScaleBalanceWeight": "default_mode"
}
},
"C72MysteryFarming": {

View File

@ -1012,13 +1012,14 @@
"type": "select",
"value": "campaign_main",
"option": [
"raid_20220127",
"raid_20210708",
"raid_20200624"
],
"tw": "raid_20210708",
"cn": "raid_20210708",
"en": "raid_20210708",
"jp": "raid_20210708"
"cn": "raid_20220127",
"en": "raid_20220127",
"jp": "raid_20220127",
"tw": "raid_20210708"
},
"Mode": {
"type": "disable",
@ -1051,7 +1052,7 @@
},
"StopCondition": {
"RunCount": {
"type": "disable",
"type": "input",
"value": 0
},
"OilLimit": {
@ -1155,17 +1156,6 @@
"type": "checkbox",
"value": false
}
},
"EnemyPriority": {
"EnemyScaleBalanceWeight": {
"type": "select",
"value": "default_mode",
"option": [
"default_mode",
"S3_enemy_first",
"S1_enemy_first"
]
}
}
},
"C72MysteryFarming": {
@ -5297,13 +5287,14 @@
"type": "select",
"value": "campaign_main",
"option": [
"raid_20220127",
"raid_20210708",
"raid_20200624"
],
"tw": "raid_20210708",
"cn": "raid_20210708",
"en": "raid_20210708",
"jp": "raid_20210708"
"cn": "raid_20220127",
"en": "raid_20220127",
"jp": "raid_20220127",
"tw": "raid_20210708"
},
"Mode": {
"type": "disable",

View File

@ -32,7 +32,6 @@ Raid:
Use2xBook: false
AmbushEvade: true
StopCondition:
RunCount: 0
MapAchievement: non_stop
StageIncrease: false
GetNewShip: false

View File

@ -40,7 +40,6 @@ Raid:
- Campaign
- StopCondition
- Emotion
- EnemyPriority
C72MysteryFarming:
- Scheduler
- C72MysteryFarming

View File

@ -430,6 +430,7 @@
"name": "Event Name",
"help": "Automatically selects to the latest event",
"campaign_main": "campaign_main",
"raid_20220127": "Joint Battle Mystery Investigation",
"event_20201229_cn": "Inverted Orthant",
"event_20211229_cn": "Tower of Transcendence",
"event_20200603_cn": "峡湾间的反击",

View File

@ -430,6 +430,7 @@
"name": "Campaign.Event.name",
"help": "Campaign.Event.help",
"campaign_main": "campaign_main",
"raid_20220127": "秘密事件調査",
"event_20201229_cn": "虚畳なりし限象",
"event_20211229_cn": "遡望せし虹彩の塔",
"event_20200603_cn": "峡湾間の反撃",

View File

@ -430,6 +430,7 @@
"name": "活动名称",
"help": "自动选择至最新的活动",
"campaign_main": "主线图",
"raid_20220127": "演习神秘事件调查",
"event_20201229_cn": "负象限作战",
"event_20211229_cn": "逆转彩虹之塔",
"event_20200603_cn": "峡湾间的反击",

View File

@ -430,6 +430,7 @@
"name": "活動名稱",
"help": "自動選擇至最新的活動圖",
"campaign_main": "主線圖",
"raid_20220127": "Joint Battle Mystery Investigation",
"event_20201229_cn": "負象限作戰",
"event_20211229_cn": "Tower of Transcendence",
"event_20200603_cn": "峽灣間的反擊",

View File

@ -4,6 +4,12 @@ from module.base.template import Template
# This file was automatically generated by dev_tools/button_extract.py.
# Don't modify it manually.
BRISTOL_OCR_REMAIN_EASY = Button(area={'cn': (1135, 536, 1195, 554), 'en': (1135, 536, 1195, 554), 'jp': (1135, 536, 1195, 554), 'tw': (1135, 536, 1195, 554)}, color={'cn': (89, 137, 227), 'en': (89, 137, 227), 'jp': (89, 137, 227), 'tw': (89, 137, 227)}, button={'cn': (1135, 536, 1195, 554), 'en': (1135, 536, 1195, 554), 'jp': (1135, 536, 1195, 554), 'tw': (1135, 536, 1195, 554)}, file={'cn': './assets/cn/raid/BRISTOL_OCR_REMAIN_EASY.png', 'en': './assets/cn/raid/BRISTOL_OCR_REMAIN_EASY.png', 'jp': './assets/cn/raid/BRISTOL_OCR_REMAIN_EASY.png', 'tw': './assets/cn/raid/BRISTOL_OCR_REMAIN_EASY.png'})
BRISTOL_OCR_REMAIN_HARD = Button(area={'cn': (1163, 292, 1223, 310), 'en': (1163, 292, 1223, 310), 'jp': (1163, 292, 1223, 310), 'tw': (1163, 292, 1223, 310)}, color={'cn': (95, 137, 212), 'en': (95, 137, 212), 'jp': (95, 137, 212), 'tw': (95, 137, 212)}, button={'cn': (1163, 292, 1223, 310), 'en': (1163, 292, 1223, 310), 'jp': (1163, 292, 1223, 310), 'tw': (1163, 292, 1223, 310)}, file={'cn': './assets/cn/raid/BRISTOL_OCR_REMAIN_HARD.png', 'en': './assets/cn/raid/BRISTOL_OCR_REMAIN_HARD.png', 'jp': './assets/cn/raid/BRISTOL_OCR_REMAIN_HARD.png', 'tw': './assets/cn/raid/BRISTOL_OCR_REMAIN_HARD.png'})
BRISTOL_OCR_REMAIN_NORMAL = Button(area={'cn': (1089, 414, 1148, 432), 'en': (1089, 414, 1148, 432), 'jp': (1089, 414, 1148, 432), 'tw': (1089, 414, 1148, 432)}, color={'cn': (93, 138, 222), 'en': (93, 138, 222), 'jp': (93, 138, 222), 'tw': (93, 138, 222)}, button={'cn': (1089, 414, 1148, 432), 'en': (1089, 414, 1148, 432), 'jp': (1089, 414, 1148, 432), 'tw': (1089, 414, 1148, 432)}, file={'cn': './assets/cn/raid/BRISTOL_OCR_REMAIN_NORMAL.png', 'en': './assets/cn/raid/BRISTOL_OCR_REMAIN_NORMAL.png', 'jp': './assets/cn/raid/BRISTOL_OCR_REMAIN_NORMAL.png', 'tw': './assets/cn/raid/BRISTOL_OCR_REMAIN_NORMAL.png'})
BRISTOL_RAID_EASY = Button(area={'cn': (1151, 490, 1203, 528), 'en': (1151, 490, 1203, 528), 'jp': (1151, 490, 1203, 528), 'tw': (1151, 490, 1203, 528)}, color={'cn': (141, 164, 177), 'en': (141, 164, 177), 'jp': (141, 164, 177), 'tw': (141, 164, 177)}, button={'cn': (1151, 490, 1203, 528), 'en': (1151, 490, 1203, 528), 'jp': (1151, 490, 1203, 528), 'tw': (1151, 490, 1203, 528)}, file={'cn': './assets/cn/raid/BRISTOL_RAID_EASY.png', 'en': './assets/cn/raid/BRISTOL_RAID_EASY.png', 'jp': './assets/cn/raid/BRISTOL_RAID_EASY.png', 'tw': './assets/cn/raid/BRISTOL_RAID_EASY.png'})
BRISTOL_RAID_HARD = Button(area={'cn': (1167, 246, 1220, 285), 'en': (1167, 246, 1220, 285), 'jp': (1167, 246, 1220, 285), 'tw': (1167, 246, 1220, 285)}, color={'cn': (136, 160, 173), 'en': (136, 160, 173), 'jp': (136, 160, 173), 'tw': (136, 160, 173)}, button={'cn': (1167, 246, 1220, 285), 'en': (1167, 246, 1220, 285), 'jp': (1167, 246, 1220, 285), 'tw': (1167, 246, 1220, 285)}, file={'cn': './assets/cn/raid/BRISTOL_RAID_HARD.png', 'en': './assets/cn/raid/BRISTOL_RAID_HARD.png', 'jp': './assets/cn/raid/BRISTOL_RAID_HARD.png', 'tw': './assets/cn/raid/BRISTOL_RAID_HARD.png'})
BRISTOL_RAID_NORMAL = Button(area={'cn': (1098, 367, 1150, 404), 'en': (1098, 367, 1150, 404), 'jp': (1098, 367, 1150, 404), 'tw': (1098, 367, 1150, 404)}, color={'cn': (129, 152, 165), 'en': (129, 152, 165), 'jp': (129, 152, 165), 'tw': (129, 152, 165)}, button={'cn': (1098, 367, 1150, 404), 'en': (1098, 367, 1150, 404), 'jp': (1098, 367, 1150, 404), 'tw': (1098, 367, 1150, 404)}, file={'cn': './assets/cn/raid/BRISTOL_RAID_NORMAL.png', 'en': './assets/cn/raid/BRISTOL_RAID_NORMAL.png', 'jp': './assets/cn/raid/BRISTOL_RAID_NORMAL.png', 'tw': './assets/cn/raid/BRISTOL_RAID_NORMAL.png'})
ESSEX_OCR_REMAIN_EASY = Button(area={'cn': (1073, 501, 1092, 520), 'en': (1073, 501, 1092, 520), 'jp': (1073, 501, 1092, 520), 'tw': (1073, 501, 1092, 520)}, color={'cn': (99, 133, 255), 'en': (99, 133, 255), 'jp': (99, 133, 255), 'tw': (99, 133, 255)}, button={'cn': (1073, 501, 1092, 520), 'en': (1073, 501, 1092, 520), 'jp': (1073, 501, 1092, 520), 'tw': (1073, 501, 1092, 520)}, file={'cn': './assets/cn/raid/ESSEX_OCR_REMAIN_EASY.png', 'en': './assets/en/raid/ESSEX_OCR_REMAIN_EASY.png', 'jp': './assets/jp/raid/ESSEX_OCR_REMAIN_EASY.png', 'tw': './assets/tw/raid/ESSEX_OCR_REMAIN_EASY.png'})
ESSEX_OCR_REMAIN_HARD = Button(area={'cn': (1090, 271, 1109, 290), 'en': (1090, 271, 1109, 290), 'jp': (1090, 271, 1109, 290), 'tw': (1090, 271, 1109, 290)}, color={'cn': (100, 132, 255), 'en': (100, 132, 255), 'jp': (100, 132, 255), 'tw': (100, 132, 255)}, button={'cn': (1090, 271, 1109, 290), 'en': (1090, 271, 1109, 290), 'jp': (1090, 271, 1109, 290), 'tw': (1090, 271, 1109, 290)}, file={'cn': './assets/cn/raid/ESSEX_OCR_REMAIN_HARD.png', 'en': './assets/en/raid/ESSEX_OCR_REMAIN_HARD.png', 'jp': './assets/jp/raid/ESSEX_OCR_REMAIN_HARD.png', 'tw': './assets/tw/raid/ESSEX_OCR_REMAIN_HARD.png'})
ESSEX_OCR_REMAIN_NORMAL = Button(area={'cn': (1051, 385, 1070, 404), 'en': (1051, 385, 1070, 404), 'jp': (1051, 385, 1070, 404), 'tw': (1051, 385, 1070, 404)}, color={'cn': (99, 132, 255), 'en': (99, 132, 255), 'jp': (99, 132, 255), 'tw': (99, 132, 255)}, button={'cn': (1051, 385, 1070, 404), 'en': (1051, 385, 1070, 404), 'jp': (1051, 385, 1070, 404), 'tw': (1051, 385, 1070, 404)}, file={'cn': './assets/cn/raid/ESSEX_OCR_REMAIN_NORMAL.png', 'en': './assets/en/raid/ESSEX_OCR_REMAIN_NORMAL.png', 'jp': './assets/jp/raid/ESSEX_OCR_REMAIN_NORMAL.png', 'tw': './assets/tw/raid/ESSEX_OCR_REMAIN_NORMAL.png'})

View File

@ -1,10 +1,22 @@
import re
from module.base.filter import Filter
from module.logger import logger
from module.raid.raid import raid_ocr
from module.raid.run import RaidRun
from module.ui.page import page_raid
RECORD_OPTION = ('DailyRecord', 'raid')
RECORD_SINCE = (0,)
class RaidStage:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
STAGES = ['easy', 'normal', 'hard']
STAGE_FILTER = Filter(regex=re.compile('(\w+)'), attr=['name'])
class RaidDaily(RaidRun):
@ -16,39 +28,28 @@ class RaidDaily(RaidRun):
Returns:
int:
"""
ocr = raid_ocr(raid=self.config.RAID_DAILY_NAME, mode=mode)
ocr = raid_ocr(raid=self.config.Campaign_Event, mode=mode)
remain, _, _ = ocr.ocr(self.device.image)
logger.attr(f'{mode.capitalize()} Remain', remain)
return remain
def record_executed_since(self):
return self.config.record_executed_since(option=RECORD_OPTION, since=RECORD_SINCE)
def record_save(self):
return self.config.record_save(option=RECORD_OPTION)
def run(self, name=''):
"""
Args:
name (str): Raid name, such as 'raid_20200624'
"""
self.reward_backup_daily_reward_settings()
name = name if name else self.config.RAID_DAILY_NAME
name = name if name else self.config.Campaign_Event
stages = [RaidStage(name) for name in STAGES]
STAGE_FILTER.load(self.config.RaidDaily_StageFilter)
stages = STAGE_FILTER.apply(stages)
self.ui_ensure(page_raid)
if self.config.RAID_HARD:
remain = self.get_remain(mode='hard')
for stage in stages:
mode = stage.name
logger.hr(mode, level=1)
remain = self.get_remain(mode=mode)
if remain > 0:
super().run(name=name, mode='hard', total=remain)
super().run(name=name, mode=mode, total=remain)
if self.config.RAID_NORMAL:
remain = self.get_remain(mode='normal')
if remain > 0:
super().run(name=name, mode='normal', total=remain)
if self.config.RAID_EASY:
remain = self.get_remain(mode='easy')
if remain > 0:
super().run(name=name, mode='easy', total=remain)
self.reward_recover_daily_reward_settings()
self.config.task_delay(server_update=True)

View File

@ -34,6 +34,8 @@ def raid_name_shorten(name):
return 'ESSEX'
elif name == 'raid_20210708':
return 'SURUGA'
elif name == 'raid_20220127':
return 'BRISTOL'
else:
raise ScriptError(f'Unknown raid name: {name}')
@ -71,6 +73,8 @@ def raid_ocr(raid, mode):
return RaidCounter(button, letter=(57, 52, 255), threshold=128)
elif raid == 'SURUGA':
return RaidCounter(button, letter=(49, 48, 49), threshold=128)
elif raid == 'BRISTOL':
return RaidCounter(button, letter=(214, 231, 219), threshold=128)
except KeyError:
raise ScriptError(f'Raid entrance asset not exists: {key}')
@ -88,7 +92,7 @@ class Raid(MapOperation, Combat):
oil_checked = False
if emotion_reduce:
self.emotion.wait(fleet=fleet_index)
self.emotion.wait(fleet_index)
while 1:
self.device.screenshot()
@ -96,13 +100,13 @@ class Raid(MapOperation, Combat):
if self.appear(BATTLE_PREPARATION):
if self.handle_combat_automation_set(auto=auto):
continue
if not oil_checked and self.config.STOP_IF_OIL_LOWER_THAN:
if not oil_checked and self.config.StopCondition_OilLimit:
self.ensure_combat_oil_loaded()
oil = OCR_OIL.ocr(self.device.image)
oil_checked = True
if oil < self.config.STOP_IF_OIL_LOWER_THAN:
if oil < self.config.StopCondition_OilLimit:
logger.hr('Triggered oil limit')
raise OilExhausted()
raise OilExhausted
if self.handle_raid_ticket_use():
continue
if self.handle_retirement():
@ -128,7 +132,7 @@ class Raid(MapOperation, Combat):
bool: If clicked.
"""
if self.appear(TICKET_USE_CONFIRM, offset=(30, 30), interval=1):
if self.config.RAID_USE_TICKET:
if self.config.Raid_UseTicket:
self.device.click(TICKET_USE_CONFIRM)
else:
self.device.click(TICKET_USE_CANCEL)
@ -136,11 +140,23 @@ class Raid(MapOperation, Combat):
return False
def raid_enter(self, mode, raid):
logger.hr('Raid Enter')
def raid_enter(self, mode, raid, skip_first_screenshot=True):
"""
Args:
mode:
raid:
skip_first_screenshot:
Pages:
in: page_raid
out: BATTLE_PREPARATION
"""
entrance = raid_entrance(raid=raid, mode=mode)
while 1:
self.device.screenshot()
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if self.appear_then_click(entrance, offset=(10, 10), interval=5):
continue
@ -155,7 +171,18 @@ class Raid(MapOperation, Combat):
return self.appear(RAID_CHECK, offset=(30, 30))
def raid_execute_once(self, mode, raid):
"""
Args:
mode:
raid:
Returns:
in: page_raid
out: page_raid
"""
logger.hr('Raid Execute')
self.raid_enter(mode=mode, raid=raid)
self.config.override(Campaign_Name=f'{raid}_{mode}')
self.combat(balance_hp=False, expected_end=self.raid_expected_end)
logger.hr('Raid End')

View File

@ -1,11 +1,27 @@
from module.campaign.run import CampaignRun
from module.exception import ScriptEnd
from module.exception import ScriptEnd, ScriptError
from module.logger import logger
from module.raid.raid import Raid, OilExhausted
from module.ui.page import page_raid
class RaidRun(Raid, CampaignRun):
class RaidRun(Raid):
run_count: int
run_limit: int
def triggered_stop_condition(self):
"""
Returns:
bool: If triggered a stop condition.
"""
# Run count limit
if self.run_limit and self.config.StopCondition_RunCount <= 0:
logger.hr('Triggered stop condition: Run count')
self.config.StopCondition_RunCount = 0
self.config.Scheduler_Enable = False
return True
return False
def run(self, name='', mode='', total=0):
"""
Args:
@ -13,36 +29,27 @@ class RaidRun(Raid, CampaignRun):
mode (str): Raid mode, such as 'hard', 'normal', 'easy'
total (int): Total run count
"""
logger.hr('Raid', level=1)
name = name if name else self.config.RAID_NAME
mode = mode if mode else self.config.RAID_MODE
name = name if name else self.config.Campaign_Event
mode = mode if mode else self.config.Raid_Mode
if not name or not mode:
logger.warning(f'RaidRun arguments unfilled. name={name}, mode={mode}')
self.campaign = self # A trick to call CampaignRun
self.campaign_name_set(f'{name}_{mode}')
self.device.screenshot()
raise ScriptError(f'RaidRun arguments unfilled. name={name}, mode={mode}')
self.run_count = 0
self.run_limit = self.config.StopCondition_RunCount
while 1:
if self.handle_app_restart():
pass
if self.handle_reward():
pass
# End
if total and self.run_count == total:
break
# Log
if self.config.STOP_IF_COUNT_GREATER_THAN > 0:
logger.info(f'Count: [{self.run_count}/{self.config.STOP_IF_COUNT_GREATER_THAN}]')
logger.hr(f'{name}_{mode}', level=2)
if self.config.StopCondition_RunCount > 0:
logger.info(f'Count remain: {self.config.StopCondition_RunCount}')
else:
logger.info(f'Count: [{self.run_count}]')
logger.info(f'Count: {self.run_count}')
# End
if self.triggered_stop_condition(oil_check=False):
if self.triggered_stop_condition():
break
# UI ensure
@ -50,9 +57,10 @@ class RaidRun(Raid, CampaignRun):
# Run
try:
self.raid_execute_once(mode=mode if mode else self.config.RAID_MODE, raid=name)
self.raid_execute_once(mode=mode, raid=name)
except OilExhausted:
self.ui_goto_main()
logger.hr('Triggered stop condition: Oil limit')
self.config.task_delay(minute=(120, 240))
break
except ScriptEnd as e:
logger.hr('Script end')
@ -61,8 +69,8 @@ class RaidRun(Raid, CampaignRun):
# After run
self.run_count += 1
if self.config.STOP_IF_COUNT_GREATER_THAN > 0:
count = self.config.STOP_IF_COUNT_GREATER_THAN - self.run_count
count = 0 if count < 0 else count
self.config.config.set('Setting', 'if_count_greater_than', str(count))
self.config.save()
if self.config.StopCondition_RunCount:
self.config.StopCondition_RunCount -= 1
# Scheduler
if self.config.task_switched():
self.config.task_stop()