* init, wip * time to test * remove unused dataclass * tests passing, just need to run in-game * fix wait logic * add threading lock, delete excess funcs * start putting best_match back in to search_and_wait() * bugfixes, found a bad template * scope * fix npc detect
152 lines
6.0 KiB
Python
152 lines
6.0 KiB
Python
import keyboard
|
|
from ui import skills
|
|
from utils.custom_mouse import mouse
|
|
from char import IChar,CharacterCapabilities
|
|
import template_finder
|
|
from pather import Pather
|
|
from logger import Logger
|
|
from screen import convert_abs_to_monitor
|
|
from config import Config
|
|
from utils.misc import wait, cut_roi
|
|
import time
|
|
from pather import Pather, Location
|
|
|
|
|
|
class Basic(IChar):
|
|
def __init__(self, skill_hotkeys: dict, pather: Pather):
|
|
Logger.info("Setting up Basic Character")
|
|
super().__init__(skill_hotkeys)
|
|
self._pather = pather
|
|
self._do_pre_move = True
|
|
|
|
def on_capabilities_discovered(self, capabilities: CharacterCapabilities):
|
|
# offset shenk final position further to the right and bottom
|
|
if capabilities.can_teleport_natively:
|
|
self._pather.offset_node(149, [120, 70])
|
|
|
|
def _cast_attack_pattern(self, time_in_s: float):
|
|
keyboard.send(Config().char["stand_still"], do_release=False)
|
|
wait(0.05, 0.1)
|
|
keyboard.send(self._skill_hotkeys["left_attack"])
|
|
wait(0.05, 0.1)
|
|
keyboard.send(self._skill_hotkeys["right_attack"])
|
|
wait(0.05, 0.1)
|
|
start = time.time()
|
|
while (time.time() - start) < time_in_s:
|
|
if skills.is_right_skill_active():
|
|
wait(0.05, 0.1)
|
|
mouse.click(button="right")
|
|
else:
|
|
wait(0.05, 0.1)
|
|
mouse.click(button="left")
|
|
wait(0.01, 0.05)
|
|
keyboard.send(Config().char["stand_still"], do_press=False)
|
|
|
|
def pre_buff(self):
|
|
if Config().char["cta_available"]:
|
|
self._pre_buff_cta()
|
|
if self._skill_hotkeys["buff_1"]:
|
|
keyboard.send(self._skill_hotkeys["buff_1"])
|
|
wait(0.5, 0.15)
|
|
mouse.click(button="right")
|
|
wait(0.5, 0.15)
|
|
if self._skill_hotkeys["buff_2"]:
|
|
keyboard.send(self._skill_hotkeys["buff_2"])
|
|
wait(0.5, 0.15)
|
|
mouse.click(button="right")
|
|
wait(0.5, 0.15)
|
|
|
|
def pre_move(self):
|
|
# select teleport if available
|
|
super().pre_move()
|
|
|
|
def _move_and_attack(self, abs_move: tuple[int, int], atk_len: float):
|
|
pos_m = convert_abs_to_monitor(abs_move)
|
|
self.pre_move()
|
|
self.move(pos_m, force_move=True)
|
|
self._cast_attack_pattern(atk_len)
|
|
|
|
|
|
#this is where we kill bosses
|
|
|
|
def kill_pindle(self) -> bool:
|
|
wait(0.1, 0.15)
|
|
if self.capabilities.can_teleport_natively:
|
|
self._pather.traverse_nodes_fixed("pindle_end", self)
|
|
else:
|
|
if not self._do_pre_move:
|
|
# keyboard.send(self._skill_hotkeys["concentration"])
|
|
# wait(0.05, 0.15)
|
|
self._pather.traverse_nodes((Location.A5_PINDLE_SAFE_DIST, Location.A5_PINDLE_END), self, timeout=1.0, do_pre_move=self._do_pre_move)
|
|
self._pather.traverse_nodes((Location.A5_PINDLE_SAFE_DIST, Location.A5_PINDLE_END), self, timeout=0.1)
|
|
self._cast_attack_pattern(Config().char["atk_len_pindle"])
|
|
wait(0.1, 0.15)
|
|
return True
|
|
|
|
def kill_eldritch(self) -> bool:
|
|
if self.capabilities.can_teleport_natively:
|
|
self._pather.traverse_nodes_fixed("eldritch_end", self)
|
|
else:
|
|
if not self._do_pre_move:
|
|
# keyboard.send(self._skill_hotkeys["concentration"])
|
|
# wait(0.05, 0.15)
|
|
self._pather.traverse_nodes((Location.A5_ELDRITCH_SAFE_DIST, Location.A5_ELDRITCH_END), self, timeout=1.0, do_pre_move=self._do_pre_move)
|
|
wait(0.05, 0.1)
|
|
self._cast_attack_pattern(Config().char["atk_len_eldritch"])
|
|
return True
|
|
|
|
def kill_shenk(self):
|
|
# if not self._do_pre_move:
|
|
# keyboard.send(self._skill_hotkeys["concentration"])
|
|
# wait(0.05, 0.15)
|
|
self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, timeout=1.0, do_pre_move=self._do_pre_move)
|
|
wait(0.05, 0.1)
|
|
self._cast_attack_pattern(Config().char["atk_len_shenk"])
|
|
wait(0.1, 0.15)
|
|
return True
|
|
|
|
def kill_council(self) -> bool:
|
|
# Check out the node screenshot in assets/templates/trav/nodes to see where each node is at
|
|
atk_len = Config().char["atk_len_trav"]
|
|
# Go inside and war cry a bit
|
|
self._pather.traverse_nodes([228, 229], self, timeout=2.5, force_tp=True)
|
|
self._cast_attack_pattern(atk_len)
|
|
# Move a bit back and another round
|
|
self._move_and_attack((40, 20), atk_len)
|
|
# Here we have two different attack sequences depending if tele is available or not
|
|
if self.capabilities.can_teleport_natively:
|
|
# Back to center stairs and more war cry
|
|
self._pather.traverse_nodes([226], self, timeout=2.5, force_tp=True)
|
|
self._cast_attack_pattern(atk_len)
|
|
# move a bit to the top
|
|
self._move_and_attack((65, -30), atk_len)
|
|
else:
|
|
# Stay inside and cast war cry again moving forward
|
|
self._move_and_attack((40, 10), atk_len)
|
|
self._move_and_attack((-40, -20), atk_len)
|
|
return True
|
|
|
|
def kill_nihlathak(self, end_nodes: list[int]) -> bool:
|
|
# Move close to nihlathak
|
|
self._pather.traverse_nodes(end_nodes, self, timeout=0.8, do_pre_move=False)
|
|
# move mouse to center (leftover from hammerdin)
|
|
pos_m = convert_abs_to_monitor((0, 0))
|
|
mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7])
|
|
self._cast_attack_pattern(Config().char["atk_len_nihlathak"] * 0.4)
|
|
self._cast_attack_pattern(0.8)
|
|
self._move_and_attack((30, 15), Config().char["atk_len_nihlathak"] * 0.3)
|
|
self._cast_attack_pattern(0.8)
|
|
self._move_and_attack((-30, -15), Config().char["atk_len_nihlathak"] * 0.4)
|
|
wait(0.1, 0.15)
|
|
self._cast_attack_pattern(1.2)
|
|
return True
|
|
|
|
if __name__ == "__main__":
|
|
import os
|
|
import keyboard
|
|
keyboard.add_hotkey('f12', lambda: Logger.info('Force Exit (f12)') or os._exit(1))
|
|
keyboard.wait("f11")
|
|
from config import Config
|
|
pather = Pather()
|
|
char = Basic(Config().basic, Config().char, pather)
|