mirror of
https://github.com/fishyboteso/fishyboteso.git
synced 2024-08-30 18:32:13 +00:00
fullauto reworked with the new parent class
- removed double beep on turnoff - removed show crop feature in fullauto - semi fisher is started only when needed, and turned off when the job is done by mode, instead of full auto engine - use the last coord from recording isntead of getting a new one when using editor in recorder mode, to avoid recording failure when saving the recording
This commit is contained in:
parent
a5236e9b30
commit
245493fbc4
@ -29,15 +29,18 @@ class IEngine:
|
||||
|
||||
return self.get_gui().funcs
|
||||
|
||||
@property
|
||||
def start(self):
|
||||
return self.state == 1
|
||||
|
||||
def toggle_start(self):
|
||||
if self.state == 1:
|
||||
self.turn_off()
|
||||
elif self.state == 0:
|
||||
if self.state == 0:
|
||||
self.turn_on()
|
||||
else:
|
||||
self.turn_on()
|
||||
|
||||
def turn_on(self):
|
||||
self.state = 1
|
||||
playsound(helper.manifest_file("beep.wav"), False)
|
||||
self.thread = Thread(target=self._crash_safe)
|
||||
self.thread.start()
|
||||
|
||||
@ -46,8 +49,12 @@ class IEngine:
|
||||
this method only signals the thread to close using start flag,
|
||||
its the responsibility of the thread to shut turn itself off
|
||||
"""
|
||||
self.state = 2
|
||||
helper.playsound_multiple(helper.manifest_file("beep.wav"))
|
||||
if self.state == 1:
|
||||
logging.info("turning off...")
|
||||
self.state = 2
|
||||
else:
|
||||
logging.error("engine already signaled to turn off")
|
||||
# todo: implement force turn off on repeated calls
|
||||
|
||||
# noinspection PyBroadException
|
||||
def _crash_safe(self):
|
||||
|
@ -7,7 +7,6 @@ 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
|
||||
@ -19,10 +18,9 @@ from fishy.engine.common.qr_detection import (get_qr_location,
|
||||
get_values_from_image, image_pre_process)
|
||||
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 import hotkey
|
||||
from fishy.helper.config import config
|
||||
from fishy.helper.helper import log_raise, wait_until, is_eso_active
|
||||
from fishy.helper.helper import sign
|
||||
from fishy.helper.helper import wait_until, is_eso_active, sign
|
||||
|
||||
mse = mouse.Controller()
|
||||
kb = keyboard.Controller()
|
||||
@ -45,7 +43,6 @@ class FullAuto(IEngine):
|
||||
self.mode = None
|
||||
|
||||
def run(self):
|
||||
self.gui.bot_started(True)
|
||||
self.window = WindowClient(color=cv2.COLOR_RGB2GRAY, show_name="Full auto debug")
|
||||
|
||||
self.mode = None
|
||||
@ -55,7 +52,11 @@ class FullAuto(IEngine):
|
||||
self.mode = Player(self)
|
||||
elif FullAutoMode(config.get("full_auto_mode", 0)) == FullAutoMode.Recorder:
|
||||
self.mode = Recorder(self)
|
||||
else:
|
||||
logging.error("not a valid mode selected")
|
||||
return
|
||||
|
||||
# block thread until game window becomes active
|
||||
if not is_eso_active():
|
||||
logging.info("Waiting for eso window to be active...")
|
||||
wait_until(lambda: is_eso_active() or not self.start)
|
||||
@ -63,37 +64,34 @@ class FullAuto(IEngine):
|
||||
logging.info("starting in 2 secs...")
|
||||
time.sleep(2)
|
||||
|
||||
if not self._pre_run_checks():
|
||||
return
|
||||
|
||||
if config.get("tabout_stop", 1):
|
||||
self.stop_on_inactive()
|
||||
|
||||
# noinspection PyBroadException
|
||||
try:
|
||||
if self.window.get_capture() is None:
|
||||
log_raise("Game window not found")
|
||||
|
||||
self.window.crop = get_qr_location(self.window.get_capture())
|
||||
if self.window.crop is None:
|
||||
log_raise("FishyQR not found, try to drag it around and try again")
|
||||
|
||||
if not (type(self.mode) is Calibrator) and not self.calibrator.all_calibrated():
|
||||
log_raise("you need to calibrate first")
|
||||
|
||||
self.fisher.toggle_start()
|
||||
fishing_event.unsubscribe()
|
||||
if self.show_crop:
|
||||
self.start_show()
|
||||
|
||||
if config.get("tabout_stop", 1):
|
||||
self.stop_on_inactive()
|
||||
|
||||
self.mode.run()
|
||||
|
||||
except Exception:
|
||||
logging.error("exception occurred while running full auto mode")
|
||||
traceback.print_exc()
|
||||
self.start = False
|
||||
|
||||
self.gui.bot_started(False)
|
||||
self.window.show(False)
|
||||
logging.info("Quitting")
|
||||
self.window.destory()
|
||||
self.fisher.toggle_start()
|
||||
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
|
||||
|
||||
def start_show(self):
|
||||
def func():
|
||||
@ -103,8 +101,10 @@ class FullAuto(IEngine):
|
||||
|
||||
def stop_on_inactive(self):
|
||||
def func():
|
||||
wait_until(lambda: not is_eso_active())
|
||||
self.start = False
|
||||
logging.info("stop on inactive started")
|
||||
wait_until(lambda: not is_eso_active() or self.start != 1)
|
||||
self.turn_off()
|
||||
logging.info("stop on inactive stopped")
|
||||
Thread(target=func).start()
|
||||
|
||||
def get_coords(self):
|
||||
@ -143,6 +143,7 @@ class FullAuto(IEngine):
|
||||
time.sleep(walking_time)
|
||||
kb.release('w')
|
||||
print("done")
|
||||
# todo: maybe check if it reached the destination before returning true?
|
||||
return True
|
||||
|
||||
def rotate_to(self, target_angle, from_angle=None) -> bool:
|
||||
@ -177,6 +178,7 @@ class FullAuto(IEngine):
|
||||
valid_states = [fishing_mode.State.LOOKING, fishing_mode.State.FISHING]
|
||||
_hole_found_flag = FishingMode.CurrentMode in valid_states
|
||||
|
||||
# if vertical movement is disabled
|
||||
if not config.get("look_for_hole", 1):
|
||||
return _hole_found_flag
|
||||
|
||||
|
@ -75,25 +75,25 @@ class Calibrator(IMode):
|
||||
def _walk_calibrate(self):
|
||||
walking_time = 3
|
||||
|
||||
coods = self.engine.get_coords()
|
||||
if coods is None:
|
||||
coords = self.engine.get_coords()
|
||||
if coords is None:
|
||||
return
|
||||
|
||||
x1, y1, rot1 = coods
|
||||
x1, y1, rot1 = coords
|
||||
|
||||
kb.press('w')
|
||||
time.sleep(walking_time)
|
||||
kb.release('w')
|
||||
time.sleep(0.5)
|
||||
|
||||
coods = self.engine.get_coords()
|
||||
if coods is None:
|
||||
coords = self.engine.get_coords()
|
||||
if coords is None:
|
||||
return
|
||||
x2, y2, rot2 = coods
|
||||
x2, y2, rot2 = coords
|
||||
|
||||
move_factor = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) / walking_time
|
||||
_update_factor("move_factor", move_factor)
|
||||
logging.info("walk calibrate done")
|
||||
logging.info(f"walk calibrate done, move_factor: {move_factor}")
|
||||
|
||||
def _rotate_calibrate(self):
|
||||
from fishy.engine.fullautofisher.engine import FullAuto
|
||||
@ -119,7 +119,7 @@ class Calibrator(IMode):
|
||||
|
||||
rot_factor = (rot3 - rot2) / rotate_times
|
||||
_update_factor("rot_factor", rot_factor)
|
||||
logging.info("rotate calibrate done")
|
||||
logging.info(f"rotate calibrate done, rot_factor: {rot_factor}")
|
||||
|
||||
def run(self):
|
||||
self._walk_calibrate()
|
||||
|
@ -2,14 +2,11 @@ import logging
|
||||
import math
|
||||
import pickle
|
||||
import time
|
||||
from pprint import pprint
|
||||
|
||||
import typing
|
||||
from threading import Thread
|
||||
|
||||
from fishy.engine.fullautofisher.mode.imode import IMode
|
||||
from fishy.engine.semifisher import fishing_event, fishing_mode
|
||||
from fishy.helper.helper import log_raise, wait_until, kill_thread
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from fishy.engine.fullautofisher.engine import FullAuto
|
||||
@ -56,23 +53,28 @@ class Player(IMode):
|
||||
self.timeline = None
|
||||
|
||||
def run(self):
|
||||
self._init()
|
||||
if not self._init():
|
||||
return
|
||||
|
||||
while self.engine.start:
|
||||
self._loop()
|
||||
time.sleep(0.1)
|
||||
|
||||
logging.info("player stopped")
|
||||
|
||||
def _init(self):
|
||||
def _init(self) -> bool:
|
||||
self.timeline = get_rec_file()
|
||||
if not self.timeline:
|
||||
log_raise("data not found, can't start")
|
||||
logging.info("starting player")
|
||||
logging.error("data not found, can't start")
|
||||
return False
|
||||
|
||||
coords = self.engine.get_coords()
|
||||
if not coords:
|
||||
log_raise("QR not found")
|
||||
logging.error("QR not found")
|
||||
return False
|
||||
|
||||
self.i = find_nearest(self.timeline, coords)[0]
|
||||
logging.info("starting player")
|
||||
|
||||
def _loop(self):
|
||||
action = self.timeline[self.i]
|
||||
@ -87,21 +89,22 @@ class Player(IMode):
|
||||
if not self.engine.rotate_to(action[1][2]):
|
||||
return
|
||||
|
||||
fishing_mode.subscribers.append(self._hole_complete_callback)
|
||||
fishing_event.subscribe()
|
||||
self.engine.fisher.turn_on()
|
||||
# scan for fish hole
|
||||
logging.info("scanning")
|
||||
# if found start fishing and wait for hole to complete
|
||||
if self.engine.look_for_hole():
|
||||
logging.info("starting fishing")
|
||||
fishing_mode.subscribers.append(self._hole_complete_callback)
|
||||
self.hole_complete_flag = False
|
||||
helper.wait_until(lambda: self.hole_complete_flag or not self.engine.start)
|
||||
fishing_mode.subscribers.remove(self._hole_complete_callback)
|
||||
|
||||
self.engine.rotate_back()
|
||||
else:
|
||||
logging.info("no hole found")
|
||||
# continue when hole completes
|
||||
fishing_mode.subscribers.remove(self._hole_complete_callback)
|
||||
fishing_event.unsubscribe()
|
||||
self.engine.fisher.turn_off()
|
||||
|
||||
self.next()
|
||||
|
||||
|
@ -9,20 +9,18 @@ import typing
|
||||
from tkinter.filedialog import asksaveasfile
|
||||
|
||||
from fishy.engine.fullautofisher.mode import player
|
||||
from fishy.helper import helper
|
||||
|
||||
from fishy.helper.helper import empty_function, log_raise
|
||||
from fishy.helper.helper import empty_function
|
||||
from fishy.helper.hotkey.process import Key
|
||||
|
||||
from fishy.helper.popup import PopUp
|
||||
from playsound import playsound
|
||||
|
||||
from fishy.helper.config import config
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from fishy.engine.fullautofisher.engine import FullAuto
|
||||
from fishy.engine.fullautofisher.mode.imode import IMode
|
||||
from fishy.helper.hotkey.hotkey_process import HotKey, hotkey
|
||||
from fishy.helper.hotkey.hotkey_process import hotkey
|
||||
|
||||
|
||||
class Recorder(IMode):
|
||||
@ -49,48 +47,50 @@ class Recorder(IMode):
|
||||
|
||||
old_timeline = player.get_rec_file()
|
||||
if not old_timeline:
|
||||
log_raise("Edit mode selected, but no fishy file selected")
|
||||
logging.error("Edit mode selected, but no fishy file selected")
|
||||
return
|
||||
|
||||
coords = self.engine.get_coords()
|
||||
if not coords:
|
||||
log_raise("QR not found")
|
||||
logging.error("QR not found")
|
||||
return
|
||||
|
||||
start_from = player.find_nearest(old_timeline, coords)
|
||||
if not self.engine.move_to(start_from[2]):
|
||||
log_raise("QR not found")
|
||||
logging.error("QR not found")
|
||||
return
|
||||
|
||||
logging.info("starting, press LMB to mark hole")
|
||||
hotkey.hook(Key.LMB, self._mark_hole)
|
||||
|
||||
self.timeline = []
|
||||
|
||||
last_coord = None
|
||||
while self.engine.start:
|
||||
start_time = time.time()
|
||||
coods = self.engine.get_coords()
|
||||
if not coods:
|
||||
coords = self.engine.get_coords()
|
||||
if not coords:
|
||||
logging.warning("missed a frame, as qr not be read properly...")
|
||||
time.sleep(0.1)
|
||||
continue
|
||||
|
||||
self.timeline.append(("move_to", (coods[0], coods[1])))
|
||||
self.timeline.append(("move_to", (coords[0], coords[1])))
|
||||
|
||||
# maintaining constant frequency for recording
|
||||
time_took = time.time() - start_time
|
||||
if time_took <= Recorder.recording_fps:
|
||||
time.sleep(Recorder.recording_fps - time_took)
|
||||
else:
|
||||
logging.warning("Took too much time to record")
|
||||
last_coord = coords
|
||||
|
||||
hotkey.free(Key.LMB)
|
||||
|
||||
if config.get("edit_recorder_mode"):
|
||||
logging.info("moving to nearest coord in recording")
|
||||
|
||||
# todo allow the user the chance to wait for qr
|
||||
coords = self.engine.get_coords()
|
||||
if not coords:
|
||||
log_raise("QR not found")
|
||||
|
||||
end = player.find_nearest(old_timeline, coords)
|
||||
end = player.find_nearest(old_timeline, last_coord)
|
||||
self.engine.move_to(end[2])
|
||||
|
||||
# recording stitching
|
||||
part1 = old_timeline[:start_from[0]]
|
||||
part2 = old_timeline[end[0]:]
|
||||
self.timeline = part1 + self.timeline + part2
|
||||
|
Loading…
x
Reference in New Issue
Block a user