diff --git a/README.md b/README.md index f56e26c..14427d2 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Open up D2R and wait till you are at the hero selection screen. Make sure the ch ### 4) Start Botty -You can either run from python. Follow [development.md](development.md) for that. Or you download the a prebuilt release [here](https://github.com/aeon0/botty/releases) (the .rar file!). Start `main.exe` in the botty folder. Focus your D2R window and press the start key (default f11). You can always force stop botty with f12. +You can either run from python. Follow [development.md](development.md) for that. Or you download the a prebuilt release [here](https://github.com/aeon0/botty/releases) (the .rar file!). Start `main.exe` in the botty folder. Focus your D2R window and press the start key (default f11). You can always force stop botty with f12. Note: Botty will use the /nopickup command in the first game to avoid pickup up trash while traversing. This command will only allow item pickup when "show items" is active. ## Graphic Debugger @@ -70,6 +70,7 @@ run_shenk=0 | run_eldritch | Run Eldritch in each new game. Select "1" to run it "0" to leave it out. | | run_shenk | Run shenk in each new game. Select "1" to run it "0" to leave it out. | | run_nihlatak | Run Nihlatak in each new game. Select "1" to run it "0" to leave it out. (Teleport required) | +| run_arcane | Run Arcane Sanctuary in each new game. Select "1" to run it "0" to leave it out. (Teleport required) | | [char] | Descriptions | | ------------------ | -------------------------------------------------------------------------------------------------| @@ -94,6 +95,7 @@ run_shenk=0 | stash_gold | Bool value to stash gold each time when stashing items | | gold_trav_only | Hacky config that will restrict gold pickup to trav only. misc_gold must be set to 1 for this to have any effect | | use_merc | Set to 1 for using merc. Set to 0 for not using merc (will not revive merc when dead), default = 1 | +| atk_len_arc | Attack length for hdin/sorc fighting arcane | | atk_len_trav | Attack length for hdin fighting trav (note this atk length will be applied in 4 different spots each) | | atk_len_pindle | Attack length for hdin or number of attack sequences for sorc when fighting pindle | | atk_len_eldritch | Attack length for hdin or number of attack sequences for sorc when fighting eldritch | @@ -112,7 +114,8 @@ run_shenk=0 | belt_mp_columns | Number of belt columns for mana potions | | pre_buff_every_run | 0: Will only prebuff on first run, 1: Will prebuff after each run/boss | | always_repair | 0: Will only repair when needed, 1: Will repair at the start of each run (EXPENSIVE FOR HIGH RUNEWORDS) | -| id_items | will identify items at cain before stashing them. Cain must be recused for this to work.| +| id_items | Will identify items at cain before stashing them. Cain must be rescued for this to work.| +| open_chests | Open up chests in some places. E.g. on dead ends of arcane. Note: currently bad runtime. | ### Builds | [sorceress] | Descriptions | @@ -132,6 +135,10 @@ run_shenk=0 | ice_blast | Optional Hotkey for ice_blast (must be bound to left skill) | | blizzard | Required Hotkey for Blizzard (must be bound to right skill) | +| [nova_sorc] | Descriptions | +| ------------- | ----------------------------------------------------------------------------- | +| nova | Required Hotkey for Nova (must be bound to right skill) | + | [hammerdin] | Descriptions | | -------------- | ----------------------------------------------------------------------------------- | | teleport | Optional Hotkey for teleport. If left empty hammerdin will run instead of teleport. | diff --git a/assets/chests/arcane/arc_stash1.png b/assets/chests/arcane/arc_stash1.png new file mode 100644 index 0000000..6266183 Binary files /dev/null and b/assets/chests/arcane/arc_stash1.png differ diff --git a/assets/chests/arcane/arc_stash11.png b/assets/chests/arcane/arc_stash11.png new file mode 100644 index 0000000..2a8924e Binary files /dev/null and b/assets/chests/arcane/arc_stash11.png differ diff --git a/assets/chests/arcane/arc_stash12.png b/assets/chests/arcane/arc_stash12.png new file mode 100644 index 0000000..092b2ed Binary files /dev/null and b/assets/chests/arcane/arc_stash12.png differ diff --git a/assets/chests/arcane/arc_stash2.png b/assets/chests/arcane/arc_stash2.png new file mode 100644 index 0000000..91c1fb3 Binary files /dev/null and b/assets/chests/arcane/arc_stash2.png differ diff --git a/assets/chests/arcane/arc_stash3.png b/assets/chests/arcane/arc_stash3.png new file mode 100644 index 0000000..7cb648d Binary files /dev/null and b/assets/chests/arcane/arc_stash3.png differ diff --git a/assets/chests/arcane/arc_stash5.png b/assets/chests/arcane/arc_stash5.png new file mode 100644 index 0000000..b64cf4e Binary files /dev/null and b/assets/chests/arcane/arc_stash5.png differ diff --git a/assets/chests/arcane/arc_stash6.png b/assets/chests/arcane/arc_stash6.png new file mode 100644 index 0000000..eac7033 Binary files /dev/null and b/assets/chests/arcane/arc_stash6.png differ diff --git a/assets/chests/arcane/arc_stash8.png b/assets/chests/arcane/arc_stash8.png new file mode 100644 index 0000000..b66f7a4 Binary files /dev/null and b/assets/chests/arcane/arc_stash8.png differ diff --git a/assets/chests/arcane/arc_stash9.png b/assets/chests/arcane/arc_stash9.png new file mode 100644 index 0000000..4ad23f1 Binary files /dev/null and b/assets/chests/arcane/arc_stash9.png differ diff --git a/assets/chests/chest_label.png b/assets/chests/chest_label.png new file mode 100644 index 0000000..537a6dc Binary files /dev/null and b/assets/chests/chest_label.png differ diff --git a/assets/chests/locked.png b/assets/chests/locked.png new file mode 100644 index 0000000..c53c800 Binary files /dev/null and b/assets/chests/locked.png differ diff --git a/assets/items/misc_key_of_hate.png b/assets/items/misc_key_of_hate.png new file mode 100644 index 0000000..4b2a376 Binary files /dev/null and b/assets/items/misc_key_of_hate.png differ diff --git a/assets/npc/fara/fara_dark_1.png b/assets/npc/fara/fara_dark_1.png new file mode 100644 index 0000000..e7aeb48 Binary files /dev/null and b/assets/npc/fara/fara_dark_1.png differ diff --git a/assets/npc/fara/fara_dark_2.png b/assets/npc/fara/fara_dark_2.png new file mode 100644 index 0000000..f150d8b Binary files /dev/null and b/assets/npc/fara/fara_dark_2.png differ diff --git a/assets/npc/fara/fara_dark_3.png b/assets/npc/fara/fara_dark_3.png new file mode 100644 index 0000000..b4bf3b6 Binary files /dev/null and b/assets/npc/fara/fara_dark_3.png differ diff --git a/assets/npc/fara/fara_dark_4.png b/assets/npc/fara/fara_dark_4.png new file mode 100644 index 0000000..741ce4e Binary files /dev/null and b/assets/npc/fara/fara_dark_4.png differ diff --git a/assets/npc/fara/fara_dark_5.png b/assets/npc/fara/fara_dark_5.png new file mode 100644 index 0000000..763582f Binary files /dev/null and b/assets/npc/fara/fara_dark_5.png differ diff --git a/assets/npc/fara/fara_dark_6.png b/assets/npc/fara/fara_dark_6.png new file mode 100644 index 0000000..cf38b5e Binary files /dev/null and b/assets/npc/fara/fara_dark_6.png differ diff --git a/assets/npc/fara/fara_dark_7.png b/assets/npc/fara/fara_dark_7.png new file mode 100644 index 0000000..4d81fe2 Binary files /dev/null and b/assets/npc/fara/fara_dark_7.png differ diff --git a/assets/npc/fara/fara_light_1.png b/assets/npc/fara/fara_light_1.png new file mode 100644 index 0000000..d74f261 Binary files /dev/null and b/assets/npc/fara/fara_light_1.png differ diff --git a/assets/npc/fara/fara_light_2.png b/assets/npc/fara/fara_light_2.png new file mode 100644 index 0000000..f4fc431 Binary files /dev/null and b/assets/npc/fara/fara_light_2.png differ diff --git a/assets/npc/fara/fara_light_3.png b/assets/npc/fara/fara_light_3.png new file mode 100644 index 0000000..e97f0ce Binary files /dev/null and b/assets/npc/fara/fara_light_3.png differ diff --git a/assets/npc/fara/fara_light_4.png b/assets/npc/fara/fara_light_4.png new file mode 100644 index 0000000..c578fc6 Binary files /dev/null and b/assets/npc/fara/fara_light_4.png differ diff --git a/assets/npc/fara/fara_light_5.png b/assets/npc/fara/fara_light_5.png new file mode 100644 index 0000000..c9fa607 Binary files /dev/null and b/assets/npc/fara/fara_light_5.png differ diff --git a/assets/npc/fara/fara_light_6.png b/assets/npc/fara/fara_light_6.png new file mode 100644 index 0000000..b216cb8 Binary files /dev/null and b/assets/npc/fara/fara_light_6.png differ diff --git a/assets/npc/fara/fara_light_7.png b/assets/npc/fara/fara_light_7.png new file mode 100644 index 0000000..51fb2f8 Binary files /dev/null and b/assets/npc/fara/fara_light_7.png differ diff --git a/assets/npc/fara/fara_light_8.png b/assets/npc/fara/fara_light_8.png new file mode 100644 index 0000000..8f971f0 Binary files /dev/null and b/assets/npc/fara/fara_light_8.png differ diff --git a/assets/npc/fara/fara_light_9.png b/assets/npc/fara/fara_light_9.png new file mode 100644 index 0000000..18dbe09 Binary files /dev/null and b/assets/npc/fara/fara_light_9.png differ diff --git a/assets/npc/fara/fara_medium_1.png b/assets/npc/fara/fara_medium_1.png new file mode 100644 index 0000000..fa0512f Binary files /dev/null and b/assets/npc/fara/fara_medium_1.png differ diff --git a/assets/npc/fara/fara_medium_2.png b/assets/npc/fara/fara_medium_2.png new file mode 100644 index 0000000..80e79d0 Binary files /dev/null and b/assets/npc/fara/fara_medium_2.png differ diff --git a/assets/npc/fara/fara_medium_3.png b/assets/npc/fara/fara_medium_3.png new file mode 100644 index 0000000..c05760b Binary files /dev/null and b/assets/npc/fara/fara_medium_3.png differ diff --git a/assets/npc/fara/fara_medium_4.png b/assets/npc/fara/fara_medium_4.png new file mode 100644 index 0000000..0cfe2e4 Binary files /dev/null and b/assets/npc/fara/fara_medium_4.png differ diff --git a/assets/npc/fara/fara_medium_5.png b/assets/npc/fara/fara_medium_5.png new file mode 100644 index 0000000..4c75790 Binary files /dev/null and b/assets/npc/fara/fara_medium_5.png differ diff --git a/assets/npc/fara/fara_medium_6.png b/assets/npc/fara/fara_medium_6.png new file mode 100644 index 0000000..e99da82 Binary files /dev/null and b/assets/npc/fara/fara_medium_6.png differ diff --git a/assets/npc/fara/fara_medium_7.png b/assets/npc/fara/fara_medium_7.png new file mode 100644 index 0000000..a39a71d Binary files /dev/null and b/assets/npc/fara/fara_medium_7.png differ diff --git a/assets/npc/fara/fara_name_tag_gold.png b/assets/npc/fara/fara_name_tag_gold.png new file mode 100644 index 0000000..eabe1d9 Binary files /dev/null and b/assets/npc/fara/fara_name_tag_gold.png differ diff --git a/assets/npc/fara/fara_name_tag_white.png b/assets/npc/fara/fara_name_tag_white.png new file mode 100644 index 0000000..8d275c5 Binary files /dev/null and b/assets/npc/fara/fara_name_tag_white.png differ diff --git a/assets/templates/a2_stash_dark.png b/assets/templates/a2_stash_dark.png new file mode 100644 index 0000000..19ff3ea Binary files /dev/null and b/assets/templates/a2_stash_dark.png differ diff --git a/assets/templates/a2_stash_light.png b/assets/templates/a2_stash_light.png new file mode 100644 index 0000000..3166052 Binary files /dev/null and b/assets/templates/a2_stash_light.png differ diff --git a/assets/templates/a2_stash_medium.png b/assets/templates/a2_stash_medium.png new file mode 100644 index 0000000..696a3b8 Binary files /dev/null and b/assets/templates/a2_stash_medium.png differ diff --git a/assets/templates/a2_town/a2_town_0.png b/assets/templates/a2_town/a2_town_0.png new file mode 100644 index 0000000..9f48167 Binary files /dev/null and b/assets/templates/a2_town/a2_town_0.png differ diff --git a/assets/templates/a2_town/a2_town_1.png b/assets/templates/a2_town/a2_town_1.png new file mode 100644 index 0000000..04fca83 Binary files /dev/null and b/assets/templates/a2_town/a2_town_1.png differ diff --git a/assets/templates/a2_town/a2_town_10.png b/assets/templates/a2_town/a2_town_10.png new file mode 100644 index 0000000..f9cf9ea Binary files /dev/null and b/assets/templates/a2_town/a2_town_10.png differ diff --git a/assets/templates/a2_town/a2_town_11.png b/assets/templates/a2_town/a2_town_11.png new file mode 100644 index 0000000..d3e129b Binary files /dev/null and b/assets/templates/a2_town/a2_town_11.png differ diff --git a/assets/templates/a2_town/a2_town_12.png b/assets/templates/a2_town/a2_town_12.png new file mode 100644 index 0000000..60f9d9d Binary files /dev/null and b/assets/templates/a2_town/a2_town_12.png differ diff --git a/assets/templates/a2_town/a2_town_13.png b/assets/templates/a2_town/a2_town_13.png new file mode 100644 index 0000000..31c0973 Binary files /dev/null and b/assets/templates/a2_town/a2_town_13.png differ diff --git a/assets/templates/a2_town/a2_town_14.png b/assets/templates/a2_town/a2_town_14.png new file mode 100644 index 0000000..5cd95f3 Binary files /dev/null and b/assets/templates/a2_town/a2_town_14.png differ diff --git a/assets/templates/a2_town/a2_town_15.png b/assets/templates/a2_town/a2_town_15.png new file mode 100644 index 0000000..5e528c3 Binary files /dev/null and b/assets/templates/a2_town/a2_town_15.png differ diff --git a/assets/templates/a2_town/a2_town_16.png b/assets/templates/a2_town/a2_town_16.png new file mode 100644 index 0000000..d56223d Binary files /dev/null and b/assets/templates/a2_town/a2_town_16.png differ diff --git a/assets/templates/a2_town/a2_town_17.png b/assets/templates/a2_town/a2_town_17.png new file mode 100644 index 0000000..5273ae7 Binary files /dev/null and b/assets/templates/a2_town/a2_town_17.png differ diff --git a/assets/templates/a2_town/a2_town_18.png b/assets/templates/a2_town/a2_town_18.png new file mode 100644 index 0000000..a58c10c Binary files /dev/null and b/assets/templates/a2_town/a2_town_18.png differ diff --git a/assets/templates/a2_town/a2_town_19.png b/assets/templates/a2_town/a2_town_19.png new file mode 100644 index 0000000..108e681 Binary files /dev/null and b/assets/templates/a2_town/a2_town_19.png differ diff --git a/assets/templates/a2_town/a2_town_2.png b/assets/templates/a2_town/a2_town_2.png new file mode 100644 index 0000000..8a1517d Binary files /dev/null and b/assets/templates/a2_town/a2_town_2.png differ diff --git a/assets/templates/a2_town/a2_town_20.png b/assets/templates/a2_town/a2_town_20.png new file mode 100644 index 0000000..84a8a81 Binary files /dev/null and b/assets/templates/a2_town/a2_town_20.png differ diff --git a/assets/templates/a2_town/a2_town_21.png b/assets/templates/a2_town/a2_town_21.png new file mode 100644 index 0000000..f4c7d1f Binary files /dev/null and b/assets/templates/a2_town/a2_town_21.png differ diff --git a/assets/templates/a2_town/a2_town_22.png b/assets/templates/a2_town/a2_town_22.png new file mode 100644 index 0000000..963704d Binary files /dev/null and b/assets/templates/a2_town/a2_town_22.png differ diff --git a/assets/templates/a2_town/a2_town_3.png b/assets/templates/a2_town/a2_town_3.png new file mode 100644 index 0000000..eb79940 Binary files /dev/null and b/assets/templates/a2_town/a2_town_3.png differ diff --git a/assets/templates/a2_town/a2_town_5.png b/assets/templates/a2_town/a2_town_5.png new file mode 100644 index 0000000..26c7acd Binary files /dev/null and b/assets/templates/a2_town/a2_town_5.png differ diff --git a/assets/templates/a2_town/a2_town_6.png b/assets/templates/a2_town/a2_town_6.png new file mode 100644 index 0000000..c624d39 Binary files /dev/null and b/assets/templates/a2_town/a2_town_6.png differ diff --git a/assets/templates/a2_town/a2_town_7.png b/assets/templates/a2_town/a2_town_7.png new file mode 100644 index 0000000..c09accf Binary files /dev/null and b/assets/templates/a2_town/a2_town_7.png differ diff --git a/assets/templates/a2_town/a2_town_8.png b/assets/templates/a2_town/a2_town_8.png new file mode 100644 index 0000000..0417375 Binary files /dev/null and b/assets/templates/a2_town/a2_town_8.png differ diff --git a/assets/templates/a2_town/a2_town_9.png b/assets/templates/a2_town/a2_town_9.png new file mode 100644 index 0000000..9eb9123 Binary files /dev/null and b/assets/templates/a2_town/a2_town_9.png differ diff --git a/assets/templates/a2_wp_dark.png b/assets/templates/a2_wp_dark.png new file mode 100644 index 0000000..a8067ba Binary files /dev/null and b/assets/templates/a2_wp_dark.png differ diff --git a/assets/templates/a2_wp_light.png b/assets/templates/a2_wp_light.png new file mode 100644 index 0000000..bd3d972 Binary files /dev/null and b/assets/templates/a2_wp_light.png differ diff --git a/assets/templates/arcane/arc_altar.png b/assets/templates/arcane/arc_altar.png new file mode 100644 index 0000000..c5fffab Binary files /dev/null and b/assets/templates/arcane/arc_altar.png differ diff --git a/assets/templates/arcane/arc_altar3.png b/assets/templates/arcane/arc_altar3.png new file mode 100644 index 0000000..517ff75 Binary files /dev/null and b/assets/templates/arcane/arc_altar3.png differ diff --git a/assets/templates/arcane/arc_center.png b/assets/templates/arcane/arc_center.png new file mode 100644 index 0000000..40b49ec Binary files /dev/null and b/assets/templates/arcane/arc_center.png differ diff --git a/assets/templates/arcane/arc_center_2.png b/assets/templates/arcane/arc_center_2.png new file mode 100644 index 0000000..eda9bff Binary files /dev/null and b/assets/templates/arcane/arc_center_2.png differ diff --git a/assets/templates/arcane/arc_end_stairs.png b/assets/templates/arcane/arc_end_stairs.png new file mode 100644 index 0000000..82442b5 Binary files /dev/null and b/assets/templates/arcane/arc_end_stairs.png differ diff --git a/assets/templates/arcane/arc_end_stairs_2.png b/assets/templates/arcane/arc_end_stairs_2.png new file mode 100644 index 0000000..3d20cbd Binary files /dev/null and b/assets/templates/arcane/arc_end_stairs_2.png differ diff --git a/assets/templates/arcane/arc_platform_1.png b/assets/templates/arcane/arc_platform_1.png new file mode 100644 index 0000000..31f77b7 Binary files /dev/null and b/assets/templates/arcane/arc_platform_1.png differ diff --git a/assets/templates/arcane/arc_platform_2.png b/assets/templates/arcane/arc_platform_2.png new file mode 100644 index 0000000..9d430f2 Binary files /dev/null and b/assets/templates/arcane/arc_platform_2.png differ diff --git a/assets/templates/arcane/arc_platform_3.png b/assets/templates/arcane/arc_platform_3.png new file mode 100644 index 0000000..2758362 Binary files /dev/null and b/assets/templates/arcane/arc_platform_3.png differ diff --git a/assets/templates/arcane/arc_speech.png b/assets/templates/arcane/arc_speech.png new file mode 100644 index 0000000..5b33602 Binary files /dev/null and b/assets/templates/arcane/arc_speech.png differ diff --git a/assets/templates/arcane/arc_start.png b/assets/templates/arcane/arc_start.png new file mode 100644 index 0000000..ca901d8 Binary files /dev/null and b/assets/templates/arcane/arc_start.png differ diff --git a/assets/templates/wp_a2_active.png b/assets/templates/wp_a2_active.png new file mode 100644 index 0000000..82f41ae Binary files /dev/null and b/assets/templates/wp_a2_active.png differ diff --git a/config/game.ini b/config/game.ini index cbff917..a17cb50 100644 --- a/config/game.ini +++ b/config/game.ini @@ -86,7 +86,7 @@ item_width_min=20 ; pather reached_node_dist=100 min_walk_dist=25 -max_walk_dist=127 +max_walk_dist=177 [ui_roi] ; all rois are in [left, top, width, height] format @@ -101,6 +101,7 @@ gold_btn_stash=150,480,40,65 health_globe=160,580,240,140 mana_globe=887,580,240,140 cut_skill_bar=0,0,1280,653 +reduce_to_center=120,60,1040,540 merc_icon=0,0,100,100 loading_left_black=0,0,350,720 death=513,193,253,50 @@ -140,3 +141,8 @@ ni2_a_safe_dist=267,499, 279,533, 372,536, 283,529, 360,524, 513,553, 289,449, 1 ni2_b_safe_dist=864,373, 987,549, 842,521, 977,504, 886,453, 896,449, 861,461, 1206,279, 1068,569 ni2_c_safe_dist=810,98, 989,195, 969,250, 957,234, 962,179, 954,203, 1202,220, 985,89 ni2_d_safe_dist=449,165, 334,198, 377,183, 402,181, 382,196, 377,230, 9,288, 290,104 +# Arcane Sanctuary Layouts +arc_top_right=1236,43, 1236,43, 1241,39, 1060,179, 1240,669, 1208,649, 1109,63, 1181,60, 1221,64, 1237,51, 1239,43, 1226,48, 1234,48, 1246,60, 93,50, 115,65, 1203,36, 1169,198 +arc_bottom_left=60,653, 60,653, 60,653, 254,559, 1249,634, 1209,628, 54,613, 58,613, 69,658, 74,643, 74,643, 74,643, 74,643, 89,614, 17,122, 103,146, 20,495, 88,624 +arc_top_left=86,55, 98,69, 110,111, 135,69, 1195,97, 1154,89, 95,81, 93,88, 93,88, 92,88, 92,88, 92,88, 92,88, 92,88, 92,88, 63,654, 103,609, 101,63, 133,104 +arc_bottom_right=1230,649, 1189,685, 1201,632, 992,503, 1161,45, 1166,55, 1236,607, 1233,617, 1162,663, 1169,650, 1224,627, 1221,613, 1224,638, 1254,627, 60,691, 63,617, 1234,701, 1199,668 diff --git a/config/params.ini b/config/params.ini index 1692be5..331628b 100644 --- a/config/params.ini +++ b/config/params.ini @@ -25,8 +25,9 @@ run_pindle=1 run_eldritch=1 run_shenk=0 run_nihlatak=0 +run_arcane=0 ; Note: You can not split up or change order of eldritch and shenk as botty treats it as a single run -order=run_trav, run_pindle, run_eldritch, run_shenk, run_nihlatak +order=run_trav, run_pindle, run_eldritch, run_shenk, run_nihlatak, run_arcane [char] ; ========================== @@ -60,6 +61,7 @@ stash_gold=1 gold_trav_only=0 use_merc=1 ; Attack length for barbarians should be as high as 8-10 and even 10-12 for trav/shenk +atk_len_arc=2.5 atk_len_trav=3.0 atk_len_pindle=3.0 atk_len_eldritch=3.0 @@ -79,6 +81,7 @@ belt_mp_columns=1 pre_buff_every_run=0 always_repair=0 id_items=0 +open_chests=1 ; =========================== ; ==== Builds: Sorceress ==== diff --git a/config/pickit.ini b/config/pickit.ini index e029f2c..37d4b4b 100644 --- a/config/pickit.ini +++ b/config/pickit.ini @@ -45,6 +45,7 @@ misc_greater_mana_potion=0 ;misc misc_gold=0 misc_key_of_destruction=1 +misc_key_of_hate=1 ;---------------------------------------; ;================= GEMS ================; diff --git a/src/bot.py b/src/bot.py index cbb685e..bd0108e 100644 --- a/src/bot.py +++ b/src/bot.py @@ -28,8 +28,8 @@ from char.sorceress import LightSorc, BlizzSorc, NovaSorc from char.trapsin import Trapsin from char.hammerdin import Hammerdin from char.barbarian import Barbarian -from run import Pindle, ShenkEld, Trav, Nihlatak -from town import TownManager, A3, A4, A5 +from run import Pindle, ShenkEld, Trav, Nihlatak, Arcane +from town import TownManager, A2, A3, A4, A5 # Added for dclone ip hunt from messenger import Messenger @@ -70,7 +70,8 @@ class Bot: a5 = A5(self._screen, self._template_finder, self._pather, self._char, npc_manager) 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) - self._town_manager = TownManager(self._template_finder, self._ui_manager, self._item_finder, a3, a4, a5) + 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) self._route_config = self._config.routes self._route_order = self._config.routes_order @@ -83,6 +84,7 @@ class Bot: "run_pindle": self._route_config["run_pindle"], "run_shenk": self._route_config["run_shenk"] or self._route_config["run_eldritch"], "run_nihlatak": self._route_config["run_nihlatak"], + "run_arcane": self._route_config["run_arcane"], } # Adapt order to the config self._do_runs = OrderedDict((k, self._do_runs[k]) for k in self._route_order if k in self._do_runs and self._do_runs[k]) @@ -94,6 +96,7 @@ class Bot: self._shenk = ShenkEld(self._template_finder, self._pather, self._town_manager, self._ui_manager, self._char, self._pickit) self._trav = Trav(self._template_finder, self._pather, self._town_manager, self._ui_manager, self._char, self._pickit) self._nihlatak = Nihlatak(self._screen, self._template_finder, self._pather, self._town_manager, self._ui_manager, self._char, self._pickit) + self._arcane = Arcane(self._template_finder, self._pather, self._town_manager, self._ui_manager, self._char, self._pickit) # Create member variables self._pick_corpse = pick_corpse @@ -108,7 +111,7 @@ class Bot: self._ran_no_pickup = False # Create State Machine - self._states=['hero_selection', 'town', 'pindle', 'shenk', 'trav', 'nihlatak'] + self._states=['hero_selection', 'town', 'pindle', 'shenk', 'trav', 'nihlatak', 'arcane'] self._transitions = [ { 'trigger': 'create_game', 'source': 'hero_selection', 'dest': 'town', 'before': "on_create_game"}, # Tasks within town @@ -118,9 +121,10 @@ class Bot: { 'trigger': 'run_shenk', 'source': 'town', 'dest': 'shenk', 'before': "on_run_shenk"}, { 'trigger': 'run_trav', 'source': 'town', 'dest': 'trav', 'before': "on_run_trav"}, { 'trigger': 'run_nihlatak', 'source': 'town', 'dest': 'nihlatak', 'before': "on_run_nihlatak"}, + { 'trigger': 'run_arcane', 'source': 'town', 'dest': 'arcane', 'before': "on_run_arcane"}, # End run / game - { 'trigger': 'end_run', 'source': ['shenk', 'pindle', 'nihlatak','trav'], 'dest': 'town', 'before': "on_end_run"}, - { 'trigger': 'end_game', 'source': ['town', 'shenk', 'pindle', 'nihlatak', 'trav', 'end_run'], 'dest': 'hero_selection', 'before': "on_end_game"}, + { 'trigger': 'end_run', 'source': ['shenk', 'pindle', 'nihlatak', 'trav', 'arcane'], 'dest': 'town', 'before': "on_end_run"}, + { 'trigger': 'end_game', 'source': ['town', 'shenk', 'pindle', 'nihlatak', 'trav', 'arcane', 'end_run'], 'dest': 'hero_selection', 'before': "on_end_game"}, ] self.machine = Machine(model=self, states=self._states, initial="hero_selection", transitions=self._transitions, queued=True) @@ -258,7 +262,7 @@ class Bot: # Check if we are out of tps or need repairing need_repair = self._ui_manager.repair_needed() - if self._tps_left < random.randint(2, 5) or need_repair or self._config.char["always_repair"]: + if self._tps_left < random.randint(3, 5) or need_repair or self._config.char["always_repair"]: if need_repair: Logger.info("Repair needed. Gear is about to break") else: Logger.info("Repairing and buying TPs at next Vendor") self._curr_loc = self._town_manager.repair_and_fill_tps(self._curr_loc) @@ -360,3 +364,13 @@ class Bot: if self._curr_loc: res = self._nihlatak.battle(not self._pre_buffed) self._ending_run_helper(res) + + def on_run_arcane(self): + res = False + self._do_runs["run_arcane"] = False + self._game_stats.update_location("Arc" if self._config.general['discord_status_condensed'] else "Arcane") + self._curr_loc = self._arcane.approach(self._curr_loc) + if self._curr_loc: + res = self._arcane.battle(not self._pre_buffed) + self._tps_left -= self._arcane.used_tps + self._ending_run_helper(res) diff --git a/src/char/hammerdin.py b/src/char/hammerdin.py index a6736e8..757cb40 100644 --- a/src/char/hammerdin.py +++ b/src/char/hammerdin.py @@ -143,6 +143,20 @@ class Hammerdin(IChar): self._cast_hammers(1.2, "redemption") return True + def kill_summoner(self) -> bool: + # move mouse to below altar + pos_m = self._screen.convert_abs_to_monitor((0, 20)) + mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7]) + # Attack + self._cast_hammers(self._char_config["atk_len_arc"]) + wait(0.1, 0.15) + self._cast_hammers(1.6, "redemption") + # Move a bit back and another round + self._move_and_attack((0, 80), self._char_config["atk_len_arc"] * 0.5) + wait(0.1, 0.15) + self._cast_hammers(1.6, "redemption") + return True + if __name__ == "__main__": import os diff --git a/src/char/i_char.py b/src/char/i_char.py index 2bcc15f..6914afa 100644 --- a/src/char/i_char.py +++ b/src/char/i_char.py @@ -42,7 +42,8 @@ class IChar: template_type: Union[str, List[str]], success_func: Callable = None, time_out: float = 8, - threshold: float = 0.68 + threshold: float = 0.68, + telekinesis: bool = False ) -> bool: """ Finds any template from the template finder and interacts with it @@ -192,7 +193,6 @@ class IChar: Logger.warning("Failed to switch weapon, try again") wait(0.5) - def pre_buff(self): pass @@ -210,3 +210,6 @@ class IChar: def kill_nihlatak(self, end_nodes: list[int]) -> bool: raise ValueError("Nihlatak is not implemented!") + + def kill_summoner(self) -> bool: + raise ValueError("Arcane is not implemented!") diff --git a/src/char/sorceress/blizz_sorc.py b/src/char/sorceress/blizz_sorc.py index 8fddc81..fd3e89c 100644 --- a/src/char/sorceress/blizz_sorc.py +++ b/src/char/sorceress/blizz_sorc.py @@ -220,7 +220,19 @@ class BlizzSorc(Sorceress): self._blizzard((0, 0), spray=10) return True - + def kill_summoner(self) -> bool: + # Attack + delay = [0.2, 0.3] + cast_pos_abs = np.array([0, 0]) + pos_m = self._screen.convert_abs_to_monitor((-20, 20)) + mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7]) + for _ in range(int(self._char_config["atk_len_arc"])): + self._right_attack(cast_pos_abs, delay, 11) + self._left_attack(cast_pos_abs, delay, 11) + wait(self._cast_duration, self._cast_duration + 0.2) + return True + + if __name__ == "__main__": import os import keyboard diff --git a/src/char/sorceress/light_sorc.py b/src/char/sorceress/light_sorc.py index 1d35aaa..5aa1f39 100644 --- a/src/char/sorceress/light_sorc.py +++ b/src/char/sorceress/light_sorc.py @@ -145,6 +145,17 @@ class LightSorc(Sorceress): self._pather.traverse_nodes(end_nodes, self, time_out=0.8) return True + def kill_summoner(self) -> bool: + # Attack + delay = [0.2, 0.3] + cast_pos_abs = np.array([0, 0]) + pos_m = self._screen.convert_abs_to_monitor((-20, 20)) + mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7]) + for _ in range(int(self._char_config["atk_len_arc"])): + self._right_attack(cast_pos_abs, delay, 11) + self._left_attack(cast_pos_abs, delay, 11) + wait(self._cast_duration, self._cast_duration + 0.2) + return True if __name__ == "__main__": import os diff --git a/src/char/sorceress/nova_sorc.py b/src/char/sorceress/nova_sorc.py index 359a98b..497cf6e 100644 --- a/src/char/sorceress/nova_sorc.py +++ b/src/char/sorceress/nova_sorc.py @@ -41,15 +41,13 @@ class NovaSorc(Sorceress): def kill_eldritch(self) -> bool: self._pather.traverse_nodes_fixed([(675, 30)], self) self._cast_static(0.6) - atk_len = max(1.3, self._char_config["atk_len_eldritch"] - 0.7) - self._nova(atk_len) + self._nova(self._char_config["atk_len_eldritch"]) return True def kill_shenk(self) -> bool: self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, time_out=1.0) self._cast_static(0.6) - atk_len = max(1.5, self._char_config["atk_len_shenk"] - 1.0) - self._nova(atk_len) + self._nova(self._char_config["atk_len_shenk"]) return True def kill_council(self) -> bool: @@ -84,6 +82,18 @@ class NovaSorc(Sorceress): self._move_and_attack((-70, -35), atk_len) return True + def kill_summoner(self) -> bool: + # move mouse to below altar + pos_m = self._screen.convert_abs_to_monitor((0, 20)) + mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7]) + # Attack + self._nova(self._char_config["atk_len_arc"]) + # Move a bit back and another round + self._move_and_attack((0, 80), self._char_config["atk_len_arc"] * 0.5) + wait(0.1, 0.15) + self._nova(self._char_config["atk_len_arc"] * 0.5) + return True + if __name__ == "__main__": import os diff --git a/src/char/sorceress/sorceress.py b/src/char/sorceress/sorceress.py index aa566f1..26e8f22 100644 --- a/src/char/sorceress/sorceress.py +++ b/src/char/sorceress/sorceress.py @@ -1,4 +1,5 @@ import keyboard +from typing import Dict, Tuple, Union, List, Callable from utils.custom_mouse import mouse from char import IChar from template_finder import TemplateFinder @@ -33,6 +34,39 @@ class Sorceress(IChar): else: return super().pick_up_item(pos, item_name, prev_cast_start) + def select_by_template( + self, + template_type: Union[str, List[str]], + success_func: Callable = None, + time_out: float = 8, + threshold: float = 0.68, + telekinesis: bool = False + ) -> bool: + # In case telekinesis is False or hotkey is not set, just call the base implementation + if not self._skill_hotkeys["telekinesis"] and telekinesis: + return super().select_by_template(template_type, success_func, time_out, threshold) + if type(template_type) == list and "A5_STASH" in template_type: + # sometimes waypoint is opened and stash not found because of that, check for that + if self._template_finder.search("WAYPOINT_MENU", self._screen.grab()).valid: + keyboard.send("esc") + start = time.time() + while time_out is None or (time.time() - start) < time_out: + template_match = self._template_finder.search(template_type, self._screen.grab(), threshold=threshold) + if template_match.valid: + x_m, y_m = self._screen.convert_screen_to_monitor(template_match.position) + keyboard.send(self._skill_hotkeys["telekinesis"]) + wait(0.1, 0.2) + mouse.move(x_m, y_m) + wait(0.2, 0.3) + mouse.click(button="right") + # check the successfunction for 2 sec, if not found, try again + check_success_start = time.time() + while time.time() - check_success_start < 2: + if success_func is None or success_func(): + return True + # In case telekinesis fails, try again with the base implementation + return super().select_by_template(template_type, success_func, time_out, threshold) + def pre_buff(self): if self._char_config["cta_available"]: self._pre_buff_cta() diff --git a/src/char/trapsin.py b/src/char/trapsin.py index 3fb9ade..888816c 100644 --- a/src/char/trapsin.py +++ b/src/char/trapsin.py @@ -150,4 +150,3 @@ if __name__ == "__main__": pather = Pather(screen, t_finder) ui_manager = UiManager(screen, t_finder) char = Trapsin(config.trapsin, config.char, screen, t_finder, ui_manager, pather) - diff --git a/src/chest.py b/src/chest.py new file mode 100644 index 0000000..08d538d --- /dev/null +++ b/src/chest.py @@ -0,0 +1,80 @@ +import time +import os + +from logger import Logger +from template_finder import TemplateFinder +from screen import Screen +from char import IChar +from config import Config +from utils.custom_mouse import mouse +from utils.misc import wait + + +class Chest: + def __init__(self, char: IChar, template_finder: TemplateFinder, template: str = None): + self._config = Config() + self._screen = Screen(self._config.general["monitor"]) + self._char = char + self._template_finder = template_finder + self._folder_name = "chests" + # load all templates + self._templates = [] + for filename in os.listdir(f'assets/{self._folder_name}/{template}'): + filename = filename.lower() + if filename.endswith('.png'): + chest = filename[:-4].upper() + self._templates.append(chest) + + def open_up_chests(self, time_out: float = 8.0, threshold: float = 0.73) -> bool: + Logger.debug("Open chests") + templates = self._templates + found_chest = True + start = time.time() + while time.time() - start < time_out: + template_match = self._template_finder.search(templates, self._screen.grab(), roi=self._config.ui_roi["reduce_to_center"], threshold=threshold, use_grayscale=True, best_match=True) + # search for at least 1.5 second, if no chest found, break + if not template_match.valid: + if time.time() - start > 1.5: + break + else: + found_chest = True + x_m, y_m = self._screen.convert_screen_to_monitor(template_match.position) + # move mouse and check for label + mouse.move(x_m, y_m, delay_factor=[0.4, 0.6]) + wait(0.13, 0.16) + chest_label = self._template_finder.search("CHEST_LABEL", self._screen.grab(), threshold=0.85) + if chest_label.valid: + Logger.debug(f"Opening {template_match.name} ({template_match.score*100:.1f}% confidence)") + # TODO: Act as picking up a potion to support telekinesis. This workaround needs a proper solution. + self._char.pick_up_item([x_m, y_m], 'potion') + wait(0.13, 0.16) + locked_chest = self._template_finder.search("LOCKED", self._screen.grab(), threshold=0.85) + if locked_chest.valid: + templates.remove(template_match.name) + Logger.debug("No more keys, removing locked chest template") + continue + else: + templates.remove(template_match.name) + Logger.debug("No chests left") + return found_chest + + +if __name__ == "__main__": + import keyboard + import os + keyboard.add_hotkey('f12', lambda: Logger.info('Force Exit (f12)') or os._exit(1)) + print("Move to d2r window and press f11") + keyboard.wait("f11") + from char.hammerdin import Hammerdin + from screen import Screen + from pather import Pather + from config import Config + from ui import UiManager + config = Config() + screen = Screen(config.general["monitor"]) + template_finder = TemplateFinder(screen) + pather = Pather(screen, template_finder) + ui_manager = UiManager(screen, template_finder) + char = Hammerdin(config.hammerdin, config.char, screen, template_finder, ui_manager, pather) + chest = Chest(char, template_finder, 'arcane') + chest.open_up_chests(threshold=0.8) diff --git a/src/config.py b/src/config.py index bcf15ae..ee64da7 100644 --- a/src/config.py +++ b/src/config.py @@ -104,13 +104,15 @@ class Config: "stash_gold": bool(int(self._select_val("char", "stash_gold"))), "gold_trav_only": bool(int(self._select_val("char", "gold_trav_only"))), "use_merc": bool(int(self._select_val("char", "use_merc"))), - "id_items": bool(int(self._select_val("char", "ID_items"))), + "id_items": bool(int(self._select_val("char", "id_items"))), + "open_chests": bool(int(self._select_val("char", "open_chests"))), "pre_buff_every_run": bool(int(self._select_val("char", "pre_buff_every_run"))), "cta_available": bool(int(self._select_val("char", "cta_available"))), "weapon_switch": self._select_val("char", "weapon_switch"), "battle_orders": self._select_val("char", "battle_orders"), "battle_command": self._select_val("char", "battle_command"), "casting_frames": int(self._select_val("char", "casting_frames")), + "atk_len_arc": float(self._select_val("char", "atk_len_arc")), "atk_len_trav": float(self._select_val("char", "atk_len_trav")), "atk_len_pindle": float(self._select_val("char", "atk_len_pindle")), "atk_len_eldritch": float(self._select_val("char", "atk_len_eldritch")), diff --git a/src/health_manager.py b/src/health_manager.py index 9febf38..a350ccf 100644 --- a/src/health_manager.py +++ b/src/health_manager.py @@ -48,7 +48,7 @@ class HealthManager: def update_location(self, loc: Location): if loc is not None and type(loc) == str: - bosses = ["shenk", "eldritch", "pindle", "nihlatak", "trav"] + bosses = ["shenk", "eldritch", "pindle", "nihlatak", "trav", "arc"] prev_value = self._pausing self._pausing = not any(substring in loc for substring in bosses) if self._pausing != prev_value: diff --git a/src/item/item_finder.py b/src/item/item_finder.py index 7e62875..27c7f0b 100644 --- a/src/item/item_finder.py +++ b/src/item/item_finder.py @@ -145,4 +145,4 @@ if __name__ == "__main__": # cv2.putText(img, item.name, item.center, cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 1, cv2.LINE_AA) # img = cv2.resize(img, None, fx=0.5, fy=0.5) cv2.imshow('test', img) - cv2.waitKey(1) + cv2.waitKey(1) \ No newline at end of file diff --git a/src/npc_manager.py b/src/npc_manager.py index 461df2e..10ad85c 100644 --- a/src/npc_manager.py +++ b/src/npc_manager.py @@ -16,6 +16,7 @@ class Npc: ANYA = "anya" TYRAEL = "tyrael" ORMUS = "ormus" + FARA = "fara" CAIN = "cain" class NpcManager: @@ -90,6 +91,17 @@ class NpcManager: }, "template_group": ["ORMUS_0", "ORMUS_1", "ORMUS_2", "ORMUS_3", "ORMUS_4", "ORMUS_5"] }, + Npc.FARA: { + "name_tag_white": color_filter(self._template_finder.get_template("FARA_NAME_TAG_WHITE"), self._config.colors["white"])[1], + "name_tag_gold": color_filter(self._template_finder.get_template("FARA_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": ["FARA_LIGHT_1", "FARA_LIGHT_2", "FARA_LIGHT_3", "FARA_LIGHT_4", "FARA_LIGHT_5", "FARA_LIGHT_6", "FARA_LIGHT_7", "FARA_LIGHT_8", "FARA_LIGHT_9", "FARA_MEDIUM_1", "FARA_MEDIUM_2", "FARA_MEDIUM_3", "FARA_MEDIUM_4", "FARA_MEDIUM_5", "FARA_MEDIUM_6", "FARA_MEDIUM_7", "FARA_DARK_1", "FARA_DARK_2", "FARA_DARK_3", "FARA_DARK_4", "FARA_DARK_5", "FARA_DARK_6", "FARA_DARK_7"] + }, # Currently just nametag added to avoid having him focused when wanting to talk to tyrael or qual #added in the ability to ID items at cain. Npc.CAIN: { diff --git a/src/pather.py b/src/pather.py index a60d722..07cbec6 100644 --- a/src/pather.py +++ b/src/pather.py @@ -46,12 +46,21 @@ class Location: A3_ORMUS = "a3_ormus" A3_STASH_WP = "a3_stash_wp" A3_ASHEARA = "a3_asheara" + # A2 Town + A2_TOWN_START = "a2_town_start" + A2_WP = "a2_wp" + A2_TP = "a2_tp" + A2_FARA_STASH = "a2_fara_stash" # Trav A3_TRAV_START = "a3_trav_start" A3_TRAV_CENTER_STAIRS = "a3_trav_center_stairs" # Nihalatk A5_NIHLATAK_START = "a5_nihlatak_lvl1_start" A5_NIHLATAK_END = "a5_nihlatak_lvl2_end" + # Arcane + A2_ARC_START = "a2_arc_start" + A2_ARC_CHECKPOINT = "a2_arc_checkpoint" + A2_ARC_END = "a2_arc_end" class Pather: @@ -126,6 +135,15 @@ class Pather: 190: {"A3_TOWN_12": (27, -198), "A3_TOWN_16": (831, 258), "A3_TOWN_14": (-318, 185), "A3_TOWN_15": (411, -9), "A3_TOWN_5": (-301, -334), "A3_TOWN_13": (-543, -10), "A3_TOWN_17": (707, 541)}, 191: {"A3_TOWN_15": (-79, -256), "A3_TOWN_16": (341, 11), "A3_TOWN_17": (217, 294), "A3_TOWN_18": (542, 408), "A3_TOWN_19": (779, 171)}, 192: {"A3_TOWN_17": (-187, 78), "A3_TOWN_16": (-63, -205), "A3_TOWN_18": (138, 192), "A3_TOWN_19": (375, -45)}, + # A2 town + 400: {"A2_TOWN_2": (-169, 160), "A2_TOWN_0": (290, -114), "A2_TOWN_3": (-348, 225), "A2_TOWN_1": (-345, -374)}, + 401: {"A2_TOWN_3": (45, -202), "A2_TOWN_7": (-40, 266), "A2_TOWN_2": (224, -267), "A2_TOWN_6": (-505, 26), "A2_TOWN_5": (116, 203)}, + 402: {"A2_TOWN_8": (182, 121), "A2_TOWN_6": (103, -348), "A2_TOWN_11": (128, 357), "A2_TOWN_9": (-324, 223), "A2_TOWN_12": (-213, 500)}, + 403: {"A2_TOWN_11": (161, -18), "A2_TOWN_12": (-180, 125), "A2_TOWN_9": (-291, -152), "A2_TOWN_8": (215, -254), "A2_TOWN_13": (149, 392)}, + 404: {"A2_TOWN_14": (79, 190), "A2_TOWN_15": (244, -12), "A2_TOWN_13": (-270, 123), "A2_TOWN_11": (-258, -287), "A2_TOWN_12": (-599, -143)}, + 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)}, # 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)}, @@ -142,6 +160,13 @@ class Pather: 301: {"TRAV_V3_7": (63, -113), "TRAV_V3_6": (55, 77), "TRAV_V3_0": (-27, -315), "TRAV_V3_5": (-450, -175), "TRAV_V3_8": (329, -188)}, 302: {"TRAV_V3_0": (-18, 6), "TRAV_V3_7": (73, 208), "TRAV_V3_8": (339, 133), "TRAV_V3_6": (65, 398), "TRAV_V3_5": (-440, 146)}, 304: {"TRAV_V2_4": (125, -148), "TRAV_V2_3": (-187, 55), "TRAV_V2_1": (-207, 59), "TRAV_V2_2": (267, 183), "TRAV_V2_0": (-159, 403)}, + # Arcane + 450: {"ARC_START": (49, 62)}, + 453: {"ARC_START": (-259, 62)}, + 456: {"ARC_START": (145, 264)}, + 459: {"ARC_START": (-356, 258)}, + 461: {"ARC_ALTAR": (60, 120), "ARC_ALTAR3": (-272, 200), "ARC_CENTER_2": (67, 41), "ARC_END_STAIRS": (76, -344), "ARC_END_STAIRS_2": (60, -160)}, + 462: {"ARC_PLATFORM_1": (0, -100), "ARC_PLATFORM_2": (50, -100), "ARC_PLATFORM_3": (70, 0)}, # Nil - End of Arm A 500: {"NIL2A_0": (-200, 1), "NIL2A_2": (-181, -102), "NIL2A_1": (329, 146), "NIL2A_4": (835, 24), "NIL2A_5": (-384, -20), "NIL2A_6": (-600, 410)}, 501: {"NIL2A_4": (270+20, 259-50), "NIL2A_1": (-236+20, 381-50), "NIL2A_2": (-746+20, 133-50), "NIL2A_0": (-765+20, 236-50)}, @@ -176,7 +201,7 @@ class Pather: (Location.A5_QUAL_KEHK, Location.A5_NIHLATHAK_PORTAL): [12, 11, 10, 6, 8, 9], (Location.A5_QUAL_KEHK, Location.A5_WP): [12, 11, 10, 6], (Location.A5_QUAL_KEHK, Location.A5_STASH): [12, 11, 10, 6, 5], - (Location.A5_LARZUK, Location.A5_QUAL_KEHK): [13, 14, 5, 6, 10, 11, 12], + (Location.A5_LARZUK, Location.A5_QUAL_KEHK): [13, 14, 5, 6, 10, 11, 12], (Location.A5_LARZUK, Location.A5_NIHLATHAK_PORTAL): [14, 13, 5, 6, 8, 9], (Location.A5_LARZUK, Location.A5_WP): [14, 13, 5], # Pindle @@ -201,6 +226,12 @@ class Pather: (Location.A3_ASHEARA, Location.A3_STASH_WP): [191, 190, 189, 185, 186, 187, 188], (Location.A3_STASH_WP, Location.A3_STASH_WP): [188], (Location.A3_STASH_WP, Location.A3_ORMUS): [187, 186, 185], + # A2 Town + (Location.A2_TOWN_START, Location.A2_WP): [400, 401, 402, 403, 404], + (Location.A2_TOWN_START, Location.A2_FARA_STASH): [400, 401, 402, 405], + (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], # Trav (Location.A3_TRAV_START, Location.A3_TRAV_CENTER_STAIRS): [220, 221, 222, 223, 224, 225, 226], } @@ -226,7 +257,7 @@ class Pather: def _convert_rel_to_abs(rel_loc: Tuple[float, float], pos_abs: Tuple[float, float]) -> Tuple[float, float]: return (rel_loc[0] + pos_abs[0], rel_loc[1] + pos_abs[1]) - def traverse_nodes_fixed(self, key: Union[str, List[Tuple[float, float]]], char: IChar): + def traverse_nodes_fixed(self, key: Union[str, List[Tuple[float, float]]], char: IChar) -> bool: if not char.can_teleport(): error_msg = "Teleport is requiered for static pathing" Logger.error(error_msg) @@ -237,6 +268,7 @@ class Pather: else: path = key i = 0 + stuck_count = 0 while i < len(path): x_m, y_m = self._screen.convert_screen_to_monitor(path[i]) x_m += int(random.random() * 6 - 3) @@ -252,9 +284,13 @@ class Pather: if score > 0.15: i += 1 else: + stuck_count += 1 Logger.debug(f"Teleport cancel detected. Try same teleport action again. ({score:.4f})") + if stuck_count >= 5: + return False # if type(key) == str and ("_save_dist" in key or "_end" in key): # cv2.imwrite(f"./info_screenshots/nil_path_{key}_" + time.strftime("%Y%m%d_%H%M%S") + ".png", self._screen.grab()) + return True def _adjust_abs_range_to_screen(self, abs_pos: Tuple[float, float]) -> Tuple[float, float]: """ @@ -367,7 +403,7 @@ class Pather: Logger.error("Got stuck exit pather") return False - # Sometimes we get stuck at rocks and stuff, after 2.5 seconds force a move into the last know direction + # Sometimes we get stuck at rocks and stuff, after a few seconds force a move into the last know direction if not did_force_move and time.time() - last_move > 3.1: pos_abs = (0, 150) if last_direction is not None: @@ -425,7 +461,7 @@ if __name__ == "__main__": x, y = pather._screen.convert_abs_to_screen(ref_pos_abs) cv2.circle(display_img, (x, y), 5, (0, 255, 0), 3) cv2.putText(display_img, template_type, (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA) - # display_img = cv2.resize(display_img, None, fx=0.5, fy=0.5) + display_img = cv2.resize(display_img, None, fx=0.5, fy=0.5) cv2.imshow("debug", display_img) cv2.waitKey(1) @@ -441,7 +477,7 @@ if __name__ == "__main__": t_finder = TemplateFinder(screen) pather = Pather(screen, t_finder) - display_all_nodes(pather, "ELD") + display_all_nodes(pather, "A2_TOWN") # # changing node pos and generating new code # code = "" @@ -455,5 +491,5 @@ if __name__ == "__main__": ui_manager = UiManager(screen, t_finder) char = Hammerdin(config.hammerdin, config.char, screen, t_finder, ui_manager, pather) - pather.traverse_nodes_fixed("trav_safe_dist", char) - # pather.traverse_nodes([226, 228, 229], char) + # pather.traverse_nodes([452], char) + pather.traverse_nodes_fixed("arc_top_right", char) diff --git a/src/run/__init__.py b/src/run/__init__.py index ba0a383..392bde0 100644 --- a/src/run/__init__.py +++ b/src/run/__init__.py @@ -2,3 +2,4 @@ from .pindle import Pindle from .shenk_eld import ShenkEld from .trav import Trav from .nihlatak import Nihlatak +from .arcane import Arcane diff --git a/src/run/arcane.py b/src/run/arcane.py new file mode 100644 index 0000000..d789057 --- /dev/null +++ b/src/run/arcane.py @@ -0,0 +1,125 @@ +from char.i_char import IChar +from config import Config +from logger import Logger +from pather import Location, Pather +from typing import Union +from item.pickit import PickIt +from template_finder import TemplateFinder +from town.town_manager import TownManager +from ui import UiManager +from utils.misc import wait +from dataclasses import dataclass +from chest import Chest + + +class Arcane: + def __init__( + self, + template_finder: TemplateFinder, + pather: Pather, + town_manager: TownManager, + ui_manager: UiManager, + char: IChar, + pickit: PickIt + ): + self._config = Config() + self._template_finder = template_finder + self._pather = pather + self._town_manager = town_manager + self._ui_manager = ui_manager + self._char = char + self._pickit = pickit + self._chest = Chest(self._char, self._template_finder, 'arcane') + self.used_tps = 0 + + def approach(self, start_loc: Location) -> Union[bool, Location]: + Logger.info("Run Arcane") + if not self._char.can_teleport(): + raise ValueError("Arcane requires teleport") + if not self._town_manager.open_wp(start_loc): + return False + wait(0.4) + self._ui_manager.use_wp(2, 7) + return Location.A2_ARC_START + + def _find_summoner(self, traverse_to_summoner: list[tuple[float, float]]) -> bool: + # Check if we arrived at platform + templates_platform = ["ARC_PLATFORM_1", "ARC_PLATFORM_2", "ARC_PLATFORM_3", "ARC_CENTER"] + tempaltes_summoner = ["ARC_ALTAR", "ARC_ALTAR3", "ARC_END_STAIRS", "ARC_END_STAIRS_2"] + match_platform = self._template_finder.search_and_wait(templates_platform, threshold=0.55, time_out=0.5, use_grayscale=True, take_ss=False) + match_summoner = self._template_finder.search_and_wait(tempaltes_summoner, threshold=0.79, time_out=0.5, use_grayscale=True, take_ss=False) + if not match_platform.valid and not match_summoner.valid: + # We might have arrived at summoner, move up stairs with static traverse + self._pather.traverse_nodes_fixed(traverse_to_summoner, self._char) + # try to match summoner again + match_summoner = self._template_finder.search_and_wait(tempaltes_summoner, threshold=0.79, time_out=1.0, use_grayscale=True, take_ss=False) + if match_summoner.valid: + if self._pather.traverse_nodes([461], self._char, time_out=2.2, force_tp=True): + return True + else: + # Traverse to center of platform + self._pather.traverse_nodes([462], self._char, time_out=1.3, force_tp=True) + return False + + def battle(self, do_pre_buff: bool) -> Union[bool, tuple[Location, bool]]: + picked_up_items = False + @dataclass + class PathData: + calib_node_start: int + static_path_forward: str + jump_to_summoner: list[tuple[float, float]] + + path_arr = [ + PathData(450, "arc_top_right", [(500, 40)]), + PathData(453, "arc_top_left", [(500, 40)]), + PathData(456, "arc_bottom_right", [(500, 40)]), + PathData(459, "arc_bottom_left", [(500, 20), (700, 100)]) + ] + + picked_up_items = False + self.used_tps = 0 + if do_pre_buff: + self._char.pre_buff() + + for i, data in enumerate(path_arr): + # calibrating at start and moving towards the end of the arm + self._pather.traverse_nodes([data.calib_node_start], self._char, force_tp=True) + if not self._pather.traverse_nodes_fixed(data.static_path_forward, self._char): + return False + found = self._find_summoner(data.jump_to_summoner) + # Kill the summoner or trash mob + self._char.kill_summoner() + if self._config.char["open_chests"]: + self._chest.open_up_chests() + picked_up_items |= self._pickit.pick_up_items(self._char) + if found: + return (Location.A2_ARC_END, picked_up_items) + elif i < len(path_arr) - 1: + # Open TP and return back to town, walk to wp and start over + if not self._char.tp_town(): + Logger.warning("TP to town failed, cancel run") + self.used_tps += 20 + return False + self.used_tps += 1 + if not self._town_manager.wait_for_tp(Location.A2_TP): + return False + if not self.approach(Location.A2_FARA_STASH): + return False + return False + + +if __name__ == "__main__": + from screen import Screen + import keyboard + from game_stats import GameStats + import os + keyboard.add_hotkey('f12', lambda: os._exit(1)) + keyboard.wait("f11") + from config import Config + from ui import UiManager + from bot import Bot + config = Config() + screen = Screen(config.general["monitor"]) + game_stats = GameStats() + bot = Bot(screen, game_stats, False) + bot._arcane._find_summoner([(500, 40)]) diff --git a/src/run/nihlatak.py b/src/run/nihlatak.py index 3ed195d..90e1835 100644 --- a/src/run/nihlatak.py +++ b/src/run/nihlatak.py @@ -107,4 +107,4 @@ class Nihlatak: self._char.kill_nihlatak(end_nodes) wait(0.2, 0.3) picked_up_items = self._pickit.pick_up_items(self._char) - return (Location.A5_NIHLATAK_END, picked_up_items) + return (Location.A5_NIHLATAK_END, picked_up_items) \ No newline at end of file diff --git a/src/screen.py b/src/screen.py index ae3e24c..9ff3eb5 100644 --- a/src/screen.py +++ b/src/screen.py @@ -117,7 +117,7 @@ if __name__ == "__main__": p1 = (x, y) p2 = (x+w, y+h) cv2.rectangle(test_img, p1, p2, (0, 255, 0), 2) - cv2.putText(test_img, roi_key, (p1[0], p1[1]+20), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 1, cv2.LINE_AA) + cv2.putText(test_img, roi_key, (p1[0], p1[1]+20), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 1, cv2.LINE_AA) if show_pt: pass diff --git a/src/template_finder.py b/src/template_finder.py index 642d90f..d3b82cd 100644 --- a/src/template_finder.py +++ b/src/template_finder.py @@ -22,7 +22,7 @@ class TemplateFinder: Loads images from assets/templates and assets/npc and provides search functions to find these assets within another image """ - def __init__(self, screen: Screen, template_pathes: list[str] = ["assets\\templates", "assets\\npc", "assets\\item_properties"]): + def __init__(self, screen: Screen, template_pathes: list[str] = ["assets\\templates", "assets\\npc", "assets\\item_properties", "assets\\chests"]): self._screen = screen self._config = Config() self.last_res = None @@ -185,18 +185,19 @@ if __name__ == "__main__": config = Config() screen = Screen(config.general["monitor"]) template_finder = TemplateFinder(screen) - search_templates = ["REPAIR_NEEDED"] + search_templates = ["ARC_ALTAR", "ARC_ALTAR2"] while 1: # img = cv2.imread("") img = screen.grab() display_img = img.copy() start = time.time() for key in search_templates: - template_match = template_finder.search(key, img, best_match=True, threshold=0.35, use_grayscale=True) + template_match = template_finder.search(key, img, best_match=True, threshold=0.5, use_grayscale=True) if template_match.valid: - cv2.putText(display_img, str(template_match.name), template_match.position, cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2, cv2.LINE_AA) + cv2.putText(display_img, str(template_match.name), template_match.position, cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA) cv2.circle(display_img, template_match.position, 7, (255, 0, 0), thickness=5) - print(f"Name: {template_match.name} Pos: {template_match.position}, Score: {template_match.score}") + x, y = template_match.position + print(f"Name: {template_match.name} Pos: {template_match.position}, Dist: {625-x, 360-y}, Score: {template_match.score}") # print(time.time() - start) display_img = cv2.resize(display_img, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_NEAREST) cv2.imshow('test', display_img) diff --git a/src/town/__init__.py b/src/town/__init__.py index d38c745..90495ec 100644 --- a/src/town/__init__.py +++ b/src/town/__init__.py @@ -1,3 +1,4 @@ +from .a2 import A2 from .a3 import A3 from .a4 import A4 from .a5 import A5 diff --git a/src/town/a2.py b/src/town/a2.py new file mode 100644 index 0000000..d614c39 --- /dev/null +++ b/src/town/a2.py @@ -0,0 +1,62 @@ +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 A2(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.A2_WP + def can_stash(self) -> bool: return True + def can_buy_pots(self) -> bool: return False + def can_heal(self) -> bool: return True + def can_trade_and_repair(self) -> bool: return True + + def heal(self, curr_loc: Location) -> Union[Location, bool]: + if not self._pather.traverse_nodes((curr_loc, Location.A2_FARA_STASH), self._char): return False + self._npc_manager.open_npc_menu(Npc.FARA) + return Location.A2_FARA_STASH + + def open_stash(self, curr_loc: Location) -> Union[Location, bool]: + if not self._pather.traverse_nodes((curr_loc, Location.A2_FARA_STASH), self._char): + return False + wait(0.3) + 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(["A2_STASH_LIGHT", "A2_STASH_DARK"], stash_is_open_func, telekinesis=True): + return False + return Location.A2_FARA_STASH + + def open_trade_and_repair_menu(self, curr_loc: Location) -> Union[Location, bool]: + if not self._pather.traverse_nodes((curr_loc, Location.A2_FARA_STASH), self._char): return + self._npc_manager.open_npc_menu(Npc.FARA) + self._npc_manager.press_npc_btn(Npc.FARA, "trade_repair") + return Location.A2_FARA_STASH + + def open_wp(self, curr_loc: Location) -> bool: + if not self._pather.traverse_nodes((curr_loc, Location.A2_WP), self._char, force_move=True): return False + wait(0.5, 0.7) + found_wp_func = lambda: self._template_finder.search("WAYPOINT_MENU", self._screen.grab()).valid + return self._char.select_by_template(["A2_WP_LIGHT", "A2_WP_DARK"], found_wp_func, telekinesis=True) + + def wait_for_tp(self) -> Union[Location, bool]: + template_match = self._template_finder.search_and_wait(["A2_TOWN_21", "A2_TOWN_22", "A2_TOWN_20", "A2_TOWN_19"], time_out=20) + if template_match.valid: + self._pather.traverse_nodes((Location.A2_TP, Location.A2_FARA_STASH), self._char, force_move=True) + return Location.A2_FARA_STASH + return False diff --git a/src/town/a3.py b/src/town/a3.py index 526221b..e766e34 100644 --- a/src/town/a3.py +++ b/src/town/a3.py @@ -7,7 +7,6 @@ from pather import Pather, Location from typing import Union from template_finder import TemplateFinder from utils.misc import wait -from utils.custom_mouse import mouse class A3(IAct): @@ -44,7 +43,7 @@ class A3(IAct): 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("A3_STASH", stash_is_open_func): + if not self._char.select_by_template("A3_STASH", stash_is_open_func, telekinesis=True): return False return Location.A3_STASH_WP @@ -52,7 +51,7 @@ class A3(IAct): if not self._pather.traverse_nodes((curr_loc, Location.A3_STASH_WP), self._char, force_move=True): return False wait(0.5, 0.7) found_wp_func = lambda: self._template_finder.search("WAYPOINT_MENU", self._screen.grab()).valid - return self._char.select_by_template("A3_WP", found_wp_func) + return self._char.select_by_template("A3_WP", found_wp_func, telekinesis=True) def wait_for_tp(self) -> Union[Location, bool]: template_match = self._template_finder.search_and_wait("A3_TOWN_10", time_out=20) diff --git a/src/town/a4.py b/src/town/a4.py index c7d2618..8b5b67d 100644 --- a/src/town/a4.py +++ b/src/town/a4.py @@ -34,7 +34,7 @@ class A4(IAct): 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(["A4_WP", "A4_WP_2"], found_wp_func, threshold=0.62) + return self._char.select_by_template(["A4_WP", "A4_WP_2"], found_wp_func, threshold=0.62, telekinesis=True) def wait_for_tp(self) -> Union[Location, bool]: success = self._template_finder.search_and_wait(["A4_TOWN_4", "A4_TOWN_5", "A4_TOWN_6"], time_out=20).valid diff --git a/src/town/a5.py b/src/town/a5.py index 7abf457..bc94cd2 100644 --- a/src/town/a5.py +++ b/src/town/a5.py @@ -62,7 +62,7 @@ class A5(IAct): 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(["A5_STASH", "A5_STASH_2"], stash_is_open_func): + if not self._char.select_by_template(["A5_STASH", "A5_STASH_2"], stash_is_open_func, telekinesis=True): return False return Location.A5_STASH @@ -76,7 +76,7 @@ class A5(IAct): if not self._pather.traverse_nodes((curr_loc, Location.A5_WP), self._char): return False wait(0.5, 0.7) found_wp_func = lambda: self._template_finder.search("WAYPOINT_MENU", self._screen.grab()).valid - return self._char.select_by_template("A5_WP", found_wp_func) + return self._char.select_by_template("A5_WP", found_wp_func, telekinesis=True) def wait_for_tp(self) -> Union[Location, bool]: success = self._template_finder.search_and_wait(["A5_TOWN_1", "A5_TOWN_0"], time_out=20).valid diff --git a/src/town/town_manager.py b/src/town/town_manager.py index deb1c6b..2d0e052 100644 --- a/src/town/town_manager.py +++ b/src/town/town_manager.py @@ -5,17 +5,18 @@ from config import Config from pather import Location from logger import Logger from ui import UiManager -from town import IAct, A3, A4, A5 +from town import IAct, A2, A3, A4, A5 from utils.misc import wait class TownManager: - def __init__(self, template_finder: TemplateFinder, ui_manager: UiManager, item_finder: ItemFinder, a3: A3, a4: A4, a5: A5): + def __init__(self, template_finder: TemplateFinder, ui_manager: UiManager, item_finder: ItemFinder, 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.A2_TOWN_START: a2, Location.A3_TOWN_START: a3, Location.A4_TOWN_START: a4, Location.A5_TOWN_START: a5 @@ -30,6 +31,8 @@ class TownManager: location = Location.A4_TOWN_START elif loc.upper().startswith("A3_"): location = Location.A3_TOWN_START + elif loc.upper().startswith("A2_"): + location = Location.A2_TOWN_START return location def wait_for_town_spawn(self, time_out: float = None) -> Location: @@ -40,7 +43,8 @@ class TownManager: template_match = self._template_finder.search_and_wait([ "A5_TOWN_0", "A5_TOWN_1", "A4_TOWN_4", "A4_TOWN_5", - "A3_TOWN_0", "A3_TOWN_1" + "A3_TOWN_0", "A3_TOWN_1", + "A2_TOWN_0", "A2_TOWN_1", "A2_TOWN_10" ], best_match=True, time_out=time_out) if template_match.valid: return TownManager.get_act_from_location(template_match.name) @@ -60,7 +64,8 @@ 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 == 3: act = Location.A3_TOWN_START + if 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 else: @@ -179,5 +184,6 @@ if __name__ == "__main__": a5 = A5(screen, template_finder, pather, char, npc_manager) a4 = A4(screen, template_finder, pather, char, npc_manager) a3 = A3(screen, template_finder, pather, char, npc_manager) - town_manager = TownManager(template_finder, ui_manager, item_finder, a3, a4, a5) - print(town_manager.stash(Location.A5_STASH)) + 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)) diff --git a/src/ui/belt_manager.py b/src/ui/belt_manager.py index 3b48146..dc90fde 100644 --- a/src/ui/belt_manager.py +++ b/src/ui/belt_manager.py @@ -189,4 +189,4 @@ if __name__ == "__main__": ui_manager = UiManager(screen, template_finder) belt_manager = BeltManager(screen, template_finder) belt_manager.update_pot_needs() - print(belt_manager._pot_needs) + print(belt_manager._pot_needs) \ No newline at end of file diff --git a/src/ui/ui_manager.py b/src/ui/ui_manager.py index c2bd894..345a21b 100644 --- a/src/ui/ui_manager.py +++ b/src/ui/ui_manager.py @@ -34,7 +34,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_A3_ACTIVE": 3, "WP_A4_ACTIVE": 4, "WP_A5_ACTIVE": 5} + str_to_idx_map = {"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: diff --git a/src/utils/node_recorder.py b/src/utils/node_recorder.py index ef3e1d9..8501580 100644 --- a/src/utils/node_recorder.py +++ b/src/utils/node_recorder.py @@ -47,7 +47,7 @@ class NodeRecorder: def find_templates(self, img): ref_points = {} for key in self._template_finder._templates: - found = self._template_finder.search(key, img, use_grayscale=True) + found = self._template_finder.search(key, img, use_grayscale=False, threshold=0.77) if found.valid: ref_points[key] = found.position return ref_points @@ -127,7 +127,7 @@ class NodeRecorder: results = sorted(new_path, key=lambda r: r["dist"]) code = f"{k}: " + "{" for i, res in enumerate(results): - if res["dist"] < 900 and i < 5: + if res["dist"] < 1100 and i < 8: code += f'"{res["key"].upper()}": {res["pos"]}, ' f.write(code + "}\n") f.close() @@ -156,5 +156,6 @@ if __name__ == "__main__": cv2.putText(img, key, recorder.ref_points[key], cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA) except Exception: pass + img = cv2.resize(img, None, fx=0.5, fy=0.5) cv2.imshow("vis", img) cv2.waitKey(1)