@@ -1,6 +1,7 @@
|
|||||||
package memory
|
package memory
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"math"
|
"math"
|
||||||
@@ -35,6 +36,13 @@ type MercOption struct {
|
|||||||
Cost int
|
Cost int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CharacterFlags struct {
|
||||||
|
Hardcore bool
|
||||||
|
HasEverDied bool
|
||||||
|
Expansion bool
|
||||||
|
Ladder bool
|
||||||
|
}
|
||||||
|
|
||||||
var WidgetStateFlags = map[string]uint64{
|
var WidgetStateFlags = map[string]uint64{
|
||||||
"WeaponSwap": 0xF2D7CF8E9CC08212,
|
"WeaponSwap": 0xF2D7CF8E9CC08212,
|
||||||
}
|
}
|
||||||
@@ -494,3 +502,60 @@ func (gd *GameReader) GetActiveWeaponSlot() int {
|
|||||||
}
|
}
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gd *GameReader) GetCharacterFlags(characterName string) (CharacterFlags, error) {
|
||||||
|
const (
|
||||||
|
charDataHeaderSize = 16
|
||||||
|
charNameOffset = 0x010
|
||||||
|
charFlagsOffset = 0x122
|
||||||
|
maxCharCount = 47
|
||||||
|
|
||||||
|
flagHardcore = 0x04
|
||||||
|
flagDead = 0x08
|
||||||
|
flagExpansion = 0x20
|
||||||
|
flagLadder = 0x40
|
||||||
|
)
|
||||||
|
|
||||||
|
charDataPtr := gd.moduleBaseAddressPtr + gd.offset.CharData
|
||||||
|
if charDataPtr == 0 {
|
||||||
|
return CharacterFlags{}, errors.New("character data pointer is invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
headerBuffer := gd.Process.ReadBytesFromMemory(charDataPtr, charDataHeaderSize)
|
||||||
|
if len(headerBuffer) < charDataHeaderSize {
|
||||||
|
return CharacterFlags{}, errors.New("failed to read character data header")
|
||||||
|
}
|
||||||
|
|
||||||
|
charArrayPtr := uintptr(ReadUIntFromBuffer(headerBuffer, 0x00, Uint64))
|
||||||
|
charCount := int(ReadIntFromBuffer(headerBuffer, 0x08, Uint64))
|
||||||
|
|
||||||
|
if charArrayPtr == 0 || charCount <= 0 || charCount > maxCharCount {
|
||||||
|
return CharacterFlags{}, fmt.Errorf("invalid character metadata: arrayPtr=%v, count=%d", charArrayPtr, charCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
charPointerArray := gd.Process.ReadBytesFromMemory(charArrayPtr, uint(charCount*8))
|
||||||
|
|
||||||
|
for i := 0; i < charCount; i++ {
|
||||||
|
charStructPtr := uintptr(ReadUIntFromBuffer(charPointerArray, uint(i*8), Uint64))
|
||||||
|
if charStructPtr == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
charName := gd.Process.ReadStringFromMemory(charStructPtr+charNameOffset, 0)
|
||||||
|
|
||||||
|
if charName == characterName {
|
||||||
|
fieldValue := uint16(gd.Process.ReadUInt(charStructPtr+charFlagsOffset, Uint16))
|
||||||
|
|
||||||
|
flags := CharacterFlags{
|
||||||
|
Hardcore: (fieldValue & flagHardcore) != 0,
|
||||||
|
HasEverDied: (fieldValue & flagDead) != 0,
|
||||||
|
Expansion: (fieldValue & flagExpansion) != 0,
|
||||||
|
Ladder: (fieldValue & flagLadder) != 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CharacterFlags{}, fmt.Errorf("character not found: %s", characterName)
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ type Offset struct {
|
|||||||
Quests uintptr
|
Quests uintptr
|
||||||
Ping uintptr
|
Ping uintptr
|
||||||
LegacyGraphics uintptr
|
LegacyGraphics uintptr
|
||||||
|
CharData uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateOffsets(process *Process) Offset {
|
func calculateOffsets(process *Process) Offset {
|
||||||
@@ -118,6 +119,12 @@ func calculateOffsets(process *Process) Offset {
|
|||||||
legacyGfxPtr := uintptr(process.ReadUInt(pattern+2, Uint32))
|
legacyGfxPtr := uintptr(process.ReadUInt(pattern+2, Uint32))
|
||||||
legacyGfxOffset := pattern - process.moduleBaseAddressPtr + 7 + legacyGfxPtr
|
legacyGfxOffset := pattern - process.moduleBaseAddressPtr + 7 + legacyGfxPtr
|
||||||
|
|
||||||
|
// CharData
|
||||||
|
pattern = process.FindPattern(memory, "\x48\x8D\x05\x00\x00\x00\x00\x89\x93\xF4\x0C\x00\x00", "xxx????xxxxxx")
|
||||||
|
bytes = process.ReadBytesFromMemory(pattern+3, 4)
|
||||||
|
relativeOffset = int32(binary.LittleEndian.Uint32(bytes))
|
||||||
|
charDataOffset := pattern - process.moduleBaseAddressPtr + 7 + uintptr(relativeOffset)
|
||||||
|
|
||||||
return Offset{
|
return Offset{
|
||||||
GameData: gameDataOffset,
|
GameData: gameDataOffset,
|
||||||
UnitTable: unitTableOffset,
|
UnitTable: unitTableOffset,
|
||||||
@@ -136,5 +143,6 @@ func calculateOffsets(process *Process) Offset {
|
|||||||
Quests: questDataOffset,
|
Quests: questDataOffset,
|
||||||
Ping: pingOffset,
|
Ping: pingOffset,
|
||||||
LegacyGraphics: legacyGfxOffset,
|
LegacyGraphics: legacyGfxOffset,
|
||||||
|
CharData: charDataOffset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user