Подробный гайд: Создание ASI-мода для мгновенной остановки транспорта в SA:MP

Гайд по созданию ASI-мода для SA-MP: мгновенная остановка транспорта игрока по нажатию клавиши. Два способа: через память GTA SA и через SAMPFUNCS.

2026.09.05                  


Подробный гайд: Создание ASI-мода для мгновенной остановки транспорта в SA:MPПодробный гайд: Создание ASI-мода для мгновенной остановки транспорта в SA:MP ASI-моды — это динамические библиотеки (.dll), загружаемые в процесс игры GTA San Andreas с помощью специального загрузчика (ASI Loader). Они позволяют изменять поведение игры, вызывать внутренние функции и работать с памятью напрямую. В SA:MP (San Andreas Multiplayer) ASI-моды часто используются для добавления новых возможностей, не предусмотренных клиентом.

В этом руководстве мы создадим ASI-мод, который по нажатию определённой клавиши мгновенно останавливает транспорт, в котором находится локальный игрок. Это может быть полезно для тренировок, ролевых ситуаций или просто для удобства.



Внимание!

Использование подобных модификаций на публичных серверах может быть расценено как читерство и привести к бану. Используйте только на серверах, где это разрешено, или в одиночной игре.


1. Подготовка окружения

Требования

  • Visual Studio (2015, 2017, 2019 или 2022) с набором инструментов для C++.
  • ASI Loader (например, встроенный в SA-MP).
  • SAMPFUNCS (опционально, упрощает работу с SA-MP) — можно скачать с BlastHack - https://www.blasthack.net/.
  • Базовые знания C++ и понимание работы памяти процесса.

Установка ASI Loader

  1. Скачайте ASI Loader.
  2. Поместите файл vorbisFile.dll (или d3d9.dll в зависимости от версии) в корневую папку с игрой (где находится gta_sa.exe).
  3. Создайте папку asi в корне игры, если её нет.

Теперь любой .asi файл, помещённый в папку asi (или в корень), будет автоматически загружен при запуске игры.


2. Создание проекта ASI

Шаг 1: Создание пустого проекта DLL

  1. Откройте Visual Studio → Создать проектБиблиотека динамической компоновки (DLL).
  2. Назовите проект, например InstantStop.
  3. Удалите все автоматически созданные файлы (.cpp, .h, framework.h и т.д.), оставив только пустой проект.

Шаг 2: Настройка свойств проекта

Откройте Свойства проекта (правой кнопкой по проекту → Properties):

  • ConfigurationAll Configurations.
  • C/C++ → General → Additional Include Directories — добавьте путь к заголовкам SAMPFUNCS (если используете) и, при необходимости, к DirectX SDK.
  • C/C++ → Preprocessor → Preprocessor Definitions — добавьте _CRT_SECURE_NO_WARNINGS, _WINDLL, _UNICODE, UNICODE.
  • Linker → General → Output File — укажите расширение .asi вместо .dll (например, $(OutDir)\$(ProjectName).asi).
  • Linker → Input → Additional Dependencies — добавьте samp.lib (если работаете с SA-MP напрямую), sampfuncs.lib (если используете SAMPFUNCS). При использовании только адресов GTA SA дополнительные библиотеки не нужны.
  • C/C++ → Code Generation → Runtime Library — для Release лучше выбрать /MT (статическая линковка), чтобы не зависеть от внешних DLL.

Шаг 3: Точка входа

ASI-мод должен экспортировать функцию DllMain, которая будет вызвана при загрузке. В ней мы создадим поток или зарегистрируем хук.


3. Вариант 1: Использование адресов GTA San Andreas (без SAMPFUNCS)

Этот метод не требует внешних библиотек, кроме стандартных. Мы будем напрямую обращаться к памяти игры и вызывать её внутренние функции.

Необходимые адреса (для GTA SA 1.0 US)

  • FindPlayerPed (получение указателя на локального игрока) — 0xB6F5F0 (функция, возвращает CPed*).
  • Смещение до указателя на транспорт в CPed0x58C (CVehicle* m_pVehicle).
  • Смещение до вектора скорости в CVehicle0x44 (float[3] m_vecMoveSpeed).
  • Смещение до вектора угловой скорости в CVehicle0x50 (float[3] m_vecTurnSpeed).
  • Функция CVehicle::SetMoveSpeed (опционально) — 0x6D9F20 (thiscall, принимает три float).

Код

#include <windows.h>
#include <cstdint>

// Прототип функции FindPlayerPed
typedef uintptr_t* (*FindPlayerPed_t)();
FindPlayerPed_t FindPlayerPed = (FindPlayerPed_t)0xB6F5F0;

// Функция для вызова CVehicle::SetMoveSpeed (thiscall)
typedef void(__thiscall* SetMoveSpeed_t)(uintptr_t vehicle, float x, float y, float z);
SetMoveSpeed_t SetMoveSpeed = (SetMoveSpeed_t)0x6D9F20;

// Глобальный флаг для контроля потока
bool g_shouldStopVehicle = false;
bool g_running = true;

// Поток, проверяющий нажатие клавиши
DWORD WINAPI MainThread(LPVOID lpParam)
{
    while (g_running)
    {
        // Проверяем клавишу (например, клавиша 'X')
        if (GetAsyncKeyState('X') & 0x8000)
        {
            if (!g_shouldStopVehicle) // защита от повторного срабатывания при удержании
            {
                g_shouldStopVehicle = true;

                // Получаем указатель на игрока
                uintptr_t* playerPtr = FindPlayerPed();
                if (playerPtr)
                {
                    uintptr_t player = *playerPtr;
                    if (player)
                    {
                        // Читаем указатель на транспорт из CPed + 0x58C
                        uintptr_t* vehiclePtr = reinterpret_cast<uintptr_t*>(player + 0x58C);
                        uintptr_t vehicle = *vehiclePtr;
                        if (vehicle)
                        {
                            // Останавливаем транспорт (вариант через прямое обнуление скорости)
                            float* moveSpeed = reinterpret_cast<float*>(vehicle + 0x44);
                            moveSpeed[0] = 0.0f;
                            moveSpeed[1] = 0.0f;
                            moveSpeed[2] = 0.0f;

                            float* turnSpeed = reinterpret_cast<float*>(vehicle + 0x50);
                            turnSpeed[0] = 0.0f;
                            turnSpeed[1] = 0.0f;
                            turnSpeed[2] = 0.0f;

                            // Альтернатива: вызов функции SetMoveSpeed
                            // SetMoveSpeed(vehicle, 0.0f, 0.0f, 0.0f);
                        }
                    }
                }
            }
        }
        else
        {
            g_shouldStopVehicle = false; // сброс, когда клавиша отпущена
        }

        Sleep(10); // небольшая задержка, чтобы не грузить процессор
    }
    return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        DisableThreadLibraryCalls(hModule);
        // Создаём поток
        CreateThread(NULL, 0, MainThread, NULL, 0, NULL);
        break;
    case DLL_PROCESS_DETACH:
        g_running = false;
        break;
    }
    return TRUE;
}


Пояснения

  • GetAsyncKeyState — системная функция Windows, определяет, нажата ли клавиша в данный момент.
  • FindPlayerPed — стандартная функция GTA SA, возвращает указатель на объект CPed локального игрока.
  • Смещение 0x58C в структуре CPed указывает на указатель на CVehicle (транспорт), в котором находится игрок (nullptr, если не в транспорте).
  • Поля m_vecMoveSpeed (0x44) и m_vecTurnSpeed (0x50) — скорости линейного и углового движения транспорта. Обнуление мгновенно останавливает его.
  • Можно также вызвать SetMoveSpeed по адресу 0x6D9F20, что эквивалентно обнулению.

4. Вариант 2: Использование SAMPFUNCS (более просто и надёжно)

SAMPFUNCS — библиотека, предоставляющая удобный API для работы с SA-MP. Она скрывает многие детали (адреса, смещения) и автоматически обновляется под новые версии.

Установка SAMPFUNCS

  1. Скачайте последнюю версию SAMPFUNCS (например, для SA-MP 0.3.7).
  2. Поместите sampfuncs.asi в папку игры (или в папку asi).
  3. В проекте подключите заголовочные файлы и библиотеку sampfuncs.lib.

Код с использованием SAMPFUNCS

#include <windows.h>
#include "SAMPFUNCS/SAMPFUNCS.h"

SAMPFUNCS* SF = new SAMPFUNCS();

bool g_shouldStop = false;
bool g_running = true;

DWORD WINAPI MainThread(LPVOID lpParam)
{
    while (g_running)
    {
        if (GetAsyncKeyState('X') & 0x8000)
        {
            if (!g_shouldStop)
            {
                g_shouldStop = true;

                // Получаем локального игрока
                SAMP::CPlayer* localPlayer = SF->getSAMP()->getPlayers()->getLocalPlayer();
                if (localPlayer)
                {
                    // Проверяем, находится ли игрок в транспорте
                    if (localPlayer->isInVehicle())
                    {
                        // Получаем указатель на транспорт
                        SAMP::CVehicle* vehicle = localPlayer->getVehicle();
                        if (vehicle)
                        {
                            // Устанавливаем нулевую скорость
                            vehicle->setSpeedVector(CVector(0.0f, 0.0f, 0.0f));
                            // или vehicle->setMoveSpeedVector(...);
                        }
                    }
                }
            }
        }
        else
        {
            g_shouldStop = false;
        }

        Sleep(10);
    }
    return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        DisableThreadLibraryCalls(hModule);
        CreateThread(NULL, 0, MainThread, NULL, 0, NULL);
        break;
    case DLL_PROCESS_DETACH:
        g_running = false;
        delete SF;
        break;
    }
    return TRUE;
}


Пояснения

  • SAMPFUNCS предоставляет готовые классы (SAMP::CPlayer, SAMP::CVehicle), методы которых используют актуальные адреса.
  • setSpeedVector — метод, обнуляющий скорость транспорта.
  • Код получается короче и меньше зависит от версии игры/SA-MP.

5. Компиляция и установка

  1. Выберите конфигурацию Release и платформу x86 (GTA SA — 32-битное приложение).
  2. Нажмите Build Solution.
  3. В папке Release появится файл с расширением .asi.
  4. Скопируйте этот файл в корневую папку игры (где gta_sa.exe) или в папку asi (если ASI Loader это поддерживает).
  5. Запустите игру, подключитесь к серверу SA-MP.

Тестирование:

  • Сядьте в любой транспорт.
  • Нажмите клавишу X (или ту, которую вы указали в коде).
  • Транспорт должен мгновенно остановиться (скорость станет нулевой).

6. Возможные проблемы и их решение

1. ASI-файл не загружается

  • Убедитесь, что ASI Loader установлен правильно (vorbisFile.dll или другой заменён).
  • Проверьте, что файл имеет расширение .asi, а не .dll.
  • Попробуйте поместить .asi прямо в корень игры.

2. Игра вылетает при нажатии клавиши

  • Проверьте правильность адресов (для варианта 1). Возможно, у вас другая версия GTA SA (не 1.0 US). Используйте SAMPFUNCS для надёжности.
  • Убедитесь, что вы работаете с 32-битным процессом (x86).

3. Транспорт не останавливается полностью

  • Попробуйте также обнулить m_vecTurnSpeed (смещение 0x50) или вызвать функцию SetMoveSpeed, как указано выше.
  • В SA-MP может быть серверная синхронизация, которая вернёт небольшую скорость. Это нормально.

4. Срабатывание слишком часто при удержании

  • В коде используется флаг g_shouldStop, который предотвращает повторное выполнение до отпускания клавиши. Если вы хотите, чтобы остановка происходила каждый кадр, уберите эту проверку.

5. Анти-чит сервера блокирует мод

  • Некоторые серверы имеют собственные защитные механизмы. Используйте мод только на доверенных серверах или в одиночной игре.

Важно

Мы рассмотрели два способа создания ASI-мода для мгновенной остановки транспорта в SA-MP: через прямое обращение к памяти GTA San Andreas и через библиотеку SAMPFUNCS. Второй способ проще и безопаснее, но требует наличия этой библиотеки у пользователя. Первый способ полностью автономен, но зависит от точных адресов.



Вы можете модифицировать код: назначить другую клавишу, остановить только свой транспорт или транспорт перед вами, добавить звуковой сигнал и т.д. Помните об этичности использования подобных модов на публичных серверах.

Удачи в разработке!


Мы делимся этой технической информацией, чтобы помочь вам в решении задач — используйте её с пониманием. Статья носит рекомендательный характер, поэтому, пожалуйста, применяйте описанные методы осмотрительно.


Статью подготовил: Аверко Денис Сергеевич @Nymexis г. Омск (специалист по ЗИ)

Комментарии

Загрузка...
Если комментарии не загружаются, можете попробовать отключить блокировщик рекламы для этого сайта