diff --git a/cmd/itemwatcher/internal/watcher.go b/cmd/itemwatcher/internal/watcher.go index 5a073e8..b6eef35 100644 --- a/cmd/itemwatcher/internal/watcher.go +++ b/cmd/itemwatcher/internal/watcher.go @@ -53,7 +53,7 @@ func (w *Watcher) Start(ctx context.Context) error { time.Sleep(100 * time.Millisecond) d := w.gr.GetData() - for _, i := range d.Items.ByLocation(item.LocationGround) { + for _, i := range d.Inventory.ByLocation(item.LocationGround) { for _, r := range w.rules { res, err := r.Evaluate(i) if err != nil { @@ -92,7 +92,7 @@ func (w *Watcher) Start(ctx context.Context) error { purgedNotifiedItems := make([]itemFootprint, 0) for _, t := range w.alreadyNotifiedItemIDs { found := false - for _, it := range d.Items.ByLocation(item.LocationGround) { + for _, it := range d.Inventory.ByLocation(item.LocationGround) { if t.Match(d.PlayerUnit.Area, it) { found = true } diff --git a/pkg/data/data.go b/pkg/data/data.go index 924ab57..ab8fb46 100644 --- a/pkg/data/data.go +++ b/pkg/data/data.go @@ -31,7 +31,7 @@ type Data struct { CollisionGrid [][]bool PlayerUnit PlayerUnit NPCs NPCs - Items Items + Inventory Inventory Objects Objects AdjacentLevels []Level Rooms []Room @@ -163,8 +163,8 @@ func (pu PlayerUnit) MaxGold() int { return goldPerLevel * lvl.Value } -// TotalGold returns the amount of gold, including inventory and stash -func (pu PlayerUnit) TotalGold() int { +// TotalPlayerGold returns the amount of gold, including inventory and player stash (excluding shared stash) +func (pu PlayerUnit) TotalPlayerGold() int { gold, _ := pu.FindStat(stat.Gold, 0) stashGold, _ := pu.FindStat(stat.StashGold, 0) diff --git a/pkg/data/items.go b/pkg/data/items.go index 412c859..3d54816 100644 --- a/pkg/data/items.go +++ b/pkg/data/items.go @@ -7,12 +7,14 @@ import ( "github.com/hectorgimenez/d2go/pkg/data/stat" ) -type Items struct { - Belt Belt - AllItems []Item +type Inventory struct { + Belt Belt + AllItems []Item + Gold int + StashedGold [4]int } -func (i Items) Find(name item.Name, locations ...item.Location) (Item, bool) { +func (i Inventory) Find(name item.Name, locations ...item.Location) (Item, bool) { for _, it := range i.AllItems { if strings.EqualFold(string(it.Name), string(name)) { // If no locations are specified, return the first item found @@ -31,7 +33,7 @@ func (i Items) Find(name item.Name, locations ...item.Location) (Item, bool) { return Item{}, false } -func (i Items) ByLocation(locations ...item.Location) []Item { +func (i Inventory) ByLocation(locations ...item.Location) []Item { var items []Item for _, it := range i.AllItems { @@ -75,19 +77,19 @@ func (i Item) IsPotion() bool { } func (i Item) IsHealingPotion() bool { - return strings.Contains(string(i.Name), string(HealingPotion)) + return i.Type().IsType(item.TypeHealingPotion) } func (i Item) IsManaPotion() bool { - return strings.Contains(string(i.Name), string(ManaPotion)) + return i.Type().IsType(item.TypeManaPotion) } func (i Item) IsRejuvPotion() bool { - return strings.Contains(string(i.Name), string(RejuvenationPotion)) + return i.Type().IsType(item.TypeRejuvPotion) } func (i Item) IsFromQuest() bool { - return i.Desc().Type == item.TypeQuest + return i.Type().IsType(item.TypeQuest) } func (i Item) FindStat(id stat.ID, layer int) (stat.Data, bool) { diff --git a/pkg/memory/game_reader.go b/pkg/memory/game_reader.go index c3f4271..2659531 100644 --- a/pkg/memory/game_reader.go +++ b/pkg/memory/game_reader.go @@ -49,7 +49,7 @@ func (gd *GameReader) GetData() data.Data { }, Monsters: gd.Monsters(pu.Position, hover), PlayerUnit: pu, - Items: gd.Items(rawPlayerUnits, hover), + Inventory: gd.Inventory(rawPlayerUnits, hover), Objects: gd.Objects(pu.Position, hover), OpenMenus: gd.openMenus(), Roster: roster, diff --git a/pkg/memory/item.go b/pkg/memory/item.go index 2b82c78..39e570f 100644 --- a/pkg/memory/item.go +++ b/pkg/memory/item.go @@ -11,7 +11,7 @@ import ( "github.com/hectorgimenez/d2go/pkg/utils" ) -func (gd *GameReader) Items(rawPlayerUnits RawPlayerUnits, hover data.HoverData) data.Items { +func (gd *GameReader) Inventory(rawPlayerUnits RawPlayerUnits, hover data.HoverData) data.Inventory { mainPlayer := rawPlayerUnits.GetMainPlayer() baseAddr := gd.Process.moduleBaseAddressPtr + gd.offset.UnitTable + (4 * 1024) unitTableBuffer := gd.Process.ReadBytesFromMemory(baseAddr, 128*8) @@ -27,7 +27,20 @@ func (gd *GameReader) Items(rawPlayerUnits RawPlayerUnits, hover data.HoverData) } slices.Sort(stashPlayerUnitOrder) - items := data.Items{} + // Gold + inventoryGold, _ := mainPlayer.BaseStats.FindStat(stat.Gold, 0) + mainPlayerStashedGold, _ := mainPlayer.BaseStats.FindStat(stat.StashGold, 0) + stashedGold := [4]int{} + stashedGold[0] = mainPlayerStashedGold.Value + for i, puKey := range stashPlayerUnitOrder { + stashGold, _ := stashPlayerUnits[puKey].BaseStats.FindStat(stat.StashGold, 0) + stashedGold[i+1] = stashGold.Value + } + + inventory := data.Inventory{ + Gold: inventoryGold.Value, + StashedGold: stashedGold, + } belt := data.Belt{} for i := 0; i < 128; i++ { itemOffset := 8 * i @@ -122,7 +135,7 @@ func (gd *GameReader) Items(rawPlayerUnits RawPlayerUnits, hover data.HoverData) itm.Location = location - // We don't care about the items we don't know where they are, probably previous games or random crap + // We don't care about the inventory we don't know where they are, probably previous games or random crap if location != item.LocationUnknown { // Item Stats statsListExPtr := uintptr(ReadUIntFromBuffer(itemDataBuffer, 0x88, Uint64)) @@ -133,7 +146,7 @@ func (gd *GameReader) Items(rawPlayerUnits RawPlayerUnits, hover data.HoverData) if location == item.LocationBelt { belt.Items = append(belt.Items, itm) } else { - items.AllItems = append(items.AllItems, itm) + inventory.AllItems = append(inventory.AllItems, itm) } } @@ -141,16 +154,16 @@ func (gd *GameReader) Items(rawPlayerUnits RawPlayerUnits, hover data.HoverData) } } - items.Belt = belt + inventory.Belt = belt - sort.SliceStable(items.AllItems, func(i, j int) bool { - distanceI := utils.DistanceFromPoint(mainPlayer.Position, items.AllItems[i].Position) - distanceJ := utils.DistanceFromPoint(mainPlayer.Position, items.AllItems[j].Position) + sort.SliceStable(inventory.AllItems, func(i, j int) bool { + distanceI := utils.DistanceFromPoint(mainPlayer.Position, inventory.AllItems[i].Position) + distanceJ := utils.DistanceFromPoint(mainPlayer.Position, inventory.AllItems[j].Position) return distanceI < distanceJ }) - return items + return inventory } func (gd *GameReader) getItemStats(statsListExPtr uintptr) (stat.Stats, stat.Stats) { diff --git a/pkg/memory/player.go b/pkg/memory/player.go index 54e2e25..1c652e8 100644 --- a/pkg/memory/player.go +++ b/pkg/memory/player.go @@ -43,6 +43,8 @@ func (gd *GameReader) GetRawPlayerUnits() RawPlayerUnits { isCorpse := gd.Process.ReadUInt(playerUnit+0x1A6, Uint8) statsListExPtr := uintptr(gd.Process.ReadUInt(playerUnit+0x88, Uint64)) + baseStats := gd.getStatsList(statsListExPtr + 0x30) + stats := gd.getStatsList(statsListExPtr + 0x88) states := gd.getStates(statsListExPtr) rawPlayerUnits = append(rawPlayerUnits, RawPlayerUnit{ @@ -58,6 +60,8 @@ func (gd *GameReader) GetRawPlayerUnits() RawPlayerUnits { }, IsHovered: hover.IsHovered && hover.UnitID == data.UnitID(unitID) && hover.UnitType == 0, States: states, + Stats: stats, + BaseStats: baseStats, }) playerUnit = uintptr(gd.Process.ReadUInt(playerUnit+0x150, Uint64)) } @@ -67,11 +71,6 @@ func (gd *GameReader) GetRawPlayerUnits() RawPlayerUnits { } func (gd *GameReader) GetPlayerUnit(mainPlayerUnit RawPlayerUnit) data.PlayerUnit { - // Get Stats - statsListExPtr := uintptr(gd.Process.ReadUInt(mainPlayerUnit.Address+0x88, Uint64)) - baseStats := gd.getStatsList(statsListExPtr + 0x30) - stats := gd.getStatsList(statsListExPtr + 0x88) - // Skills skillListPtr := uintptr(gd.Process.ReadUInt(mainPlayerUnit.Address+0x100, Uint64)) skills := gd.getSkills(skillListPtr) @@ -104,8 +103,8 @@ func (gd *GameReader) GetPlayerUnit(mainPlayerUnit RawPlayerUnit) data.PlayerUni ID: mainPlayerUnit.UnitID, Area: mainPlayerUnit.Area, Position: mainPlayerUnit.Position, - Stats: stats, - BaseStats: baseStats, + Stats: mainPlayerUnit.Stats, + BaseStats: mainPlayerUnit.BaseStats, Skills: skills, States: mainPlayerUnit.States, Class: class, diff --git a/pkg/memory/player_unit.go b/pkg/memory/player_unit.go index f1e0607..1c2b9f4 100644 --- a/pkg/memory/player_unit.go +++ b/pkg/memory/player_unit.go @@ -3,6 +3,7 @@ package memory import ( "github.com/hectorgimenez/d2go/pkg/data" "github.com/hectorgimenez/d2go/pkg/data/area" + "github.com/hectorgimenez/d2go/pkg/data/stat" "github.com/hectorgimenez/d2go/pkg/data/state" ) @@ -16,6 +17,8 @@ type RawPlayerUnit struct { Position data.Position IsHovered bool States state.States + Stats stat.Stats + BaseStats stat.Stats } type RawPlayerUnits []RawPlayerUnit