-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDS3ModelMaskPatcher.py
149 lines (124 loc) · 5.19 KB
/
DS3ModelMaskPatcher.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import pymem
from DS3PartUtil import EquipModelCategory
class DS3ModelMaskPatcher:
"""Patches Params in DARK SOULS III's memory for part model masks"""
def __init__(self):
self.__pyMem = pymem.Pymem('DarkSoulsIII.exe')
self.__paramOffset = None
self.__paramTable = {}
def __accessMultilevelPointer(self, cTypeName, offsets):
if len(offsets) == 0:
return None
baseAddress = offsets[0]
address = None
if len(offsets) == 1:
if cTypeName == 'int8':
try:
return self.__pyMem.read_bytes(baseAddress, 1)[0]
except pymem.exception.MemoryReadError as error:
return None
elif cTypeName == 'int16':
try:
return self.__pyMem.read_short(baseAddress)
except pymem.exception.MemoryReadError as error:
return None
elif cTypeName == 'int32':
try:
return self.__pyMem.read_int(baseAddress)
except pymem.exception.MemoryReadError as error:
return None
elif cTypeName == 'uint64':
try:
return self.__pyMem.read_ulonglong(baseAddress)
except pymem.exception.MemoryReadError as error:
return None
elif cTypeName == 'float':
try:
return self.__pyMem.read_float(baseAddress)
except pymem.exception.MemoryReadError as error:
return None
try:
address = self.__pyMem.read_ulonglong(baseAddress)
except pymem.exception.MemoryReadError as error:
return None
offsets.pop(0)
offset = offsets[0]
offsets[0] = address + offset
return self.__accessMultilevelPointer(cTypeName, offsets)
def __loadEquipParamProtector(self):
self.__paramOffset = self.__accessMultilevelPointer('uint64',
[self.__pyMem.base_address + 0x4798108, 0xB8, 0x68, 0x68])
tableSize = self.__accessMultilevelPointer('int16',
[self.__paramOffset + 0xA])
for i in range(tableSize):
paramId = self.__accessMultilevelPointer('uint64',
[self.__paramOffset + 0x40 + 0x18 * i])
idOffset = self.__accessMultilevelPointer('uint64',
[self.__paramOffset + 0x48 + 0x18 * i])
self.__paramTable[paramId] = self.__paramOffset + idOffset
def getParamIdByEquipModelIdAndEquipModelCategory(self, equipModelId, equipModelCategory):
equipModelCategoryId = None
if equipModelCategory.lower() == EquipModelCategory.HEAD.value:
equipModelCategoryId = 5
elif equipModelCategory.lower() == EquipModelCategory.BODY.value:
equipModelCategoryId = 2
elif equipModelCategory.lower() == EquipModelCategory.ARMS.value:
equipModelCategoryId = 1
elif equipModelCategory.lower() == EquipModelCategory.LEGS.value:
equipModelCategoryId = 6
else:
return None
for paramId in self.__paramTable:
try:
if self.__pyMem.read_bytes(self.__paramTable[paramId] + 0xD0, 1)[0] == equipModelCategoryId and equipModelId == self.__pyMem.read_ushort(self.__paramTable[paramId] + 0xA0):
return paramId
except pymem.exception.MemoryReadError as error:
continue
return None
def readModelMask(self, id, maskOffset):
try:
return self.__pyMem.read_bytes(self.__paramTable[id] + 0x12E + maskOffset, 1)[0]
except pymem.exception.MemoryReadError as error:
return None
def writeModelMask(self, id, maskOffset, isHide):
try:
self.__pyMem.write_bytes(self.__paramTable[id] + 0x12E + maskOffset, bytes([isHide]), 1)
except pymem.exception.MemoryReadError as error:
return
def isAttached(self):
if not self.__pyMem.process_id:
return False
result = None
try:
result = self.__accessMultilevelPointer('uint64',
[self.__pyMem.base_address + 0x4798108])
except pymem.exception.ProcessError as error:
return False
if result != None:
return True
else:
return False
def isParamsDefined(self):
return self.__paramOffset != None
def undefineParams(self):
self.__paramOffset = None
self.__paramTable = {}
def attach(self):
try:
self.__pyMem.open_process_from_name('DarkSoulsIII')
except pymem.exception.ProcessNotFound as error:
return
except pymem.exception.CouldNotOpenProcess as error:
return
if not self.isAttached():
return
try:
self.__loadEquipParamProtector()
return
except TypeError as error:
self.undefineParams()
return
except pymem.exception.ProcessNotFound as error:
return
except pymem.exception.MemoryReadError as error:
return