Skip to content

Commit

Permalink
fix tyrael, simplified logic
Browse files Browse the repository at this point in the history
  • Loading branch information
elobo91 committed Jan 25, 2025
1 parent 6b31168 commit 4b79591
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 81 deletions.
1 change: 1 addition & 0 deletions internal/action/identify.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ func CainIdentify() error {
// Verify menu opened
menuWait := time.Now().Add(2 * time.Second)
for time.Now().Before(menuWait) {
ctx.PauseIfNotPriority()
ctx.RefreshGameData()
if ctx.Data.OpenMenus.NPCInteract {
break
Expand Down
100 changes: 19 additions & 81 deletions internal/action/step/interact_npc.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package step

import (
"errors"
"fmt"
"time"

"github.com/hectorgimenez/d2go/pkg/data"
"github.com/hectorgimenez/d2go/pkg/data/npc"
"github.com/hectorgimenez/koolo/internal/context"
"github.com/hectorgimenez/koolo/internal/game"
"github.com/hectorgimenez/koolo/internal/pather"
"github.com/hectorgimenez/koolo/internal/ui"
)

Expand All @@ -18,53 +16,22 @@ func InteractNPC(npcID npc.ID) error {
ctx.SetLastStep("InteractNPC")

const (
maxAttempts = 8
interactionTimeout = 3 * time.Second
minMenuOpenWait = 300 * time.Millisecond
maxDistance = 15
hoverTimeout = 800 * time.Millisecond
maxAttempts = 8
minMenuOpenWait = 300 * time.Millisecond
maxDistance = 15
hoverWait = 800 * time.Millisecond
)

var lastInteractionTime time.Time
var targetNPCID data.UnitID

for attempts := 0; attempts < maxAttempts; attempts++ {
// Pause the execution if the priority is not the same as the execution priority
ctx.PauseIfNotPriority()

// Clear last interaction if we've waited too long
if !lastInteractionTime.IsZero() && time.Since(lastInteractionTime) > interactionTimeout {
lastInteractionTime = time.Time{}
targetNPCID = 0
}

// Check if interaction succeeded and menu is open
// If menu is already open and distance is good, we're done
if ctx.Data.OpenMenus.NPCInteract || ctx.Data.OpenMenus.NPCShop {
// Find current NPC position
if targetNPCID != 0 {
if currentNPC, found := ctx.Data.Monsters.FindByID(targetNPCID); found {
currentDistance := pather.DistanceFromPoint(currentNPC.Position, ctx.Data.PlayerUnit.Position)
if currentDistance <= maxDistance {
// Success - wait minimum time for menu to fully open
time.Sleep(minMenuOpenWait)
return nil
}
}
}

// Wrong NPC, too far, or NPC moved away - close menu and retry
CloseAllMenus()
time.Sleep(200 * time.Millisecond)
targetNPCID = 0
continue
}

// Don't attempt new interaction if we're waiting for previous one
if !lastInteractionTime.IsZero() && time.Since(lastInteractionTime) < minMenuOpenWait {
time.Sleep(50 * time.Millisecond)
continue
time.Sleep(minMenuOpenWait)
return nil
}

// Find and validate target NPC
townNPC, found := ctx.Data.Monsters.FindOne(npcID, data.MonsterTypeNone)
if !found {
if attempts == maxAttempts-1 {
Expand All @@ -79,54 +46,25 @@ func InteractNPC(npcID npc.ID) error {
return fmt.Errorf("NPC %d is too far away (distance: %d)", npcID, distance)
}

// Calculate screen coordinates based on current NPC position
// Calculate click position
x, y := ui.GameCoordsToScreenCords(townNPC.Position.X, townNPC.Position.Y)
// Special case for Tyrael's hitbox
if npcID == npc.ID(240) {
y = y - 40
if npcID == npc.Tyrael2 {
y = y - 40 // Act 4 Tyrael has a super weird hitbox
}

// Move mouse and wait for hover
ctx.HID.MovePointer(x, y)
hoverStart := time.Now()

// Wait for hover before clicking
hoverWaitStart := time.Now()
hoverFound := false
var hoveredNPC data.Monster

for time.Since(hoverWaitStart) < hoverTimeout {
// Get fresh NPC position in case they moved
if currentNPC, found := ctx.Data.Monsters.FindOne(npcID, data.MonsterTypeNone); found {
if currentNPC.IsHovered {
hoveredNPC = currentNPC
hoverFound = true
break
}

// Update mouse position if NPC moved
newX, newY := ui.GameCoordsToScreenCords(currentNPC.Position.X, currentNPC.Position.Y)
if newX != x || newY != y {
if npcID == npc.ID(240) {
newY = newY - 40
}
ctx.HID.MovePointer(newX, newY)
x, y = newX, newY
}
for time.Since(hoverStart) < hoverWait {
if currentNPC, found := ctx.Data.Monsters.FindOne(npcID, data.MonsterTypeNone); found && currentNPC.IsHovered {
ctx.HID.Click(game.LeftButton, x, y)
time.Sleep(minMenuOpenWait)
break
}
time.Sleep(50 * time.Millisecond)
}

if !hoverFound {
continue
}

// Store the NPC ID we're interacting with
targetNPCID = hoveredNPC.UnitID
ctx.HID.Click(game.LeftButton, x, y)
lastInteractionTime = time.Now()

// Wait a bit for the menu to open
time.Sleep(minMenuOpenWait)
}

return errors.New("failed to interact with NPC after all attempts")
return fmt.Errorf("failed to interact with NPC after %d attempts", maxAttempts)
}

0 comments on commit 4b79591

Please sign in to comment.