2021-05-09 07:05:51 +00:00
|
|
|
import logging
|
2020-06-24 23:16:23 +00:00
|
|
|
import math
|
2021-05-09 07:05:51 +00:00
|
|
|
import time
|
2020-11-30 21:04:33 +00:00
|
|
|
from threading import Thread
|
2020-10-17 08:06:49 +00:00
|
|
|
|
2021-05-09 07:05:51 +00:00
|
|
|
from pynput import keyboard, mouse
|
2020-06-01 12:58:18 +00:00
|
|
|
|
2020-10-17 08:06:49 +00:00
|
|
|
from fishy.engine import SemiFisherEngine
|
2020-10-17 10:52:04 +00:00
|
|
|
from fishy.engine.common.IEngine import IEngine
|
2021-05-09 07:05:51 +00:00
|
|
|
from fishy.engine.common.window import WindowClient
|
2021-05-02 16:49:44 +00:00
|
|
|
from fishy.engine.fullautofisher.mode.calibrator import Calibrator
|
2021-05-02 15:39:59 +00:00
|
|
|
from fishy.engine.fullautofisher.mode.imode import FullAutoMode
|
|
|
|
from fishy.engine.fullautofisher.mode.player import Player
|
|
|
|
from fishy.engine.fullautofisher.mode.recorder import Recorder
|
2021-11-21 07:12:14 +00:00
|
|
|
from fishy.engine.common.qr_detection import (get_qr_location,
|
|
|
|
get_values_from_image, image_pre_process)
|
2022-02-02 23:59:10 +00:00
|
|
|
from fishy.engine.semifisher import fishing_mode
|
2020-10-17 19:45:57 +00:00
|
|
|
from fishy.engine.semifisher.fishing_mode import FishingMode
|
2021-05-02 15:39:59 +00:00
|
|
|
from fishy.helper.config import config
|
2022-02-01 16:50:57 +00:00
|
|
|
from fishy.helper.helper import wait_until, is_eso_active, sign, print_exc
|
2020-06-25 13:40:05 +00:00
|
|
|
|
2020-06-24 23:16:23 +00:00
|
|
|
mse = mouse.Controller()
|
|
|
|
kb = keyboard.Controller()
|
|
|
|
|
|
|
|
|
2020-06-01 12:58:18 +00:00
|
|
|
class FullAuto(IEngine):
|
2020-10-15 01:26:31 +00:00
|
|
|
rotate_by = 30
|
|
|
|
|
2020-10-17 19:06:07 +00:00
|
|
|
def __init__(self, gui_ref):
|
2020-11-07 16:40:57 +00:00
|
|
|
from fishy.engine.fullautofisher.test import Test
|
2020-06-24 23:16:23 +00:00
|
|
|
|
2020-11-07 16:40:57 +00:00
|
|
|
super().__init__(gui_ref)
|
2020-10-15 02:23:15 +00:00
|
|
|
self._curr_rotate_y = 0
|
|
|
|
|
2020-10-17 22:35:20 +00:00
|
|
|
self.fisher = SemiFisherEngine(None)
|
2021-04-17 16:31:19 +00:00
|
|
|
self.calibrator = Calibrator(self)
|
2020-11-07 16:40:57 +00:00
|
|
|
self.test = Test(self)
|
2020-11-30 21:04:33 +00:00
|
|
|
self.show_crop = False
|
2020-10-17 23:12:48 +00:00
|
|
|
|
2021-05-02 15:39:59 +00:00
|
|
|
self.mode = None
|
|
|
|
|
2020-06-01 12:58:18 +00:00
|
|
|
def run(self):
|
2021-05-02 16:49:44 +00:00
|
|
|
self.mode = None
|
|
|
|
if config.get("calibrate", False):
|
|
|
|
self.mode = Calibrator(self)
|
|
|
|
elif FullAutoMode(config.get("full_auto_mode", 0)) == FullAutoMode.Player:
|
|
|
|
self.mode = Player(self)
|
|
|
|
elif FullAutoMode(config.get("full_auto_mode", 0)) == FullAutoMode.Recorder:
|
|
|
|
self.mode = Recorder(self)
|
2022-02-01 11:27:14 +00:00
|
|
|
else:
|
|
|
|
logging.error("not a valid mode selected")
|
|
|
|
return
|
2021-05-02 16:49:44 +00:00
|
|
|
|
2022-02-01 11:27:14 +00:00
|
|
|
# block thread until game window becomes active
|
2021-05-02 18:05:06 +00:00
|
|
|
if not is_eso_active():
|
|
|
|
logging.info("Waiting for eso window to be active...")
|
2021-05-15 12:54:27 +00:00
|
|
|
wait_until(lambda: is_eso_active() or not self.start)
|
|
|
|
if self.start:
|
|
|
|
logging.info("starting in 2 secs...")
|
|
|
|
time.sleep(2)
|
2021-05-02 18:05:06 +00:00
|
|
|
|
2022-02-01 11:27:14 +00:00
|
|
|
if not self._pre_run_checks():
|
|
|
|
return
|
2020-11-19 13:19:27 +00:00
|
|
|
|
2022-02-01 11:27:14 +00:00
|
|
|
if config.get("tabout_stop", 1):
|
|
|
|
self.stop_on_inactive()
|
2020-11-30 21:04:33 +00:00
|
|
|
|
2022-02-01 11:27:14 +00:00
|
|
|
# noinspection PyBroadException
|
|
|
|
try:
|
2021-05-02 15:39:59 +00:00
|
|
|
self.mode.run()
|
|
|
|
except Exception:
|
2022-02-01 11:27:14 +00:00
|
|
|
logging.error("exception occurred while running full auto mode")
|
2022-02-01 16:50:57 +00:00
|
|
|
print_exc()
|
2020-10-17 19:45:57 +00:00
|
|
|
|
2022-02-01 11:27:14 +00:00
|
|
|
def _pre_run_checks(self):
|
|
|
|
if self.window.get_capture() is None:
|
|
|
|
logging.error("Game window not found")
|
|
|
|
return False
|
|
|
|
|
|
|
|
self.window.crop = get_qr_location(self.window.get_capture())
|
|
|
|
if self.window.crop is None:
|
|
|
|
logging.error("FishyQR not found, try to drag it around and try again")
|
|
|
|
return False
|
|
|
|
|
|
|
|
if not (type(self.mode) is Calibrator) and not self.calibrator.all_calibrated():
|
|
|
|
logging.error("you need to calibrate first")
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
2020-06-03 01:41:54 +00:00
|
|
|
|
2021-05-02 15:39:59 +00:00
|
|
|
def start_show(self):
|
|
|
|
def func():
|
|
|
|
while self.start and WindowClient.running():
|
|
|
|
self.window.show(self.show_crop, func=image_pre_process)
|
|
|
|
Thread(target=func).start()
|
|
|
|
|
2021-05-02 18:05:06 +00:00
|
|
|
def stop_on_inactive(self):
|
|
|
|
def func():
|
2022-02-01 16:50:57 +00:00
|
|
|
logging.debug("stop on inactive started")
|
|
|
|
wait_until(lambda: not is_eso_active() or not self.start)
|
|
|
|
if self.start and not is_eso_active():
|
|
|
|
self.turn_off()
|
|
|
|
logging.debug("stop on inactive stopped")
|
2021-05-02 18:05:06 +00:00
|
|
|
Thread(target=func).start()
|
|
|
|
|
2021-05-15 12:20:38 +00:00
|
|
|
def get_coords(self):
|
|
|
|
"""
|
|
|
|
There is chance that this function give None instead of a QR.
|
|
|
|
Need to handle manually
|
|
|
|
todo find a better way of handling None: switch from start bool to state which knows
|
|
|
|
todo its waiting for qr which doesn't block the engine when commanded to close
|
|
|
|
"""
|
2020-11-07 16:40:57 +00:00
|
|
|
img = self.window.processed_image(func=image_pre_process)
|
2022-02-01 16:50:57 +00:00
|
|
|
values = get_values_from_image(img)
|
|
|
|
return values[:3] if values else None
|
2020-06-24 23:16:23 +00:00
|
|
|
|
2021-05-15 12:20:38 +00:00
|
|
|
def move_to(self, target) -> bool:
|
|
|
|
current = self.get_coords()
|
|
|
|
if not current:
|
|
|
|
return False
|
2020-06-25 13:40:05 +00:00
|
|
|
|
2022-02-02 22:39:39 +00:00
|
|
|
logging.debug(f"Moving from {(current[0], current[1])} to {target}")
|
2020-06-25 13:40:05 +00:00
|
|
|
move_vec = target[0] - current[0], target[1] - current[1]
|
2020-10-17 22:04:25 +00:00
|
|
|
|
|
|
|
dist = math.sqrt(move_vec[0] ** 2 + move_vec[1] ** 2)
|
2022-02-02 22:39:39 +00:00
|
|
|
logging.debug(f"distance: {dist}")
|
2020-10-17 22:04:25 +00:00
|
|
|
if dist < 5e-05:
|
2022-02-02 22:39:39 +00:00
|
|
|
logging.debug("distance very small skipping")
|
2021-05-15 12:20:38 +00:00
|
|
|
return True
|
2020-10-17 22:04:25 +00:00
|
|
|
|
|
|
|
target_angle = math.degrees(math.atan2(-move_vec[1], move_vec[0])) + 90
|
2020-10-15 01:26:31 +00:00
|
|
|
from_angle = current[2]
|
|
|
|
|
2021-05-15 12:20:38 +00:00
|
|
|
if not self.rotate_to(target_angle, from_angle):
|
|
|
|
return False
|
2020-10-15 01:26:31 +00:00
|
|
|
|
2021-04-17 16:31:19 +00:00
|
|
|
walking_time = dist / self.calibrator.move_factor
|
2022-02-02 22:39:39 +00:00
|
|
|
logging.debug(f"walking for {walking_time}")
|
2020-10-15 01:26:31 +00:00
|
|
|
kb.press('w')
|
|
|
|
time.sleep(walking_time)
|
|
|
|
kb.release('w')
|
2022-02-02 22:39:39 +00:00
|
|
|
logging.debug("done")
|
2022-02-01 11:27:14 +00:00
|
|
|
# todo: maybe check if it reached the destination before returning true?
|
2021-05-15 12:20:38 +00:00
|
|
|
return True
|
2020-10-15 01:26:31 +00:00
|
|
|
|
2021-05-15 12:20:38 +00:00
|
|
|
def rotate_to(self, target_angle, from_angle=None) -> bool:
|
2020-10-17 19:45:57 +00:00
|
|
|
if from_angle is None:
|
2021-05-15 12:20:38 +00:00
|
|
|
coords = self.get_coords()
|
|
|
|
if not coords:
|
|
|
|
return False
|
|
|
|
_, _, from_angle = coords
|
2020-10-15 01:26:31 +00:00
|
|
|
|
2020-06-25 13:40:05 +00:00
|
|
|
if target_angle < 0:
|
|
|
|
target_angle = 360 + target_angle
|
|
|
|
while target_angle > 360:
|
|
|
|
target_angle -= 360
|
2022-02-02 22:39:39 +00:00
|
|
|
logging.debug(f"Rotating from {from_angle} to {target_angle}")
|
2020-06-25 13:40:05 +00:00
|
|
|
|
2020-10-15 01:26:31 +00:00
|
|
|
angle_diff = target_angle - from_angle
|
2020-06-25 13:40:05 +00:00
|
|
|
|
|
|
|
if abs(angle_diff) > 180:
|
2020-06-25 16:39:05 +00:00
|
|
|
angle_diff = (360 - abs(angle_diff)) * sign(angle_diff) * -1
|
2020-06-25 13:40:05 +00:00
|
|
|
|
2021-04-17 16:31:19 +00:00
|
|
|
rotate_times = int(angle_diff / self.calibrator.rot_factor) * -1
|
2020-06-25 13:40:05 +00:00
|
|
|
|
2022-02-02 22:39:39 +00:00
|
|
|
logging.debug(f"rotate_times: {rotate_times}")
|
2020-06-25 13:40:05 +00:00
|
|
|
|
|
|
|
for _ in range(abs(rotate_times)):
|
2020-10-15 01:26:31 +00:00
|
|
|
mse.move(sign(rotate_times) * FullAuto.rotate_by * -1, 0)
|
2020-06-25 13:40:05 +00:00
|
|
|
time.sleep(0.05)
|
|
|
|
|
2021-05-15 12:20:38 +00:00
|
|
|
return True
|
|
|
|
|
|
|
|
def look_for_hole(self) -> bool:
|
2021-12-01 05:57:16 +00:00
|
|
|
valid_states = [fishing_mode.State.LOOKING, fishing_mode.State.FISHING]
|
2021-12-20 06:27:55 +00:00
|
|
|
_hole_found_flag = FishingMode.CurrentMode in valid_states
|
|
|
|
|
2022-02-01 11:27:14 +00:00
|
|
|
# if vertical movement is disabled
|
2021-12-20 06:27:55 +00:00
|
|
|
if not config.get("look_for_hole", 1):
|
|
|
|
return _hole_found_flag
|
2020-10-15 02:23:15 +00:00
|
|
|
|
|
|
|
t = 0
|
2021-12-20 06:27:55 +00:00
|
|
|
while not _hole_found_flag and t <= 2.5:
|
2021-12-01 05:57:16 +00:00
|
|
|
direction = -1 if t > 1.25 else 1
|
|
|
|
mse.move(0, FullAuto.rotate_by*direction)
|
2020-10-15 02:23:15 +00:00
|
|
|
time.sleep(0.05)
|
|
|
|
t += 0.05
|
2021-12-20 06:27:55 +00:00
|
|
|
_hole_found_flag = FishingMode.CurrentMode in valid_states
|
2020-10-15 02:23:15 +00:00
|
|
|
|
|
|
|
self._curr_rotate_y = t
|
2021-12-20 06:27:55 +00:00
|
|
|
return _hole_found_flag
|
2020-10-15 02:23:15 +00:00
|
|
|
|
2020-10-17 19:45:57 +00:00
|
|
|
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
|
|
|
|
|
2020-06-03 01:41:54 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2020-06-25 01:22:39 +00:00
|
|
|
# noinspection PyTypeChecker
|
2020-10-17 19:06:07 +00:00
|
|
|
bot = FullAuto(None)
|
2020-06-03 01:41:54 +00:00
|
|
|
bot.toggle_start()
|