mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-26 18:20:42 +00:00
commit
7dd2ef6ab1
1
alas.py
1
alas.py
@ -42,6 +42,7 @@ class AzurLaneAutoScript:
|
||||
print(f'{key} = {value}')
|
||||
|
||||
logger.hr('Settings saved')
|
||||
self.config.config_check()
|
||||
|
||||
def reward(self):
|
||||
for key, value in self.config.config['Reward'].items():
|
||||
|
78
campaign/campaign_main/campaign_9_2.py
Normal file
78
campaign/campaign_main/campaign_9_2.py
Normal file
@ -0,0 +1,78 @@
|
||||
from module.campaign.campaign_base import CampaignBase
|
||||
from module.map.map_base import CampaignMap
|
||||
from module.map.map_grids import SelectedGrids, RoadGrids
|
||||
from module.logger import logger
|
||||
|
||||
|
||||
MAP = CampaignMap('9-2')
|
||||
MAP.shape = 'I5'
|
||||
MAP.map_data = '''
|
||||
++ ++ ME -- MB ME -- ME --
|
||||
MM ++ ME ME MB ME ++ ME --
|
||||
ME -- ME ++ ++ ++ ++ ME ++
|
||||
-- ++ -- -- ++ SP -- ME --
|
||||
-- ME -- SP ++ SP -- -- --
|
||||
'''
|
||||
MAP.weight_data = '''
|
||||
10 10 30 10 10 10 10 10 10
|
||||
10 10 20 20 10 30 10 10 10
|
||||
30 10 20 10 10 10 10 10 10
|
||||
10 10 10 10 10 10 10 10 10
|
||||
10 30 10 10 10 10 10 10 10
|
||||
'''
|
||||
#MAP.camera_data = ['D4']
|
||||
MAP.spawn_data = [
|
||||
{'battle': 0, 'enemy': 3},
|
||||
{'battle': 1, 'enemy': 2},
|
||||
{'battle': 2, 'enemy': 2},
|
||||
{'battle': 3, 'enemy': 1},
|
||||
{'battle': 4, 'enemy': 1},
|
||||
{'battle': 5, 'boss': 1},
|
||||
]
|
||||
|
||||
A1, B1, C1, D1, E1, F1, G1, H1, I1, \
|
||||
A2, B2, C2, D2, E2, F2, G2, H2, I2, \
|
||||
A3, B3, C3, D3, E3, F3, G3, H3, I3, \
|
||||
A4, B4, C4, D4, E4, F4, G4, H4, I4, \
|
||||
A5, B5, C5, D5, E5, F5, G5, H5, I5, \
|
||||
= MAP.flatten()
|
||||
|
||||
road_main = RoadGrids([C3, C2, [C1, D2], F1, H1, H2, H3, H4])
|
||||
|
||||
class Config:
|
||||
INTERNAL_LINES_HOUGHLINES_THRESHOLD = 40
|
||||
EDGE_LINES_HOUGHLINES_THRESHOLD = 40
|
||||
COINCIDENT_POINT_ENCOURAGE_DISTANCE = 1.5
|
||||
INTERNAL_LINES_FIND_PEAKS_PARAMETERS = {
|
||||
'height': (150, 255 - 24),
|
||||
'width': (0.9, 10),
|
||||
'prominence': 10,
|
||||
'distance': 35,
|
||||
}
|
||||
EDGE_LINES_FIND_PEAKS_PARAMETERS = {
|
||||
'height': (255 - 24, 255),
|
||||
'prominence': 10,
|
||||
'distance': 50,
|
||||
'width': (0, 10),
|
||||
'wlen': 1000,
|
||||
}
|
||||
|
||||
class Campaign(CampaignBase):
|
||||
MAP = MAP
|
||||
|
||||
def battle_0(self):
|
||||
if self.clear_roadblocks([road_main]):
|
||||
return True
|
||||
if self.clear_potential_roadblocks([road_main]):
|
||||
return True
|
||||
|
||||
return self.battle_default()
|
||||
|
||||
def battle_5(self):
|
||||
boss = self.map.select(is_boss=True)
|
||||
if boss:
|
||||
if not self.check_accessibility(boss[0], fleet=2):
|
||||
if self.clear_roadblocks([road_main]):
|
||||
return True
|
||||
|
||||
return self.fleet_2.clear_boss()
|
82
campaign/campaign_main/campaign_9_4.py
Normal file
82
campaign/campaign_main/campaign_9_4.py
Normal file
@ -0,0 +1,82 @@
|
||||
from module.campaign.campaign_base import CampaignBase
|
||||
from module.map.map_base import CampaignMap
|
||||
from module.map.map_grids import SelectedGrids, RoadGrids
|
||||
from module.logger import logger
|
||||
|
||||
MAP = CampaignMap('9-4')
|
||||
MAP.shape = 'I6'
|
||||
|
||||
MAP.map_data = '''
|
||||
MB -- ME -- ++ ++ ++ -- MB
|
||||
-- ++ __ ME -- ME ME ME --
|
||||
ME -- ME -- ME -- __ ++ --
|
||||
ME -- ++ ++ -- -- ME __ ME
|
||||
SP -- MA ++ ME -- ++ ME --
|
||||
SP -- -- ME -- ME ++ -- MB
|
||||
'''
|
||||
|
||||
MAP.weight_data = '''
|
||||
10 10 20 10 10 10 10 10 10
|
||||
10 10 10 20 10 10 10 10 10
|
||||
10 10 20 10 20 10 10 10 10
|
||||
20 10 10 10 10 10 10 10 10
|
||||
10 10 10 10 10 10 10 10 10
|
||||
10 10 10 10 10 10 10 10 10
|
||||
'''
|
||||
|
||||
MAP.spawn_data = [
|
||||
{'battle': 0, 'enemy': 3},
|
||||
{'battle': 1, 'enemy': 2},
|
||||
{'battle': 2, 'enemy': 2},
|
||||
{'battle': 3, 'enemy': 1},
|
||||
{'battle': 4, 'enemy': 2},
|
||||
{'battle': 5, 'boss': 1},
|
||||
]
|
||||
|
||||
A1, B1, C1, D1, E1, F1, G1, H1, I1, \
|
||||
A2, B2, C2, D2, E2, F2, G2, H2, I2, \
|
||||
A3, B3, C3, D3, E3, F3, G3, H3, I3, \
|
||||
A4, B4, C4, D4, E4, F4, G4, H4, I4, \
|
||||
A5, B5, C5, D5, E5, F5, G5, H5, I5, \
|
||||
A6, B6, C6, D6, E6, F6, G6, H6, I6, \
|
||||
= MAP.flatten()
|
||||
|
||||
road_main = RoadGrids([A3, D6, [E5, F6], G4, I4])
|
||||
|
||||
class Config:
|
||||
INTERNAL_LINES_HOUGHLINES_THRESHOLD = 40
|
||||
EDGE_LINES_HOUGHLINES_THRESHOLD = 40
|
||||
COINCIDENT_POINT_ENCOURAGE_DISTANCE = 1.5
|
||||
INTERNAL_LINES_FIND_PEAKS_PARAMETERS = {
|
||||
'height': (150, 255 - 24),
|
||||
'width': (0.9, 10),
|
||||
'prominence': 10,
|
||||
'distance': 35,
|
||||
}
|
||||
EDGE_LINES_FIND_PEAKS_PARAMETERS = {
|
||||
'height': (255 - 24, 255),
|
||||
'prominence': 10,
|
||||
'distance': 50,
|
||||
'width': (0, 10),
|
||||
'wlen': 1000,
|
||||
}
|
||||
|
||||
class Campaign(CampaignBase):
|
||||
MAP = MAP
|
||||
|
||||
def battle_0(self):
|
||||
if self.clear_roadblocks([road_main]):
|
||||
return True
|
||||
if self.clear_potential_roadblocks([road_main]):
|
||||
return True
|
||||
|
||||
return self.battle_default()
|
||||
|
||||
def battle_5(self):
|
||||
boss = self.map.select(is_boss=True)
|
||||
if boss:
|
||||
if not self.check_accessibility(boss[0], fleet=2):
|
||||
if self.clear_roadblocks([road_main]):
|
||||
return True
|
||||
|
||||
return self.fleet_2.clear_boss()
|
83
dev_tools/grids_debug.py
Normal file
83
dev_tools/grids_debug.py
Normal file
@ -0,0 +1,83 @@
|
||||
import module.config.server as server
|
||||
|
||||
server.server = 'cn' # Don't need to edit, it's used to avoid error.
|
||||
|
||||
from module.map.grids import Grids
|
||||
from module.config.config import AzurLaneConfig
|
||||
from PIL import Image
|
||||
|
||||
"""
|
||||
This file is use to debug a perspective error.
|
||||
It will call the map detection module (module/map/grids.py), outside Alas.
|
||||
"""
|
||||
|
||||
"""
|
||||
Put image here.
|
||||
"""
|
||||
file = ''
|
||||
|
||||
|
||||
class Config:
|
||||
pass
|
||||
|
||||
INTERNAL_LINES_HOUGHLINES_THRESHOLD = 40
|
||||
EDGE_LINES_HOUGHLINES_THRESHOLD = 40
|
||||
COINCIDENT_POINT_ENCOURAGE_DISTANCE = 1.5
|
||||
|
||||
INTERNAL_LINES_FIND_PEAKS_PARAMETERS = {
|
||||
'height': (150, 255 - 24),
|
||||
'width': (0.9, 10),
|
||||
'prominence': 10,
|
||||
'distance': 35,
|
||||
}
|
||||
EDGE_LINES_FIND_PEAKS_PARAMETERS = {
|
||||
'height': (255 - 24, 255),
|
||||
'prominence': 10,
|
||||
'distance': 50,
|
||||
'width': (0, 10),
|
||||
'wlen': 1000
|
||||
}
|
||||
|
||||
# These are the full configuration in module/config/config.py
|
||||
"""
|
||||
MAP_HAS_SIREN = False
|
||||
MAP_HAS_DYNAMIC_RED_BORDER = False
|
||||
MAP_SIREN_TEMPLATE = ['1', '2', '3', 'DD']
|
||||
|
||||
# Parameters for scipy.signal.find_peaks
|
||||
# https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks.html
|
||||
INTERNAL_LINES_FIND_PEAKS_PARAMETERS = {
|
||||
'height': (150, 255 - 40),
|
||||
'width': (0.9, 10),
|
||||
'prominence': 10,
|
||||
'distance': 35,
|
||||
}
|
||||
EDGE_LINES_FIND_PEAKS_PARAMETERS = {
|
||||
'height': (255 - 24, 255),
|
||||
'prominence': 10,
|
||||
'distance': 50,
|
||||
# 'width': (0, 7),
|
||||
'wlen': 1000
|
||||
}
|
||||
# Parameters for cv2.HoughLines
|
||||
INTERNAL_LINES_HOUGHLINES_THRESHOLD = 75
|
||||
EDGE_LINES_HOUGHLINES_THRESHOLD = 75
|
||||
# Parameters for lines pre-cleansing
|
||||
HORIZONTAL_LINES_THETA_THRESHOLD = 0.005
|
||||
VERTICAL_LINES_THETA_THRESHOLD = 18
|
||||
TRUST_EDGE_LINES = False # True to use edge to crop inner, false to use inner to crop edge
|
||||
# Parameters for perspective calculating
|
||||
VANISH_POINT_RANGE = ((540, 740), (-3000, -1000))
|
||||
DISTANCE_POINT_X_RANGE = ((-3200, -1600),)
|
||||
# Parameters for line cleansing
|
||||
COINCIDENT_POINT_ENCOURAGE_DISTANCE = 3
|
||||
ERROR_LINES_TOLERANCE = (-10, 10)
|
||||
MID_DIFF_RANGE_H = (129 - 3, 129 + 3)
|
||||
MID_DIFF_RANGE_V = (129 - 3, 129 + 3)
|
||||
"""
|
||||
|
||||
|
||||
cfg = AzurLaneConfig().merge(Config())
|
||||
grids = Grids(Image.open(file), cfg)
|
||||
grids.predict()
|
||||
grids.show()
|
143
doc/debug_perspective_en.md
Normal file
143
doc/debug_perspective_en.md
Normal file
@ -0,0 +1,143 @@
|
||||
# How to debug a perspective error
|
||||
|
||||
## Normal logs
|
||||
|
||||
This is an example log.
|
||||
|
||||
```
|
||||
2020-06-03 00:44:46.221 | INFO | vanish_point: ( 646, -1736)
|
||||
2020-06-03 00:44:46.222 | INFO | distant_point: (-2321, -1736)
|
||||
2020-06-03 00:44:46.266 | INFO | 0.235s _ Horizontal: 5 (7 inner, 3 edge)
|
||||
2020-06-03 00:44:46.266 | INFO | Edges: / \ Vertical: 9 (10 inner, 3 edge)
|
||||
2020-06-03 00:44:46.273 | INFO | Center grid: (3, 1)
|
||||
2020-06-03 00:44:46.493 | INFO | -- -- -- -- -- 2M -- --
|
||||
2020-06-03 00:44:46.501 | INFO | MY -- -- MY -- -- 3M --
|
||||
2020-06-03 00:44:46.501 | INFO | -- -- FL -- -- -- -- --
|
||||
2020-06-03 00:44:46.501 | INFO | -- 1L -- MY -- 2L --
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Too few grid lines
|
||||
|
||||
This may happens when it detected too few grid lines.
|
||||
|
||||
``` File "E:\ProgramData\Pycharm\AzurLaneAutoScript\module\map\camera.py", line 114, in update
|
||||
File "AzurLaneAutoScript\module\map\camera.py", line 114, in update
|
||||
self.grids = Grids(self.device.image, config=self.config)
|
||||
File "AzurLaneAutoScript\module\map\grids.py", line 19, in __init__
|
||||
super().__init__(image, config)
|
||||
File "AzurLaneAutoScript\module\map\perspective.py", line 81, in __init__
|
||||
self.crossings = self.horizontal.cross(self.vertical)
|
||||
File "AzurLaneAutoScript\module\map\perspective_items.py", line 170, in cross
|
||||
points = np.vstack(self.cross_two_lines(self, other))
|
||||
File "lib\site-packages\numpy\core\shape_base.py", line 234, in vstack
|
||||
return _nx.concatenate([atleast_2d(_m) for _m in tup], 0)
|
||||
File "lib\site-packages\numpy\core\shape_base.py", line 234, in <listcomp>
|
||||
return _nx.concatenate([atleast_2d(_m) for _m in tup], 0)
|
||||
File "AzurLaneAutoScript\module\map\perspective_items.py", line 163, in cross_two_lines
|
||||
for rho1, sin1, cos1 in zip(lines1.rho, lines1.sin, lines1.cos):
|
||||
AttributeError: 'Lines' object has no attribute 'rho'
|
||||
```
|
||||
|
||||
```
|
||||
File "AzurLaneAutoScript\module\map\camera.py", line 114, in update
|
||||
self.grids = Grids(self.device.image, config=self.config)
|
||||
File "AzurLaneAutoScript\module\map\grids.py", line 19, in __init__
|
||||
super().__init__(image, config)
|
||||
File "AzurLaneAutoScript\module\map\perspective.py", line 98, in __init__
|
||||
self.horizontal, inner=inner_h.group(), edge=edge_h)
|
||||
File "AzurLaneAutoScript\module\map\perspective.py", line 352, in line_cleanse
|
||||
clean = self.mid_cleanse(origin, is_horizontal=lines.is_horizontal, threshold=threshold)
|
||||
File "AzurLaneAutoScript\module\map\perspective.py", line 346, in mid_cleanse
|
||||
mids = convert_to_y(mids)
|
||||
File "AzurLaneAutoScript\module\map\perspective.py", line 277, in convert_to_y
|
||||
return Points([[x, self.config.SCREEN_CENTER[1]] for x in xs], config=self.config) \
|
||||
File "AzurLaneAutoScript\module\map\perspective_items.py", line 15, in __init__
|
||||
self.x, self.y = self.points.T
|
||||
ValueError: not enough values to unpack (expected 2, got 0)
|
||||
```
|
||||
|
||||
Try reduce the threshold of `cv2.HoughLines`. Default is 75.
|
||||
|
||||
Lower threshold means more lines.
|
||||
|
||||
```
|
||||
INTERNAL_LINES_HOUGHLINES_THRESHOLD = 40
|
||||
EDGE_LINES_HOUGHLINES_THRESHOLD = 40
|
||||
```
|
||||
|
||||
Then you should also lower this and make a closer fit to the lines.
|
||||
|
||||
Lower means closer fit, ignore more wrong lines.
|
||||
|
||||
```
|
||||
COINCIDENT_POINT_ENCOURAGE_DISTANCE = 1.5
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Camera outside map
|
||||
|
||||
```
|
||||
File "AzurLaneAutoScript-master\module\map\camera.py", line 114, in update
|
||||
self.grids = Grids(self.device.image, config=self.config)
|
||||
File "AzurLaneAutoScript-master\module\map\grids.py", line 19, in __init__
|
||||
super().__init__(image, config)
|
||||
File "AzurLaneAutoScript-master\module\map\perspective.py", line 98, in __init__
|
||||
self.horizontal, inner=inner_h.group(), edge=edge_h)
|
||||
File "AzurLaneAutoScript-master\module\map\perspective.py", line 383, in line_cleanse
|
||||
raise PerspectiveError('Camera outside map: to the %s' % ('upper' if lines.is_horizontal else 'right'))
|
||||
module.exception.PerspectiveError: Camera outside map: to the upper
|
||||
```
|
||||
|
||||
Alas can not handle if camera is not focusing on any map grid, it will swipe back if catches `Camera outside map`. This may happens when some inner lines are detected as edge lines.
|
||||
|
||||
Try adjust the parameter of `scipy.signal.find_peaks`, the `height` value.
|
||||
|
||||
- **height** Lower means detect lighter lines, 255 means pure black.
|
||||
- **width** Line width, in pixels.
|
||||
- **prominence** Line needs to be how much darker than surrounding pixels.
|
||||
- **distance** Minimum distance between two detected point on line.
|
||||
- **wlen** Maximum amount of data to be processed in one time.
|
||||
|
||||
Know more about these parameters [here](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks.html)
|
||||
|
||||
```
|
||||
INTERNAL_LINES_FIND_PEAKS_PARAMETERS = {
|
||||
'height': (150, 255 - 24),
|
||||
'width': (0.9, 10),
|
||||
'prominence': 10,
|
||||
'distance': 35,
|
||||
}
|
||||
EDGE_LINES_FIND_PEAKS_PARAMETERS = {
|
||||
'height': (255 - 24, 255),
|
||||
'prominence': 10,
|
||||
'distance': 50,
|
||||
'width': (0, 10),
|
||||
'wlen': 1000
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Coincident point unexpected
|
||||
|
||||
```
|
||||
2020-05-31 20:04:47.397 | INFO | Horizontal coincident point unexpected: [-92.817316 141.99589405]
|
||||
2020-05-31 20:04:48.509 | INFO | Vertical coincident point unexpected: [-692.01967461 141.68981244]
|
||||
```
|
||||
|
||||
Try adjust the initial value of coincident point. if 141.99589405 is in (129 - 3, 129 + 3), it shut up.
|
||||
|
||||
But remember, an incorrect value will ruin everything in map detection, it usually works fine with these logs show up.
|
||||
|
||||
```
|
||||
MID_DIFF_RANGE_H = (129 - 3, 129 + 3)
|
||||
MID_DIFF_RANGE_V = (129 - 3, 129 + 3)
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Too many deleted lines
|
||||
|
@ -84,6 +84,9 @@ class Timer:
|
||||
pass
|
||||
else:
|
||||
confirm_timer.reset()
|
||||
|
||||
Also, It's a good idea to set `count`, to make alas run more stable on slow computers.
|
||||
Expected speed is 0.35 second / screenshot.
|
||||
"""
|
||||
self.limit = limit
|
||||
self.count = count
|
||||
|
@ -141,12 +141,12 @@ def main(ini_name=''):
|
||||
f1.add_argument('--舰队步长1', default=default('--舰队步长1'), choices=['1', '2', '3', '4', '5', '6'])
|
||||
|
||||
f2 = fleet.add_argument_group('BOSS队')
|
||||
f2.add_argument('--舰队编号2', default=default('--舰队编号2'), choices=['不使用', '1', '2', '3', '4', '5', '6'])
|
||||
f2.add_argument('--舰队编号2', default=default('--舰队编号2'), choices=['1', '2', '3', '4', '5', '6'])
|
||||
f2.add_argument('--舰队阵型2', default=default('--舰队阵型2'), choices=['单纵阵', '复纵阵', '轮形阵'])
|
||||
f2.add_argument('--舰队步长2', default=default('--舰队步长2'), choices=['1', '2', '3', '4', '5', '6'])
|
||||
|
||||
f3 = fleet.add_argument_group('备用道中队')
|
||||
f3.add_argument('--舰队编号3', default=default('--舰队编号3'), choices=['不使用', '1', '2', '3', '4', '5', '6'])
|
||||
f3.add_argument('--舰队编号3', default=default('--舰队编号3'), choices=['1', '2', '3', '4', '5', '6'])
|
||||
f3.add_argument('--舰队阵型3', default=default('--舰队阵型3'), choices=['单纵阵', '复纵阵', '轮形阵'])
|
||||
f3.add_argument('--舰队步长3', default=default('--舰队步长3'), choices=['1', '2', '3', '4', '5', '6'])
|
||||
|
||||
|
@ -139,12 +139,12 @@ def main(ini_name=''):
|
||||
f1.add_argument('--fleet_step_1', default=default('--fleet_step_1'), choices=['1', '2', '3', '4', '5', '6'], help='In event map, fleet has limit on moving, so fleet_step is how far can a fleet goes in one operation, if map cleared, it will be ignored')
|
||||
|
||||
f2 = fleet.add_argument_group('Boss Fleet')
|
||||
f2.add_argument('--fleet_index_2', default=default('--fleet_index_2'), choices=['do_not_use', '1', '2', '3', '4', '5', '6'])
|
||||
f2.add_argument('--fleet_index_2', default=default('--fleet_index_2'), choices=['1', '2', '3', '4', '5', '6'])
|
||||
f2.add_argument('--fleet_formation_2', default=default('--fleet_formation_2'), choices=['Line Ahead', 'Double Line', 'Diamond'])
|
||||
f2.add_argument('--fleet_step_2', default=default('--fleet_step_2'), choices=['1', '2', '3', '4', '5', '6'], help='In event map, fleet has limit on moving, so fleet_step is how far can a fleet goes in one operation, if map cleared, it will be ignored')
|
||||
|
||||
f3 = fleet.add_argument_group('Alternate Mob Fleet')
|
||||
f3.add_argument('--fleet_index_3', default=default('--fleet_index_3'), choices=['do_not_use', '1', '2', '3', '4', '5', '6'])
|
||||
f3.add_argument('--fleet_index_3', default=default('--fleet_index_3'), choices=['1', '2', '3', '4', '5', '6'])
|
||||
f3.add_argument('--fleet_formation_3', default=default('--fleet_formation_3'), choices=['Line Ahead', 'Double Line', 'Diamond'])
|
||||
f3.add_argument('--fleet_step_3', default=default('--fleet_step_3'), choices=['1', '2', '3', '4', '5', '6'], help='In event map, fleet has limit on moving, so fleet_step is how far can a fleet goes in one operation, if map cleared, it will be ignored')
|
||||
|
||||
|
@ -375,6 +375,13 @@ class AzurLaneConfig:
|
||||
self.CONFIG_FILE = f'./config/{name}.ini'
|
||||
self.config.read_file(codecs.open(self.CONFIG_FILE, "r", "utf8"))
|
||||
self.load_from_config(self.config)
|
||||
self.config_check()
|
||||
|
||||
def config_check(self):
|
||||
if self.FLEET_1 == self.FLEET_2:
|
||||
logger.warning(f'Mob fleet [{self.FLEET_1}] and boss fleet [{self.FLEET_2}] is the same')
|
||||
logger.warning('They should to be set to different fleets')
|
||||
exit(1)
|
||||
|
||||
def save(self):
|
||||
self.config.write(codecs.open(self.CONFIG_FILE, "w+", "utf8"))
|
||||
|
@ -30,7 +30,7 @@ class UI(ModuleBase):
|
||||
logger.hr('UI click')
|
||||
if appear_button is None:
|
||||
appear_button = click_button
|
||||
click_timer = Timer(retry_wait)
|
||||
click_timer = Timer(retry_wait, count=retry_wait // 0.5)
|
||||
while 1:
|
||||
if skip_first_screenshot:
|
||||
skip_first_screenshot = False
|
||||
|
Loading…
Reference in New Issue
Block a user