Skip to content

Commit

Permalink
Merge branch 'hectorgimenez:main' into Mephisto-Chests-No-Council
Browse files Browse the repository at this point in the history
  • Loading branch information
braccali1 authored Feb 7, 2025
2 parents ad4f973 + 0d0efd6 commit 6105e32
Show file tree
Hide file tree
Showing 17 changed files with 600 additions and 86 deletions.
1 change: 1 addition & 0 deletions config/template/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,4 @@ backtotown:
noHpPotions: true
noMpPotions: false
mercDied: true
noKeys: false
7 changes: 4 additions & 3 deletions internal/action/clear_area.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,15 @@ func ClearThroughPath(pos data.Position, radius int, filter data.MonsterFilter)
Y: path[movementDistance-1].Y + ctx.Data.AreaData.OffsetY,
}

// Let's handle the last movement logic to MoveToCoords function, we will trust the pathfinder because
// Let's handle the last movement logic to MoveTo function, we will trust the pathfinder because
// it can finish within a bigger distance than we expect (because blockers), so we will just check how far
// we should be after the latest movement in a theoretical way
if len(path)-movementDistance <= step.DistanceToFinishMoving {
lastMovement = true
}

err := MoveToCoords(dest)
// Increasing DistanceToFinishMoving prevent not being to able to finish movement if our destination is center of a large object like Seal in diablo run.
// is used only for pathing, attack.go will use default DistanceToFinishMoving
err := step.MoveTo(dest, step.WithDistanceToFinish(7))
if err != nil {
return err
}
Expand Down
23 changes: 16 additions & 7 deletions internal/action/interaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package action

import (
"fmt"
"strings"

"github.com/hectorgimenez/d2go/pkg/data"
"github.com/hectorgimenez/d2go/pkg/data/area"
Expand All @@ -12,13 +13,18 @@ import (
"github.com/hectorgimenez/koolo/internal/game"
)

func InteractNPC(npc npc.ID) error {
func InteractNPC(NPC npc.ID) error {
ctx := context.Get()
ctx.SetLastAction("InteractNPC")

pos, found := getNPCPosition(npc, ctx.Data)
pos, found := getNPCPosition(NPC, ctx.Data)
if !found {
return fmt.Errorf("npc with ID %d not found", npc)

if NPC == npc.Hratli {
pos = data.Position{X: 5224, Y: 5039}
} else {
return fmt.Errorf("npc with ID %d not found", NPC)
}
}

var err error
Expand All @@ -28,7 +34,7 @@ func InteractNPC(npc npc.ID) error {
continue
}

err = step.InteractNPC(npc)
err = step.InteractNPC(NPC)
if err != nil {
continue
}
Expand All @@ -38,7 +44,7 @@ func InteractNPC(npc npc.ID) error {
return err
}

event.Send(event.InteractedTo(event.Text(ctx.Name, ""), int(npc), event.InteractionTypeNPC))
event.Send(event.InteractedTo(event.Text(ctx.Name, ""), int(NPC), event.InteractionTypeNPC))

return nil
}
Expand All @@ -48,17 +54,20 @@ func InteractObject(o data.Object, isCompletedFn func() bool) error {
ctx.SetLastAction("InteractObject")

pos := o.Position
distFinish := step.DistanceToFinishMoving
if ctx.Data.PlayerUnit.Area == area.RiverOfFlame && o.IsWaypoint() {
pos = data.Position{X: 7800, Y: 5919}
// Special case for seals: we cant teleport directly to center. Interaction range is bigger then DistanceToFinishMoving so we modify it
} else if strings.Contains(o.Desc().Name, "Seal") {
distFinish = 10
}

var err error
for range 5 {
err = step.MoveTo(pos)
err = step.MoveTo(pos, step.WithDistanceToFinish(distFinish))
if err != nil {
continue
}

err = step.InteractObject(o, isCompletedFn)
if err != nil {
continue
Expand Down
24 changes: 24 additions & 0 deletions internal/action/item_pickup.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,30 @@ func shouldBePickedUp(i data.Item) bool {
return true
}

// Check if we should pick up some keys. The goal is to have 12 keys in total (single stack)
if i.Name == "Key" {
quantityOnGround := 0
st, statFound := i.FindStat(stat.Quantity, 0)
if statFound {
quantityOnGround = st.Value
}

quantityInInventory := 0
for _, item := range ctx.Data.Inventory.AllItems {
if item.Name == "Key" {
qty, _ := item.FindStat(stat.Quantity, 0)
quantityInInventory += qty.Value
}
}

// We only want to pick them up if either:
// 1. They have the option to return to town enabled or
// 2. They already had some keys in inventory, so we just want to get closer to 12
if (ctx.CharacterCfg.BackToTown.NoKeys || quantityInInventory > 0) && quantityOnGround+quantityInInventory <= 12 {
return true
}
}

// Pick up quest items if we're in leveling or questing run
specialRuns := slices.Contains(ctx.CharacterCfg.Game.Runs, "quests") || slices.Contains(ctx.CharacterCfg.Game.Runs, "leveling")
if specialRuns {
Expand Down
30 changes: 21 additions & 9 deletions internal/action/step/attack.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package step
import (
"errors"
"fmt"
"sync"
"time"

"github.com/hectorgimenez/d2go/pkg/data"
Expand All @@ -16,6 +17,11 @@ import (

const attackCycleDuration = 120 * time.Millisecond

var (
statesMutex sync.RWMutex
monsterStates = make(map[data.UnitID]*attackState)
)

// Contains all configuration for an attack sequence
type attackSettings struct {
primaryAttack bool // Whether this is a primary (left click) attack
Expand All @@ -41,8 +47,6 @@ type attackState struct {
position data.Position
}

var monsterAttackStates = make(map[data.UnitID]*attackState)

// Distance configures attack to follow enemy within specified range
func Distance(minimum, maximum int) AttackOption {
return func(step *attackSettings) {
Expand Down Expand Up @@ -296,7 +300,7 @@ func ensureEnemyIsInRange(monster data.Monster, maxDistance, minDistance int, ne
hasLoS := ctx.PathFinder.LineOfSight(currentPos, monster.Position)

// We have line of sight, and we are inside the attack range, we can skip
if hasLoS && distanceToMonster <= maxDistance && distanceToMonster >= minDistance && !needsRepositioning {
if hasLoS && distanceToMonster <= maxDistance && !needsRepositioning {
return nil
}
// Handle repositioning if needed
Expand Down Expand Up @@ -349,14 +353,17 @@ func ensureEnemyIsInRange(monster data.Monster, maxDistance, minDistance int, ne
}

func checkMonsterDamage(monster data.Monster) (bool, *attackState) {
state, exists := monsterAttackStates[monster.UnitID]
statesMutex.Lock()
defer statesMutex.Unlock()

state, exists := monsterStates[monster.UnitID]
if !exists {
state = &attackState{
lastHealth: monster.Stats[stat.Life],
lastHealthCheckTime: time.Now(),
position: monster.Position,
}
monsterAttackStates[monster.UnitID] = state
monsterStates[monster.UnitID] = state
}

didDamage := false
Expand All @@ -375,11 +382,16 @@ func checkMonsterDamage(monster data.Monster) (bool, *attackState) {
state.lastHealth = currentHealth
state.lastHealthCheckTime = time.Now()
state.position = monster.Position
}

// Clean up state map occasionally
if len(monsterAttackStates) > 100 {
monsterAttackStates = make(map[data.UnitID]*attackState)
// Clean up old entries periodically
if len(monsterStates) > 100 {
now := time.Now()
for id, s := range monsterStates {
if now.Sub(s.lastHealthCheckTime) > 5*time.Minute {
delete(monsterStates, id)
}
}
}
}

return didDamage, state
Expand Down
15 changes: 11 additions & 4 deletions internal/action/town.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/hectorgimenez/d2go/pkg/data/skill"
"github.com/hectorgimenez/koolo/internal/action/step"
"github.com/hectorgimenez/koolo/internal/context"
"github.com/hectorgimenez/koolo/internal/utils"
)

func PreRun(firstRun bool) error {
Expand All @@ -26,14 +27,14 @@ func PreRun(firstRun bool) error {

// Store items that need to be left unidentified
if HaveItemsToStashUnidentified() {
Stash(firstRun)
Stash(false)
}

// Identify - either via Cain or Tome
IdentifyAll(firstRun)
IdentifyAll(false)

// Stash before vendor
Stash(firstRun)
Stash(false)

// Refill pots, sell, buy etc
VendorRefill(false, true)
Expand Down Expand Up @@ -106,6 +107,12 @@ func InRunReturnTownRoutine() error {
ReviveMerc()
HireMerc()
Repair()


if (ctx.CharacterCfg.Companion.Leader) {
UsePortalInTown()
utils.Sleep(500)
return OpenTPIfLeader()
}

return UsePortalInTown()
}
Loading

0 comments on commit 6105e32

Please sign in to comment.