> For the complete documentation index, see [llms.txt](https://lessons.sannybuilder.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lessons.sannybuilder.com/00100/00500/00074.-dinamicheskie-adresa-pamyati.-chast-1-struktura-aktyora.md).

# 00074. Динамические адреса памяти. ( Часть 1 - структура актёра )

Динамические адреса памяти. ( Часть 1 - структура актёра )|Сегодня мы будем бегать по адресам памяти, связанных со структурой актёра.|wmysterio|wmysterio||||Всем привет! Наконец то вышел урок по динамичным адресам памяти. Он будет составляться с большим количеством частей и не один раз будут переписываться, так как я успел изучить немного, но этого уже достаточно, что бы внести свои коррективы в игровой процесс. Прежде всего создадим актёра "0@", который будет жертвой наших испытаний:

```
{$CLEO}
0000:

var
#WMYDRUG: model
0@: actor
end

:A
thread "A"
wait 0
#WMYDRUG.Load
038B: load_requested_models

:A_1
wait 0
if
#WMYDRUG.Available
jf @A_1
0@.Create(4, #WMYDRUG, 2493.6321, -1670.4906, 12.3359)
0@.Angle = 189.6409
#WMYDRUG.destroy

0A93: end_custom_thread
```

Создав актёра, нужно получить его структуру опкодом:

```
0A96: 1@ = actor 0@ struct
```

Здесь:\
0@ - хендл актёра\
1@ - в переменную будет записан адрес структуры. Именно от неё мы будем сдвигаться по памяти. По сути в переменную запишется огромное число

Основная часть сделана. Получив структуру, мы можем двигаться по памяти и читать нужные адреса. Для сдвига очень полезно использовать опкод:

```
0A8E: 1@ = 0@ + 5 // int
```

В переменную "1@" будет записана сумма двух целых чисел. Используя этот опкод, давайте получим адрес брони актёра:

```
0A96: 1@ = actor 0@ struct
0A8E: 2@ = 1@ + 0x548
```

Теперь в переменной "2@" будет находится адрес брони.

Здесь:\
1@ + 0x548 - смещение от структуры ( см. смещения в [Структуре актёра](https://github.com/wmysterio/scm-scripting-lessons/blob/main/dir/gta_sa/dinamicheskie_adresa_pamjati_struktura_aktjora/1-1-0-28/README.md) )\
2@ - результат этого смещения. Именно результат можно читать и записывать

Адрес мы вычислили. Теперь нам нужно узнать размер результата в байтах. Как видим, тип у этого адреса - float, значит размер ( size ) записи будет составлять 4 байта и значение собственно будет дробным. Давайте запишем 25.0 по этому адресу. Затем считаем броню обычным опкодом и запишем результат в ini-файл, что бы проверить правильность адреса. В результате в нас должен выйти такой скрипт:

```
{$CLEO}
0000:

var
#WMYDRUG: model
0@: actor
end

:A
thread "A"
wait 0
#WMYDRUG.Load
038B: load_requested_models

:A_1
wait 0
if
#WMYDRUG.Available
jf @A_1
0@.Create(4, #WMYDRUG, 2493.6321, -1670.4906, 12.3359)
0@.Angle = 189.6409

0A96: 1@ = actor 0@ struct // получаем адрес структуры
0A8E: 2@ = 1@ + 0x548 // делам сдвиг по памяти
0A8C: write_memory 2@ size 4 value 25.0 virtual_protect 0 // запишем по адресу значение 25.0

04DD: 3@ = actor 0@ armour // считываем текущую броню актёра. До выполнения лазейки в память, броня актёра была равна 0.
0AF1: write_int 3@ to_ini_file "cleo&#92;config.ini" section "SectionName" key "intKey" // запишем значение в ini-файл

0A93: end_custom_thread
```

Запускаем игру. После того, как увидели актёра, сворачиваем её и проверим, что адрес действительно правильный и в актёра стало 25 брони. Открываем созданный ini-файл и смотрим результат:

![](https://github.com/wmysterio/scm-scripting-lessons/blob/main/_pu/1/78488779.png)

Выводы:

* адрес правильный, запись была без ошибок;
* в этом адресе принимаются дробные значения, хотя в опкодах это обозначено как целое число;

Вот и первая удачная лазейка помогла изменить свойства актёра без использования опкода. Используя базу данных вы можете провести свои тесты :) Естественно пока творить особо не над чем, так как пока эта база не полная, но со временем она будет обновляться и дописываться а так же выходить новые уроки по этой хитроумной памяти.|1549|1|0|78488779`png`336\`130

```
`\||dinamicheskie_adresa_pamjati_chast_1_struktura_aktjora|1499710257
```
