diff --git a/fishy/constants.py b/fishy/constants.py index 20ae28b..ec39bc7 100644 --- a/fishy/constants.py +++ b/fishy/constants.py @@ -1,5 +1,5 @@ apiversion = 2 -chalutier = ("Chalutier", "https://github.com/fishyboteso/Chalutier/raw/619b4ab0b8ff91746afda855542e886d27b7a794/Chalutier_1.1.2.zip", 112) +chalutier = ("Chalutier", "https://www.esoui.com/downloads/dl2934/Chalutier_1.1.4.zip", 114) lam2 = ("LibAddonMenu-2.0", "https://www.esoui.com/downloads/dl7/LibAddonMenu-2.0r32.zip", 32) fishyqr = ("FishyQR", "https://github.com/fishyboteso/FishyQR/files/6329586/FishyQR.zip", 100) diff --git a/fishy/engine/common/window_server.py b/fishy/engine/common/window_server.py index 4b4907b..65170e3 100644 --- a/fishy/engine/common/window_server.py +++ b/fishy/engine/common/window_server.py @@ -60,8 +60,6 @@ def loop(): temp_screen = np.array(ImageGrab.grab(bbox=bbox)) - temp_screen = cv2.cvtColor(temp_screen, cv2.COLOR_BGR2RGB) - rect = win32gui.GetWindowRect(WindowServer.hwnd) crop = ( rect[0] + WindowServer.windowOffset, rect[1] + WindowServer.titleOffset, rect[2] - WindowServer.windowOffset, diff --git a/fishy/engine/semifisher/engine.py b/fishy/engine/semifisher/engine.py index f4d7bb9..17270ca 100644 --- a/fishy/engine/semifisher/engine.py +++ b/fishy/engine/semifisher/engine.py @@ -10,12 +10,14 @@ import logging from fishy.engine.semifisher.fishing_event import FishEvent from fishy.engine.common.window import WindowClient -from fishy.engine.semifisher.fishing_mode import FishingMode +from fishy.engine.semifisher.fishing_mode import Colors, FishingMode from fishy.engine.common.IEngine import IEngine from fishy.engine.semifisher import fishing_mode, fishing_event from fishy.engine.semifisher.pixel_loc import PixelLoc +from fishy.helper.luaparser import sv_color_extract + if typing.TYPE_CHECKING: from fishy.gui import GUI @@ -31,11 +33,13 @@ class SemiFisherEngine(IEngine): code explained in comments in detail """ fishing_event.init() - self.fishPixWindow = WindowClient(color=cv2.COLOR_RGB2HSV) + self.fishPixWindow = WindowClient() # check for game window and stuff self.gui.bot_started(True) + sv_color_extract(Colors) + if self.get_gui: logging.info("Starting the bot engine, look at the fishing hole to start fishing") Thread(target=self._wait_and_check).start() diff --git a/fishy/engine/semifisher/fishing_event.py b/fishy/engine/semifisher/fishing_event.py index 895d566..5c6527e 100644 --- a/fishy/engine/semifisher/fishing_event.py +++ b/fishy/engine/semifisher/fishing_event.py @@ -98,11 +98,14 @@ def fisher_callback(event: State): State.FIGHT: on_fight, State.DEAD: on_dead } + try: callbacks_map[event]() FishEvent.previousState = event except KeyError as ex: - pass + logging.error("KeyError: State " + str(event) + " is not known.") + except TypeError as ex: + logging.error("TypeError when reading state: " + str(event)) def on_idle(): diff --git a/fishy/engine/semifisher/fishing_mode.py b/fishy/engine/semifisher/fishing_mode.py index 7846fc7..4049dfe 100644 --- a/fishy/engine/semifisher/fishing_mode.py +++ b/fishy/engine/semifisher/fishing_mode.py @@ -5,17 +5,32 @@ subscribers = [] class State(Enum): - IDLE = [ 0, 0, 255] - LOOKAWAY = [150, 255, 76] - LOOKING = [100, 255, 101] - DEPLETED = [ 30, 255, 76] - NOBAIT = [ 96, 255, 255] - FISHING = [ 18, 165, 213] - REELIN = [ 60, 255, 204] - LOOT = [ 0, 255, 204] - INVFULL = [ 0, 255, 51] - FIGHT = [120, 255, 204] - DEAD = [ 0, 0, 51] + IDLE = 0 + LOOKAWAY = 1 + LOOKING = 2 + DEPLETED = 3 + NOBAIT = 5 + FISHING = 6 + REELIN = 7 + LOOT = 8 + INVFULL = 9 + FIGHT = 14 + DEAD = 15 + +Colors = { + State.IDLE : [255, 255, 255], + State.LOOKAWAY : [ 76, 0, 76], + State.LOOKING : [101, 69, 0], + State.DEPLETED : [ 0, 76, 76], + State.NOBAIT : [255, 204, 0], + State.FISHING : [ 75, 156, 213], + State.REELIN : [ 0, 204, 0], + State.LOOT : [ 0, 0, 204], + State.INVFULL : [ 0, 0, 51], + State.FIGHT : [204, 0, 0], + State.DEAD : [ 51, 51, 51] +} + def _notify(event): for subscriber in subscribers: @@ -27,16 +42,16 @@ class FishingMode: PrevMode = State.IDLE -def loop(hsv): +def loop(rgb): """ Executed in the start of the main loop in fishy.py Changes modes, calls mode events (callbacks) when mode is changed - :param hsv: hsv read by the bot + :param rgb: rgb read by the bot """ FishingMode.CurrentMode = State.IDLE for s in State: - if all(hsv == s.value): + if all(rgb == Colors[s]): FishingMode.CurrentMode = s if FishingMode.CurrentMode != FishingMode.PrevMode: diff --git a/fishy/helper/__init__.py b/fishy/helper/__init__.py index dabfc52..2d3f6cf 100644 --- a/fishy/helper/__init__.py +++ b/fishy/helper/__init__.py @@ -1,4 +1,6 @@ from .auto_update import auto_upgrade, upgrade_avail, versions from .config import Config from .helper import open_web, initialize_uid, install_thread_excepthook, unhandled_exception_logging, manifest_file, \ - create_shortcut_first, addon_exists, get_addonversion, install_addon, remove_addon, restart, create_shortcut, not_implemented, update + create_shortcut_first, addon_exists, get_addonversion, install_addon, remove_addon, restart, create_shortcut, \ + not_implemented, update, get_savedvarsdir +from .luaparser import sv_color_extract diff --git a/fishy/helper/helper.py b/fishy/helper/helper.py index fb0b591..66b6036 100644 --- a/fishy/helper/helper.py +++ b/fishy/helper/helper.py @@ -145,11 +145,18 @@ def create_shortcut(anti_ghosting: bool): logging.error("Couldn't create shortcut") +def get_savedvarsdir(): + # noinspection PyUnresolvedReferences + from win32com.shell import shell, shellcon + documents = shell.SHGetFolderPath(0, shellcon.CSIDL_PERSONAL, None, 0) + return os.path.join(documents, "Elder Scrolls Online", "live", "SavedVariables") + + def get_addondir(): # noinspection PyUnresolvedReferences from win32com.shell import shell, shellcon documents = shell.SHGetFolderPath(0, shellcon.CSIDL_PERSONAL, None, 0) - return os.path.join(documents, "Elder Scrolls Online", "live", "Addons") + return os.path.join(documents, "Elder Scrolls Online", "live", "Addons") def addon_exists(name, url=None, v=None): diff --git a/fishy/helper/luaparser.py b/fishy/helper/luaparser.py new file mode 100644 index 0000000..ec621a8 --- /dev/null +++ b/fishy/helper/luaparser.py @@ -0,0 +1,79 @@ +import os +import logging +from math import floor +from .helper import get_savedvarsdir + + +def _sv_parser(path): + try: + with open(path, "r") as f: + lua = f.read() + + """ + bring lua saved-var file into a useable format: + - one line per expression (add \n where needed) + - remove all redundant characters + - make lowercase, split into list of expressions + - remove empty expressions + EXPRESSIONS: A) List-Start "name=", B) Variable assignment "name=val", C) List End "}" + """ + for old, new in ((",","\n"), ("{","{\n"), ("}","}\n"), ("{",""), (",", ""), ("[", ""), ("]", ""), ('"', ""), (" ", "")): + lua = lua.replace(old, new) + lua = lua.lower().split("\n") + lua = [expression for expression in lua if expression] + + """ + the lua saved-var file is parsed to a tree of dicts + each line represents either one node in the tree or the end of a subtree + the last symbol of each line decides the type of the node (branch vertex or leaf) + """ + stack = [] + root = (dict(),"root") + stack.append(root) + for line in lua: + if line == "": + break + if line[-1] == '=': #subtree start + t = dict() + tname = line.split("=")[0] + stack.append((t,tname)) + elif line[-1] == '}': #subtree end + t = stack.pop() + tp = stack.pop() + tp[0][t[1]] = t[0] + stack.append(tp) + else: #new element in tree + name,val = line.split("=") + t = stack.pop() + t[0][name] = val + stack.append(t) + return root[0] + + except Exception as ex: + logging.error("Error: '" + str(ex) + "' occured, while parsing ESO variables.") + return None + + +def sv_color_extract(Colors): + root = _sv_parser(os.path.join(get_savedvarsdir(), "Chalutier.lua")) + if root == None: + return Colors + + for i in range(4): + name, root = root.popitem() + colors = [] + for i in root["colors"]: + """ + ingame representation of colors range from 0 to 1 in float + these values are scaled by 255 + """ + rgb=[ + floor(float(root["colors"][i]["r"])*255), + floor(float(root["colors"][i]["g"])*255), + floor(float(root["colors"][i]["b"])*255) + ] + colors.append(rgb) + for i,c in enumerate(Colors): + Colors[c] = colors[i] + return Colors +