package memory import ( "github.com/hectorgimenez/d2go/pkg/data" "github.com/hectorgimenez/d2go/pkg/data/item" "github.com/hectorgimenez/d2go/pkg/data/stat" "github.com/hectorgimenez/d2go/pkg/utils" "sort" ) func (gd *GameReader) Items(playerPosition data.Position) data.Items { hoveredUnitID, hoveredType, isHovered := gd.hoveredData() baseAddr := gd.Process.moduleBaseAddressPtr + gd.offset.UnitTable + (4 * 1024) unitTableBuffer := gd.Process.ReadBytesFromMemory(baseAddr, 128*8) items := data.Items{} for i := 0; i < 128; i++ { itemOffset := 8 * i itemUnitPtr := uintptr(ReadUIntFromBuffer(unitTableBuffer, uint(itemOffset), Uint64)) for itemUnitPtr > 0 { itemDataBuffer := gd.Process.ReadBytesFromMemory(itemUnitPtr, 144) itemType := ReadUIntFromBuffer(itemDataBuffer, 0x00, Uint32) txtFileNo := ReadUIntFromBuffer(itemDataBuffer, 0x04, Uint32) unitID := ReadUIntFromBuffer(itemDataBuffer, 0x08, Uint32) // itemLoc = 0 in inventory, 1 equipped, 2 in belt, 3 on ground, 4 cursor, 5 dropping, 6 socketed itemLoc := ReadUIntFromBuffer(itemDataBuffer, 0x0C, Uint32) if itemType != 4 { itemUnitPtr = uintptr(gd.Process.ReadUInt(itemUnitPtr+0x150, Uint64)) continue } unitDataPtr := uintptr(ReadUIntFromBuffer(itemDataBuffer, 0x10, Uint64)) unitDataBuffer := gd.Process.ReadBytesFromMemory(unitDataPtr, 144) flags := ReadUIntFromBuffer(unitDataBuffer, 0x18, Uint32) invPage := ReadUIntFromBuffer(unitDataBuffer, 0x55, Uint8) itemQuality := ReadUIntFromBuffer(unitDataBuffer, 0x00, Uint32) //itemOwnerNPC := ReadUIntFromBuffer(unitDataBuffer, 0x0C, Uint32) // Item coordinates (X, Y) pathPtr := uintptr(ReadUIntFromBuffer(itemDataBuffer, 0x38, Uint64)) pathBuffer := gd.Process.ReadBytesFromMemory(pathPtr, 144) itemX := ReadUIntFromBuffer(pathBuffer, 0x10, Uint16) itemY := ReadUIntFromBuffer(pathBuffer, 0x14, Uint16) // Item Stats statsListExPtr := uintptr(ReadUIntFromBuffer(itemDataBuffer, 0x88, Uint64)) statsListExBuffer := gd.Process.ReadBytesFromMemory(statsListExPtr, 180) statPtr := uintptr(ReadUIntFromBuffer(statsListExBuffer, 0x30, Uint64)) statCount := ReadUIntFromBuffer(statsListExBuffer, 0x38, Uint32) statExPtr := uintptr(ReadUIntFromBuffer(statsListExBuffer, 0x88, Uint64)) statExCount := ReadUIntFromBuffer(statsListExBuffer, 0x90, Uint32) stats := gd.getItemStats(statCount, statPtr, statExCount, statExPtr) name := item.GetNameByEnum(txtFileNo) itemHovered := false if isHovered && hoveredType == 4 && hoveredUnitID == unitID { itemHovered = true } itm := data.Item{ UnitID: data.UnitID(unitID), Name: name, Quality: item.Quality(itemQuality), Position: data.Position{ X: int(itemX), Y: int(itemY), }, IsHovered: itemHovered, Stats: stats, } setProperties(&itm, uint32(flags)) switch itemLoc { case 0: if itm.IsVendor { items.Shop = append(items.Shop, itm) } else if invPage == 0 { items.Inventory = append(items.Inventory, itm) } case 1: items.Equipped = append(items.Equipped, itm) case 2: items.Belt = append(items.Belt, itm) case 3, 5: items.Ground = append(items.Ground, itm) } itemUnitPtr = uintptr(gd.Process.ReadUInt(itemUnitPtr+0x150, Uint64)) } } sort.SliceStable(items.Ground, func(i, j int) bool { distanceI := utils.DistanceFromPoint(playerPosition, items.Ground[i].Position) distanceJ := utils.DistanceFromPoint(playerPosition, items.Ground[j].Position) return distanceI < distanceJ }) return items } func (gd *GameReader) getItemStats(statCount uint, statPtr uintptr, statExCount uint, statExPtr uintptr) map[stat.Stat]int { stats := map[stat.Stat]int{} if statCount < 20 && statCount > 0 { statBuffer := gd.Process.ReadBytesFromMemory(statPtr, statCount*10) for i := 0; i < int(statCount); i++ { offset := uint(i * 8) statEnum := ReadUIntFromBuffer(statBuffer, offset+0x2, Uint16) statValue := ReadUIntFromBuffer(statBuffer, offset+0x4, Uint32) st, value := getStatData(statEnum, statValue) stats[st] = value } } if statExCount < 20 && statExCount > 0 { statBuffer := gd.Process.ReadBytesFromMemory(statExPtr, statExCount*10) for i := 0; i < int(statExCount); i++ { offset := uint(i * 8) statEnum := ReadUIntFromBuffer(statBuffer, offset+0x2, Uint16) statValue := ReadUIntFromBuffer(statBuffer, offset+0x4, Uint32) st, value := getStatData(statEnum, statValue) stats[st] = value } } return stats }