Skip to content

Commit

Permalink
overlay (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
aeon0 authored Nov 1, 2023
1 parent f87b455 commit 56344c2
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 22 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ main.build/
main.dist/
main.onefile-build/
generated/
botty_v*/
custom.ini
config/custom.ini
config/custom.*.ini
Expand Down
1 change: 1 addition & 0 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dependencies:
- pytesseract==0.3.10
- rapidfuzz
- mss
- tk
- numpy
- mouse
- coverage
Expand Down
9 changes: 9 additions & 0 deletions src/item/read_descr.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,21 @@ def _find_number(s):
return None


def _remove_text_after_first_keyword(text, keywords):
for keyword in keywords:
match = re.search(re.escape(keyword), text)
if match:
return text[: match.start()]
return text


def _clean_str(s):
cleaned_str = re.sub(r"(\+)?\d+(\.\d+)?%?", "", s) # Remove numbers and trailing % or preceding +
cleaned_str = re.sub(r"[\[\]+\-:%\']", "", cleaned_str) # Remove [ and ] and leftover +, -, %, :, '
cleaned_str = re.sub(
r"\((rogue|barbarian|druid|sorcerer|necromancer) only\)", "", cleaned_str
) # this is not included in our affix table
cleaned_str = _remove_text_after_first_keyword(cleaned_str, ["requires level", "account", "sell value"])
cleaned_str = re.sub(
r"(scroll up|account bound|requires level|sell value|durability|barbarian|rogue|sorceress|druid|necromancer|not useable|by your class|by your clas)",
"",
Expand Down
2 changes: 1 addition & 1 deletion src/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def init(lvl=logging.DEBUG):
Logger.logger.removeHandler(hdlr)

# Create the logger
Logger.logger = logging.getLogger("botty")
Logger.logger = logging.getLogger("d4lf")
for hdlr in Logger.logger.handlers:
Logger.logger.removeHandler(hdlr)
Logger.logger.setLevel(Logger._logger_level)
Expand Down
19 changes: 11 additions & 8 deletions src/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import keyboard
import os
import threading
from utils.window import start_detecting_window
from beautifultable import BeautifulTable
import logging
Expand All @@ -9,9 +7,10 @@
from version import __version__
from config import Config
from logger import Logger
from loot_filter import run_loot_filter
from utils.misc import wait
from cam import Cam
from overlay import Overlay
import keyboard


def main():
Expand All @@ -30,24 +29,28 @@ def main():
else:
print(f"ERROR: Unkown log_lvl {Config().advanced_options['log_lvl']}. Must be one of [info, debug]")

overlay = None

print(f"============ D4 Loot Filter {__version__} ============")
table = BeautifulTable()
table.set_style(BeautifulTable.STYLE_BOX_ROUNDED)
table.rows.append([Config().advanced_options["run_key"], "Run Loot Filter"])
table.rows.append([Config().advanced_options["run_key"], "Run/Stop Loot Filter"])
table.rows.append([Config().advanced_options["exit_key"], "Stop"])
table.columns.header = ["hotkey", "action"]
print(table)
print("\n")

keyboard.add_hotkey(Config().advanced_options["run_key"], lambda: threading.Thread(target=run_loot_filter, daemon=True).start())
keyboard.add_hotkey(Config().advanced_options["run_key"], lambda: overlay.filter_items())
keyboard.add_hotkey(Config().advanced_options["exit_key"], lambda: safe_exit())
keyboard.wait()

overlay = Overlay()
overlay.run()


if __name__ == "__main__":
try:
main()
except:
traceback.print_exc()
print("Press Enter to exit ...")
input()
print("Press Enter to exit ...")
input()
96 changes: 96 additions & 0 deletions src/overlay.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import tkinter as tk
import threading
from utils.window import move_window_to_foreground
from loot_filter import run_loot_filter
from version import __version__
from utils.process_handler import kill_thread
from logger import Logger
import logging


class ListboxHandler(logging.Handler):
def __init__(self, listbox):
logging.Handler.__init__(self)
self.listbox = listbox

def emit(self, record):
log_entry = self.format(record)
padded_text = " " * 1 + log_entry + " " * 1
self.listbox.insert(tk.END, padded_text)
self.listbox.yview(tk.END) # Auto-scroll to the end


class Overlay:
def __init__(self):
self.loot_filter_thread = None
self.is_minimized = True
self.root = tk.Tk()
self.root.title("LootFilter Overlay")
self.root.attributes("-alpha", 0.8)
self.root.overrideredirect(True)
# self.root.wm_attributes("-transparentcolor", "white")
self.root.wm_attributes("-topmost", True)

self.screen_width = self.root.winfo_screenwidth()
self.screen_height = self.root.winfo_screenheight()
self.initial_height = int(30)
self.initial_width = int(self.screen_width * 0.18)
self.maximized_height = int(160)

self.canvas = tk.Canvas(self.root, bg="black", height=self.initial_height, width=self.initial_width, highlightthickness=0)
self.root.geometry(f"{self.initial_width}x{self.initial_height}+{self.screen_width//2 - self.initial_width//2}+0")
self.canvas.pack()

self.toggle_button = tk.Button(self.root, text="toggle", bg="#222222", fg="#555555", borderwidth=0, command=self.toggle_size)
self.canvas.create_window(28, 15, window=self.toggle_button)

self.filter_button = tk.Button(self.root, text="filter", bg="#222222", fg="#555555", borderwidth=0, command=self.filter_items)
self.canvas.create_window(70, 15, window=self.filter_button)

self.terminal_listbox = tk.Listbox(
self.canvas,
bg="black",
fg="white",
highlightcolor="white",
highlightthickness=0,
selectbackground="#222222",
activestyle=tk.NONE,
borderwidth=0,
font=("Courier New", 9),
)
self.terminal_listbox.place(relx=0, rely=0, relwidth=1, relheight=1, y=30)

# Setup the listbox logger handler
listbox_handler = ListboxHandler(self.terminal_listbox)
listbox_handler.setLevel(Logger._logger_level)
Logger.logger.addHandler(listbox_handler)

def toggle_size(self):
if not self.is_minimized:
self.canvas.config(height=self.initial_height, width=self.initial_width)
self.root.geometry(f"{self.initial_width}x{self.initial_height}+{self.screen_width//2 - self.initial_width//2}+0")
else:
self.canvas.config(height=self.maximized_height, width=self.initial_width)
self.root.geometry(f"{self.initial_width}x{self.maximized_height}+{self.screen_width//2 - self.initial_width//2}+0")
self.is_minimized = not self.is_minimized
move_window_to_foreground()

def filter_items(self):
if self.loot_filter_thread is not None:
Logger.info("Stoping Filter process")
kill_thread(self.loot_filter_thread)
self.loot_filter_thread = None
return
if self.is_minimized:
self.toggle_size()
self.loot_filter_thread = threading.Thread(target=self._wrapper_run_loot_filter, daemon=True)
self.loot_filter_thread.start()

def _wrapper_run_loot_filter(self):
try:
run_loot_filter()
finally:
self.loot_filter_thread = None

def run(self):
self.root.mainloop()
12 changes: 0 additions & 12 deletions src/utils/custom_mouse.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,18 +253,6 @@ def move(x: int, y: int, absolute: bool = True, randomize: int | tuple[int, int]

@staticmethod
def _is_clicking_safe():
# TODO: Implement
# # Because of reports that botty lost equiped items, let's check if the inventory is open, and if it is, restrict the mouse move
# mouse_pos = Cam().monitor_to_window(_mouse.get_position())
# is_inventory_open = template_finder.search(
# "INVENTORY_GOLD_BTN", Cam().grab(), threshold=0.8, roi=Config().ui_roi["gold_btn"], use_grayscale=True
# ).valid
# if is_inventory_open:
# is_in_equipped_area = is_in_roi(Config().ui_roi["equipped_inventory_area"], mouse_pos)
# is_in_restricted_inventory_area = is_in_roi(Config().ui_roi["restricted_inventory_area"], mouse_pos)
# if is_in_restricted_inventory_area or is_in_equipped_area:
# Logger.error("Mouse wants to click in equipped area. Cancel action.")
# return False
return True

@staticmethod
Expand Down
1 change: 1 addition & 0 deletions src/utils/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ def stop_detecting_window():
def move_window_to_foreground(window_spec: WindowSpec = D4_WINDOW):
hwnd = get_window_spec_id(window_spec)
if hwnd is not None:
ctypes.windll.user32.ShowWindow(hwnd, 5)
ctypes.windll.user32.SetForegroundWindow(hwnd)


Expand Down

0 comments on commit 56344c2

Please sign in to comment.