Merge pull request #27 from BjarkeM/improve-available-waypoints
Refactor availableWPs to give a full list of waypoints
This commit is contained in:
@@ -13,7 +13,7 @@ type Offset struct {
|
||||
RosterOffset uintptr
|
||||
PanelManagerContainerOffset uintptr
|
||||
WidgetStatesOffset uintptr
|
||||
WaypointsOffset uintptr
|
||||
WaypointTableOffset uintptr
|
||||
FPS uintptr
|
||||
KeyBindingsOffset uintptr
|
||||
KeyBindingsSkillsOffset uintptr
|
||||
@@ -72,7 +72,7 @@ func calculateOffsets(process *Process) Offset {
|
||||
// Waypoints
|
||||
pattern = process.FindPattern(memory, "\x48\x89\x05\x00\x00\x00\x00\x0F\x11\x00", "xxx????xxx")
|
||||
offsetBuffer := process.ReadUInt(pattern+3, Uint32)
|
||||
WaypointsOffset := pattern - process.moduleBaseAddressPtr + 23 + uintptr(offsetBuffer)
|
||||
WaypointTableOffset := pattern - process.moduleBaseAddressPtr + 7 + uintptr(offsetBuffer)
|
||||
|
||||
// FPS
|
||||
pattern = process.FindPattern(memory, "\x8B\x1D\x00\x00\x00\x00\x48\x8D\x05\x00\x00\x00\x00\x48\x8D\x4C\x24\x40", "xx????xxx????xxxxx")
|
||||
@@ -134,7 +134,7 @@ func calculateOffsets(process *Process) Offset {
|
||||
RosterOffset: rosterOffset,
|
||||
PanelManagerContainerOffset: panelManagerContainerOffset,
|
||||
WidgetStatesOffset: WidgetStatesOffset,
|
||||
WaypointsOffset: WaypointsOffset,
|
||||
WaypointTableOffset: WaypointTableOffset,
|
||||
FPS: fpsOffset,
|
||||
KeyBindingsOffset: keyBindingsOffset,
|
||||
KeyBindingsSkillsOffset: keyBindingsSkillsOffset,
|
||||
|
||||
@@ -90,16 +90,7 @@ func (gd *GameReader) GetPlayerUnit(mainPlayerUnit RawPlayerUnit) data.PlayerUni
|
||||
// Class
|
||||
class := data.Class(gd.Process.ReadUInt(mainPlayerUnit.Address+0x17C, Uint32))
|
||||
|
||||
availableWPs := make([]area.ID, 0)
|
||||
// Probably there is a better place to pick up those values, since this seems to be very tied to the UI
|
||||
wpList := gd.Process.ReadBytesFromMemory(gd.moduleBaseAddressPtr+gd.offset.WaypointsOffset, 0x48)
|
||||
for i := 0; i < 0x48; i = i + 8 {
|
||||
a := binary.LittleEndian.Uint32(wpList[i : i+4])
|
||||
available := binary.LittleEndian.Uint32(wpList[i+4 : i+8])
|
||||
if available == 1 || mainPlayerUnit.Area == area.ID(a) {
|
||||
availableWPs = append(availableWPs, area.ID(a))
|
||||
}
|
||||
}
|
||||
availableWPs := gd.decodeWaypointMasks()
|
||||
|
||||
d := data.PlayerUnit{
|
||||
Address: mainPlayerUnit.Address,
|
||||
@@ -121,6 +112,69 @@ func (gd *GameReader) GetPlayerUnit(mainPlayerUnit RawPlayerUnit) data.PlayerUni
|
||||
return d
|
||||
}
|
||||
|
||||
// WaypointTableData returns the waypoint table struct and the data buffer it points to
|
||||
func (gd *GameReader) WaypointTableData() (structAddr uintptr, structBuf []byte, dataAddr uintptr, dataBuf []byte) {
|
||||
var structSize = uint(0x100)
|
||||
var dataSize = uint(0x200)
|
||||
|
||||
ptrAddr := gd.moduleBaseAddressPtr + gd.offset.WaypointTableOffset
|
||||
structAddr = uintptr(gd.Process.ReadUInt(ptrAddr, Uint64))
|
||||
structBuf = gd.Process.ReadBytesFromMemory(structAddr, structSize)
|
||||
if len(structBuf) >= 0x18 {
|
||||
dataAddr = uintptr(binary.LittleEndian.Uint64(structBuf[0x10:]))
|
||||
if dataAddr != 0 {
|
||||
dataBuf = gd.Process.ReadBytesFromMemory(dataAddr, dataSize)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// decodeWaypointMasks reads the global waypoint bitfield from the waypoint table.
|
||||
// It returns nil if the table cannot be read.
|
||||
func (gd *GameReader) decodeWaypointMasks() []area.ID {
|
||||
waypointOrder := []area.ID{
|
||||
// Act 1
|
||||
area.RogueEncampment, area.ColdPlains, area.StonyField, area.DarkWood, area.BlackMarsh,
|
||||
area.OuterCloister, area.JailLevel1, area.InnerCloister, area.CatacombsLevel2,
|
||||
// Act 2
|
||||
area.LutGholein, area.SewersLevel2Act2, area.DryHills, area.HallsOfTheDeadLevel2, area.FarOasis,
|
||||
area.LostCity, area.PalaceCellarLevel1, area.ArcaneSanctuary, area.CanyonOfTheMagi,
|
||||
// Act 3
|
||||
area.KurastDocks, area.SpiderForest, area.GreatMarsh, area.FlayerJungle, area.LowerKurast,
|
||||
area.KurastBazaar, area.UpperKurast, area.Travincal, area.DuranceOfHateLevel2,
|
||||
// Act 4
|
||||
area.ThePandemoniumFortress, area.CityOfTheDamned, area.RiverOfFlame,
|
||||
// Act 5
|
||||
area.Harrogath, area.FrigidHighlands, area.ArreatPlateau, area.CrystallinePassage, area.GlacialTrail,
|
||||
area.HallsOfPain, area.FrozenTundra, area.TheAncientsWay, area.TheWorldStoneKeepLevel2,
|
||||
}
|
||||
_, structBuf, _, _ := gd.WaypointTableData()
|
||||
if len(structBuf) < 4 {
|
||||
return nil
|
||||
}
|
||||
// First two bytes are the 0x0201 header; the next five bytes hold the bitfield (per classic D2 layout).
|
||||
if structBuf[0] != 0x02 || structBuf[1] != 0x01 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var bits uint64
|
||||
for i := 0; i < 5 && 2+i < len(structBuf); i++ {
|
||||
bits |= uint64(structBuf[2+i]) << (8 * i)
|
||||
}
|
||||
|
||||
if bits == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
out := make([]area.ID, 0, len(waypointOrder))
|
||||
for idx, wpArea := range waypointOrder {
|
||||
if bits&(1<<uint(idx)) != 0 {
|
||||
out = append(out, wpArea)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (gd *GameReader) getSkills(skillListPtr uintptr) map[skill.ID]skill.Points {
|
||||
skills := make(map[skill.ID]skill.Points)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user