From 917bf9e2d99aae10bbf51dde907b8fa3e126247d Mon Sep 17 00:00:00 2001 From: "DESKTOP-JVKHS7I\\Adam" Date: Sat, 16 Feb 2019 17:02:20 +0530 Subject: [PATCH] shows error message when window is dragged out of screen, removed old pixelloc code, removed old window config code, increase version, updated reamde --- README.md | 16 +++------ controls.py | 4 --- fishing_mode.py | 2 ++ fishy.py | 95 ++++++++++--------------------------------------- fishy_config.py | 11 ------ init.py | 50 ++++++-------------------- pixel_loc.py | 59 ++++++++++++++++++++++-------- window.py | 62 ++++++++++++++++++++++---------- 8 files changed, 125 insertions(+), 174 deletions(-) delete mode 100644 fishy_config.py diff --git a/README.md b/README.md index b9564c8..c104f5b 100644 --- a/README.md +++ b/README.md @@ -23,23 +23,17 @@ Installing Project Requirements: Executing the Bot: - Start the game. -- (For phone notification configuration, follow the instructions below instead) Type command `python fishy.py`. - -Configuring Pixel Location: (You only need to do this configuration once) -- Go to a fishing hole and look at the hole. -- Press '.' to go into mouse mode then press `f8` to start pixel config mode. -- Locate the brown color bar on the middle top part of the game, above the emojie. -- Hover the mouse over that brown color, and confirm the color is correct in the window. -- Press `f8` again to save the configuration. +- Type command `python fishy.py` (For phone notification configuration, follow the instructions below instead). Starting fishing: -- Now start fishing manually on a fishing whole +- Now look at a fishing hole (don't start fishing) - And then press `f9` to start the bot. +- After the fishing is done, just move to next hole and look at it, fishing will start automatically. - **IMPORTANT**: Keep the window focus on the game. Tip: -If its taking alot of load on your cpu, try using these options to start the bot -`python fishy.py --hook-threshold 0 --check-frequency 1` +To increase the check rate of the bot, try changing `--check-frequency` option to less than 1, like +`python fishy.py --check-frequency 0.5` ### For Phone Notification (Only Android) - Install `notificationApp.apk` from the project files in your phone. diff --git a/controls.py b/controls.py index 5ed168d..596cc5b 100644 --- a/controls.py +++ b/controls.py @@ -2,8 +2,6 @@ from init import * class Control: - -#todo change to 0 current = 1 if arguments["--debug"] else 0 class Keywords(Enum): @@ -11,7 +9,6 @@ class Control: StartPause = "start/pause" Debug = "debug" Stop = "stop" - ConfigPixLoc = "config pixel location" ClearPrintOnce = "clear print once" controls = [ @@ -20,7 +17,6 @@ class Control: "controls": [ [Keywords.SwitchMode, Key.f8], [Keywords.StartPause, Key.f9], - [Keywords.ConfigPixLoc, Key.f10], [Keywords.Stop, Key.f11] ] }, diff --git a/fishing_mode.py b/fishing_mode.py index f9d0b7e..c3403e3 100644 --- a/fishing_mode.py +++ b/fishing_mode.py @@ -9,6 +9,7 @@ class FishingMode: PrevLabel = -1 CurrentMode = None PrevMode = None + FishingStarted = False Modes = [] @@ -25,6 +26,7 @@ class FishingMode: if m.label == label: return m + @staticmethod def Loop(hueValue, pause): current_label = 3 diff --git a/fishy.py b/fishy.py index 21d8260..7986172 100644 --- a/fishy.py +++ b/fishy.py @@ -13,11 +13,17 @@ def on_release(key): return if c[0] == Control.Keywords.StartPause: - G.pause = not G.pause - if G.pause: + + if not G.pause: print("PAUSED") - else: + G.pause = True + return + + if PixelLoc.config(): print("STARTED") + G.pause = False + else: + print("look on a fishing hole before starting") elif c[0] == Control.Keywords.Debug: G.debug = not G.debug @@ -25,9 +31,6 @@ def on_release(key): elif c[0] == Control.Keywords.Stop: G.stop = True - elif c[0] == Control.Keywords.ConfigPixLoc: - G.configPL = not G.configPL - elif c[0] == Control.Keywords.SwitchMode: Control.nextState() Log.ctrl() @@ -36,43 +39,6 @@ def on_release(key): Log.clearPrintIds() -def ipDebug(img): - # Setup SimpleBlobDetector parameters. - hsvImg = cv2.cvtColor(img, cv2.COLOR_RGB2HSV) - lower = (99, 254, 100) - upper = (100, 255, 101) - mask = cv2.inRange(hsvImg, lower, upper) - #mask = cv2.bitwise_not(mask) - - # Setup SimpleBlobDetector parameters. - params = cv2.SimpleBlobDetector_Params() - - # Change thresholds - params.minThreshold = 10 - params.maxThreshold = 255 - - params.filterByColor = True - params.blobColor = 255 - - params.filterByCircularity = False - params.filterByConvexity = False - params.filterByInertia = False - - params.filterByArea = True - params.minArea = 10.0 - - detector = cv2.SimpleBlobDetector_create(params) - - # Detect blobs. - keypoints = detector.detect(mask) - - # Draw detected blobs as red circles. - # cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures the size of the circle corresponds to the size of blob - draw_keypoints(img, keypoints) - - return img - - def hsv2rgb(img): return cv2.cvtColor(img, cv2.COLOR_HSV2RGB) @@ -83,9 +49,6 @@ def startFishing(): :return: void """ - if not arguments["--no-resize"]: - config_win() - use_net = arguments["--ip"] is not None if use_net: net.initialize(arguments["--ip"]) @@ -97,49 +60,24 @@ def startFishing(): FishingMode("look", 2, LookEvent()) FishingMode("idle", 3, IdleEvent(use_net)) - fishPixWindow = Window("fishPixWindow", PixelLoc.val, cv2.COLOR_BGR2HSV) - - try: - hwnd = win32gui.FindWindow(None, "Elder Scrolls Online") - - rect = win32gui.GetWindowRect(hwnd) - clientRect = win32gui.GetClientRect(hwnd) - windowOffset = math.floor(((rect[2] - rect[0]) - clientRect[2]) / 2) - titleOffset = ((rect[3] - rect[1]) - clientRect[3]) - windowOffset - windowLoc = (rect[0] + windowOffset, rect[1] + titleOffset, rect[2] - windowOffset, rect[3] - windowOffset) - - gameScreen = Window("game", windowLoc, cv2.COLOR_BGR2RGB) - - except pywintypes.error: - print("Game window not found") - return - Log.ctrl() - # todo - time.time() + fishPixWindow = Window(color=cv2.COLOR_RGB2HSV) + + Window.Init() with Listener(on_release=on_release): while not G.stop: current_time = time.time() - Window.Loop() Log.Loop() - PixelLoc.Loop() - pixelVal = (PixelLoc.val[0], PixelLoc.val[1], PixelLoc.val[0] + 1, PixelLoc.val[1] + 1) - fishPixWindow.crop = pixelVal + fishPixWindow.crop = PixelLoc.val hueValue = fishPixWindow.getCapture()[0][0][0] FishingMode.Loop(hueValue, G.pause) - if G.configPL: - fishPixWindow.show(resize=200, func=hsv2rgb) - Log.ou(str(FishingMode.CurrentMode.label) + ":" + str(fishPixWindow.getCapture()[0][0])) - if G.debug: - rect = win32gui.GetWindowRect(hwnd) - gameScreen.crop = (rect[0] + windowOffset, rect[1] + titleOffset, rect[2] - windowOffset, - rect[3] - windowOffset) - gameScreen.show(func=ipDebug) + fishPixWindow.show("pixloc", resize=200, func=hsv2rgb) + Log.ou(str(FishingMode.CurrentMode.label) + ":" + str(fishPixWindow.getCapture()[0][0])) Log.LoopEnd() Window.LoopEnd() @@ -147,6 +85,9 @@ def startFishing(): frameTime = time.time() - current_time if frameTime < sleepFor: time.sleep(sleepFor - frameTime) + else: + Log.po(231, "Program taking more time than expected, this might slow your computer try increasing " + "\"--check-frequency\".") if __name__ == "__main__": diff --git a/fishy_config.py b/fishy_config.py deleted file mode 100644 index 96bec7d..0000000 --- a/fishy_config.py +++ /dev/null @@ -1,11 +0,0 @@ -import win32gui - - -def config_win(): - X, Y, W, H = -8, 0, 815, 608 - hwnd = win32gui.FindWindow(None, "Elder Scrolls Online") - win32gui.MoveWindow(hwnd, X, Y, W, H, True) - - -if __name__ == "__main__": - config_win() diff --git a/init.py b/init.py index 78cac6f..bcd9f43 100644 --- a/init.py +++ b/init.py @@ -3,7 +3,7 @@ Usage: fishy.py -h | --help fishy.py -v | --version - fishy.py [--debug] [--ip=] [--hook-threshold=] [--check-frequency=] [--no-resize] + fishy.py [--debug] [--ip=] [--hook-threshold=] [--check-frequency=] Options: -h, --help Show this screen. @@ -14,7 +14,7 @@ Options: --debug Start program in debug controls. """ -VERSION = "0.1.0" +VERSION = "0.1.1" print("Fishy " + VERSION + " for Elder Scrolls Online") try: @@ -32,7 +32,6 @@ try: import pyautogui import time import fishy_network as net - from fishy_config import config_win from pynput.keyboard import Key, Listener from decimal import Decimal from win32api import GetSystemMetrics @@ -62,12 +61,17 @@ init class G: + """ + Initialize global variables + """ fishCaught = 0 stickInitTime = 0 stop = False pause = True debug = False - configPL = False + + +"""Helper functions""" def round_float(v, ndigits=2, rt_str=False): @@ -80,39 +84,7 @@ def round_float(v, ndigits=2, rt_str=False): def draw_keypoints(vis, keypoints, color=(0, 0, 255)): for kp in keypoints: - x, y = kp.pt - cv2.circle(vis, (int(x), int(y)), 5, color, -1) + x, y = kp.pt + cv2.circle(vis, (int(x), int(y)), 5, color, -1) - -def image_resize(image, width=None, height=None, inter = cv2.INTER_AREA): - # initialize the dimensions of the image to be resized and - # grab the image size - dim = None - (h, w) = image.shape[:2] - - # if both the width and height are None, then return the - # original image - if width is None and height is None: - return image - - # check to see if the width is None - if width is None: - # calculate the ratio of the height and construct the - # dimensions - r = height / float(h) - dim = (int(w * r), height) - - # otherwise, the height is None - else: - # calculate the ratio of the width and construct the - # dimensions - r = width / float(w) - dim = (width, int(h * r)) - - # resize the image - resized = cv2.resize(image, dim, interpolation = inter) - - # return the resized image - return resized - -# np.set_printoptions(threshold=sys.maxsize) \ No newline at end of file +# np.set_printoptions(threshold=sys.maxsize) diff --git a/pixel_loc.py b/pixel_loc.py index 51fc116..9a699c6 100644 --- a/pixel_loc.py +++ b/pixel_loc.py @@ -1,20 +1,51 @@ from fishing_event import * -class PixelLoc: - configPixelSaved = True +def GetKeypointFromImage(img): + # Setup SimpleBlobDetector parameters. + hsvImg = cv2.cvtColor(img, cv2.COLOR_RGB2HSV) + lower = (99, 254, 100) + upper = (100, 255, 101) + mask = cv2.inRange(hsvImg, lower, upper) - try: - val = pickle.load(open("pixelLoc.pickle", "rb")) - except (OSError, IOError) as e: - val = (240, 31) + # Setup SimpleBlobDetector parameters. + params = cv2.SimpleBlobDetector_Params() + + # Change thresholds + params.minThreshold = 10 + params.maxThreshold = 255 + + params.filterByColor = True + params.blobColor = 255 + + params.filterByCircularity = False + params.filterByConvexity = False + params.filterByInertia = False + + params.filterByArea = True + params.minArea = 10.0 + + detector = cv2.SimpleBlobDetector_create(params) + + # Detect blobs. + keypoints = detector.detect(mask) + + if len(keypoints) <= 0: + return None + + return int(keypoints[0].pt[0]), int(keypoints[0].pt[1]) + + +class PixelLoc: + val = None @staticmethod - def Loop(): - if G.configPL: - x, y = pyautogui.position() - PixelLoc.val = (x, y) - PixelLoc.configPixelSaved = False - elif not PixelLoc.configPixelSaved: - pickle.dump(PixelLoc.val, open("pixelLoc.pickle", "wb")) - PixelLoc.configPixelSaved = True + def config(): + win = Window() + t = GetKeypointFromImage(win.getCapture()) + + if t is None: + return False + + PixelLoc.val = (t[0], t[1], t[0] + 1, t[1] + 1) + return True diff --git a/window.py b/window.py index f419437..6e09c90 100644 --- a/window.py +++ b/window.py @@ -3,37 +3,63 @@ from log import * class Window: Screen = None - wins = [] + windowOffset = None + titleOffset = None + hwnd = None + showing = False - def __init__(self, name, crop, color, scale=None): + def __init__(self, crop=None, color=None, scale=None): self.color = color self.crop = crop self.scale = scale - self.name = name - self.showed = False - Window.wins.append(self) + @staticmethod + def Init(): + try: + Window.hwnd = win32gui.FindWindow(None, "Elder Scrolls Online") + rect = win32gui.GetWindowRect(Window.hwnd) + clientRect = win32gui.GetClientRect(Window.hwnd) + Window.windowOffset = math.floor(((rect[2] - rect[0]) - clientRect[2]) / 2) + Window.titleOffset = ((rect[3] - rect[1]) - clientRect[3]) - Window.windowOffset + except pywintypes.error: + print("Game window not found") + quit() @staticmethod def Loop(): - bbox = (0, 0, GetSystemMetrics(0), GetSystemMetrics(1)) - Window.Screen = np.array(ImageGrab.grab(bbox=bbox)) + Window.showing = False + bbox = (0, 0, GetSystemMetrics(0), GetSystemMetrics(1)) + + tempScreen = np.array(ImageGrab.grab(bbox=bbox)) + + tempScreen = cv2.cvtColor(tempScreen, cv2.COLOR_BGR2RGB) + + rect = win32gui.GetWindowRect(Window.hwnd) + crop = (rect[0] + Window.windowOffset, rect[1] + Window.titleOffset, rect[2] - Window.windowOffset, + rect[3] - Window.windowOffset) + + Window.Screen = tempScreen[crop[1]:crop[3], crop[0]:crop[2]] + + if Window.Screen.size == 0: + print("Don't drag game window outside the screen") + quit(1) @staticmethod def LoopEnd(): cv2.waitKey(25) - for w in Window.wins: - - if not w.showed: - cv2.destroyWindow(w.name) - - w.showed = False + if not Window.showing: + cv2.destroyAllWindows() def getCapture(self): - temp_img = cv2.cvtColor(Window.Screen, self.color) - temp_img = temp_img[self.crop[1]:self.crop[3], self.crop[0]:self.crop[2]] + temp_img = Window.Screen + + if self.color is not None: + temp_img = cv2.cvtColor(temp_img, self.color) + + if self.crop is not None: + temp_img = temp_img[self.crop[1]:self.crop[3], self.crop[0]:self.crop[2]] if self.scale is not None: temp_img = cv2.resize(temp_img, (self.scale[0], self.scale[1]), interpolation=cv2.INTER_AREA) @@ -46,12 +72,12 @@ class Window: else: return func(self.getCapture()) - def show(self, resize=None, func=None): + def show(self, name, resize=None, func=None): img = self.processedImage(func) if resize is not None: img = imutils.resize(img, width=resize) - cv2.imshow(self.name, img) + cv2.imshow(name, img) - self.showed = True + Window.showing = True