Add some memory reading stuff, based on many other open source projects
This commit is contained in:
201
pkg/memory/monsters.go
Normal file
201
pkg/memory/monsters.go
Normal file
@@ -0,0 +1,201 @@
|
||||
package memory
|
||||
|
||||
import (
|
||||
"github.com/hectorgimenez/d2go/pkg/data"
|
||||
"github.com/hectorgimenez/d2go/pkg/data/npc"
|
||||
"github.com/hectorgimenez/d2go/pkg/data/stat"
|
||||
"github.com/hectorgimenez/d2go/pkg/utils"
|
||||
"sort"
|
||||
)
|
||||
|
||||
func (gd *GameReader) Monsters(playerPosition data.Position) data.Monsters {
|
||||
hoveredUnitID, hoveredType, isHovered := gd.hoveredData()
|
||||
|
||||
baseAddr := gd.Process.moduleBaseAddressPtr + gd.offset.UnitTable + 1024
|
||||
unitTableBuffer := gd.Process.ReadBytesFromMemory(baseAddr, 128*8)
|
||||
|
||||
monsters := data.Monsters{}
|
||||
for i := 0; i < 128; i++ {
|
||||
monsterOffset := 8 * i
|
||||
monsterUnitPtr := uintptr(ReadUIntFromBuffer(unitTableBuffer, uint(monsterOffset), Uint64))
|
||||
for monsterUnitPtr > 0 {
|
||||
monsterDataBuffer := gd.Process.ReadBytesFromMemory(monsterUnitPtr, 144)
|
||||
|
||||
//monsterType := ReadUIntFromBuffer(monsterDataBuffer, 0x00, Uint32)
|
||||
txtFileNo := ReadUIntFromBuffer(monsterDataBuffer, 0x04, Uint32)
|
||||
if !gd.shouldBeIgnored(txtFileNo) {
|
||||
unitID := ReadUIntFromBuffer(monsterDataBuffer, 0x08, Uint32)
|
||||
|
||||
//mode := ReadUIntFromBuffer(monsterDataBuffer, 0x0C, Uint32)
|
||||
|
||||
unitDataPtr := uintptr(ReadUIntFromBuffer(monsterDataBuffer, 0x10, Uint64))
|
||||
//isUnique := gd.Process.ReadUInt(unitDataPtr+0x18, Uint16)
|
||||
flag := gd.Process.ReadBytesFromMemory(unitDataPtr+0x1A, Uint8)[0]
|
||||
isCorpse := gd.Process.ReadUInt(monsterUnitPtr+0x1A6, Uint8)
|
||||
|
||||
//unitDataBuffer := gd.Process.ReadBytesFromMemory(unitDataPtr, 144)
|
||||
|
||||
// Coordinates (X, Y)
|
||||
pathPtr := uintptr(gd.Process.ReadUInt(monsterUnitPtr+0x38, Uint64))
|
||||
posX := gd.Process.ReadUInt(pathPtr+0x02, Uint16)
|
||||
posY := gd.Process.ReadUInt(pathPtr+0x06, Uint16)
|
||||
|
||||
hovered := false
|
||||
if isHovered && hoveredType == 1 && hoveredUnitID == unitID {
|
||||
hovered = true
|
||||
}
|
||||
|
||||
statsListExPtr := uintptr(ReadUIntFromBuffer(monsterDataBuffer, 0x88, Uint64))
|
||||
statPtr := uintptr(gd.Process.ReadUInt(statsListExPtr+0x30, Uint64))
|
||||
statCount := gd.Process.ReadUInt(statsListExPtr+0x38, Uint64)
|
||||
|
||||
stats := gd.getMonsterStats(statCount, statPtr)
|
||||
|
||||
m := data.Monster{
|
||||
UnitID: data.UnitID(unitID),
|
||||
Name: npc.ID(int(txtFileNo)),
|
||||
IsHovered: hovered,
|
||||
Position: data.Position{
|
||||
X: int(posX),
|
||||
Y: int(posY),
|
||||
},
|
||||
Stats: stats,
|
||||
Type: getMonsterType(flag),
|
||||
}
|
||||
|
||||
if isCorpse == 0 {
|
||||
monsters = append(monsters, m)
|
||||
}
|
||||
}
|
||||
|
||||
monsterUnitPtr = uintptr(gd.Process.ReadUInt(monsterUnitPtr+0x150, Uint64))
|
||||
}
|
||||
}
|
||||
|
||||
sort.SliceStable(monsters, func(i, j int) bool {
|
||||
distanceI := utils.DistanceFromPoint(playerPosition, monsters[i].Position)
|
||||
distanceJ := utils.DistanceFromPoint(playerPosition, monsters[j].Position)
|
||||
|
||||
return distanceI < distanceJ
|
||||
})
|
||||
|
||||
return monsters
|
||||
}
|
||||
|
||||
func getMonsterType(typeFlag byte) data.MonsterType {
|
||||
switch typeFlag {
|
||||
case 10:
|
||||
return data.MonsterTypeSuperUnique
|
||||
case 1 << 2:
|
||||
return data.MonsterTypeChampion
|
||||
case 1 << 3:
|
||||
return data.MonsterTypeUnique
|
||||
case 1 << 4:
|
||||
return data.MonsterTypeMinion
|
||||
}
|
||||
|
||||
return data.MonsterTypeNone
|
||||
}
|
||||
|
||||
func (gd *GameReader) getMonsterStats(statCount uint, statPtr uintptr) map[stat.Stat]int {
|
||||
stats := map[stat.Stat]int{}
|
||||
|
||||
if statCount > 0 {
|
||||
statBuffer := gd.Process.ReadBytesFromMemory(statPtr+0x2, statCount*8)
|
||||
for i := 0; i < int(statCount); i++ {
|
||||
offset := uint(i * 8)
|
||||
statEnum := ReadUIntFromBuffer(statBuffer, offset, Uint16)
|
||||
statValue := ReadUIntFromBuffer(statBuffer, offset+0x2, Uint32)
|
||||
stats[stat.Stat(statEnum)] = int(statValue)
|
||||
}
|
||||
}
|
||||
|
||||
return stats
|
||||
}
|
||||
|
||||
func (gd *GameReader) shouldBeIgnored(txtNo uint) bool {
|
||||
switch npc.ID(txtNo) {
|
||||
case npc.Chicken,
|
||||
npc.Rat,
|
||||
npc.Rogue,
|
||||
npc.HellMeteor,
|
||||
npc.Bird,
|
||||
npc.Bird2,
|
||||
npc.Bat,
|
||||
npc.Act2Male,
|
||||
npc.Act2Female,
|
||||
npc.Act2Child,
|
||||
npc.Cow,
|
||||
npc.Camel,
|
||||
npc.Act2Guard,
|
||||
npc.Act2Vendor,
|
||||
npc.Act2Vendor2,
|
||||
npc.Maggot,
|
||||
npc.Bug,
|
||||
npc.Scorpion,
|
||||
npc.Rogue2,
|
||||
npc.Rogue3,
|
||||
npc.Larva,
|
||||
npc.Familiar,
|
||||
npc.Act3Male,
|
||||
npc.ClayGolem,
|
||||
npc.BloodGolem,
|
||||
npc.IronGolem,
|
||||
npc.FireGolem,
|
||||
npc.Act3Female,
|
||||
npc.Snake,
|
||||
npc.Parrot,
|
||||
npc.Fish,
|
||||
npc.EvilHole,
|
||||
npc.EvilHole2,
|
||||
npc.EvilHole3,
|
||||
npc.EvilHole4,
|
||||
npc.EvilHole5,
|
||||
npc.FireboltTrap,
|
||||
npc.HorzMissileTrap,
|
||||
npc.VertMissileTrap,
|
||||
npc.PoisonCloudTrap,
|
||||
npc.LightningTrap,
|
||||
npc.InvisoSpawner,
|
||||
//338, //Guard
|
||||
npc.MiniSper,
|
||||
npc.BoneWall,
|
||||
npc.Hydra,
|
||||
npc.Hydra2,
|
||||
npc.Hydra3,
|
||||
npc.SevenTombs,
|
||||
npc.Valkyrie,
|
||||
npc.IronWolf,
|
||||
npc.NecroSkeleton,
|
||||
npc.NecroMage,
|
||||
npc.CompellingOrbNpc,
|
||||
npc.SpiritMummy,
|
||||
npc.Act2Guard4,
|
||||
npc.Act2Guard5,
|
||||
npc.Window,
|
||||
npc.Window2,
|
||||
npc.MephistoSpirit,
|
||||
npc.WakeOfDestruction,
|
||||
npc.ChargedBoltSentry,
|
||||
npc.LightningSentry,
|
||||
npc.InvisiblePet,
|
||||
npc.InfernoSentry,
|
||||
npc.DeathSentry,
|
||||
npc.ShadowWarrior,
|
||||
npc.ShadowMaster,
|
||||
npc.DruHawk,
|
||||
npc.DruSpiritWolf,
|
||||
npc.DruFenris,
|
||||
npc.HeartOfWolverine,
|
||||
npc.OakSage,
|
||||
npc.DruBear,
|
||||
npc.BaalThrone,
|
||||
npc.InjuredBarbarian,
|
||||
npc.InjuredBarbarian2,
|
||||
npc.InjuredBarbarian3,
|
||||
npc.DemonHole:
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user