Рейтинг - 4.4 (7)

Написание простого ASI плагина с plugin-sdk.

Для написания плагина с plugin-sdk необходимо следующее:

  1. Установить Visual Studio (желательно последнюю версию - 2017). Подробнее - здесь;
  2. Скачать plugin-sdk и настроить его. Подробнее - здесь.

Итак, после того, как plugin-sdk настроен, мы можем создать плагин в Visual Studio. Для этого создаём новый проект и выбираем нужный нам шаблон, например, - GTA SA .ASI plugin.

Не забываем также указать название проекта и выбрать место его расположения. По умолчанию, у нас в проекте есть один файл исходного кода - Main.cpp. Открываем этот файл и подключаем нужные заголовочные файлы.

#include "plugin.h"
#include "game_sa\CMessages.h"
#include "game_sa\CClock.h"

using namespace plugin;

Мы будем изменять игровое время ( класс CClock отвечает за работу с игровыми "часами") и выводить сообщение ( класс CMessage предоставляет функции для вывода сообщений ).

Для удобства, мы разместим все данные и функции в классе. В конструктор этого класса мы поместим код инициализации нашего плагина. В глобальной области видимости мы создадим экземпляр этого класса, таким образом, при подключении нашего плагина ( а плагин - это динамическая библиотека с расширением .asi ) ASI-loader'ом, будет вызван конструктор нашего класса.

Такой подход позволяет избавиться от явного использования функции DllMain, но, впрочем, никто вам не запрещает выполнять инициализацию плагина так, как вам удобно.

#include "plugin.h"
#include "game_sa\CMessages.h"
#include "game_sa\CClock.h"

using namespace plugin;

class TestPlugin {
public:
 TestPlugin() {
 // код инициализации плагина
 }
} test; // создание экземпляра класса TestPlugin в глобальной области видимости

Инициализация плагина

В plugin-sdk реализована идея "событий" (events). Т.е., есть возможность выполнить свой код в какой-то определённый момент игры. Обращаться ко всем событиям можно из пространства имён plugin::Events. Вот как это выглядит:

Events::gameProcessEvent.Add(MyFunction); // Добавить вызов функции MyFunction, когда игра вызывает функцию CGame::Process

Метод Add добавляет указанную функцию к конкретному игровому"событию". При этом, у метода "Add" есть альтернатива в виде оператора +=

Events::gameProcessEvent += MyFunction; // Добавить вызов функции MyFunction, когда игра вызывает функцию CGame::Process

Также, есть возможность указать - когда именно вызывать нашу функцию - до "события" или после:

Events::gameProcessEvent.before += MyFunction; // Добавить вызов функции MyFunction, перед вызовом CGame::Process
Events::gameProcessEvent.after += MyFunction; // Добавить вызов функции MyFunction, поле вызова CGame::Process (стандартное поведение - т.е. аналогично вызову "Events::gameProcessEvent +=")

Бывают ситуации, когда такая возможность может быть действительно полезной - например, когда надо выполнить какие-то операции до и после отрисовки игрового субьекта (например, транспорта).

Ниже приведен список некоторых событий, доступных в plugin-sdk:

Событие Функция-прототип Описание
drawingEvent void() Отрисовка в 2D
drawHudEvent void() Отрисовка HUD-элементов
drawRadarEvent void() Отрисовка радара
drawBlipsEvent void() Отрисовка иконок на радаре
drawRadarOverlayEvent void(bool bInMenu) Отрисовка зон влияния на радаре
drawMenuBackgroundEvent void(void *menuManager) Отрисовка фона в меню
initRwEvent void() Инициализация графического движка
shutdownRwEvent void() Деинициализация графического движка
vehicleRenderEvent void(CVehicle* vehicle) Рендер транспорта
pedRenderEvent void(CPed* ped) Рендер педа
objectRenderEvent void(CObject* object) Рендер обьекта
vehicleSetModelEvent void(CVehicle* vehicle, int modelId) Установка модели транспорта
pedSetModelEvent void(CPed* ped, int modelId) Установка модели педа
d3dResetEvent void() Пересоздание D3D-девайса
d3dLostEvent void() Утерян доступ к D3D-девайсу
gameProcessEvent void() Обработка разных компонентов игры
initGameEvent void() Инициализация игры
reInitGameEvent void() Повторная инициализация игры
onPauseAllSounds void() Остановка всех звуков в игре
onResumeAllSounds void() Включение всех звуков в игре
initScriptsEvent void() Инициализация скриптов
processScriptsEvent void() Обработка скриптов

Используя лямбда-выражение в C++, мы можем записать добавление функции в таком виде:

Events::gameProcessEvent += [] {
 // код нашей функции
};

Код.

Мы сделаем изменение времени после нажатия клавиши Delete. Вот так будет выглядеть наш код:

#include "plugin.h"
#include "game_sa\CMessages.h"
#include "game_sa\CClock.h"

using namespace plugin;

class TestPlugin {
public:
 TestPlugin() {
 Events::gameProcessEvent += [] {
 // Если нажата клавиша Delete
 if (KeyPressed(VK_DELETE)) {
 // Устанавливаем время
 CClock::SetGameClock(12, 0, CClock::ms_nGameClockDayOfWeek);
 // Выводим сообщение
 CMessages::AddMessageJumpQ("You have set time to ~b~12:00", 3000, 0, false);
 }
 };
 }
} test;

Код готов, переключаемся в Release-режим и компилируем проект (F7).

Итак, что мы получаем в случае использования Plugin SDK? Чистые хуки без явно видимых патчей и работы напрямую с адресами памяти.


SHooZ   (23.06.14 00:32)
Обновление SDK есть?
Вход на сайт

Поиск
Категории раздела
Мини-чат
Пожалуйста, все вопросы по скриптингу задавать на форуме!
Наш опрос
Какая GTA Вам понравилась больше всего?
Всего ответов: 6
Активность на сайте
Пожертвования
Кошельки WebMoney:
U859420971000
R407741810602
Z331072372430
E314272616890
Друзья сайта
Полезные ресурсы
Статистика

Онлайн всего: 2
Гостей: 2
Пользователей: 0

Сегодня нас посетили:
Artyom_assasin, Zhonmoo
Реклама