Кровь из глаз.
Тебе скинули другое решение, но всё же объясню тебе то, что ты хотел сделать.
У тебя тут, видимо, указатель 3 уровня.
Вкратце, в чём суть. У тебя есть память, покажем её табличкой:
Адрес памяти | Значение, которое там записано |
0xB6BC90 | 82 |
0xB6BC94 | 54 |
0xB6BC98 | 12 |
0xB6BC9С | 112 |
То есть, если совсем просто, память состоит из ячеек (битов), в которых записаны значения (0 или 1). Обращение к каждому биту невозможно в силу реализации чтения/записи в память, поэтому биты объединили по 8 соседних и получили байт — им и присвоили адреса (т. е. адрес 0xB1 и 0xB2 это два соседних байта, а не два соседних бита).
Тип
int использует 4 байта (то, как именно число записывается, можно
почитать тут). Поэтому давай смотреть таблицу, где слева указан адрес памяти, а справа — число
int, которое записано в этих 4-х байтах, начиная с того, адрес которого указан слева.
Дальше нужно осознать, что есть необходимость указывать на другие адреса (то есть значением одних адресов является другой адрес). Например, у тебя есть структура игрока (где хранится вся информация о нём). Она БОЛЬШАЯ (т. е. занимает много сотен байтов), и если у нас большое количество игроков в зоне стрима — все их структуры надо хранить. Если их хранить «одна за другой», то так много свободного места
подряд может тупо не найтись в памяти. Поэтому решили хранить в массиве только адреса начала структур, а сами структуры создавать в произвольном пустом месте, совсем необязательно подряд.
Туда же можно отнести и передачу больших массивов данных в функции (например, в рекурсии). Если каждый раз копировать
весь массив и передавать целиком массив при рекурсии — память закончится почти сразу в реальных программах. Намного эффективнее создать его 1 раз, а передавать лишь указатель на его начало (адрес памяти начала массива). Понятно, да?
Адрес памяти | Значение, которое там записано |
0xB6BC90 | 0xC834EC |
... | ... |
0xC834EC | нужное нам значение |
В таком примере, чтобы получил нужное нам значение, зная только адрес указателя, мы должны прочитать то, что записано там, а потом перейти по этому адресу — и прочитать уже его значение. А если это структура?
Адрес памяти | Значение, которое там записано |
0xB6BC90 | 0xC834EC (к примеру, указатель на начало структуры игрока) |
... | ... |
0xC834EC (начало структуры) | ... |
0xC834EC + 0x4 (к примеру, здоровье игрока) | ... |
0xC834EC + 0x8 (к примеру, броня игрока) | ... |
0xC834EC + 0xC (к примеру, скин игрока) | нужное нам значение |
Тогда тебе к адресу нужно прибавить смещение
+0xC
, это называется оффсет.
У тебя такой процесс нужно провернуть 3 раза: указатель на указатель на указатель на числовое значение.
В коде это будет вот так:
local CAudioEngine = memory.getint32(0xB6BC90)
local CAEScriptAudioEntity = memory.getint32(CAudioEngine + 0x2A0)
local m_dwLastTimeHornPlayed = memory.getuint32(CAEScriptAudioEntity + 0x80)
local time = m_dwLastTimeHornPlayed -- то, что тебе нужно