Act 1 town full usage (#381)

* Act 4 - Full usage

Added Jamella as working NPC.
Added Halbu as working NPC.
Set Cain to Identify.
Added stash capabilities.

* Delete pickit.ini

* Delete a3.py

* Update pather.py

* Update npc_manager.py

* oopsy doodle

* Fixing more issues.

* Create pickit.ini

* Update a4.py

* Update a3.py

* Update pather.py

* Update pickit.ini

reverted pickit

* A1 - Completed NPCS

i hate my life.
All npcs that matter are working.
charsi repairs and tomes.
akara heals and pots.
cain identifys.
kashya resurrects.
warriv STANDS IN FRONT OF THE DAMNED STASH SO IT CAN'T BE CLICKED.
the stash .. uh stashes.
waypoints work (as long as it's the SOUTH ONE ONLY.)

#todo: fix the WP's to actively check.

* wp fix.

now it will check south and then go north.

* WP fix
This commit is contained in:
skizotenigma
2022-01-03 18:23:35 +01:00
committed by GitHub
parent 01e8078067
commit 3218d84e02
36 changed files with 216 additions and 17 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

+3 -2
View File
@@ -29,7 +29,7 @@ from char.trapsin import Trapsin
from char.hammerdin import Hammerdin
from char.barbarian import Barbarian
from run import Pindle, ShenkEld, Trav, Nihlatak, Arcane
from town import TownManager, A2, A3, A4, A5
from town import TownManager, A1, A2, A3, A4, A5
# Added for dclone ip hunt
from messenger import Messenger
@@ -71,7 +71,8 @@ class Bot:
a4 = A4(self._screen, self._template_finder, self._pather, self._char, npc_manager)
a3 = A3(self._screen, self._template_finder, self._pather, self._char, npc_manager)
a2 = A2(self._screen, self._template_finder, self._pather, self._char, npc_manager)
self._town_manager = TownManager(self._template_finder, self._ui_manager, self._item_finder, a2, a3, a4, a5)
a1 = A1(self._screen, self._template_finder, self._pather, self._char, npc_manager)
self._town_manager = TownManager(self._template_finder, self._ui_manager, self._item_finder, a1, a2, a3, a4, a5)
self._route_config = self._config.routes
self._route_order = self._config.routes_order
+49 -7
View File
@@ -10,17 +10,25 @@ from utils.custom_mouse import mouse
class Npc:
#A1
KASHYA = "kashya"
CHARSI = "charsi"
AKARA = "akara"
CAIN = "cain"
#A2
FARA = "fara"
#A3
ORMUS = "ormus"
#A4
TYRAEL = "tyrael"
JAMELLA = "jamella"
HALBU = "halbu"
#A5
QUAL_KEHK = "qual_kehk"
MALAH = "malah"
LARZUK = "larzuk"
ANYA = "anya"
TYRAEL = "tyrael"
ORMUS = "ormus"
FARA = "fara"
CAIN = "cain"
JAMELLA = "jamella"
HALBU = "halbu"
class NpcManager:
def __init__(self, screen: Screen, template_finder: TemplateFinder):
self._config = Config()
@@ -139,6 +147,40 @@ class NpcManager:
},
"template_group": ["HALBU_FRONT", "HALBU_BACK", "HALBU_SIDE", "HALBU_SIDE_2"]
},
#A1
Npc.AKARA: {
"name_tag_white": color_filter(self._template_finder.get_template("AKARA_NAME_TAG_WHITE"), self._config.colors["white"])[1],
"name_tag_gold": color_filter(self._template_finder.get_template("AKARA_NAME_TAG_GOLD"), self._config.colors["gold"])[1],
"action_btns": {
"trade": {
"white": color_filter(self._template_finder.get_template("TRADE"), self._config.colors["white"])[1],
"blue": color_filter(self._template_finder.get_template("TRADE_BLUE"), self._config.colors["blue"])[1],
}
},
"template_group": ["AKARA_FRONT", "AKARA_BACK", "AKARA_SIDE", "AKARA_SIDE_2"]
},
Npc.CHARSI: {
"name_tag_white": color_filter(self._template_finder.get_template("CHARSI_NAME_TAG_WHITE"), self._config.colors["white"])[1],
"name_tag_gold": color_filter(self._template_finder.get_template("CHARSI_NAME_TAG_GOLD"), self._config.colors["gold"])[1],
"action_btns": {
"trade_repair": {
"white": color_filter(self._template_finder.get_template("TRADE_REPAIR"), self._config.colors["white"])[1],
"blue": color_filter(self._template_finder.get_template("TRADE_REPAIR_BLUE"), self._config.colors["blue"])[1],
}
},
"template_group": ["CHARSI_FRONT", "CHARSI_BACK", "CHARSI_SIDE", "CHARSI_SIDE_2", "CHARSI_SIDE_3"]
},
Npc.KASHYA: {
"name_tag_white": color_filter(self._template_finder.get_template("KASHYA_NAME_TAG_WHITE"), self._config.colors["white"])[1],
"name_tag_gold": color_filter(self._template_finder.get_template("KASHYA_NAME_TAG_GOLD"), self._config.colors["gold"])[1],
"action_btns": {
"resurrect": {
"white": color_filter(self._template_finder.get_template("RESURRECT"), self._config.colors["white"])[1],
"blue": color_filter(self._template_finder.get_template("RESURRECT_BLUE"), self._config.colors["blue"])[1],
}
},
"template_group": ["KASHYA_FRONT", "KASHYA_BACK", "KASHYA_SIDE", "KASHYA_SIDE_2"]
},
}
def open_npc_menu(self, npc_key: Npc) -> bool:
+57
View File
@@ -52,6 +52,15 @@ class Location:
A2_WP = "a2_wp"
A2_TP = "a2_tp"
A2_FARA_STASH = "a2_fara_stash"
# A1 Town
A1_TOWN_START = "a1_town_start"
A1_STASH = "a1_stash"
A1_WP_NORTH = "a1_wp_north"
A1_WP_SOUTH = "a1_wp_south"
A1_KASHYA_CAIN = "a1_kashya_cain"
A1_AKARA = "a1_akara"
A1_CHARSI = "a1_charsi"
# Trav
A3_TRAV_START = "a3_trav_start"
A3_TRAV_CENTER_STAIRS = "a3_trav_center_stairs"
@@ -146,6 +155,21 @@ class Pather:
405: {"A2_TOWN_10": (65, -175), "A2_TOWN_17": (-108, 164), "A2_TOWN_16": (-304, -11), "A2_TOWN_9": (319, -68), "A2_TOWN_18": (-415, -284)},
406: {"A2_TOWN_18": (108, -143), "A2_TOWN_16": (219, 129), "A2_TOWN_19": (-293, 21), "A2_TOWN_17": (415, 304), "A2_TOWN_10": (588, -34)},
408: {"A2_TOWN_20": (-26, -109), "A2_TOWN_22": (-82, 278), "A2_TOWN_19": (344, 38), "A2_TOWN_21": (-518, -299), "A2_TOWN_18": (745, -125)},
# A1 town
#kashya_cain
700: {"A1_TOWN_3": (134, 40), "A1_TOWN_4": (162, 132), "A1_TOWN_0": (186, 276), "A1_TOWN_1": (345, 373), "A1_TOWN_6": (210, 733), "A1_TOWN_5": (399, 690), },
#stash
701: {"A1_TOWN_4": (56, -71), "A1_TOWN_0": (80, 73), "A1_TOWN_3": (28, -163), "A1_TOWN_1": (239, 170), "A1_TOWN_6": (104, 530), "A1_TOWN_5": (293, 487), },
#wp check (north)
702: {"A1_TOWN_0": (279, -83), "A1_TOWN_4": (255, -227), "A1_TOWN_3": (227, -319), "A1_TOWN_1": (438, 14), "A1_TOWN_6": (303, 374), "A1_TOWN_5": (492, 331), },
703: {"A1_TOWN_6": (-36, 161), "A1_TOWN_5": (153, 118), "A1_TOWN_1": (99, -199), "A1_TOWN_0": (-60, -296), "A1_TOWN_4": (-84, -440), "A1_TOWN_3": (-112, -532), },
#charsi
704: {"A1_TOWN_5": (-104, 108), "A1_TOWN_1": (-158, -209), "A1_TOWN_6": (-293, 151), "A1_TOWN_0": (-317, -306), "A1_TOWN_2": (-476, -222), "A1_TOWN_10": (-495, -224), "A1_TOWN_4": (-341, -450), "A1_TOWN_3": (-369, -542), },
#wp check (south)
705: {"A1_TOWN_3": (457, -29), "A1_TOWN_4": (485, 63), "A1_TOWN_0": (509, 207), "A1_TOWN_7": (-608, -188), "A1_TOWN_1": (668, 304), },
706: {"A1_TOWN_7": (-79, -33), "A1_TOWN_8": (-666, 21), "A1_TOWN_3": (986, 126), "A1_TOWN_4": (1014, 218), },
#akara
707: {"A1_TOWN_8": (-230, 93), "A1_TOWN_7": (357, 39), },
# Trav
220: {"TRAV_0": (445, 384), "TRAV_20": (-259, 267), "TRAV_1": (-248, -139), "TRAV_2": (-682, 21), "TRAV_21": (25, 180)},
221: {"TRAV_2": (-153, -101), "TRAV_3": (-125, 201), "TRAV_20": (270, 145), "TRAV_1": (281, -261), "TRAV_4": (-459, 122)},
@@ -246,6 +270,39 @@ class Pather:
(Location.A2_FARA_STASH, Location.A2_WP): [403, 404],
(Location.A2_TP, Location.A2_FARA_STASH): [408, 406, 405],
(Location.A2_WP, Location.A2_FARA_STASH): [404, 403, 405],
# A1 Town
#spawned in where do we go?
(Location.A1_TOWN_START, Location.A1_STASH): [701],
(Location.A1_TOWN_START, Location.A1_KASHYA_CAIN): [700],
(Location.A1_TOWN_START, Location.A1_CHARSI): [702, 703, 704],
(Location.A1_TOWN_START, Location.A1_AKARA): [705, 706, 707],
(Location.A1_TOWN_START, Location.A1_WP_NORTH): [702],
(Location.A1_TOWN_START, Location.A1_WP_SOUTH): [705],
#from the stash to where?
(Location.A1_STASH, Location.A1_KASHYA_CAIN): [701, 700],
(Location.A1_STASH, Location.A1_CHARSI): [701, 702, 703, 704],
(Location.A1_STASH, Location.A1_AKARA): [701, 705, 706, 707],
(Location.A1_STASH, Location.A1_WP_NORTH): [701, 702],
(Location.A1_STASH, Location.A1_WP_SOUTH): [701, 705],
#from the Kashya/Cain to where?
(Location.A1_KASHYA_CAIN, Location.A1_STASH): [700, 701],
(Location.A1_KASHYA_CAIN, Location.A1_CHARSI): [700, 702, 703, 704],
(Location.A1_KASHYA_CAIN, Location.A1_AKARA): [700, 705, 706, 707],
(Location.A1_KASHYA_CAIN, Location.A1_WP_NORTH): [700, 702],
(Location.A1_KASHYA_CAIN, Location.A1_WP_SOUTH): [700, 705],
#from the Charsi to where?
(Location.A1_CHARSI, Location.A1_STASH): [704, 703, 702, 701],
(Location.A1_CHARSI, Location.A1_KASHYA_CAIN): [704, 703, 702, 700],
(Location.A1_CHARSI, Location.A1_AKARA): [704, 703, 702, 705, 706, 707],
(Location.A1_CHARSI, Location.A1_WP_NORTH): [704, 703, 702],
(Location.A1_CHARSI, Location.A1_WP_SOUTH): [704, 703, 702, 705],
#from the Akara to where?
(Location.A1_AKARA, Location.A1_STASH): [707, 706, 705, 701],
(Location.A1_AKARA, Location.A1_KASHYA_CAIN): [707, 706, 705, 700],
(Location.A1_AKARA, Location.A1_CHARSI): [707, 706, 705, 702, 703, 704],
(Location.A1_AKARA, Location.A1_WP_NORTH): [707, 706, 705, 702],
(Location.A1_AKARA, Location.A1_WP_SOUTH): [707, 706, 706],
(Location.A1_WP_SOUTH, Location.A1_WP_NORTH): [702],
# Trav
(Location.A3_TRAV_START, Location.A3_TRAV_CENTER_STAIRS): [220, 221, 222, 223, 224, 225, 226],
}
+1
View File
@@ -1,3 +1,4 @@
from .a1 import A1
from .a2 import A2
from .a3 import A3
from .a4 import A4
+90
View File
@@ -0,0 +1,90 @@
from char import IChar
from town.i_act import IAct
from screen import Screen
from config import Config
from npc_manager import NpcManager, Npc
from pather import Pather, Location
from typing import Union
from template_finder import TemplateFinder
from utils.misc import wait
class A1(IAct):
def __init__(self, screen: Screen, template_finder: TemplateFinder, pather: Pather, char: IChar, npc_manager: NpcManager):
self._config = Config()
self._screen = screen
self._pather = pather
self._char = char
self._npc_manager = npc_manager
self._template_finder = template_finder
def get_wp_location(self) -> Location: return Location.A1_WP_NORTH
def can_resurrect(self) -> bool: return True
def can_buy_pots(self) -> bool: return True
def can_identify(self) -> bool: return True
def can_heal(self) -> bool: return True
def can_stash(self) -> bool: return True
def can_trade_and_repair(self) -> bool: return True
def resurrect(self, curr_loc: Location) -> Union[Location, bool]:
if not self._pather.traverse_nodes((curr_loc, Location.A1_KASHYA_CAIN), self._char, force_move=True):
return False
if self._npc_manager.open_npc_menu(Npc.KASHYA):
self._npc_manager.press_npc_btn(Npc.KASHYA, "resurrect")
return Location.A1_KASHYA_CAIN
return False
def open_wp(self, curr_loc: Location) -> bool:
if not self._pather.traverse_nodes((curr_loc, Location.A1_WP_SOUTH), self._char): return False
wait(0.5, 0.7)
if not self._char._template_finder.search("A1_WP", self._screen.grab()).valid:
curr_loc = Location.A1_WP_SOUTH
if not self._pather.traverse_nodes((curr_loc, Location.A1_WP_NORTH), self._char): return False
wait(0.5, 0.7)
found_wp_func = lambda: self._template_finder.search("WAYPOINT_MENU", self._screen.grab()).valid
# decreased threshold because we sometimes walk "over" it during pathing
return self._char.select_by_template(["A1_WP"], found_wp_func, threshold=0.62)
def wait_for_tp(self) -> Union[Location, bool]:
success = self._template_finder.search_and_wait(["A1_TOWN_0", "A1_TOWN_1", "A1_TOWN_3"], time_out=20).valid
if success:
return Location.A1_TOWN_START
return False
def identify(self, curr_loc: Location) -> Union[Location, bool]:
if not self._pather.traverse_nodes((curr_loc, Location.A1_KASHYA_CAIN), self._char): return False
if self._npc_manager.open_npc_menu(Npc.CAIN):
self._npc_manager.press_npc_btn(Npc.CAIN, "identify")
return Location.A1_KASHYA_CAIN
return False
def open_trade_menu(self, curr_loc: Location) -> Union[Location, bool]:
if not self._pather.traverse_nodes((curr_loc, Location.A1_AKARA), self._char, force_move=True): return False
self._npc_manager.open_npc_menu(Npc.AKARA)
self._npc_manager.press_npc_btn(Npc.AKARA, "trade")
return Location.A1_AKARA
def open_stash(self, curr_loc: Location) -> Union[Location, bool]:
if not self._pather.traverse_nodes((curr_loc, Location.A1_STASH), self._char):
return False
wait(0.5, 0.6)
def stash_is_open_func():
img = self._screen.grab()
found = self._template_finder.search("INVENTORY_GOLD_BTN", img, roi=self._config.ui_roi["gold_btn"]).valid
found |= self._template_finder.search("INVENTORY_GOLD_BTN", img, roi=self._config.ui_roi["gold_btn_stash"]).valid
return found
if not self._char.select_by_template(["A1_TOWN_0"], stash_is_open_func):
return False
return Location.A1_STASH
def heal(self, curr_loc: Location) -> Union[Location, bool]:
if not self._pather.traverse_nodes((curr_loc, Location.A1_AKARA), self._char, force_move=True): return False
self._npc_manager.open_npc_menu(Npc.AKARA)
return Location.A1_AKARA
def open_trade_and_repair_menu(self, curr_loc: Location) -> Union[Location, bool]:
if not self._pather.traverse_nodes((curr_loc, Location.A1_CHARSI), self._char): return False
self._npc_manager.open_npc_menu(Npc.CHARSI)
self._npc_manager.press_npc_btn(Npc.CHARSI, "trade_repair")
return Location.A1_CHARSI
+15 -7
View File
@@ -5,17 +5,18 @@ from config import Config
from pather import Location
from logger import Logger
from ui import UiManager
from town import IAct, A2, A3, A4, A5
from town import IAct, A1, A2, A3, A4, A5
from utils.misc import wait
class TownManager:
def __init__(self, template_finder: TemplateFinder, ui_manager: UiManager, item_finder: ItemFinder, a2: A2, a3: A3, a4: A4, a5: A5):
def __init__(self, template_finder: TemplateFinder, ui_manager: UiManager, item_finder: ItemFinder, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5):
self._config = Config()
self._template_finder = template_finder
self._ui_manager = ui_manager
self._item_finder = item_finder
self._acts: dict[Location, IAct] = {
Location.A1_TOWN_START: a1,
Location.A2_TOWN_START: a2,
Location.A3_TOWN_START: a3,
Location.A4_TOWN_START: a4,
@@ -33,6 +34,8 @@ class TownManager:
location = Location.A3_TOWN_START
elif loc.upper().startswith("A2_"):
location = Location.A2_TOWN_START
elif loc.upper().startswith("A1_"):
location = Location.A1_TOWN_START
return location
def wait_for_town_spawn(self, time_out: float = None) -> Location:
@@ -44,7 +47,10 @@ class TownManager:
"A5_TOWN_0", "A5_TOWN_1",
"A4_TOWN_4", "A4_TOWN_5",
"A3_TOWN_0", "A3_TOWN_1",
"A2_TOWN_0", "A2_TOWN_1", "A2_TOWN_10"
"A2_TOWN_0", "A2_TOWN_1",
"A2_TOWN_10", "A1_TOWN_0",
"A1_TOWN_1"
], best_match=True, time_out=time_out)
if template_match.valid:
return TownManager.get_act_from_location(template_match.name)
@@ -64,10 +70,11 @@ class TownManager:
curr_act = TownManager.get_act_from_location(curr_loc)
if curr_act is None: return False
# check if we already are in the desired act
if act_idx == 2: act = Location.A2_TOWN_START
if act_idx == 1: act = Location.A1_TOWN_START
elif act_idx == 2: act = Location.A2_TOWN_START
elif act_idx == 3: act = Location.A3_TOWN_START
elif act_idx == 4: act = Location.A4_TOWN_START
elif act_idx == 5: act = Location.A5_TOWN_START
elif act_idx == 5: act = Location.A5_TOWN_START
else:
Logger.error(f"Act {act_idx} is not supported")
return False
@@ -185,5 +192,6 @@ if __name__ == "__main__":
a4 = A4(screen, template_finder, pather, char, npc_manager)
a3 = A3(screen, template_finder, pather, char, npc_manager)
a2 = A2(screen, template_finder, pather, char, npc_manager)
town_manager = TownManager(template_finder, ui_manager, item_finder, a2, a3, a4, a5)
print(town_manager.open_wp(Location.A2_TOWN_START))
a1 = A1(screen, template_finder, pather, char, npc_manager)
town_manager = TownManager(template_finder, ui_manager, item_finder, a1, a2, a3, a4, a5)
print(town_manager.open_wp(Location.A1_TOWN_START))
+1 -1
View File
@@ -36,7 +36,7 @@ class UiManager():
:param act: Index of the desired act starting at 1 [A1 = 1, A2 = 2, A3 = 3, ...]
:param idx: Index of the waypoint from top. Note that it start at 0!
"""
str_to_idx_map = {"WP_A2_ACTIVE": 2, "WP_A3_ACTIVE": 3, "WP_A4_ACTIVE": 4, "WP_A5_ACTIVE": 5}
str_to_idx_map = {"WP_A1_ACTIVE": 1, "WP_A2_ACTIVE": 2, "WP_A3_ACTIVE": 3, "WP_A4_ACTIVE": 4, "WP_A5_ACTIVE": 5}
template_match = self._template_finder.search([*str_to_idx_map], self._screen.grab(), threshold=0.7, best_match=True, roi=self._config.ui_roi["wp_act_roi"])
curr_active_act = str_to_idx_map[template_match.name] if template_match.valid else -1
if curr_active_act != act: