152 lines
5.4 KiB
Python
152 lines
5.4 KiB
Python
import time
|
|
from screen import grab
|
|
from config import Config
|
|
from input_layer import keyboard
|
|
from input_layer import mouse
|
|
from logger import Logger
|
|
from utils.misc import wait
|
|
from ui_manager import wait_until_hidden, wait_until_visible, detect_screen_object, select_screen_object_match, ScreenObjects, list_visible_objects, is_visible
|
|
from inventory import common
|
|
from screen import convert_screen_to_monitor
|
|
from threading import Lock
|
|
|
|
exit_mutex = Lock()
|
|
|
|
def enable_no_pickup() -> bool:
|
|
# """
|
|
# Checks the best match between enabled and disabled an retrys if already set.
|
|
# :return: Returns True if we succesfully set the nopickup option
|
|
# """
|
|
keyboard.send('enter')
|
|
wait(0.1, 0.25)
|
|
keyboard.write('/nopickup',delay=.20)
|
|
keyboard.send('enter')
|
|
wait(0.1, 0.25)
|
|
if not (item_pickup_text := wait_until_visible(ScreenObjects.ItemPickupText, timeout=1.3)).valid:
|
|
return False
|
|
if item_pickup_text.name == "ITEM_PICKUP_DISABLED":
|
|
return True
|
|
keyboard.send('enter')
|
|
wait(0.1, 0.25)
|
|
keyboard.send('up')
|
|
wait(0.1, 0.25)
|
|
keyboard.send('enter')
|
|
wait(0.1, 0.25)
|
|
return True
|
|
|
|
def fast_save_and_exit() -> bool:
|
|
"""
|
|
Performes save and exit action from within game as fast as possible
|
|
:return: Bool if action was successful
|
|
"""
|
|
success = False
|
|
attempts = 0
|
|
|
|
x_center = Config().ui_roi["save_and_exit"][0] + Config().ui_roi["save_and_exit"][2]/2
|
|
y_center = Config().ui_roi["save_and_exit"][1] + Config().ui_roi["save_and_exit"][3]/2
|
|
save_and_exit_pos = convert_screen_to_monitor( (x_center,y_center) )
|
|
|
|
exit_mutex.acquire() #Prevent game_controller and health_manager threads from conflict
|
|
while attempts < 6 and not success:
|
|
keyboard.send("esc") #Ensure we close anything opened (chat box, inv, options etc)
|
|
keyboard.send("space") #To ensure we are in proper state, press space to close menu if openned
|
|
keyboard.send("esc") #Open save and exit menu
|
|
mouse.move(*save_and_exit_pos, delay_factor=(0.02, 0.05)) #Move the mouse to the save & exit
|
|
wait(0.02, 0.05)
|
|
mouse.click("left")
|
|
|
|
attempts += 1
|
|
success = wait_until_hidden(ScreenObjects.InGame, 0.5)
|
|
if not success:
|
|
Logger.debug(f"Failed to perform fast save/exit on attempt #{attempts}")
|
|
exit_mutex.release()
|
|
if success:
|
|
Logger.info(f"Successfully performed fast save/exit in {attempts} attempt(s)")
|
|
else:
|
|
Logger.error("Failed to perform fast save/exit")
|
|
return success
|
|
|
|
def save_and_exit() -> bool:
|
|
"""
|
|
Performes save and exit action from within game
|
|
:return: Bool if action was successful
|
|
"""
|
|
# if exit button isn't detected already, press escape
|
|
attempts = 1
|
|
success = False
|
|
while attempts <= 2 and not success:
|
|
if not (exit_button := detect_screen_object(ScreenObjects.SaveAndExit)).valid:
|
|
keyboard.send("esc")
|
|
# wait for exit button to appear
|
|
exit_button = wait_until_visible(ScreenObjects.SaveAndExit, 1)
|
|
# if exit button is found, double click it to be sure
|
|
if exit_button.valid:
|
|
select_screen_object_match(exit_button, delay_factor=(0.02, 0.05))
|
|
wait(0.02, 0.05)
|
|
mouse.click(button="left")
|
|
# if center icon on player bar disappears then save/exit was successful
|
|
success = wait_until_hidden(ScreenObjects.InGame, 3)
|
|
attempts += 1
|
|
if not success:
|
|
Logger.debug("Failed to find or click save/exit button")
|
|
return success
|
|
|
|
def dismiss_skills_icon() -> bool:
|
|
start = time.time()
|
|
while (match := detect_screen_object(ScreenObjects.QuestSkillBtn)).valid:
|
|
select_screen_object_match(match)
|
|
wait(0.6)
|
|
common.close()
|
|
if (time.time() - start) > 15:
|
|
return False
|
|
return True
|
|
|
|
def pickup_corpse():
|
|
Logger.info("Pickup corpse")
|
|
move_to_corpse()
|
|
wait(0.4,0.6)
|
|
mouse.click(button="left")
|
|
#TODO: handle "Overburdened"
|
|
|
|
def move_to_corpse():
|
|
pos = convert_screen_to_monitor((Config().ui_pos["corpse_x"], Config().ui_pos["corpse_y"]))
|
|
mouse.move(*pos)
|
|
|
|
def return_to_play() -> bool:
|
|
substrings = ["NPC", "Panel", "SaveAndExit"]
|
|
img=grab()
|
|
start=time.time()
|
|
while (elapsed := (time.time() - start) < 5):
|
|
need_escape = False
|
|
match = detect_screen_object(ScreenObjects.InGame, img)
|
|
if match.valid and "DARK" in match.name:
|
|
need_escape = True
|
|
if not need_escape:
|
|
for substring in substrings:
|
|
if (need_escape := any(substring in string for string in list_visible_objects(img))):
|
|
break
|
|
if need_escape:
|
|
keyboard.send("esc")
|
|
wait(1)
|
|
img=grab()
|
|
else:
|
|
break
|
|
if not elapsed:
|
|
Logger.error("return_to_play(): failed to return to neutral play screen")
|
|
return False
|
|
return True
|
|
|
|
# Testing
|
|
if __name__ == "__main__":
|
|
from input_layer import keyboard
|
|
import os
|
|
from screen import start_detecting_window, stop_detecting_window
|
|
start_detecting_window()
|
|
keyboard.add_hotkey('f12', lambda: Logger.info('Force Exit (f12)') or stop_detecting_window() or os._exit(1))
|
|
print("Go to D2R window and press f11 to start game")
|
|
keyboard.wait("f11")
|
|
from config import Config
|
|
import template_finder
|
|
|
|
return_to_play()
|