mirror of
https://github.com/fishyboteso/fishyboteso.git
synced 2024-08-30 18:32:13 +00:00
ai fix and full-auto test setup:
gui - enable "Debug > Keep Console" to unhide full auto - Removed Log Dump from Debug menu semi-auto - starting ai fix, sometime bot doesnt start - minimize bug fix, when minimized gui goes out of sync - keyboard button to pause play, now bot can be paused and played using f9 - now shows running as admin message - better error message, now tells to check #read-me-first instead full-auto - add tesseract binary in directory - install addon for full auto
This commit is contained in:
parent
648f3a8a32
commit
1ae645294d
@ -3,6 +3,7 @@ include README.md
|
||||
include requirements.txt
|
||||
include fishy/icon.ico
|
||||
include fishy/ProvisionsChalutier.zip
|
||||
include fishy/FooAddon.zip
|
||||
include fishy/fishybot_logo.png
|
||||
|
||||
recursive-include tests *
|
||||
|
BIN
fishy/FooAddon.zip
Normal file
BIN
fishy/FooAddon.zip
Normal file
Binary file not shown.
@ -1,2 +1,2 @@
|
||||
from fishy.__main__ import main
|
||||
__version__ = "0.3.5"
|
||||
__version__ = "0.3.6"
|
||||
|
@ -11,7 +11,6 @@ from fishy import web, helper, gui
|
||||
from fishy.engine.event_handler import EngineEventHandler
|
||||
from fishy.gui import GUI
|
||||
from fishy.helper import Config
|
||||
from fishy.engine import SemiFisherEngine
|
||||
|
||||
|
||||
# noinspection PyBroadException
|
||||
@ -42,7 +41,10 @@ def initialize(c: Config, window_to_hide):
|
||||
helper.install_thread_excepthook()
|
||||
sys.excepthook = helper.unhandled_exception_logging
|
||||
|
||||
helper.check_addon()
|
||||
helper.check_addon("ProvisionsChalutier")
|
||||
|
||||
if c.get("debug", False):
|
||||
helper.check_addon("FooAddon")
|
||||
|
||||
|
||||
def main():
|
||||
|
0
fishy/engine/fullautofisher/__init__.py
Normal file
0
fishy/engine/fullautofisher/__init__.py
Normal file
@ -46,15 +46,16 @@ def image_pre_process(img):
|
||||
return img
|
||||
|
||||
|
||||
def get_values_from_image(img):
|
||||
# noinspection PyBroadException
|
||||
def get_values_from_image(img, tesseract_dir):
|
||||
try:
|
||||
pytesseract.pytesseract.tesseract_cmd = 'C:/Program Files (x86)/Tesseract-OCR/tesseract.exe'
|
||||
tessdata_dir_config = '--tessdata-dir "C:/Program Files (x86)/Tesseract-OCR/" -c tessedit_char_whitelist=0123456789.'
|
||||
pytesseract.pytesseract.tesseract_cmd = tesseract_dir+'/tesseract.exe'
|
||||
tessdata_dir_config = f'--tessdata-dir "{tesseract_dir}" -c tessedit_char_whitelist=0123456789.'
|
||||
|
||||
text = pytesseract.image_to_string(img, lang="eng", config=tessdata_dir_config)
|
||||
vals = text.split(":")
|
||||
return float(vals[0]), float(vals[1]), float(vals[2])
|
||||
except:
|
||||
except Exception:
|
||||
logging.error("Couldn't read coods")
|
||||
return None
|
||||
|
||||
@ -63,6 +64,7 @@ class FullAuto(IEngine):
|
||||
def __init__(self, config, gui_ref):
|
||||
super().__init__(config, gui_ref)
|
||||
self.factors = None
|
||||
self.tesseract_dir = None
|
||||
|
||||
def run(self):
|
||||
|
||||
@ -70,25 +72,35 @@ class FullAuto(IEngine):
|
||||
Window.init(False)
|
||||
except pywintypes.error:
|
||||
logging.info("Game window not found")
|
||||
self.start = False
|
||||
self.toggle_start()
|
||||
return
|
||||
|
||||
self.window = Window(color=cv2.COLOR_RGB2GRAY)
|
||||
self.window.crop = get_crop_coods(self.window)
|
||||
self.tesseract_dir = self.config.get("tesseract_dir", None)
|
||||
|
||||
time.sleep(2)
|
||||
if self.tesseract_dir is None:
|
||||
logging.warning("Can't start without Tesseract Directory")
|
||||
self.gui.bot_started(False)
|
||||
self.toggle_start()
|
||||
return
|
||||
|
||||
if self.get_gui is not None:
|
||||
self.gui.bot_started(True)
|
||||
while self.start:
|
||||
Window.loop()
|
||||
|
||||
self.window.show("test", func=image_pre_process)
|
||||
Window.loop_end()
|
||||
logging.info("Controlls:\nUP: Callibrate\nLEFT: Pring Coordinates\nDOWN: Quit")
|
||||
with keyboard.Listener(
|
||||
on_press=self.on_press,
|
||||
):
|
||||
while self.start:
|
||||
Window.loop()
|
||||
|
||||
self.window.show("test", func=image_pre_process)
|
||||
Window.loop_end()
|
||||
self.gui.bot_started(False)
|
||||
|
||||
def get_coods(self):
|
||||
return get_values_from_image(self.window.processed_image(func=image_pre_process))
|
||||
return get_values_from_image(self.window.processed_image(func=image_pre_process), self.tesseract_dir)
|
||||
|
||||
def callibrate(self):
|
||||
logging.debug("Callibrating...")
|
||||
@ -130,7 +142,9 @@ class FullAuto(IEngine):
|
||||
def on_press(self, key):
|
||||
if key == Key.down:
|
||||
bot.start = False
|
||||
quit()
|
||||
self.toggle_start()
|
||||
if self.get_gui is not None:
|
||||
quit()
|
||||
elif key == Key.left:
|
||||
logging.info(self.get_coods())
|
||||
elif key == Key.up:
|
||||
@ -139,6 +153,7 @@ class FullAuto(IEngine):
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.getLogger("").setLevel(logging.DEBUG)
|
||||
# noinspection PyTypeChecker
|
||||
bot = FullAuto(None, None)
|
||||
bot.toggle_start()
|
||||
with keyboard.Listener(
|
||||
|
@ -19,16 +19,10 @@ if typing.TYPE_CHECKING:
|
||||
from fishy.gui import GUI
|
||||
|
||||
|
||||
def _wait_and_check(gui):
|
||||
time.sleep(10)
|
||||
if not fishing_event._FishingStarted:
|
||||
gui.show_error("Doesn't look like fishing has started\n\n"
|
||||
"Check out #faqs on our discord channel to troubleshoot the issue")
|
||||
|
||||
|
||||
class SemiFisherEngine(IEngine):
|
||||
def __init__(self, config, gui_ref: 'Callable[[], GUI]'):
|
||||
super().__init__(config, gui_ref)
|
||||
self.fishPixWindow = None
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
@ -59,10 +53,15 @@ class SemiFisherEngine(IEngine):
|
||||
# check for game window and stuff
|
||||
self.gui.bot_started(True)
|
||||
logging.info("Starting the bot engine, look at the fishing hole to start fishing")
|
||||
Thread(target=_wait_and_check, args=(self.gui,)).start()
|
||||
Thread(target=self._wait_and_check).start()
|
||||
while self.start:
|
||||
# Services to be ran in the start of the main loop
|
||||
Window.loop()
|
||||
success = Window.loop()
|
||||
|
||||
if not success:
|
||||
self.gui.bot_started(False)
|
||||
self.toggle_start()
|
||||
continue
|
||||
|
||||
# get the PixelLoc and find the color values, to give it to `FishingMode.Loop`
|
||||
self.fishPixWindow.crop = PixelLoc.val
|
||||
@ -73,6 +72,12 @@ class SemiFisherEngine(IEngine):
|
||||
logging.info("Fishing engine stopped")
|
||||
self.gui.bot_started(False)
|
||||
|
||||
def _wait_and_check(self):
|
||||
time.sleep(10)
|
||||
if not fishing_event._FishingStarted and self.start:
|
||||
self.gui.show_error("Doesn't look like fishing has started\n\n"
|
||||
"Check out #read-me-first on our discord channel to troubleshoot the issue")
|
||||
|
||||
def show_pixel_vals(self):
|
||||
def show():
|
||||
freq = 0.5
|
||||
|
@ -10,10 +10,7 @@ class FishingMode:
|
||||
Modes list of states
|
||||
"""
|
||||
HValues = [60, 18, 100]
|
||||
Threshold = 1
|
||||
|
||||
CurrentCount = 0
|
||||
PrevLabel = -1
|
||||
CurrentMode = None
|
||||
PrevMode = None
|
||||
|
||||
@ -52,22 +49,17 @@ class FishingMode:
|
||||
|
||||
:param hue_values: hue_values read by the bot
|
||||
"""
|
||||
if FishingMode.PrevMode is None:
|
||||
FishingMode.PrevMode = FishingMode.get_by_label(3)
|
||||
|
||||
current_label = 3
|
||||
for i, val in enumerate(FishingMode.HValues):
|
||||
if hue_values == val:
|
||||
current_label = i
|
||||
|
||||
# check if it passes threshold, if so change labelNum
|
||||
if FishingMode.PrevLabel == current_label:
|
||||
FishingMode.CurrentCount += 1
|
||||
else:
|
||||
FishingMode.CurrentCount = 0
|
||||
FishingMode.PrevLabel = current_label
|
||||
FishingMode.CurrentMode = FishingMode.get_by_label(current_label)
|
||||
|
||||
if FishingMode.CurrentCount >= FishingMode.Threshold:
|
||||
FishingMode.CurrentMode = FishingMode.get_by_label(current_label)
|
||||
|
||||
if FishingMode.CurrentMode != FishingMode.PrevMode and FishingMode.PrevMode is not None:
|
||||
if FishingMode.CurrentMode != FishingMode.PrevMode:
|
||||
|
||||
if FishingMode.PrevMode.event is not None:
|
||||
FishingMode.PrevMode.event.on_exit_callback(FishingMode.CurrentMode)
|
||||
|
@ -67,7 +67,9 @@ class Window:
|
||||
|
||||
if Window.Screen.size == 0:
|
||||
logging.info("Don't minimize or drag game window outside the screen")
|
||||
quit(1)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def loop_end():
|
||||
@ -111,6 +113,7 @@ class Window:
|
||||
def show(self, name, resize=None, func=None, ready_img=None):
|
||||
"""
|
||||
Displays the processed image for debugging purposes
|
||||
:param ready_img: send ready image, just show the `ready_img` directly
|
||||
:param name: unique name for the image, used to create a new window
|
||||
:param resize: scale the image to make small images more visible
|
||||
:param func: function to process the image
|
||||
|
@ -12,6 +12,24 @@ if typing.TYPE_CHECKING:
|
||||
from fishy.gui import GUI
|
||||
|
||||
|
||||
def start_fullfisher_config(gui: 'GUI'):
|
||||
def save():
|
||||
gui._config.set("tesseract_dir", tesseract_entry.get(), False)
|
||||
gui._config.save_config()
|
||||
|
||||
top = PopUp(save, gui._root, background=gui._root["background"])
|
||||
controls_frame = Frame(top)
|
||||
top.title("Config")
|
||||
|
||||
Label(controls_frame, text="Tesseract Directory:").grid(row=0, column=0)
|
||||
tesseract_entry = Entry(controls_frame, justify=CENTER)
|
||||
tesseract_entry.insert(0, gui._config.get("tesseract_dir", ""))
|
||||
tesseract_entry.grid(row=0, column=1)
|
||||
|
||||
controls_frame.pack(padx=(5, 5), pady=(5, 5))
|
||||
top.start()
|
||||
|
||||
|
||||
def start_semifisher_config(gui: 'GUI'):
|
||||
def save():
|
||||
gui._config.set("action_key", action_key_entry.get(), False)
|
||||
@ -45,4 +63,3 @@ def start_semifisher_config(gui: 'GUI'):
|
||||
|
||||
controls_frame.pack(padx=(5, 5), pady=(5, 5))
|
||||
top.start()
|
||||
|
||||
|
@ -1,9 +1,13 @@
|
||||
from tkinter import messagebox, NORMAL
|
||||
from tkinter import messagebox
|
||||
|
||||
import typing
|
||||
if typing.TYPE_CHECKING:
|
||||
from fishy.gui import GUI
|
||||
|
||||
|
||||
# noinspection PyProtectedMember
|
||||
class GUIFuncs:
|
||||
def __init__(self, gui):
|
||||
def __init__(self, gui: 'GUI'):
|
||||
self.gui = gui
|
||||
|
||||
def show_error(self, error):
|
||||
@ -12,6 +16,12 @@ class GUIFuncs:
|
||||
def bot_started(self, started):
|
||||
def func():
|
||||
self.gui._bot_running = started
|
||||
self.gui._start_button["text"] = "STOP" if self.gui._bot_running else "START"
|
||||
self.gui._start_button["text"] = self.gui._get_start_stop_text()
|
||||
|
||||
self.gui.call_in_thread(func)
|
||||
|
||||
def quit(self):
|
||||
def func():
|
||||
self.gui._root.destroy()
|
||||
|
||||
self.gui.call_in_thread(func)
|
||||
|
@ -2,9 +2,10 @@ import logging
|
||||
from typing import List, Callable
|
||||
import threading
|
||||
|
||||
from ttkthemes import ThemedTk
|
||||
|
||||
from fishy.engine.event_handler import EngineEventHandler
|
||||
from fishy.gui.funcs import GUIFuncs
|
||||
from fishy.engine import SemiFisherEngine
|
||||
from . import main_gui
|
||||
from .log_config import GUIStreamHandler
|
||||
from fishy.helper import Config
|
||||
@ -26,7 +27,7 @@ class GUI:
|
||||
self._bot_running = False
|
||||
|
||||
# UI items
|
||||
self._root = None
|
||||
self._root: ThemedTk = None
|
||||
self._console = None
|
||||
self._start_button = None
|
||||
self._notify = None
|
||||
@ -57,3 +58,6 @@ class GUI:
|
||||
|
||||
def call_in_thread(self, func: Callable):
|
||||
self._function_queue.append(func)
|
||||
|
||||
def _get_start_stop_text(self):
|
||||
return "STOP (F9)" if self._bot_running else "START (F9)"
|
||||
|
@ -2,9 +2,12 @@ import logging
|
||||
import time
|
||||
from tkinter import *
|
||||
from tkinter.ttk import *
|
||||
|
||||
from pynput import keyboard
|
||||
from pynput.keyboard import Key
|
||||
from ttkthemes import ThemedTk
|
||||
|
||||
from fishy import helper, web
|
||||
from fishy import helper
|
||||
from fishy.gui import config_top
|
||||
|
||||
import typing
|
||||
@ -25,10 +28,11 @@ def _apply_theme(gui: 'GUI'):
|
||||
def _create(gui: 'GUI'):
|
||||
engines = {
|
||||
"Semi Fisher": [lambda: config_top.start_semifisher_config(gui), gui.engine.toggle_semifisher],
|
||||
"Full-Auto Fisher": [not_implemented, gui.engine.toggle_fullfisher],
|
||||
# "Lock Picker": [not_implemented, not_implemented]
|
||||
}
|
||||
|
||||
if gui._config.get('debug', False):
|
||||
engines["Full-Auto Fisher"] = [lambda: config_top.start_fullfisher_config(gui), gui.engine.toggle_fullfisher]
|
||||
|
||||
def start_engine(label):
|
||||
gui._config.set("last_started", label)
|
||||
engines[label][1]()
|
||||
@ -67,7 +71,6 @@ def _create(gui: 'GUI'):
|
||||
logging.debug("Restart to update the changes")
|
||||
|
||||
debug_menu.add_checkbutton(label="Keep Console", command=keep_console, variable=debug_var)
|
||||
debug_menu.add_command(label="Log Dump", command=not_implemented)
|
||||
debug_menu.add_command(label="Restart", command=helper.restart)
|
||||
menubar.add_cascade(label="Debug", menu=debug_menu)
|
||||
|
||||
@ -99,7 +102,7 @@ def _create(gui: 'GUI'):
|
||||
config_button = Button(start_frame, text="⚙", width=0, command=lambda: engines[engine_var.get()][0]())
|
||||
config_button.pack(side=RIGHT)
|
||||
|
||||
gui._start_button = Button(start_frame, text="STOP" if gui._bot_running else "START", width=25,
|
||||
gui._start_button = Button(start_frame, text=gui._get_start_stop_text(), width=25,
|
||||
command=lambda: start_engine(engine_var.get()))
|
||||
gui._start_button.pack(side=RIGHT)
|
||||
|
||||
@ -110,6 +113,15 @@ def _create(gui: 'GUI'):
|
||||
gui._root.update()
|
||||
gui._root.minsize(gui._root.winfo_width() + 10, gui._root.winfo_height() + 10)
|
||||
|
||||
def keyboard_listener(key):
|
||||
if key == Key.f9:
|
||||
gui.call_in_thread(lambda: start_engine(engine_var.get()))
|
||||
|
||||
kb_listener = keyboard.Listener(
|
||||
on_press=keyboard_listener,
|
||||
)
|
||||
kb_listener.start()
|
||||
|
||||
def set_destroy():
|
||||
gui._destroyed = True
|
||||
|
||||
@ -128,3 +140,5 @@ def _create(gui: 'GUI'):
|
||||
gui.engine.quit()
|
||||
break
|
||||
time.sleep(0.01)
|
||||
|
||||
kb_listener.stop()
|
||||
|
@ -118,19 +118,18 @@ def create_shortcut():
|
||||
|
||||
|
||||
# noinspection PyBroadException
|
||||
def check_addon():
|
||||
def check_addon(name):
|
||||
"""
|
||||
Extracts the addon from zip and installs it into the AddOn folder of eso
|
||||
"""
|
||||
try:
|
||||
user = os.path.expanduser("~")
|
||||
addon_dir = os.path.join(user, "Documents", "Elder Scrolls Online", "live", "Addons")
|
||||
if not os.path.exists(os.path.join(addon_dir, 'ProvisionsChalutier')):
|
||||
logging.info("Addon not found, installing it...")
|
||||
with ZipFile(manifest_file("ProvisionsChalutier.zip"), 'r') as z:
|
||||
if not os.path.exists(os.path.join(addon_dir, name)):
|
||||
logging.info(f"{name} Addon not found, installing it...")
|
||||
with ZipFile(manifest_file(f"{name}.zip"), 'r') as z:
|
||||
z.extractall(path=addon_dir)
|
||||
logging.info("Please make sure you enable \"Allow outdated addons\" in-game\n"
|
||||
"Also, make sure the addon is visible clearly on top left corner of the game window")
|
||||
logging.info("Please make sure you enable \"Allow outdated addons\" in-game")
|
||||
except Exception:
|
||||
logging.error("couldn't install addon, try doing it manually")
|
||||
|
||||
|
@ -9,7 +9,7 @@ def center(win):
|
||||
height = win.winfo_height()
|
||||
|
||||
offset_x = win.master.winfo_x() + win.master.winfo_width() // 2 - (width // 2)
|
||||
offset_y = win.master.winfo_y()+ win.master.winfo_height() // 2 - (height // 2)
|
||||
offset_y = win.master.winfo_y() + win.master.winfo_height() // 2 - (height // 2)
|
||||
|
||||
win.geometry('{}x{}+{}+{}'.format(width, height, offset_x, offset_y))
|
||||
|
||||
@ -18,7 +18,7 @@ class PopUp(Toplevel):
|
||||
def __init__(self, quit_callback, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.running = True
|
||||
self.quit_callback = quit_callback
|
||||
self.quit_callback = quit_callback
|
||||
|
||||
def quit_top(self):
|
||||
self.quit_callback()
|
||||
|
@ -10,3 +10,5 @@ pyautogui
|
||||
requests
|
||||
beautifulsoup4
|
||||
whatsmyip
|
||||
pynput
|
||||
pytesseract
|
Loading…
x
Reference in New Issue
Block a user