1313
1414import pyautogui
1515
16- from lolbot .bot import game , launcher , logger , window
16+ from lolbot .bot import game , launcher , logger , window , controller
1717from lolbot .common import accounts , config , proc
1818from lolbot .lcu .lcu_api import LCUApi , LCUError
1919
3131
3232class BotError (Exception ):
3333 """Indicates the League Client instance should be restarted."""
34+
3435 pass
3536
3637
3738class Bot :
3839 """Handles the League Client and all tasks needed to start a new game."""
40+
3941 def __init__ (self ) -> None :
4042 self .api = LCUApi ()
4143 self .config = config .load_config ()
42- self .league_dir = self .config [' league_dir' ]
43- self .max_level = self .config [' max_level' ]
44- self .lobby = self .config [' lobby' ]
45- self .champs = self .config [' champs' ]
46- self .dialog = self .config [' dialog' ]
44+ self .league_dir = self .config [" league_dir" ]
45+ self .max_level = self .config [" max_level" ]
46+ self .lobby = self .config [" lobby" ]
47+ self .champs = self .config [" champs" ]
48+ self .dialog = self .config [" dialog" ]
4749 self .account = None
4850 self .phase = None
4951 self .prev_phase = None
@@ -62,7 +64,9 @@ def run(self, message_queue: mp.Queue, games: mp.Value, errors: mp.Value) -> Non
6264 try :
6365 errors .value = self .bot_errors
6466 self .account = accounts .get_account (self .max_level )
65- launcher .launch_league (self .account ['username' ], self .account ['password' ])
67+ launcher .launch_league (
68+ self .account ["username" ], self .account ["password" ]
69+ )
6670 self .leveling_loop (games )
6771 proc .close_all_processes ()
6872 self .bot_errors = 0
@@ -93,23 +97,23 @@ def leveling_loop(self, games: mp.Value) -> None:
9397 """Loop that takes action based on the phase of the League Client, continuously starts games."""
9498 while not self .account_leveled ():
9599 match self .get_phase ():
96- case ' None' | ' Lobby' :
100+ case " None" | " Lobby" :
97101 self .start_matchmaking ()
98- case ' Matchmaking' :
102+ case " Matchmaking" :
99103 self .queue ()
100- case ' ReadyCheck' :
104+ case " ReadyCheck" :
101105 self .accept_match ()
102- case ' ChampSelect' :
106+ case " ChampSelect" :
103107 self .champ_select ()
104- case ' InProgress' :
108+ case " InProgress" :
105109 game .play_game ()
106- case ' Reconnect' :
110+ case " Reconnect" :
107111 self .reconnect ()
108- case ' WaitingForStats' :
112+ case " WaitingForStats" :
109113 self .wait_for_stats ()
110- case ' PreEndOfGame' :
114+ case " PreEndOfGame" :
111115 self .pre_end_of_game ()
112- case ' EndOfGame' :
116+ case " EndOfGame" :
113117 self .end_of_game ()
114118 games .value += 1
115119 case _:
@@ -122,7 +126,11 @@ def get_phase(self) -> str:
122126 try :
123127 self .prev_phase = self .phase
124128 self .phase = self .api .get_phase ()
125- if self .prev_phase == self .phase and self .phase != "Matchmaking" and self .phase != 'ReadyCheck' :
129+ if (
130+ self .prev_phase == self .phase
131+ and self .phase != "Matchmaking"
132+ and self .phase != "ReadyCheck"
133+ ):
126134 self .phase_errors += 1
127135 if self .phase_errors == MAX_PHASE_ERRORS :
128136 raise BotError ("Transition error. Phase will not change" )
@@ -173,7 +181,7 @@ def queue(self) -> None:
173181 start = datetime .now ()
174182 while True :
175183 try :
176- if self .api .get_phase () != ' Matchmaking' :
184+ if self .api .get_phase () != " Matchmaking" :
177185 return
178186 elif datetime .now () - start > timedelta (minutes = 15 ):
179187 raise BotError ("Queue Timeout" )
@@ -201,13 +209,21 @@ def champ_select(self) -> None:
201209 except LCUError :
202210 return
203211 try :
204- for action in data ['actions' ][0 ]:
205- if action ['actorCellId' ] == data ['localPlayerCellId' ]:
206- if action ['championId' ] == 0 : # No champ hovered. Hover a champion.
212+ for action in data ["actions" ][0 ]:
213+ if action ["actorCellId" ] == data ["localPlayerCellId" ]:
214+ if (
215+ action ["championId" ] == 0
216+ ): # No champ hovered. Hover a champion.
207217 champ_index += 1
208- self .api .hover_champion (action ['id' ], champ_list [champ_index ])
209- elif not action ['completed' ]: # Champ is hovered but not locked in.
210- self .api .lock_in_champion (action ['id' ], action ['championId' ])
218+ self .api .hover_champion (
219+ action ["id" ], champ_list [champ_index ]
220+ )
221+ elif not action [
222+ "completed"
223+ ]: # Champ is hovered but not locked in.
224+ self .api .lock_in_champion (
225+ action ["id" ], action ["championId" ]
226+ )
211227 else : # Champ is locked in. Nothing left to do.
212228 sleep (2 )
213229 except LCUError :
@@ -223,15 +239,15 @@ def reconnect(self) -> None:
223239 return
224240 except LCUError :
225241 sleep (2 )
226- log .warning (' Could not reconnect to game' )
242+ log .warning (" Could not reconnect to game" )
227243
228244 def wait_for_stats (self ) -> None :
229245 """Waits for the League Client Phase to change to something other than 'WaitingForStats'."""
230246 log .info ("Waiting for stats" )
231247 for i in range (60 ):
232248 sleep (2 )
233249 try :
234- if self .api .get_phase () != ' WaitingForStats' :
250+ if self .api .get_phase () != " WaitingForStats" :
235251 return
236252 except LCUError :
237253 pass
@@ -242,14 +258,22 @@ def pre_end_of_game(self) -> None:
242258 log .info ("Honoring teammates and accepting rewards" )
243259 sleep (3 )
244260 try :
245- proc .click (POPUP_SEND_EMAIL_X_RATIO , proc .LEAGUE_CLIENT_WINNAME , 2 )
261+ controller .left_click (
262+ POPUP_SEND_EMAIL_X_RATIO , proc .LEAGUE_CLIENT_WINNAME , 2
263+ )
246264 if not self .honor_player ():
247265 sleep (60 ) # Honor failed for some reason, wait out the honor screen
248- proc .click (POPUP_SEND_EMAIL_X_RATIO , proc .LEAGUE_CLIENT_WINNAME , 2 )
266+ controller .left_click (
267+ POPUP_SEND_EMAIL_X_RATIO , proc .LEAGUE_CLIENT_WINNAME , 2
268+ )
249269 for i in range (3 ):
250- proc .click (POST_GAME_SELECT_CHAMP_RATIO , proc .LEAGUE_CLIENT_WINNAME , 1 )
251- proc .click (POST_GAME_OK_RATIO , proc .LEAGUE_CLIENT_WINNAME , 1 )
252- proc .click (POPUP_SEND_EMAIL_X_RATIO , proc .LEAGUE_CLIENT_WINNAME , 1 )
270+ controller .left_click (
271+ POST_GAME_SELECT_CHAMP_RATIO , proc .LEAGUE_CLIENT_WINNAME , 1
272+ )
273+ controller .left_click (POST_GAME_OK_RATIO , proc .LEAGUE_CLIENT_WINNAME , 1 )
274+ controller .left_click (
275+ POPUP_SEND_EMAIL_X_RATIO , proc .LEAGUE_CLIENT_WINNAME , 1
276+ )
253277 except (window .WindowNotFound , pyautogui .FailSafeException ):
254278 sleep (3 )
255279
@@ -259,12 +283,12 @@ def honor_player(self) -> bool:
259283 try :
260284 players = self .api .get_players_to_honor ()
261285 index = random .randint (0 , len (players ) - 1 )
262- self .api .honor_player (players [index ][' summonerId' ])
286+ self .api .honor_player (players [index ][" summonerId" ])
263287 sleep (2 )
264288 return True
265289 except LCUError as e :
266290 log .warning (e )
267- log .warning (' Honor Failure' )
291+ log .warning (" Honor Failure" )
268292 return False
269293
270294 def end_of_game (self ) -> None :
@@ -273,7 +297,7 @@ def end_of_game(self) -> None:
273297 posted = False
274298 for i in range (15 ):
275299 try :
276- if self .api .get_phase () != ' EndOfGame' :
300+ if self .api .get_phase () != " EndOfGame" :
277301 return
278302 if not posted :
279303 self .api .play_again ()
@@ -289,8 +313,8 @@ def account_leveled(self) -> bool:
289313 """Checks if account has reached max level."""
290314 try :
291315 if self .api .get_summoner_level () >= self .max_level :
292- if self .account [' username' ] == self .api .get_display_name ():
293- self .account [' level' ] = self .max_level
316+ if self .account [" username" ] == self .api .get_display_name ():
317+ self .account [" level" ] = self .max_level
294318 accounts .save_or_add (self .account )
295319 log .info ("Account successfully leveled" )
296320 return True
@@ -312,23 +336,25 @@ def wait_for_patching(self) -> None:
312336 def set_game_config (self ) -> None :
313337 """Overwrites the League of Legends game config."""
314338 log .info ("Overwriting game configs" )
315- path = self .league_dir + ' /Config/game.cfg'
339+ path = self .league_dir + " /Config/game.cfg"
316340 folder = os .path .abspath (os .path .join (path , os .pardir ))
317341 for filename in os .listdir (folder ):
318342 file_path = os .path .join (folder , filename )
319343 try :
320344 if os .path .isfile (file_path ) or os .path .islink (file_path ):
321345 os .unlink (file_path )
322346 except Exception as e :
323- log .error (' Failed to delete %s. Reason: %s' % (file_path , e ))
347+ log .error (" Failed to delete %s. Reason: %s" % (file_path , e ))
324348 shutil .copy (proc .resource_path (config .GAME_CFG ), path )
325349
326350 @staticmethod
327351 def print_ascii () -> None :
328352 """Prints some League ascii art."""
329- print ("""\n \n
353+ print (
354+ """\n \n
330355 ──────▄▌▐▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▌
331356 ───▄▄██▌█ BEEP BEEP
332357 ▄▄▄▌▐██▌█ -15 LP DELIVERY
333358 ███████▌█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▌
334- ▀(⊙)▀▀▀▀▀▀▀(⊙)(⊙)▀▀▀▀▀▀▀▀▀▀(⊙)\n \n \t \t \t \t LoL Bot\n \n """ )
359+ ▀(⊙)▀▀▀▀▀▀▀(⊙)(⊙)▀▀▀▀▀▀▀▀▀▀(⊙)\n \n \t \t \t \t LoL Bot\n \n """
360+ )
0 commit comments