Add: hazard 1 leveling

This commit is contained in:
SarContDeli 2022-11-11 14:27:15 +08:00
parent 26aa797a72
commit 1f38e92e02
31 changed files with 553 additions and 62 deletions

View File

@ -308,6 +308,10 @@ class AzurLaneAutoScript:
from module.campaign.os_run import OSCampaignRun
OSCampaignRun(config=self.config, device=self.device).opsi_meowfficer_farming()
def opsi_hazard1_leveling(self):
from module.campaign.os_run import OSCampaignRun
OSCampaignRun(config=self.config, device=self.device).opsi_hazard1_leveling()
def main(self):
from module.campaign.run import CampaignRun
CampaignRun(config=self.config, device=self.device).run(

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -1550,7 +1550,7 @@
"Command": "OpsiAbyssal",
"SuccessInterval": 60,
"FailureInterval": 60,
"ServerUpdate": "00:00"
"ServerUpdate": "00:00, 12:00"
},
"OpsiAbyssal": {
"ForceRun": false
@ -1585,7 +1585,7 @@
"ServerUpdate": "00:00"
},
"OpsiMeowfficerFarming": {
"ActionPointPreserve": 500,
"ActionPointPreserve": 1000,
"HazardLevel": 5,
"TargetZone": 0
},
@ -1594,6 +1594,24 @@
"Submarine": false
}
},
"OpsiHazard1Leveling": {
"Scheduler": {
"Enable": false,
"NextRun": "2020-01-01 00:00:00",
"Command": "OpsiHazard1Leveling",
"SuccessInterval": 30,
"FailureInterval": 60,
"ServerUpdate": "00:00"
},
"OpsiHazard1Leveling": {
"StrategySearch": true,
"TargetZone": 0
},
"OpsiFleet": {
"Fleet": 1,
"Submarine": false
}
},
"Daemon": {
"Daemon": {
"EnterMap": true

View File

@ -54,6 +54,26 @@ class OSCampaignRun(OSMapOperation):
logger.info('Just less than 1 day to OpSi reset, delay 2.5 hours')
self.config.task_delay(minute=150, server_update=True)
def opsi_hazard1_leveling(self):
self.config.override(
OpsiGeneral_AkashiShopFilter='ActionPoint'
)
self.config.cross_set(keys='OpsiMeowfficerFarming.Scheduler.Enable', value=True)
if self.config.cross_get(
keys='OpsiMeowfficerFarming.OpsiMeowfficerFarming.ActionPointPreserve',
default=0
) < 1000:
self.config.cross_set(
keys='OpsiMeowfficerFarming.OpsiMeowfficerFarming.ActionPointPreserve',
value=1000
)
self.load_campaign()
try:
self.campaign.os_hazard1_leveling()
except ActionPointLimit:
self.config.task_delay(server_update=True)
def opsi_obscure(self):
self.load_campaign()
try:

View File

@ -3281,10 +3281,10 @@
"event_20200227_cn"
],
"display": "disabled",
"cn": "event_20201229_cn",
"en": "event_20201229_cn",
"jp": "event_20201229_cn",
"tw": "event_20211111_cn"
"tw": "event_20211111_cn",
"cn": "event_20220915_cn",
"en": "event_20220915_cn",
"jp": "event_20220915_cn"
},
"Mode": {
"type": "select",
@ -7772,7 +7772,7 @@
},
"ServerUpdate": {
"type": "input",
"value": "00:00",
"value": "00:00, 12:00",
"display": "hide"
}
},
@ -7869,7 +7869,7 @@
"OpsiMeowfficerFarming": {
"ActionPointPreserve": {
"type": "input",
"value": 500
"value": 1000
},
"HazardLevel": {
"type": "select",
@ -7904,6 +7904,71 @@
}
}
},
"OpsiHazard1Leveling": {
"Scheduler": {
"Enable": {
"type": "checkbox",
"value": false
},
"NextRun": {
"type": "datetime",
"value": "2020-01-01 00:00:00",
"validate": "datetime"
},
"Command": {
"type": "input",
"value": "OpsiHazard1Leveling",
"display": "hide"
},
"SuccessInterval": {
"type": "input",
"value": 30,
"display": "hide"
},
"FailureInterval": {
"type": "input",
"value": 60,
"display": "hide"
},
"ServerUpdate": {
"type": "input",
"value": "00:00",
"display": "hide"
}
},
"OpsiHazard1Leveling": {
"StrategySearch": {
"type": "checkbox",
"value": true
},
"TargetZone": {
"type": "select",
"value": 0,
"option": [
0,
44,
22
]
}
},
"OpsiFleet": {
"Fleet": {
"type": "select",
"value": 1,
"option": [
1,
2,
3,
4
]
},
"Submarine": {
"type": "checkbox",
"value": false,
"display": "hide"
}
}
},
"Daemon": {
"Daemon": {
"EnterMap": {

View File

@ -569,12 +569,17 @@ OpsiAbyssal:
OpsiStronghold:
ForceRun: false
OpsiMeowfficerFarming:
ActionPointPreserve: 500
ActionPointPreserve: 1000
HazardLevel:
value: 5
option: [3, 4, 5, 6, 10]
TargetZone:
value: 0
OpsiHazard1Leveling:
StrategySearch: True
TargetZone:
value: 0
option: [0, 44, 22]
# ==================== Tools ====================

View File

@ -57,7 +57,8 @@
"OpsiObscure",
"OpsiAbyssal",
"OpsiStronghold",
"OpsiMeowfficerFarming"
"OpsiMeowfficerFarming",
"OpsiHazard1Leveling"
],
"Tool": [
"Daemon",

View File

@ -350,7 +350,7 @@ OpsiAbyssal:
Scheduler:
SuccessInterval: 60
FailureInterval: 60
ServerUpdate: 00:00
ServerUpdate: 00:00, 12:00
OpsiStronghold:
Scheduler:
SuccessInterval: 60
@ -361,3 +361,10 @@ OpsiMeowfficerFarming:
SuccessInterval: 30
FailureInterval: 30
ServerUpdate: 00:00
OpsiHazard1Leveling:
Scheduler:
SuccessInterval: 30
FailureInterval: 60
ServerUpdate: 00:00
OpsiFleet:
Submarine: false

View File

@ -263,6 +263,10 @@ OpsiMeowfficerFarming:
- Scheduler
- OpsiMeowfficerFarming
- OpsiFleet
OpsiHazard1Leveling:
- Scheduler
- OpsiHazard1Leveling
- OpsiFleet
# ==================== Tool ====================

View File

@ -379,10 +379,14 @@ class GeneratedConfig:
OpsiStronghold_ForceRun = False
# Group `OpsiMeowfficerFarming`
OpsiMeowfficerFarming_ActionPointPreserve = 500
OpsiMeowfficerFarming_ActionPointPreserve = 1000
OpsiMeowfficerFarming_HazardLevel = 5 # 3, 4, 5, 6, 10
OpsiMeowfficerFarming_TargetZone = 0
# Group `OpsiHazard1Leveling`
OpsiHazard1Leveling_StrategySearch = True
OpsiHazard1Leveling_TargetZone = 0 # 0, 44, 22
# Group `Daemon`
Daemon_EnterMap = True

View File

@ -24,6 +24,7 @@ class ManualConfig:
> Event > Event2 > Raid > Main > Main2 > Main3
> OpsiMeowfficerFarming
> GemsFarming
> OpsiHazard1Leveling
"""
"""

View File

@ -218,6 +218,10 @@
"name": "Meowfficer Farming",
"help": ""
},
"OpsiHazard1Leveling": {
"name": "CL1 Leveling",
"help": ""
},
"Daemon": {
"name": "Normal Semi-auto",
"help": ""
@ -2098,7 +2102,7 @@
},
"ActionPointPreserve": {
"name": "Keep X Amount of AP",
"help": "Stops task if total AP (including AP boxes in inventory) is below this number, 500 is recommended\nThis value will be auto reduced to 300 at 3 days before OpSi reset and to 0 at day before reset"
"help": "Stops task if total AP (including AP boxes in inventory) is below this number, 1000 is recommended\nThis value will be auto reduced to 300 at 3 days before OpSi reset, or 500 if CL1 leveling enabled, and to 0 at day before reset"
},
"HazardLevel": {
"name": "Target Zone Hazard Level",
@ -2114,6 +2118,23 @@
"help": "Supports either Zone ID or Name in CN/EN/JP/TW, i.e. \"51\", \"NA Ocean SE Sector E\"\nIf specified, Alas will loop on this same zone after each clear\nUse default value 0 or clear the field to remove the specification\nZone information can be acquired from <./module/os/map_data.py>"
}
},
"OpsiHazard1Leveling": {
"_info": {
"name": "CL1 leveling",
"help": "OpsiHazard1Leveling._info.help"
},
"StrategySearch": {
"name": "Strategic Search",
"help": ""
},
"TargetZone": {
"name": "Target Zone ID",
"help": "Only attack target zone, which can be used to obtain world achievement stars or avoid the event that the map cannot be refreshed due to game bug",
"0": "No Specification",
"44": "44 | West Continental Shelf D",
"22": "22 | NA Ocean SW Sector B"
}
},
"Daemon": {
"_info": {
"name": "Semi-auto Clicking",

View File

@ -218,6 +218,10 @@
"name": "Task.OpsiMeowfficerFarming.name",
"help": "Task.OpsiMeowfficerFarming.help"
},
"OpsiHazard1Leveling": {
"name": "Task.OpsiHazard1Leveling.name",
"help": "Task.OpsiHazard1Leveling.help"
},
"Daemon": {
"name": "Task.Daemon.name",
"help": "Task.Daemon.help"
@ -585,7 +589,6 @@
"name": "Campaign.Event.name",
"help": "Campaign.Event.help",
"campaign_main": "campaign_main",
"event_20201229_cn": "虚畳なりし限象(復刻)",
"event_20211111_cn": "燈火のシニエ",
"raid_20221027": "戦えロイヤルメイド隊3rd",
"event_20210121_cn": "悲歎せし焔海の詩(復刻)",
@ -2114,6 +2117,23 @@
"help": "OpsiMeowfficerFarming.TargetZone.help"
}
},
"OpsiHazard1Leveling": {
"_info": {
"name": "OpsiHazard1Leveling._info.name",
"help": "OpsiHazard1Leveling._info.help"
},
"StrategySearch": {
"name": "OpsiHazard1Leveling.StrategySearch.name",
"help": "OpsiHazard1Leveling.StrategySearch.help"
},
"TargetZone": {
"name": "OpsiHazard1Leveling.TargetZone.name",
"help": "OpsiHazard1Leveling.TargetZone.help",
"0": "0",
"44": "44",
"22": "22"
}
},
"Daemon": {
"_info": {
"name": "Daemon._info.name",

View File

@ -218,6 +218,10 @@
"name": "短猫相接",
"help": ""
},
"OpsiHazard1Leveling": {
"name": "侵蚀1练级",
"help": ""
},
"Daemon": {
"name": "半自动点击",
"help": ""
@ -2098,7 +2102,7 @@
},
"ActionPointPreserve": {
"name": "保留 X 点行动力",
"help": "行动力低于 X 后停止自动打开行动力箱子X 包含箱子中的行动力,建议保留 500 点行动力\n这个值将在大世界重置前3天自动减少至300点并在最后一天自动减少至0点"
"help": "行动力低于 X 后停止自动打开行动力箱子X 包含箱子中的行动力,建议保留1000行动力给侵蚀1练级\n这个值将在大世界重置前3天自动减少至200点如果启用侵蚀1练级则改为500点并在最后一天自动减少至0点"
},
"HazardLevel": {
"name": "侵蚀等级",
@ -2114,6 +2118,23 @@
"help": "仅出击指定的海域,可以用来获取大世界成就星星\n支持海域ID、国服/国际服/日服/台服海域名称,例如 \"51\", \"NA海域东南E\", \"NA Ocean SE Sector E\"\n填入默认值0或者删除数值即可取消指定"
}
},
"OpsiHazard1Leveling": {
"_info": {
"name": "侵蚀1练级",
"help": "警告:这个功能仅推荐用于练级\n根据海事局最新的结论侵蚀1产出的行动力刚好跟消耗持平可以用来无限获取经验\n尝试使用此功能获取额外行动力被视为自负盈亏的赌博行为\n\n这个功能会自动完成地图随机事件并跳过塞壬探测装置\n推荐携带2艘预装填的保姆船以获取最高的时均经验收益\n由于在商店购买行动力需要大量作战补给凭证启用本功能后会自动启用短猫相接来补充"
},
"StrategySearch": {
"name": "使用计划作战",
"help": ""
},
"TargetZone": {
"name": "指定海域",
"help": "仅出击指定的海域可以用来获取大世界成就星星或规避游戏BUG导致的无法刷新海域",
"0": "不指定",
"44": "44 | 西大陆架D",
"22": "22 | NA海域西南B"
}
},
"Daemon": {
"_info": {
"name": "半自动点击",

View File

@ -218,6 +218,10 @@
"name": "短貓相接",
"help": ""
},
"OpsiHazard1Leveling": {
"name": "侵蝕1練級",
"help": ""
},
"Daemon": {
"name": "半自動點擊",
"help": ""
@ -2098,7 +2102,7 @@
},
"ActionPointPreserve": {
"name": "保留 X 點行動力",
"help": "行動力低於 X 後停止自動打開行動力箱子X 包含箱子中的行動力,建議保留 500 點行動力\n這個值將在大世界重置前3天自動減少至300點並在最後一天自動減少至0點"
"help": "行動力低於 X 後停止自動打開行動力箱子X 包含箱子中的行動力,建議保留 1000 點行動力给侵蝕1練級\n這個值將在大世界重置前3天自動減少至300點如果啟用侵蝕1練級則改為500點並在最後一天自動減少至0點"
},
"HazardLevel": {
"name": "侵蝕等級",
@ -2114,6 +2118,23 @@
"help": "僅出擊指定的海域,可以用來獲取大世界成就星星\n自動更新的數值填0可重置進度重置後自動跳過已開荒的海域\n支持海域ID、國服/國際服/日服/台服海域名稱,例如 \"51\", \"NA海域東南E\", \"NA Ocean SE Sector E\"\n填入默認值0或者刪除數值即可取消指定"
}
},
"OpsiHazard1Leveling": {
"_info": {
"name": "侵蝕1練級",
"help": "OpsiHazard1Leveling._info.help"
},
"StrategySearch": {
"name": "使用計畫作戰",
"help": ""
},
"TargetZone": {
"name": "指定海域",
"help": "僅出擊指定的海域可以用來獲取大世界成就星星或規避遊戲BUG導致的無法重繪海域",
"0": "不指定",
"44": "44 | 西大陸棚D",
"22": "22 | NA海域西南B"
}
},
"Daemon": {
"_info": {
"name": "半自動點擊",
@ -2149,7 +2170,7 @@
},
"AdbncScreenshot": {
"name": "測試 ADB 截圖",
"help": "Benchmark.AdbncScreenshot.help"
"help": ""
},
"Uiautomator2Screenshot": {
"name": "測試 uiautomator2 截圖",

View File

@ -1,17 +1,23 @@
from sys import maxsize
import inflection
from module.base.timer import Timer
from module.combat.assets import PAUSE
from module.config.utils import get_os_reset_remain
from module.exception import CampaignEnd, RequestHumanTakeover
from module.exception import GameTooManyClickError
from module.exception import GameTooManyClickError, GameStuckError
from module.exception import MapWalkError, ScriptError
from module.exercise.assets import QUIT_CONFIRM, QUIT_RECONFIRM
from module.logger import logger
from module.map.map import Map
from module.os.assets import FLEET_EMP_DEBUFF
from module.os.fleet import OSFleet
from module.os.globe_camera import GlobeCamera
from module.os.globe_operation import RewardUncollectedError
from module.os_handler.assets import AUTO_SEARCH_OS_MAP_OPTION_OFF, AUTO_SEARCH_OS_MAP_OPTION_ON
from module.os_handler.assets import AUTO_SEARCH_OS_MAP_OPTION_OFF, \
AUTO_SEARCH_OS_MAP_OPTION_ON, AUTO_SEARCH_REWARD
from module.ui.assets import GOTO_MAIN
from module.ui.page import page_main
from module.ui.ui import page_os
@ -72,6 +78,8 @@ class OSMap(OSFleet, Map, GlobeCamera):
if self.zone.zone_id == 154:
logger.info('In zone 154, skip running first auto search')
self.handle_ash_beacon_attack()
elif self.zone.zone_id in [22, 44]:
pass
else:
self.run_auto_search(rescan=False)
self.handle_after_auto_search()
@ -114,7 +122,7 @@ class OSMap(OSFleet, Map, GlobeCamera):
if self.zone == zone:
if refresh:
logger.info('Goto another zone to refresh current zone')
return self.globe_goto(self.zone_nearest_azur_port(self.zone),
self.globe_goto(self.zone_nearest_azur_port(self.zone),
types=('SAFE', 'DANGEROUS'), refresh=False)
else:
logger.info('Already at target zone')
@ -128,7 +136,7 @@ class OSMap(OSFleet, Map, GlobeCamera):
# IN_GLOBE
if not self.is_in_globe():
logger.warning('Trying to move in globe, but not in os globe map')
raise ScriptError('Trying to move in globe, but not in os globe map')
raise GameStuckError
# self.ensure_no_zone_pinned()
self.globe_update()
self.globe_focus_to(zone)
@ -349,32 +357,33 @@ class OSMap(OSFleet, Map, GlobeCamera):
logger.warning('Failed to solve EMP debuff after 5 trial, assume solved')
return True
def action_point_limit_override(self):
def get_action_point_limit(self):
"""
Override user config at the end of every month.
To consume all action points without manual configuration.
Returns:
bool: If overrode
int: ActionPointPreserve
"""
remain = get_os_reset_remain()
if remain <= 0:
logger.info('Just less than 1 day to OpSi reset, '
'set OpsiMeowfficerFarming.ActionPointPreserve to 0 temporarily')
self.config.override(OpsiMeowfficerFarming_ActionPointPreserve=0)
return True
'set ActionPointPreserve to 0 temporarily')
return 0
elif self.config.cross_get(
keys='OpsiHazard1Leveling.Scheduler.Enable',
default=False
) and remain <= 2:
logger.info('Just less than 3 days to OpSi reset, '
'set ActionPointPreserve to 500 temporarily for hazard 1 leveling')
return 500
elif remain <= 2:
logger.info('Just less than 3 days to OpSi reset, '
'set OpsiMeowfficerFarming.ActionPointPreserve < 300 temporarily')
self.config.override(
OpsiMeowfficerFarming_ActionPointPreserve=min(
self.config.OpsiMeowfficerFarming_ActionPointPreserve,
300)
)
return True
'set ActionPointPreserve to 300 temporarily')
return 300
else:
logger.info('Not close to OpSi reset')
return False
return maxsize
def handle_after_auto_search(self):
logger.hr('After auto search', level=2)
@ -390,7 +399,7 @@ class OSMap(OSFleet, Map, GlobeCamera):
_auto_search_battle_count = 0
def os_auto_search_daemon(self, drop=None, skip_first_screenshot=True):
def os_auto_search_daemon(self, drop=None, strategy=False, skip_first_screenshot=True):
"""
Raises:
CampaignEnd: If auto search ended
@ -404,6 +413,7 @@ class OSMap(OSFleet, Map, GlobeCamera):
logger.hr('OS auto search', level=2)
self._auto_search_battle_count = 0
unlock_checked = False
strategy_checked = False
unlock_check_timer = Timer(5, count=10).start()
self.ash_popup_canceled = False
@ -437,8 +447,14 @@ class OSMap(OSFleet, Map, GlobeCamera):
unlock_checked = True
elif self.appear(AUTO_SEARCH_OS_MAP_OPTION_ON, offset=(5, 120)):
unlock_checked = True
if self.handle_os_auto_search_map_option(drop=drop, enable=success):
if self.handle_os_auto_search_map_option(
drop=drop,
enable=success,
strategy=strategy and not strategy_checked
):
unlock_checked = True
strategy_checked = True
continue
if self.handle_retirement():
# Retire will interrupt auto search, need a retry
@ -447,6 +463,8 @@ class OSMap(OSFleet, Map, GlobeCamera):
if self.combat_appear():
self._auto_search_battle_count += 1
logger.attr('battle_count', self._auto_search_battle_count)
if strategy and self.config.task_switched():
self.interrupt_auto_search()
result = self.auto_search_combat(drop=drop)
if not result:
success = False
@ -456,11 +474,37 @@ class OSMap(OSFleet, Map, GlobeCamera):
# Auto search can not handle siren searching device.
continue
def os_auto_search_run(self, drop=None):
def interrupt_auto_search(self):
logger.info('Interrupting auto search')
while 1:
self.device.screenshot()
if self.appear(AUTO_SEARCH_REWARD, offset=(50, 50), interval=3):
self.os_auto_search_quit()
continue
if self.appear_then_click(PAUSE, interval=0.5):
continue
if self.appear_then_click(QUIT_CONFIRM, offset=(20, 20), interval=5):
continue
if self.appear_then_click(QUIT_RECONFIRM, offset=True, interval=5):
continue
if self.appear(AUTO_SEARCH_OS_MAP_OPTION_OFF, offset=(5, 120), interval=3) \
and AUTO_SEARCH_OS_MAP_OPTION_OFF.match_appear_on(self.device.image):
self.device.click(GOTO_MAIN)
continue
if self.ui_additional():
continue
# End
if self.ui_page_appear(page_main):
logger.info('Auto search interrupted')
self.config.task_stop()
def os_auto_search_run(self, drop=None, strategy=False):
for _ in range(5):
backup = self.config.temporary(Campaign_UseAutoSearch=True)
try:
self.os_auto_search_daemon(drop=drop)
self.os_auto_search_daemon(drop=drop, strategy=strategy)
except CampaignEnd:
logger.info('OS auto search finished')
finally:
@ -470,6 +514,7 @@ class OSMap(OSFleet, Map, GlobeCamera):
# Break if zone cleared
if self.config.OpsiAshBeacon_AshAttack:
if self.handle_ash_beacon_attack() or self.ash_popup_canceled:
strategy = False
continue
else:
break
@ -481,7 +526,7 @@ class OSMap(OSFleet, Map, GlobeCamera):
else:
break
def clear_question(self, drop):
def clear_question(self, drop=None):
"""
Clear nearly (and 3 grids from above) question marks on radar.
Try 3 times at max to avoid loop tries on 2 adjacent fleet mechanism.
@ -582,6 +627,19 @@ class OSMap(OSFleet, Map, GlobeCamera):
_solved_map_event = set()
_solved_fleet_mechanism = 0
def run_strategy_search(self):
self.handle_ash_beacon_attack()
logger.info('Run strategy search')
self.os_auto_search_run(strategy=True)
self.hp_reset()
self.hp_get()
self._solved_map_event = set()
self._solved_fleet_mechanism = False
self.clear_question()
self.map_rescan()
def map_rescan_current(self, drop=None):
"""
@ -626,7 +684,8 @@ class OSMap(OSFleet, Map, GlobeCamera):
grid = grids[0]
logger.info(f'Found scanning device on {grid}')
self.device.click(grid)
result = self.wait_until_walk_stable(drop=drop, walk_out_of_step=False, confirm_timer=Timer(1.5, count=4))
result = self.wait_until_walk_stable(drop=drop, walk_out_of_step=False,
confirm_timer=Timer(1.5, count=4))
self.os_auto_search_run(drop=drop)
if 'event' in result:
self._solved_map_event.add('is_scanning_device')

View File

@ -1,5 +1,6 @@
import numpy as np
from module.base.timer import Timer
from module.config.utils import (get_os_next_reset,
get_os_reset_remain,
DEFAULT_TIME)
@ -9,6 +10,7 @@ from module.map.map_grids import SelectedGrids
from module.os.fleet import BossFleet
from module.os.globe_operation import OSExploreError
from module.os.map import OSMap
from module.os_handler.shop import OCR_SHOP_YELLOW_COINS
class OperationSiren(OSMap):
@ -130,9 +132,12 @@ class OperationSiren(OSMap):
Recommend 3 or 5 for higher meowfficer searching point per action points ratio.
"""
logger.hr(f'OS meowfficer farming, hazard_level={self.config.OpsiMeowfficerFarming_HazardLevel}', level=1)
self.action_point_limit_override()
preserve = min(self.get_action_point_limit(), self.config.OpsiMeowfficerFarming_ActionPointPreserve)
if preserve == 0:
self.config.override(OpsiFleet_Submarine=False)
while 1:
self.config.OS_ACTION_POINT_PRESERVE = self.config.OpsiMeowfficerFarming_ActionPointPreserve
self.config.OS_ACTION_POINT_PRESERVE = preserve
if self.config.OpsiAshBeacon_AshAttack \
and not self._ash_fully_collected \
and self.config.OpsiAshBeacon_EnsureFullyCollected:
@ -149,6 +154,7 @@ class OperationSiren(OSMap):
raise RequestHumanTakeover('wrong input, task stopped')
else:
logger.hr(f'OS meowfficer farming, zone_id={zone.zone_id}', level=1)
self.set_action_point(zone, 'SAFE')
self.globe_goto(zone)
self.fleet_set(self.config.OpsiFleet_Fleet)
self.os_order_execute(
@ -165,6 +171,7 @@ class OperationSiren(OSMap):
.sort_by_clock_degree(center=(1252, 1012), start=self.zone.location)
logger.hr(f'OS meowfficer farming, zone_id={zones[0].zone_id}', level=1)
self.set_action_point(zones[0], 'SAFE')
self.globe_goto(zones[0])
self.fleet_set(self.config.OpsiFleet_Fleet)
self.os_order_execute(
@ -174,6 +181,68 @@ class OperationSiren(OSMap):
self.handle_after_auto_search()
self.config.check_task_switch()
def os_hazard1_leveling(self):
logger.hr('OS hazard 1 leveling', level=1)
while 1:
# Limited action point preserve of hazard 1 to 200
self.config.OS_ACTION_POINT_PRESERVE = 200
if self.config.OpsiAshBeacon_AshAttack \
and not self._ash_fully_collected \
and self.config.OpsiAshBeacon_EnsureFullyCollected:
logger.info('Ash beacon not fully collected, ignore action point limit temporarily')
self.config.OS_ACTION_POINT_PRESERVE = 0
logger.attr('OS_ACTION_POINT_PRESERVE', self.config.OS_ACTION_POINT_PRESERVE)
timeout = Timer(2).start()
skip_first_screenshot = True
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
yellow_coins = OCR_SHOP_YELLOW_COINS.ocr(self.device.image)
if yellow_coins < 100 and not timeout.reached():
logger.info('Yellow coins less than 100, assuming it is an ocr error')
continue
elif yellow_coins < 100000:
logger.info('Reach the limit of yellow coins, preserve=100000')
self.config.task_delay(server_update=True)
self.config.task_stop()
else:
break
self.get_current_zone()
if self.config.OpsiHazard1Leveling_StrategySearch:
# Preset action point to 100
self.set_action_point(cost=100)
if self.config.OpsiHazard1Leveling_TargetZone != 0:
zone = self.config.OpsiHazard1Leveling_TargetZone
else:
zone = 44
logger.hr(f'OS hazard 1 leveling, zone_id={zone}', level=1)
if self.zone.zone_id != zone or not self.is_zone_name_hidden:
self.globe_goto(self.name_to_zone(zone), types='SAFE', refresh=True)
self.fleet_set(self.config.OpsiFleet_Fleet)
self.run_strategy_search()
else:
if self.config.OpsiHazard1Leveling_TargetZone != 0:
zone = self.config.OpsiHazard1Leveling_TargetZone
logger.hr(f'OS hazard 1 leveling, zone_id={zone}', level=1)
self.globe_goto(self.name_to_zone(zone), types='SAFE', refresh=True)
else:
zones = self.zone_select(hazard_level=1) \
.delete(SelectedGrids([self.zone])) \
.delete(SelectedGrids(self.zones.select(is_port=True)))
logger.hr(f'OS hazard 1 leveling, zone_id={zones[0].zone_id}', level=1)
self.globe_goto(zones[0])
self.fleet_set(self.config.OpsiFleet_Fleet)
self.run_auto_search()
self.handle_after_auto_search()
self.config.check_task_switch()
def _os_explore_task_delay(self):
"""
Delay other OpSi tasks during os_explore
@ -311,6 +380,15 @@ class OperationSiren(OSMap):
else:
break
def delay_abyssal(self):
# No obscure coordinates, delay next run to tomorrow.
if get_os_reset_remain() > 0:
self.config.task_delay(server_update=True)
else:
logger.info('Just less than 1 day to OpSi reset, delay 2.5 hours')
self.config.task_delay(minute=150, server_update=True)
self.config.task_stop()
def clear_abyssal(self):
"""
Get one abyssal logger in storage,
@ -325,13 +403,7 @@ class OperationSiren(OSMap):
logger.hr('OS clear abyssal', level=1)
result = self.storage_get_next_item('ABYSSAL', use_logger=self.config.OpsiGeneral_UseLogger)
if not result:
# No obscure coordinates, delay next run to tomorrow.
if get_os_reset_remain() > 0:
self.config.task_delay(server_update=True)
else:
logger.info('Just less than 1 day to OpSi reset, delay 2.5 hours')
self.config.task_delay(minute=150, server_update=True)
self.config.task_stop()
self.delay_abyssal()
self.config.override(
OpsiGeneral_DoRandomMapEvent=False,
@ -344,6 +416,7 @@ class OperationSiren(OSMap):
raise RequestHumanTakeover
self.fleet_repair(revert=False)
self.delay_abyssal()
def os_abyssal(self):
while 1:

View File

@ -1,5 +1,6 @@
import module.config.server as server
from module.base.button import ButtonGrid
from module.base.timer import Timer
from module.base.utils import *
from module.logger import logger
from module.ocr.ocr import Digit, DigitCounter
@ -9,6 +10,8 @@ from module.ui.assets import OS_CHECK
from module.ui.ui import UI
OCR_ACTION_POINT_REMAIN = Digit(ACTION_POINT_REMAIN, letter=(255, 219, 66), name='OCR_ACTION_POINT_REMAIN')
OCR_ACTION_POINT_REMAIN_OS = Digit(ACTION_POINT_REMAIN_OS, letter=(239, 239, 239),
threshold=160, name='OCR_SHOP_YELLOW_COINS_OS')
if server.server != 'jp':
# Letters in ACTION_POINT_BUY_REMAIN are not the numeric fonts usually used in azur lane.
OCR_ACTION_POINT_BUY_REMAIN = DigitCounter(
@ -51,6 +54,12 @@ ACTION_POINTS_BUY = {
4: 1000,
5: 1000,
}
ACTION_POINT_BOX = {
0: 0,
1: 20,
2: 50,
3: 100,
}
class ActionPointLimit(Exception):
@ -95,7 +104,7 @@ class ActionPointHandler(UI):
current = OCR_ACTION_POINT_REMAIN.ocr(self.device.image)
total = current
if self.config.OS_ACTION_POINT_BOX_USE:
total += np.sum(np.array(box) * (0, 20, 50, 100))
total += np.sum(np.array(box) * tuple(ACTION_POINT_BOX.values()))
oil = box[0]
logger.info(f'Action points: {current}({total}), oil: {oil}')
@ -103,6 +112,23 @@ class ActionPointHandler(UI):
self._action_point_box = box
self._action_point_total = total
def action_point_safe_get(self, skip_first_screenshot=True):
timeout = Timer(1, count=2).start()
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if timeout.reached():
logger.warning('Get action points timeout')
break
self.action_point_update()
if sum(self._action_point_box[1:]) > 0 and self._action_point_box[0] > 0:
break
@staticmethod
def action_point_get_cost(zone, pinned):
"""
@ -208,11 +234,12 @@ class ActionPointHandler(UI):
"""
self.ui_click(ACTION_POINT_CANCEL, check_button=OS_CHECK, skip_first_screenshot=skip_first_screenshot)
def handle_action_point(self, zone, pinned):
def handle_action_point(self, zone, pinned, cost=None):
"""
Args:
zone (Zone): Zone to enter.
pinned (str): Zone type. Available types: DANGEROUS, SAFE, OBSCURE, ABYSSAL, STRONGHOLD.
cost (int): Custom action point cost value.
Returns:
bool: If handled.
@ -227,11 +254,15 @@ class ActionPointHandler(UI):
return False
# AP boxes have an animation to show
self.device.sleep(0.3)
self.device.screenshot()
self.action_point_update()
self.action_point_safe_get()
if cost is None:
cost = self.action_point_get_cost(zone, pinned)
buy_checked = False
if self._action_point_total <= self.config.OS_ACTION_POINT_PRESERVE:
logger.info(f'Reach the limit of action points, preserve={self.config.OS_ACTION_POINT_PRESERVE}')
self.action_point_quit()
raise ActionPointLimit
for _ in range(12):
# Having enough action points
if self._action_point_current >= cost:
@ -246,8 +277,16 @@ class ActionPointHandler(UI):
else:
buy_checked = True
# Sort action point boxes
box = []
for index in [1, 2, 3]:
if self._action_point_box[index] > 0:
if self._action_point_current + ACTION_POINT_BOX[index] >= 200:
box.append(index)
else:
box.insert(0, index)
# Use action point boxes
box = [index for index in [3, 2, 1] if self._action_point_box[index] > 0]
if len(box):
if self._action_point_total > self.config.OS_ACTION_POINT_PRESERVE:
self.action_point_set_button(box[0])
@ -264,3 +303,22 @@ class ActionPointHandler(UI):
logger.warning('Failed to get action points after 12 trial')
return False
def set_action_point(self, zone=None, pinned=None, cost=None):
"""
Args:
zone (Zone): Zone to enter.
pinned (str): Zone type. Available types: DANGEROUS, SAFE, OBSCURE, ABYSSAL, STRONGHOLD.
cost (int): Custom action point cost value.
Returns:
bool: If handled.
"""
self.ui_click(ACTION_POINT_REMAIN_OS, ACTION_POINT_USE, OS_CHECK)
if not self.handle_action_point(zone, pinned, cost):
return False
while 1:
if self.appear(IN_MAP, offset=(200, 5)):
return True
self.device.screenshot()

View File

@ -7,6 +7,7 @@ from module.base.template import Template
ACTION_POINT_BUY_REMAIN = Button(area={'cn': (803, 458, 833, 482), 'en': (907, 458, 941, 483), 'jp': (891, 464, 927, 484), 'tw': (803, 458, 833, 482)}, color={'cn': (108, 138, 125), 'en': (106, 145, 116), 'jp': (135, 142, 153), 'tw': (108, 138, 125)}, button={'cn': (803, 458, 833, 482), 'en': (907, 458, 941, 483), 'jp': (891, 464, 927, 484), 'tw': (803, 458, 833, 482)}, file={'cn': './assets/cn/os_handler/ACTION_POINT_BUY_REMAIN.png', 'en': './assets/en/os_handler/ACTION_POINT_BUY_REMAIN.png', 'jp': './assets/jp/os_handler/ACTION_POINT_BUY_REMAIN.png', 'tw': './assets/tw/os_handler/ACTION_POINT_BUY_REMAIN.png'})
ACTION_POINT_CANCEL = Button(area={'cn': (370, 528, 542, 585), 'en': (375, 531, 537, 584), 'jp': (369, 527, 544, 587), 'tw': (371, 528, 541, 586)}, color={'cn': (167, 168, 171), 'en': (170, 172, 175), 'jp': (161, 163, 165), 'tw': (168, 169, 172)}, button={'cn': (370, 528, 542, 585), 'en': (375, 531, 537, 584), 'jp': (369, 527, 544, 587), 'tw': (371, 528, 541, 586)}, file={'cn': './assets/cn/os_handler/ACTION_POINT_CANCEL.png', 'en': './assets/en/os_handler/ACTION_POINT_CANCEL.png', 'jp': './assets/jp/os_handler/ACTION_POINT_CANCEL.png', 'tw': './assets/tw/os_handler/ACTION_POINT_CANCEL.png'})
ACTION_POINT_REMAIN = Button(area={'cn': (892, 220, 952, 241), 'en': (892, 220, 952, 241), 'jp': (908, 220, 979, 240), 'tw': (892, 220, 952, 241)}, color={'cn': (124, 127, 113), 'en': (124, 127, 113), 'jp': (119, 121, 113), 'tw': (124, 127, 113)}, button={'cn': (892, 220, 952, 241), 'en': (892, 220, 952, 241), 'jp': (908, 220, 979, 240), 'tw': (892, 220, 952, 241)}, file={'cn': './assets/cn/os_handler/ACTION_POINT_REMAIN.png', 'en': './assets/en/os_handler/ACTION_POINT_REMAIN.png', 'jp': './assets/jp/os_handler/ACTION_POINT_REMAIN.png', 'tw': './assets/tw/os_handler/ACTION_POINT_REMAIN.png'})
ACTION_POINT_REMAIN_OS = Button(area={'cn': (878, 28, 928, 46), 'en': (878, 28, 928, 46), 'jp': (878, 28, 928, 46), 'tw': (878, 28, 928, 46)}, color={'cn': (78, 89, 100), 'en': (78, 89, 100), 'jp': (78, 89, 100), 'tw': (78, 89, 100)}, button={'cn': (878, 28, 928, 46), 'en': (878, 28, 928, 46), 'jp': (878, 28, 928, 46), 'tw': (878, 28, 928, 46)}, file={'cn': './assets/cn/os_handler/ACTION_POINT_REMAIN_OS.png', 'en': './assets/cn/os_handler/ACTION_POINT_REMAIN_OS.png', 'jp': './assets/cn/os_handler/ACTION_POINT_REMAIN_OS.png', 'tw': './assets/cn/os_handler/ACTION_POINT_REMAIN_OS.png'})
ACTION_POINT_USE = Button(area={'cn': (738, 528, 910, 585), 'en': (742, 531, 909, 584), 'jp': (737, 528, 911, 586), 'tw': (739, 528, 909, 585)}, color={'cn': (93, 142, 203), 'en': (107, 152, 208), 'jp': (92, 141, 203), 'tw': (95, 144, 205)}, button={'cn': (738, 528, 910, 585), 'en': (742, 531, 909, 584), 'jp': (737, 528, 911, 586), 'tw': (739, 528, 909, 585)}, file={'cn': './assets/cn/os_handler/ACTION_POINT_USE.png', 'en': './assets/en/os_handler/ACTION_POINT_USE.png', 'jp': './assets/jp/os_handler/ACTION_POINT_USE.png', 'tw': './assets/tw/os_handler/ACTION_POINT_USE.png'})
ASH_POPUP_CHECK = Button(area={'cn': (665, 318, 759, 340), 'en': (372, 324, 601, 342), 'jp': (438, 311, 534, 346), 'tw': (665, 298, 759, 320)}, color={'cn': (154, 163, 172), 'en': (174, 179, 184), 'jp': (146, 154, 161), 'tw': (157, 166, 176)}, button={'cn': (665, 318, 759, 340), 'en': (372, 324, 601, 342), 'jp': (438, 311, 534, 346), 'tw': (665, 298, 759, 320)}, file={'cn': './assets/cn/os_handler/ASH_POPUP_CHECK.png', 'en': './assets/en/os_handler/ASH_POPUP_CHECK.png', 'jp': './assets/jp/os_handler/ASH_POPUP_CHECK.png', 'tw': './assets/tw/os_handler/ASH_POPUP_CHECK.png'})
AUTO_SEARCH_OS_MAP_OPTION_OFF = Button(area={'cn': (1205, 549, 1275, 566), 'en': (1201, 524, 1274, 534), 'jp': (1204, 572, 1276, 593), 'tw': (1206, 573, 1275, 591)}, color={'cn': (196, 169, 169), 'en': (167, 140, 142), 'jp': (180, 154, 157), 'tw': (167, 143, 147)}, button={'cn': (1205, 549, 1275, 566), 'en': (1201, 524, 1274, 534), 'jp': (1204, 572, 1276, 593), 'tw': (1206, 573, 1275, 591)}, file={'cn': './assets/cn/os_handler/AUTO_SEARCH_OS_MAP_OPTION_OFF.png', 'en': './assets/en/os_handler/AUTO_SEARCH_OS_MAP_OPTION_OFF.png', 'jp': './assets/jp/os_handler/AUTO_SEARCH_OS_MAP_OPTION_OFF.png', 'tw': './assets/tw/os_handler/AUTO_SEARCH_OS_MAP_OPTION_OFF.png'})
@ -57,6 +58,16 @@ STORAGE_COORDINATE_CHECKOUT = Button(area={'cn': (554, 493, 726, 550), 'en': (56
STORAGE_ENTER = Button(area={'cn': (770, 636, 880, 699), 'en': (761, 640, 876, 695), 'jp': (757, 636, 880, 699), 'tw': (618, 638, 725, 698)}, color={'cn': (240, 199, 121), 'en': (238, 191, 115), 'jp': (237, 187, 100), 'tw': (240, 197, 125)}, button={'cn': (770, 636, 880, 699), 'en': (761, 640, 876, 695), 'jp': (757, 636, 880, 699), 'tw': (618, 638, 725, 698)}, file={'cn': './assets/cn/os_handler/STORAGE_ENTER.png', 'en': './assets/en/os_handler/STORAGE_ENTER.png', 'jp': './assets/jp/os_handler/STORAGE_ENTER.png', 'tw': './assets/tw/os_handler/STORAGE_ENTER.png'})
STORAGE_USE = Button(area={'cn': (709, 506, 769, 536), 'en': (729, 509, 786, 533), 'jp': (764, 506, 856, 536), 'tw': (709, 506, 769, 536)}, color={'cn': (161, 186, 220), 'en': (164, 189, 222), 'jp': (142, 178, 224), 'tw': (161, 186, 220)}, button={'cn': (687, 493, 860, 550), 'en': (693, 495, 858, 549), 'jp': (686, 492, 861, 552), 'tw': (687, 493, 860, 550)}, file={'cn': './assets/cn/os_handler/STORAGE_USE.png', 'en': './assets/en/os_handler/STORAGE_USE.png', 'jp': './assets/jp/os_handler/STORAGE_USE.png', 'tw': './assets/tw/os_handler/STORAGE_USE.png'})
STORATE_SCROLL = Button(area={'cn': (1256, 102, 1264, 589), 'en': (1256, 102, 1264, 589), 'jp': (1256, 102, 1264, 589), 'tw': (1256, 102, 1264, 589)}, color={'cn': (119, 109, 60), 'en': (119, 109, 60), 'jp': (119, 109, 60), 'tw': (119, 109, 60)}, button={'cn': (1256, 102, 1264, 589), 'en': (1256, 102, 1264, 589), 'jp': (1256, 102, 1264, 589), 'tw': (1256, 102, 1264, 589)}, file={'cn': './assets/cn/os_handler/STORATE_SCROLL.png', 'en': './assets/en/os_handler/STORATE_SCROLL.png', 'jp': './assets/jp/os_handler/STORATE_SCROLL.png', 'tw': './assets/tw/os_handler/STORATE_SCROLL.png'})
STRATEGY_SEARCH_MAP_OPTION_OFF = Button(area={'cn': (1178, 576, 1278, 617), 'en': (1178, 576, 1278, 617), 'jp': (1178, 576, 1278, 617), 'tw': (1178, 576, 1278, 617)}, color={'cn': (96, 102, 122), 'en': (96, 102, 122), 'jp': (96, 102, 122), 'tw': (96, 102, 122)}, button={'cn': (1178, 576, 1278, 617), 'en': (1178, 576, 1278, 617), 'jp': (1178, 576, 1278, 617), 'tw': (1178, 576, 1278, 617)}, file={'cn': './assets/cn/os_handler/STRATEGY_SEARCH_MAP_OPTION_OFF.png', 'en': './assets/cn/os_handler/STRATEGY_SEARCH_MAP_OPTION_OFF.png', 'jp': './assets/cn/os_handler/STRATEGY_SEARCH_MAP_OPTION_OFF.png', 'tw': './assets/cn/os_handler/STRATEGY_SEARCH_MAP_OPTION_OFF.png'})
STRATEGY_SEARCH_POPUP_CHECK = Button(area={'cn': (370, 166, 566, 198), 'en': (370, 166, 566, 198), 'jp': (370, 166, 566, 198), 'tw': (370, 166, 566, 198)}, color={'cn': (150, 170, 209), 'en': (150, 170, 209), 'jp': (150, 170, 209), 'tw': (150, 170, 209)}, button={'cn': (370, 166, 566, 198), 'en': (370, 166, 566, 198), 'jp': (370, 166, 566, 198), 'tw': (370, 166, 566, 198)}, file={'cn': './assets/cn/os_handler/STRATEGY_SEARCH_POPUP_CHECK.png', 'en': './assets/cn/os_handler/STRATEGY_SEARCH_POPUP_CHECK.png', 'jp': './assets/cn/os_handler/STRATEGY_SEARCH_POPUP_CHECK.png', 'tw': './assets/cn/os_handler/STRATEGY_SEARCH_POPUP_CHECK.png'})
STRATEGY_SEARCH_SAFE_OPTION_OFF = Button(area={'cn': (457, 229, 550, 257), 'en': (457, 229, 550, 257), 'jp': (457, 229, 550, 257), 'tw': (457, 229, 550, 257)}, color={'cn': (111, 141, 195), 'en': (111, 141, 195), 'jp': (111, 141, 195), 'tw': (111, 141, 195)}, button={'cn': (640, 217, 913, 270), 'en': (640, 217, 913, 270), 'jp': (640, 217, 913, 270), 'tw': (640, 217, 913, 270)}, file={'cn': './assets/cn/os_handler/STRATEGY_SEARCH_SAFE_OPTION_OFF.png', 'en': './assets/cn/os_handler/STRATEGY_SEARCH_SAFE_OPTION_OFF.png', 'jp': './assets/cn/os_handler/STRATEGY_SEARCH_SAFE_OPTION_OFF.png', 'tw': './assets/cn/os_handler/STRATEGY_SEARCH_SAFE_OPTION_OFF.png'})
STRATEGY_SEARCH_SAFE_OPTION_ON = Button(area={'cn': (731, 229, 823, 258), 'en': (731, 229, 823, 258), 'jp': (731, 229, 823, 258), 'tw': (731, 229, 823, 258)}, color={'cn': (105, 136, 192), 'en': (105, 136, 192), 'jp': (105, 136, 192), 'tw': (105, 136, 192)}, button={'cn': (731, 229, 823, 258), 'en': (731, 229, 823, 258), 'jp': (731, 229, 823, 258), 'tw': (731, 229, 823, 258)}, file={'cn': './assets/cn/os_handler/STRATEGY_SEARCH_SAFE_OPTION_ON.png', 'en': './assets/cn/os_handler/STRATEGY_SEARCH_SAFE_OPTION_ON.png', 'jp': './assets/cn/os_handler/STRATEGY_SEARCH_SAFE_OPTION_ON.png', 'tw': './assets/cn/os_handler/STRATEGY_SEARCH_SAFE_OPTION_ON.png'})
STRATEGY_SEARCH_SCROLL_AREA = Button(area={'cn': (902, 277, 910, 470), 'en': (902, 277, 910, 470), 'jp': (902, 277, 910, 470), 'tw': (902, 277, 910, 470)}, color={'cn': (151, 145, 102), 'en': (151, 145, 102), 'jp': (151, 145, 102), 'tw': (151, 145, 102)}, button={'cn': (902, 277, 910, 470), 'en': (902, 277, 910, 470), 'jp': (902, 277, 910, 470), 'tw': (902, 277, 910, 470)}, file={'cn': './assets/cn/os_handler/STRATEGY_SEARCH_SCROLL_AREA.png', 'en': './assets/cn/os_handler/STRATEGY_SEARCH_SCROLL_AREA.png', 'jp': './assets/cn/os_handler/STRATEGY_SEARCH_SCROLL_AREA.png', 'tw': './assets/cn/os_handler/STRATEGY_SEARCH_SCROLL_AREA.png'})
STRATEGY_SEARCH_WAIT_2_CHECK = Button(area={'cn': (474, 404, 556, 422), 'en': (474, 404, 556, 422), 'jp': (474, 404, 556, 422), 'tw': (474, 404, 556, 422)}, color={'cn': (149, 156, 168), 'en': (149, 156, 168), 'jp': (149, 156, 168), 'tw': (149, 156, 168)}, button={'cn': (474, 404, 556, 422), 'en': (474, 404, 556, 422), 'jp': (474, 404, 556, 422), 'tw': (474, 404, 556, 422)}, file={'cn': './assets/cn/os_handler/STRATEGY_SEARCH_WAIT_2_CHECK.png', 'en': './assets/cn/os_handler/STRATEGY_SEARCH_WAIT_2_CHECK.png', 'jp': './assets/cn/os_handler/STRATEGY_SEARCH_WAIT_2_CHECK.png', 'tw': './assets/cn/os_handler/STRATEGY_SEARCH_WAIT_2_CHECK.png'})
STRATEGY_SEARCH_WAIT_OFF = Button(area={'cn': (519, 443, 535, 458), 'en': (519, 443, 535, 458), 'jp': (519, 443, 535, 458), 'tw': (519, 443, 535, 458)}, color={'cn': (89, 128, 66), 'en': (89, 128, 66), 'jp': (89, 128, 66), 'tw': (89, 128, 66)}, button={'cn': (519, 443, 535, 458), 'en': (519, 443, 535, 458), 'jp': (519, 443, 535, 458), 'tw': (519, 443, 535, 458)}, file={'cn': './assets/cn/os_handler/STRATEGY_SEARCH_WAIT_OFF.png', 'en': './assets/cn/os_handler/STRATEGY_SEARCH_WAIT_OFF.png', 'jp': './assets/cn/os_handler/STRATEGY_SEARCH_WAIT_OFF.png', 'tw': './assets/cn/os_handler/STRATEGY_SEARCH_WAIT_OFF.png'})
STRATEGY_SEARCH_WAIT_ON = Button(area={'cn': (446, 443, 462, 458), 'en': (446, 443, 462, 458), 'jp': (446, 443, 462, 458), 'tw': (446, 443, 462, 458)}, color={'cn': (89, 128, 67), 'en': (89, 128, 67), 'jp': (89, 128, 67), 'tw': (89, 128, 67)}, button={'cn': (446, 443, 462, 458), 'en': (446, 443, 462, 458), 'jp': (446, 443, 462, 458), 'tw': (446, 443, 462, 458)}, file={'cn': './assets/cn/os_handler/STRATEGY_SEARCH_WAIT_ON.png', 'en': './assets/cn/os_handler/STRATEGY_SEARCH_WAIT_ON.png', 'jp': './assets/cn/os_handler/STRATEGY_SEARCH_WAIT_ON.png', 'tw': './assets/cn/os_handler/STRATEGY_SEARCH_WAIT_ON.png'})
STRATEGY_SEARCH_ZONE_MODE_OFF = Button(area={'cn': (750, 335, 766, 350), 'en': (750, 335, 766, 350), 'jp': (750, 335, 766, 350), 'tw': (750, 335, 766, 350)}, color={'cn': (89, 128, 67), 'en': (89, 128, 67), 'jp': (89, 128, 67), 'tw': (89, 128, 67)}, button={'cn': (750, 335, 766, 350), 'en': (750, 335, 766, 350), 'jp': (750, 335, 766, 350), 'tw': (750, 335, 766, 350)}, file={'cn': './assets/cn/os_handler/STRATEGY_SEARCH_ZONE_MODE_OFF.png', 'en': './assets/cn/os_handler/STRATEGY_SEARCH_ZONE_MODE_OFF.png', 'jp': './assets/cn/os_handler/STRATEGY_SEARCH_ZONE_MODE_OFF.png', 'tw': './assets/cn/os_handler/STRATEGY_SEARCH_ZONE_MODE_OFF.png'})
STRATEGY_SEARCH_ZONE_MODE_ON = Button(area={'cn': (551, 335, 567, 350), 'en': (551, 335, 567, 350), 'jp': (551, 335, 567, 350), 'tw': (551, 335, 567, 350)}, color={'cn': (89, 128, 67), 'en': (89, 128, 67), 'jp': (89, 128, 67), 'tw': (89, 128, 67)}, button={'cn': (551, 335, 567, 350), 'en': (551, 335, 567, 350), 'jp': (551, 335, 567, 350), 'tw': (551, 335, 567, 350)}, file={'cn': './assets/cn/os_handler/STRATEGY_SEARCH_ZONE_MODE_ON.png', 'en': './assets/cn/os_handler/STRATEGY_SEARCH_ZONE_MODE_ON.png', 'jp': './assets/cn/os_handler/STRATEGY_SEARCH_ZONE_MODE_ON.png', 'tw': './assets/cn/os_handler/STRATEGY_SEARCH_ZONE_MODE_ON.png'})
TEMPLATE_STORAGE_ABYSSAL = Template(file={'cn': './assets/cn/os_handler/TEMPLATE_STORAGE_ABYSSAL.png', 'en': './assets/en/os_handler/TEMPLATE_STORAGE_ABYSSAL.png', 'jp': './assets/jp/os_handler/TEMPLATE_STORAGE_ABYSSAL.png', 'tw': './assets/tw/os_handler/TEMPLATE_STORAGE_ABYSSAL.png'})
TEMPLATE_STORAGE_COMBAT = Template(file={'cn': './assets/cn/os_handler/TEMPLATE_STORAGE_COMBAT.png', 'en': './assets/en/os_handler/TEMPLATE_STORAGE_COMBAT.png', 'jp': './assets/jp/os_handler/TEMPLATE_STORAGE_COMBAT.png', 'tw': './assets/tw/os_handler/TEMPLATE_STORAGE_COMBAT.png'})
TEMPLATE_STORAGE_LOGGER = Template(file={'cn': './assets/cn/os_handler/TEMPLATE_STORAGE_LOGGER.gif', 'en': './assets/en/os_handler/TEMPLATE_STORAGE_LOGGER.gif', 'jp': './assets/jp/os_handler/TEMPLATE_STORAGE_LOGGER.gif', 'tw': './assets/tw/os_handler/TEMPLATE_STORAGE_LOGGER.gif'})

View File

@ -1,4 +1,5 @@
from module.base.timer import Timer
from module.base.utils import get_color
from module.combat.assets import *
from module.exception import CampaignEnd
from module.handler.assets import *
@ -7,8 +8,10 @@ from module.os.assets import GLOBE_GOTO_MAP
from module.os_handler.assets import *
from module.os_handler.enemy_searching import EnemySearchingHandler
from module.statistics.azurstats import DropImage
from module.ui.scroll import Scroll
from module.ui.switch import Switch
STRATEGY_SEARCH_SCROLL = Scroll(STRATEGY_SEARCH_SCROLL_AREA, color=(247, 211, 66), name='STRATEGY_SEARCH_SCROLL')
fleet_lock = Switch('Fleet_Lock', offset=(10, 120))
fleet_lock.add_status('on', check_button=OS_FLEET_LOCKED)
fleet_lock.add_status('off', check_button=OS_FLEET_UNLOCKED)
@ -208,7 +211,8 @@ class MapEventHandler(EnemySearchingHandler):
confirm_timer.reset()
continue
if self.appear_then_click(GLOBE_GOTO_MAP, offset=(20, 20), interval=2):
# Sometimes entered globe map after clicking AUTO_SEARCH_REWARD, but don't know why
# Sometimes entered globe map after clicking AUTO_SEARCH_REWARD
# because of duplicated clicks and clicks to places outside the map
confirm_timer.reset()
continue
@ -221,11 +225,13 @@ class MapEventHandler(EnemySearchingHandler):
return cleared
def handle_os_auto_search_map_option(self, drop=None, enable=True):
def handle_os_auto_search_map_option(self, drop=None, enable=True, strategy=False, quit=True):
"""
Args:
drop (DropImage)
drop (DropImage):
enable (bool):
strategy (bool):
quit (bool):
Returns:
bool: If clicked.
@ -238,13 +244,15 @@ class MapEventHandler(EnemySearchingHandler):
raise CampaignEnd
if self.appear(AUTO_SEARCH_REWARD, offset=(50, 50)):
self.device.screenshot_interval_set()
if self.os_auto_search_quit(drop=drop):
if quit and self.os_auto_search_quit(drop=drop):
# No more items on current map
raise CampaignEnd
else:
# Auto search stopped but map hasn't been cleared
return True
if enable:
if strategy and enable:
return self.handle_strategy_search_map_option()
elif enable:
if self.appear(AUTO_SEARCH_OS_MAP_OPTION_OFF, offset=(5, 120), interval=3) \
and AUTO_SEARCH_OS_MAP_OPTION_OFF.match_appear_on(self.device.image):
self.device.click(AUTO_SEARCH_OS_MAP_OPTION_OFF)
@ -257,6 +265,76 @@ class MapEventHandler(EnemySearchingHandler):
return False
def handle_strategy_search_map_option(self):
if STRATEGY_SEARCH_MAP_OPTION_OFF.match_appear_on(self.device.image) \
and self.appear_then_click(STRATEGY_SEARCH_MAP_OPTION_OFF, interval=2):
return False
if not self.appear(STRATEGY_SEARCH_POPUP_CHECK):
return False
self.handle_strategy_search_setting_option()
def handle_strategy_search_setting_option(self):
while 1:
self.device.screenshot()
if not self.appear(STRATEGY_SEARCH_POPUP_CHECK):
return False
if self.appear(STRATEGY_SEARCH_SAFE_OPTION_OFF) \
and get_color(self.device.image, STRATEGY_SEARCH_SAFE_OPTION_OFF.area)[2] > 185:
self.device.click(STRATEGY_SEARCH_SAFE_OPTION_OFF)
continue
if self.appear(STRATEGY_SEARCH_SAFE_OPTION_ON) \
and get_color(self.device.image, STRATEGY_SEARCH_SAFE_OPTION_ON.area)[2] > 185:
break
skip_first_screenshot = True
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if not self.appear(STRATEGY_SEARCH_POPUP_CHECK):
return False
if self.appear(STRATEGY_SEARCH_ZONE_MODE_ON) \
and self.appear(STRATEGY_SEARCH_WAIT_ON):
break
if self.appear(STRATEGY_SEARCH_ZONE_MODE_OFF):
self.device.click(STRATEGY_SEARCH_ZONE_MODE_ON)
if self.appear(STRATEGY_SEARCH_WAIT_OFF):
self.device.click(STRATEGY_SEARCH_WAIT_ON)
skip_first_screenshot = True
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if not self.appear(STRATEGY_SEARCH_POPUP_CHECK):
return False
check = self.appear(STRATEGY_SEARCH_WAIT_2_CHECK, offset=(20, 40), threshold=0.7)
if check and self.appear(STRATEGY_SEARCH_WAIT_ON, offset=(30, 60)):
break
if check and self.appear(STRATEGY_SEARCH_WAIT_OFF, offset=(30, 60)):
self.device.click(STRATEGY_SEARCH_WAIT_ON)
else:
STRATEGY_SEARCH_SCROLL.set_top(main=self)
STRATEGY_SEARCH_SCROLL.set(0.33, main=self)
skip_first_screenshot = True
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if not self.appear(STRATEGY_SEARCH_POPUP_CHECK):
return False
self.appear_then_click(POPUP_CONFIRM, offset=(30, 30), interval=2)
if self.is_in_map():
return True
def handle_os_map_fleet_lock(self, enable=None):
"""
Args: