fishyboteso/fishy/engine/fullautofisher/engine.py
2021-05-09 09:05:51 +02:00

213 lines
6.4 KiB
Python

import logging
import math
import time
import traceback
from enum import Enum
from threading import Thread
import cv2
from pynput import keyboard, mouse
from fishy.constants import fishyqr, lam2, libgps
from fishy.engine import SemiFisherEngine
from fishy.engine.common.IEngine import IEngine
from fishy.engine.common.window import WindowClient
from fishy.engine.fullautofisher.qr_detection import (get_qr_location,
get_values_from_image)
from fishy.engine.semifisher import fishing_event, fishing_mode
from fishy.engine.semifisher.fishing_mode import FishingMode
from fishy.helper import helper, hotkey
from fishy.helper.helper import sign
mse = mouse.Controller()
kb = keyboard.Controller()
def image_pre_process(img):
scale_percent = 100 # percent of original size
width = int(img.shape[1] * scale_percent / 100)
height = int(img.shape[0] * scale_percent / 100)
dim = (width, height)
img = cv2.resize(img, dim, interpolation=cv2.INTER_AREA)
return img
class State(Enum):
NONE = 0
PLAYING = 1
RECORDING = 2
OTHER = 3
class FullAuto(IEngine):
rotate_by = 30
state = State.NONE
def __init__(self, gui_ref):
from fishy.engine.fullautofisher import controls
from fishy.engine.fullautofisher.calibrator import Calibrator
from fishy.engine.fullautofisher.controls import Controls
from fishy.engine.fullautofisher.test import Test
super().__init__(gui_ref)
self._hole_found_flag = False
self._curr_rotate_y = 0
self.fisher = SemiFisherEngine(None)
self.calibrator = Calibrator(self)
self.test = Test(self)
self.controls = Controls(controls.get_controls(self))
self.show_crop = False
def run(self):
addons_req = [libgps, lam2, fishyqr]
for addon in addons_req:
if not helper.addon_exists(*addon):
helper.install_addon(*addon)
FullAuto.state = State.NONE
self.gui.bot_started(True)
self.window = WindowClient(color=cv2.COLOR_RGB2GRAY, show_name="Full auto debug")
try:
self.window.crop = get_qr_location(self.window.get_capture())
if self.window.crop is None:
logging.warning("FishyQR not found")
self.start = False
raise Exception("FishyQR not found")
if not self.calibrator.all_callibrated():
logging.error("you need to calibrate first")
self.fisher.toggle_start()
fishing_event.unsubscribe()
self.controls.initialize()
while self.start and WindowClient.running():
if self.show_crop:
self.window.show(self.show_crop, func=image_pre_process)
else:
time.sleep(0.1)
except:
traceback.print_exc()
if self.window.get_capture() is None:
logging.error("Game window not found")
self.gui.bot_started(False)
self.controls.unassign_keys()
self.window.show(False)
logging.info("Quitting")
self.window.destory()
self.fisher.toggle_start()
def get_coods(self):
img = self.window.processed_image(func=image_pre_process)
return get_values_from_image(img)
def move_to(self, target):
if target is None:
logging.error("set target first")
return
if not self.calibrator.all_callibrated():
logging.error("you need to callibrate first")
return
current = self.get_coods()
print(f"Moving from {(current[0], current[1])} to {target}")
move_vec = target[0] - current[0], target[1] - current[1]
dist = math.sqrt(move_vec[0] ** 2 + move_vec[1] ** 2)
print(f"distance: {dist}")
if dist < 5e-05:
print("distance very small skipping")
return
target_angle = math.degrees(math.atan2(-move_vec[1], move_vec[0])) + 90
from_angle = current[2]
self.rotate_to(target_angle, from_angle)
walking_time = dist / self.calibrator.move_factor
print(f"walking for {walking_time}")
kb.press('w')
time.sleep(walking_time)
kb.release('w')
print("done")
def rotate_to(self, target_angle, from_angle=None):
if from_angle is None:
_, _, from_angle = self.get_coods()
if target_angle < 0:
target_angle = 360 + target_angle
while target_angle > 360:
target_angle -= 360
print(f"Rotating from {from_angle} to {target_angle}")
angle_diff = target_angle - from_angle
if abs(angle_diff) > 180:
angle_diff = (360 - abs(angle_diff)) * sign(angle_diff) * -1
rotate_times = int(angle_diff / self.calibrator.rot_factor) * -1
print(f"rotate_times: {rotate_times}")
for _ in range(abs(rotate_times)):
mse.move(sign(rotate_times) * FullAuto.rotate_by * -1, 0)
time.sleep(0.05)
def look_for_hole(self):
self._hole_found_flag = False
if FishingMode.CurrentMode == fishing_mode.State.LOOKING:
return True
def found_hole(e):
if e == fishing_mode.State.LOOKING:
self._hole_found_flag = True
fishing_mode.subscribers.append(found_hole)
t = 0
while not self._hole_found_flag and t <= 1.25:
mse.move(0, FullAuto.rotate_by)
time.sleep(0.05)
t += 0.05
while not self._hole_found_flag and t > 0:
mse.move(0, -FullAuto.rotate_by)
time.sleep(0.05)
t -= 0.05
self._curr_rotate_y = t
fishing_mode.subscribers.remove(found_hole)
return self._hole_found_flag
def rotate_back(self):
while self._curr_rotate_y > 0.01:
mse.move(0, -FullAuto.rotate_by)
time.sleep(0.05)
self._curr_rotate_y -= 0.05
def toggle_start(self):
if self.start and FullAuto.state != State.NONE:
logging.info("Please turn off RECORDING/PLAYING first")
return
self.start = not self.start
if self.start:
self.thread = Thread(target=self.run)
self.thread.start()
if __name__ == '__main__':
logging.getLogger("").setLevel(logging.DEBUG)
hotkey.initalize()
# noinspection PyTypeChecker
bot = FullAuto(None)
bot.toggle_start()