From b278aa9ab623dc10313ffd007bb33f0026d3f419 Mon Sep 17 00:00:00 2001 From: Sorc <> Date: Wed, 15 Jan 2025 10:47:09 -0500 Subject: [PATCH] Purchase missing keys and scrolls as part of the VendorRefill method --- internal/action/town.go | 8 --- internal/action/vendor.go | 97 +++++++++++++++++++++++++---------- internal/town/shop_manager.go | 59 ++++++++++++--------- 3 files changed, 107 insertions(+), 57 deletions(-) diff --git a/internal/action/town.go b/internal/action/town.go index 200927d20..62b131d16 100644 --- a/internal/action/town.go +++ b/internal/action/town.go @@ -34,12 +34,6 @@ func PreRun(firstRun bool) error { // Refill pots, sell, buy etc VendorRefill(false, true) - // Restock keys if the above VendorRefill missed them - RestockKeys() - - // Restock tomes if the above VendorRefill missed them - RestockTomes() - // Gamble Gamble() @@ -83,8 +77,6 @@ func InRunReturnTownRoutine() error { IdentifyAll(false) VendorRefill(false, true) - RestockKeys() - RestockTomes() Stash(false) Gamble() Stash(false) diff --git a/internal/action/vendor.go b/internal/action/vendor.go index c995e16ce..c429a6cd8 100644 --- a/internal/action/vendor.go +++ b/internal/action/vendor.go @@ -15,6 +15,57 @@ import ( "github.com/hectorgimenez/d2go/pkg/data/stat" ) +func openTradeWindow(vendorNPC npc.ID) error { + ctx := context.Get() + + err := InteractNPC(vendorNPC) + if err != nil { + return err + } + + // Jamella trade button is the first one + if vendorNPC == npc.Jamella { + ctx.HID.KeySequence(win.VK_HOME, win.VK_RETURN) + } else { + ctx.HID.KeySequence(win.VK_HOME, win.VK_DOWN, win.VK_RETURN) + } + + SwitchStashTab(4) + ctx.RefreshGameData() + + return nil +} + +// Act 1 Vendors: +// Potions: Akara +// Keys: Akara +// Scrolls: Akara +// Arrows/Bolts: Charsi + +// Act 2 Vendors: +// Potions: Lysander +// Keys: Lysander +// Scrolls: Drognan +// Arrows/Bolts: Fara + +// Act 3 Vendors: +// Potions: Ormus +// Keys: Hratli +// Scrolls: Ormus +// Arrows/Bolts: Hratli + +// Act 4 Vendors: +// Potions: Jamella +// Keys: Jamella +// Scrolls: Jamella +// Arrows/Bolts: Halbu + +// Act 5 Vendors: +// Potions: Malah +// Keys: Malah +// Scrolls: Malah +// Arrows/Bolts: Larzuk + func VendorRefill(forceRefill, sellJunk bool) error { ctx := context.Get() ctx.SetLastAction("VendorRefill") @@ -32,32 +83,37 @@ func VendorRefill(forceRefill, sellJunk bool) error { vendorNPC = npc.Lysander } } - err := InteractNPC(vendorNPC) + + err := openTradeWindow(vendorNPC) if err != nil { return err } - // Jamella trade button is the first one - if vendorNPC == npc.Jamella { - ctx.HID.KeySequence(win.VK_HOME, win.VK_RETURN) - } else { - ctx.HID.KeySequence(win.VK_HOME, win.VK_DOWN, win.VK_RETURN) - } - - SwitchStashTab(4) - ctx.RefreshGameData() town.BuyConsumables(forceRefill) if sellJunk { town.SellJunk() } + // At this point we are guaranteed to have purchased potions, as the selected vendorNPC will always have these. + // Depending on the act, we may still need keys or scrolls. + + if town.ShouldBuyTPs() || town.ShouldBuyIDs() { + restockTomes() + } + + if ctx.Data.PlayerUnit.Class != data.Assassin { + _, shouldBuyKeys := town.ShouldBuyKeys() + if shouldBuyKeys { + restockKeys() + } + } + return step.CloseAllMenus() } -func RestockTomes() error { +func restockTomes() error { ctx := context.Get() - ctx.SetLastAction("RestockTomes") shouldBuyTPs := town.ShouldBuyTPs() shouldBuyIDs := town.ShouldBuyIDs() @@ -88,16 +144,11 @@ func RestockTomes() error { return nil } - err := InteractNPC(vendorNPC) + err := openTradeWindow(vendorNPC) if err != nil { return err } - ctx.HID.KeySequence(win.VK_HOME, win.VK_DOWN, win.VK_RETURN) - - SwitchStashTab(4) - ctx.RefreshGameData() - if shouldBuyTPs { town.BuyTPs() } @@ -109,9 +160,8 @@ func RestockTomes() error { return nil } -func RestockKeys() error { +func restockKeys() error { ctx := context.Get() - ctx.SetLastAction("RestockKeys") if ctx.Data.PlayerUnit.Class == data.Assassin { return nil @@ -145,16 +195,11 @@ func RestockKeys() error { return nil } - err := InteractNPC(vendorNPC) + err := openTradeWindow(vendorNPC) if err != nil { return err } - ctx.HID.KeySequence(win.VK_HOME, win.VK_DOWN, win.VK_RETURN) - - SwitchStashTab(4) - ctx.RefreshGameData() - if itm, found := ctx.Data.Inventory.Find(item.Key, item.LocationVendor); found { ctx.Logger.Debug("Vendor with keys detected, provisioning...") diff --git a/internal/town/shop_manager.go b/internal/town/shop_manager.go index df6dda278..e43352083 100644 --- a/internal/town/shop_manager.go +++ b/internal/town/shop_manager.go @@ -13,6 +13,37 @@ import ( "github.com/hectorgimenez/koolo/internal/ui" ) + +func BuyTPs() { + ctx := context.Get() + + if _, found := ctx.Data.Inventory.Find(item.TomeOfTownPortal, item.LocationInventory); !found { + ctx.Logger.Info("TP Tome not found, buying one...") + if itm, itmFound := ctx.Data.Inventory.Find(item.TomeOfTownPortal, item.LocationVendor); itmFound { + BuyItem(itm, 1) + } + } + ctx.Logger.Debug("Filling TP Tome...") + if itm, found := ctx.Data.Inventory.Find(item.ScrollOfTownPortal, item.LocationVendor); found { + BuyFullStack(itm) + } +} + +func BuyIDs() { + ctx := context.Get() + + if _, found := ctx.Data.Inventory.Find(item.TomeOfIdentify, item.LocationInventory); !found { + ctx.Logger.Info("ID Tome not found, buying one...") + if itm, itmFound := ctx.Data.Inventory.Find(item.TomeOfIdentify, item.LocationVendor); itmFound { + BuyItem(itm, 1) + } + } + ctx.Logger.Debug("Filling IDs Tome...") + if itm, found := ctx.Data.Inventory.Find(item.ScrollOfIdentify, item.LocationVendor); found { + BuyFullStack(itm) + } +} + func BuyConsumables(forceRefill bool) { ctx := context.Get() @@ -39,29 +70,11 @@ func BuyConsumables(forceRefill bool) { } if ShouldBuyTPs() || forceRefill { - if _, found := ctx.Data.Inventory.Find(item.TomeOfTownPortal, item.LocationInventory); !found { - ctx.Logger.Info("TP Tome not found, buying one...") - if itm, itmFound := ctx.Data.Inventory.Find(item.TomeOfTownPortal, item.LocationVendor); itmFound { - BuyItem(itm, 1) - } - } - ctx.Logger.Debug("Filling TP Tome...") - if itm, found := ctx.Data.Inventory.Find(item.ScrollOfTownPortal, item.LocationVendor); found { - buyFullStack(itm) - } + BuyTPs() } if ShouldBuyIDs() || forceRefill { - if _, found := ctx.Data.Inventory.Find(item.TomeOfIdentify, item.LocationInventory); !found { - ctx.Logger.Info("ID Tome not found, buying one...") - if itm, itmFound := ctx.Data.Inventory.Find(item.TomeOfIdentify, item.LocationVendor); itmFound { - BuyItem(itm, 1) - } - } - ctx.Logger.Debug("Filling IDs Tome...") - if itm, found := ctx.Data.Inventory.Find(item.ScrollOfIdentify, item.LocationVendor); found { - buyFullStack(itm) - } + BuyIDs() } keyQuantity, shouldBuyKeys := ShouldBuyKeys() @@ -71,7 +84,7 @@ func BuyConsumables(forceRefill bool) { qty, _ := itm.FindStat(stat.Quantity, 0) if (qty.Value + keyQuantity) <= 12 { - buyFullStack(itm) + BuyFullStack(itm) } } } @@ -113,7 +126,7 @@ func ShouldBuyIDs() bool { func ShouldBuyKeys() (int, bool) { keys, found := context.Get().Data.Inventory.Find(item.Key, item.LocationInventory) if !found { - return 12, false + return 12, true } qty, found := keys.FindStat(stat.Quantity, 0) @@ -154,7 +167,7 @@ func BuyItem(i data.Item, quantity int) { } } -func buyFullStack(i data.Item) { +func BuyFullStack(i data.Item) { screenPos := ui.GetScreenCoordsForItem(i) context.Get().HID.ClickWithModifier(game.RightButton, screenPos.X, screenPos.Y, game.ShiftKey)