![]() |
Все ***ня, делайте как фип: https://www.blast.hk/threads/16982/#post-147624
Когда-то уже делал такую штуку, но проебал. Так что если вдруг тема окажется баяном, то вы мне намекните. Именно намекните, потому что если заявите об этом прямо, то я обоссу старую тему найдя в ней 100500 минусов вместо того что бы просто удалить ее. И так. "Что же это за хуета?" наверно возникла у вас мысль. Ответ можно дать в 9 словах (это точное число, я считал), но у меня дипломка в следующем году и 2 курсача, так что буду тренироваться в разливание килотонн воды. Иными словами текста будет неоправданно много и не нужно. Если вы пишите или писали ранее плагины на C++ для GTA или какой-либо другой игры не имеющей для этих целей специализированного API, то вы наверняка сталкивались с тем, что вам нужно получить или записать значение по адресу в памяти. В принципе с такой задачей наверняка сталкивались даже те, кто пишет на CLEO. Рассмотрим решение данной задачи на примере. Предположим, что мы хотим прочитать или записать количество денег в игре. Адрес по которому хранится количество денег в GTA:SA нам известен: 0xB7CE50. Самый простой вариант чтения и записи значений в память выглядит следующим образом: C: Код:
intЭтот стиль записи пришел в C++ из языка программирования C, и на самом деле он рекомендуется к использованию. Если вы попытаетесь скомпилировать программу с таким кодом в компиляторе clang, то получите предупреждение о том, что так кодить не стоит. На замену такому стилю В C++ пришли следующие методы:
Изменить или прочитать значение из памяти так же можно функцией memcpy, но это более сложный вариант занимающий больше кода, по этому тут он рассмотрен не будет. Вместо этого мы обратим внимание на то, что для упрощения работы с переменными в памяти программы зачастую используются макросы. Если мы исследуем исходные коды плагина mod_s0beit, то мы можем найти записи, где непосредственно адрес переменной заменяется макросом, для нашего примера это будет такая запись: C: Код:
#define ADDR_MONEY 0xB7CE50Тогда в коде вместо численного адреса можно использовать макрос. Это может иметь более длинную запись, однако читаемость кода выше: C: Код:
intКак мы видим выше, даже не зная что хранится по адресу 0xB7CE50, программист читающий этот код сразу поймет что в нем делается. Однако тут мы находим еще один недостаток пришедший в C++ из языка программирования C - макросы. В C++ было принято соглашения, что в таких случаях следует использовать константы: C++: Код:
constЕсли мы применим все те методы C++, которые были описаны выше, то получится код вида: C++: Код:
intКак мы видим это не самая красивая форма записи, и использование приемов из языка программирования C код выглядел более читабельным. К тому же, если обратиться к макросам, то можно записать такой макрос: C: Код:
#define MONEY *(int*)0xB7CE50И тогда код будет выглядеть куда дружелюбнее к программисту: C: Код:
intТакая запись почти идеальна. Почти... но тут используются приемы из языка программирования C. Однако не стоит расстраиваться, используя приемы C++ мы тоже можем добиться такой формы записи. Правда в C++ предполагается применение ООП и достичь такой же записи будет немного труднее - нам понадобится использовать классы и шаблоны. Но не беспокойтесь, я уже написал весь код, а вам только объясню как иего использовать. С первого взгляда может показаться, что мой класс жуткий, и это правда, но он не всегда был таким. До введения возможности указывать модуль с переменной, и до введения методов работы с разрешениями, он был весьма маленький и легкочитаемый. C++: Код:
#ifndef MVAR_HКод позиционируется кк самостоятельный .h файл подключаемый к проекту. Как вы видите, не смотря на желание уйти от макросов, мне это не удалось. Дело в том, что в C++ не стандартизированного метода указания, что файл должен быть включен лишь единожды. В Microsoft VisualStudio C++ есть #pragma once, однако другие компиляторы его не поддерживают. Начнем с конструктора. Он обязательно принимает смещение в памяти и не обязательно может принимать указатель на модуль в котором располагается наша переменная. C++: Код:
MVarИз кода выше видно, что мы создали объект money, которому передали адрес денег в памяти игры. Конструктор не может быть объявлен глобально! Т.к. я использую свой шаблон для asi плагинов, который построен на классах, то у меня с этим нет проблем, однако если вы пишите плагин в стиле языка программирования C (например SF плагин), то у вас могут возникнуть с этим некоторые проблемы. Пример чтения и записи: C++: Код:
intТеперь рассмотрим остальные, менее интересные методы:
P.S. Если вы не пролистали сразу вниз после прочтения фразы: Цитата:
|
Что за мазохизм то, этот класс будет плодить в бинарнике по 7 методов для каждого типа.
|
Цитата:
|
Цитата:
|
Цитата:
|
жесть...
C++: Код:
intи можно обращаться как к обычной переменной - читать, писать. единственная проблема - нет снятия протекции. |
Цитата:
|
Цитата:
|
| Время: 19:23 |