Reworked trapsin a bit to include casting/attack delays between skills. Also added mindblast and added to pindle run.

This commit is contained in:
Randi
2024-06-26 19:59:50 -04:00
parent 8df42bbcb1
commit 30d407e978
2 changed files with 147 additions and 44 deletions
+19 -16
View File
@@ -19,7 +19,7 @@ max_runtime_before_break_m=0
; timers / fail handling
d2r_path=C:\Program Files (x86)\Diablo II Resurrected
max_consecutive_fails=5
max_game_length_s=140
max_game_length_s=55
; if you set this field to 1, botty will attempt to restart d2 after a crash or failure
restart_d2r_when_stuck=0
@@ -38,18 +38,18 @@ pickit_screenshots=0
; run_arcane
; run_diablo
; run_vizier
order=run_pindle,run_eldritch_shenk
order=run_pindle
[char]
; ==========================
; ==== Mandatory Fields ====
; ==========================
; These configs have to be alligned with your d2r settings and char build
type=blizzorb_sorc
type=trapsin
belt_rows=4
casting_frames=8
attack_frames=15
cta_available=1
casting_frames=11
attack_frames=10
cta_available=0
; safer_routines: enable for optional defensive maneuvers/etc during combat/runs at the cost of increased runtime (ex. hardcore players)
safer_routines=1
@@ -70,7 +70,7 @@ show_items=alt
; stand_still cannot be the default "shift" as it would interfere with merc healing
stand_still=capslock
; teleport: leave empty if you can't use
teleport=f7
teleport=
town_portal=f8
; call to arms settings:
weapon_switch=x
@@ -87,7 +87,7 @@ use_merc=1
atk_len_arc=2.5
atk_len_eldritch=10.0
atk_len_nihlathak=8.0
atk_len_pindle=7.0
atk_len_pindle=8.5
atk_len_shenk=8.0
atk_len_trav=3.0
@@ -109,9 +109,9 @@ belt_rejuv_columns=2
; Potion/chicken settings
take_health_potion=0.92
take_mana_potion=0.8
take_mana_potion=0.40
take_rejuv_potion_health=0.75
take_rejuv_potion_mana=0.45
take_rejuv_potion_mana=0.10
heal_merc=0.7
heal_rejuv_merc=0.3
chicken=0.5
@@ -207,13 +207,16 @@ concentration=f5
; ==========================
; Currently no Trav implementaiton!
[trapsin]
burst_of_speed=
death_sentry=
fade=
lightning_sentry=
shadow_warrior=
; We assume fire blast or shock-web is left-click skill which is optional hotkey if pre-assigned.
skill_left=
; Assume all other skills are right-click and hotkey required!
burst_of_speed=f1
death_sentry=f2
fade=
lightning_sentry=f3
shadow_warrior=f4
mind_blast=f5
; ===========================
; ==== Builds: Barbarian ====
@@ -338,7 +341,7 @@ message_body_template={{"content": "{msg}"}}
message_headers=
ocr_during_pickit=0
;use "can_teleport_natively" or "can_teleport_with_charges" if you want to force certain behavior in case autodetection isn't working properly
override_capabilities="can_teleport_natively"
override_capabilities=
pathing_delay_factor=4
;If you want to control Hyper-V window from host use 0,51 here
window_client_area_offset=0,0
+128 -28
View File
@@ -1,4 +1,5 @@
import keyboard
from ui import skills
from utils.custom_mouse import mouse
from char import IChar
from pather import Pather
@@ -6,6 +7,7 @@ from logger import Logger
from screen import convert_abs_to_monitor, convert_screen_to_abs, grab
from config import Config
from utils.misc import wait, rotate_vec, unit_vector
import time
import random
from pather import Location, Pather
import numpy as np
@@ -25,16 +27,11 @@ class Trapsin(IChar):
wait(0.1, 0.13)
mouse.click(button="right")
wait(self._cast_duration)
if self._skill_hotkeys["shadow_warrior"]:
keyboard.send(self._skill_hotkeys["shadow_warrior"])
wait(0.1, 0.13)
mouse.click(button="right")
wait(self._cast_duration)
def pre_move(self, wait_tp: bool = False):
super().pre_move(wait_tp=wait_tp)
if self._skill_hotkeys["burst_of_speed"]:
keyboard.send(self._skill_hotkeys["burst_of_speed"])
wait(0.1, 0.13)
mouse.click(button="right")
wait(self._cast_duration)
self._cast_burst_of_speed()
def _left_attack(self, cast_pos_abs: tuple[float, float], spray: int = 10):
keyboard.send(Config().char["stand_still"], do_release=False)
@@ -50,7 +47,6 @@ class Trapsin(IChar):
mouse.release(button="left")
keyboard.send(Config().char["stand_still"], do_press=False)
def _right_attack(self, cast_pos_abs: tuple[float, float], spray: float = 10):
keyboard.send(self._skill_hotkeys["lightning_sentry"])
x = cast_pos_abs[0] + (random.random() * 2 * spray - spray)
@@ -66,35 +62,139 @@ class Trapsin(IChar):
atk(4)
keyboard.send(self._skill_hotkeys["death_sentry"])
atk(1)
def _cast_shadow_warrior(self, cast_pos_abs: tuple[float, float], spray: float = 10):
if self._skill_hotkeys["shadow_warrior"]:
keyboard.send(self._skill_hotkeys["shadow_warrior"])
x = cast_pos_abs[0] + (random.random() * 2 * spray - spray)
y = cast_pos_abs[1] + (random.random() * 2 * spray - spray)
cast_pos_monitor = convert_abs_to_monitor((x, y))
mouse.move(*cast_pos_monitor)
mouse.press(button="right")
wait(0.06, 0.08)
mouse.release(button="right")
wait(self._cast_duration-0.06)
def _cast_mind_blast(self, cast_pos_abs: tuple[float, float], spray: float = 10):
if self._skill_hotkeys["mind_blast"]:
keyboard.send(self._skill_hotkeys["mind_blast"])
x = cast_pos_abs[0] + (random.random() * 2 * spray - spray)
y = cast_pos_abs[1] + (random.random() * 2 * spray - spray)
cast_pos_monitor = convert_abs_to_monitor((x, y))
mouse.move(*cast_pos_monitor)
mouse.press(button="right")
wait(0.06, 0.08)
mouse.release(button="right")
wait(self._cast_duration-0.06)
def _cast_burst_of_speed(self):
if self._skill_hotkeys["burst_of_speed"]:
keyboard.send(self._skill_hotkeys["burst_of_speed"])
mouse.press(button="right")
wait(0.06, 0.08)
mouse.release(button="right")
wait(self._cast_duration-0.06)
def _cast_fire_blast(self, cast_pos_abs: tuple[float, float], spray: float = 10, duration: float = 0.3):
keyboard.send(Config().char["stand_still"], do_release=False)
#Get mouse in initial target logcation
x = cast_pos_abs[0] + (random.random() * 2 * spray - spray)
y = cast_pos_abs[1] + (random.random() * 2 * spray - spray)
cast_pos_monitor = convert_abs_to_monitor((x, y))
mouse.move(*cast_pos_monitor)
#We just hold down left mouse button to ensure we get full attack speed.
mouse.press(button="left")
now = start = time.time()
while (now - start) < duration:
x = cast_pos_abs[0] + (random.random() * 2 * spray - spray)
y = cast_pos_abs[1] + (random.random() * 2 * spray - spray)
cast_pos_monitor = convert_abs_to_monitor((x, y))
mouse.move(*cast_pos_monitor)
wait(0.06, 0.08)
now = time.time()
mouse.release(button="left")
keyboard.send(Config().char["stand_still"], do_press=False)
wait(self._attack_duration-0.06)
def _cast_lightning_sentry(self, cast_pos_abs: tuple[float, float], spray: float = 10):
if not self._skill_hotkeys["lightning_sentry"]:
Logger.error("Lightning sentry hotkey not assigned. Required for trapsin!")
keyboard.send(self._skill_hotkeys["lightning_sentry"])
x = cast_pos_abs[0] + (random.random() * 2 * spray - spray)
y = cast_pos_abs[1] + (random.random() * 2 * spray - spray)
cast_pos_monitor = convert_abs_to_monitor((x, y))
mouse.move(*cast_pos_monitor)
mouse.press(button="right")
wait(0.06, 0.08)
mouse.release(button="right")
wait(self._attack_duration-0.06)
def _cast_death_sentry(self, cast_pos_abs: tuple[float, float], spray: float = 10):
if not self._skill_hotkeys["death_sentry"]:
Logger.error("Death sentry hotkey not assigned. Required for trapsin!")
keyboard.send(self._skill_hotkeys["death_sentry"])
x = cast_pos_abs[0] + (random.random() * 2 * spray - spray)
y = cast_pos_abs[1] + (random.random() * 2 * spray - spray)
cast_pos_monitor = convert_abs_to_monitor((x, y))
mouse.move(*cast_pos_monitor)
mouse.press(button="right")
wait(0.06, 0.08)
mouse.release(button="right")
wait(self._attack_duration-0.06)
def kill_pindle(self) -> bool:
atk_len = max(1, int(Config().char["atk_len_pindle"] / 2))
pindle_pos_abs = convert_screen_to_abs(Config().path["pindle_end"][0])
cast_pos_abs = [pindle_pos_abs[0] * 0.9, pindle_pos_abs[1] * 0.9]
for _ in range(atk_len):
self._right_attack(cast_pos_abs, 11)
self._left_attack(cast_pos_abs, 11)
# Move to items
wait(self._cast_duration, self._cast_duration + 0.2)
cast_pos_abs = [pindle_pos_abs[0] * 1.2, pindle_pos_abs[1] * 1.2]
trap_cast_pos_abs = [pindle_pos_abs[0] * 0.45, pindle_pos_abs[1] * 0.40]
start = time.time()
self._cast_mind_blast(cast_pos_abs=cast_pos_abs)
cast_pos_abs = [pindle_pos_abs[0] * 0.8, pindle_pos_abs[1] * 0.8]
self._cast_shadow_warrior(cast_pos_abs=cast_pos_abs)
for _ in range(4):
self._cast_lightning_sentry(cast_pos_abs=trap_cast_pos_abs, spray=5.0)
self._cast_death_sentry(cast_pos_abs=trap_cast_pos_abs, spray=5.0)
trap_cast_pos_abs = [pindle_pos_abs[0] * 0.50, pindle_pos_abs[1] * 0.50]
time_remaining = Config().char["atk_len_pindle"] - (time.time() - start)
self._cast_fire_blast(cast_pos_abs=cast_pos_abs, duration=time_remaining)
if self.capabilities.can_teleport_natively:
self._pather.traverse_nodes_fixed("pindle_end", self)
else:
self._pather.traverse_nodes((Location.A5_PINDLE_SAFE_DIST, Location.A5_PINDLE_END), self, force_tp=True)
return True
#Walk just close enough to pindle's position to see items. That way we leave sooner if there is nothing to grab
x_m, y_m = convert_abs_to_monitor([pindle_pos_abs[0] * 0.65, pindle_pos_abs[1] * 0.65])
self.move((x_m, y_m), force_move=True)
return False
def kill_eldritch(self) -> bool:
atk_len = max(1, int(Config().char["atk_len_eldritch"] / 2))
eld_pos_abs = convert_screen_to_abs(Config().path["eldritch_end"][0])
cast_pos_abs = [eld_pos_abs[0] * 0.9, eld_pos_abs[1] * 0.9]
for _ in range(atk_len):
self._right_attack(cast_pos_abs, 90)
self._left_attack(cast_pos_abs, 90)
# Move to items
wait(self._cast_duration, self._cast_duration + 0.2)
eldritch_pos_abs = convert_screen_to_abs(Config().path["eldritch_end"][0])
cast_pos_abs = [eldritch_pos_abs[0] * 1.5, eldritch_pos_abs[1] * 1.5]
trap_cast_pos_abs = [eldritch_pos_abs[0] * 0.70, eldritch_pos_abs[1] * 0.70]
start = time.time()
self._cast_shadow_warrior(cast_pos_abs=cast_pos_abs)
for _ in range(4):
self._cast_lightning_sentry(cast_pos_abs=trap_cast_pos_abs)
self._cast_death_sentry(cast_pos_abs=trap_cast_pos_abs)
time_remaining = Config().char["atk_len_eldritch"] - (time.time() - start)
self._cast_fire_blast(cast_pos_abs=cast_pos_abs, duration=time_remaining)
if self.capabilities.can_teleport_natively:
self._pather.traverse_nodes_fixed("eldritch_end", self)
else:
self._pather.traverse_nodes((Location.A5_ELDRITCH_SAFE_DIST, Location.A5_ELDRITCH_END), self, timeout=0.6, force_tp=True)
x_m, y_m = convert_abs_to_monitor([eldritch_pos_abs[0] * 1.0, eldritch_pos_abs[1] * 1.0])
self.move((x_m, y_m), force_move=True)
return True
def kill_shenk(self) -> bool: