- Статус
- Оффлайн
- Регистрация
- 13 Фев 2026
- Сообщения
- 507
- Реакции
- 13
Наткнулся на просторах на исходник простенького колорбота для APB Reloaded. Автор, судя по всему, решил завязать с проектом и выложил базу как есть. Самое то для тех, кто хочет поковырять логику захвата или ищет основу под свой проект.
Техническая часть:
По коду видно, что проект сыроват — например, память под массив pixels выделяется в цикле, а очистка идет не самым изящным образом. Я бы советовал переписать захват на DirectX или хотя бы оптимизировать цикл перебора пикселей, чтобы не ловить просадки FPS при большом FOV.
Инструкция:
Аим работает по зажатому SHIFT. В коде прописан поиск окна "APB RELOADED", так что если играете в оконном или полноэкранном в окне — должно подцепиться без проблем. Компилить лучше под x86/x64 в зависимости от билда игры, зависимости стандартные.
Для паблик-базы под допил вариант нормальный, особенно если прикрутить сюда нормальный фильтр цветов и сглаживание (smoothing), а то сейчас наводка может быть слишком резкой для BattlEye.
Техническая часть:
- Захват изображения реализован через классический BitBlt (GDI). Это не самый быстрый метод, но для понимания основ вполне сойдет.
- Реализована так называемая Exclusion Area — зона исключения в центре экрана. Это критически важно для колорбота, чтобы аим не сходил с ума от собственного прицела или элементов UI в центре FOV.
- Доводка идет через mouse_event. В APB античит (BattlEye) к этому относится относительно лояльно, если не наглеть, но для серьезного обхода лучше переписать на драйвер.
- Разрешение игры подхватывается автоматически через FindWindowA и GetClientRect.
В коде захардкожены следующие значения (R: 210-255, G: 0-100, B: 0-100). Это рассчитано на красные/оранжевые ники или элементы скинов. Если планируете использовать под другие цели, крутите переменные RminValue, GminValue и т.д.
Код:
#include "Windows.h"
#include "vector"
using namespace std;
HWND hwnd = 0;
POINT a, b; // top left and bottom right corners
int screenWidth; // width
int screenHeight; // height
const int width = 400; // aimfov width
const int height = 320; // aimfov height
RGBQUAD* capture(POINT a, POINT b) {
// copy screen to bitmap
HDC hScreen = GetDC(hwnd);
HDC hDC = CreateCompatibleDC(hScreen);
HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, abs(b.x - a.x), abs(b.y - a.y));
HGDIOBJ old_obj = SelectObject(hDC, hBitmap);
BOOL bRet = BitBlt(hDC, 0, 0, abs(b.x - a.x), abs(b.y - a.y), hScreen, a.x, a.y, SRCCOPY);
// Array conversion:
RGBQUAD* pixels = new RGBQUAD[width * height];
BITMAPINFOHEADER bmi = { 0 };
bmi.biSize = sizeof(BITMAPINFOHEADER);
bmi.biPlanes = 1;
bmi.biBitCount = 32;
bmi.biWidth = width;
bmi.biHeight = -height;
bmi.biCompression = BI_RGB;
bmi.biSizeImage = 0;
GetDIBits(hDC, hBitmap, 0, height, pixels, (BITMAPINFO*)&bmi, DIB_RGB_COLORS);
// clean up
SelectObject(hDC, old_obj);
DeleteDC(hDC);
ReleaseDC(hwnd, hScreen);
DeleteObject(hBitmap);
return pixels;
}
bool checkColourInRange(RGBQUAD sample, byte minRed, byte maxRed, byte minGreen, byte maxGreen, byte minBlue, byte maxBlue) {
int sampleRed = static_cast<int>(sample.rgbRed);
int sampleGreen = static_cast<int>(sample.rgbGreen);
int sampleBlue = static_cast<int>(sample.rgbBlue);
return (sampleRed >= minRed && sampleRed <= maxRed &&
sampleGreen >= minGreen && sampleGreen <= maxGreen &&
sampleBlue >= minBlue && sampleBlue <= maxBlue);
}
byte RminValue = 210;
byte RmaxValue = 255;
byte GminValue = 0;
byte GmaxValue = 100;
byte BminValue = 0;
byte BmaxValue = 100;
void Aim() {
RGBQUAD* pixels;
while (true) {
if (GetKeyState(VK_SHIFT) & 0x8000) {
pixels = capture(a, b);
int startX = -1;
int endX = -1;
// Find the first and last pixels in the specified color range
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int index = y * width + x;
// Check if the current pixel is within the exception areas
int center_x = width / 2;
int center_y = height / 2;
if (
(x >= center_x && x < center_x + 126 && y >= center_y - 6 && y < center_y + 6) ||
(x >= center_x - 18 && x < center_x + 18 && y >= center_y - 18 && y < center_y + 18) ||
(x >= center_x - 126 && x < center_x && y >= center_y - 6 && y < center_y + 6) ||
(x >= center_x - 6 && x < center_x + 6 && y >= center_y && y < center_y + 126) ||
(x >= center_x - 6 && x < center_x + 6 && y >= center_y - 40 && y < center_y)
) {
continue; // Skip aiming if the pixel is in an exception area
}
if (checkColourInRange(pixels[index], RminValue, RmaxValue, GminValue, GmaxValue, BminValue, BmaxValue)) {
if (startX == -1) {
startX = x;
}
endX = x;
}
}
}
// Calculate the middle of the range
int middleX = (startX + endX) / 2;
int middleY = height / 2;
int xAdjust = middleX - width / 2;
int yAdjust = middleY - height / 2;
// Introduce a slight delay before making the adjustment
Sleep(5);
mouse_event(MOUSEEVENTF_MOVE, xAdjust, yAdjust, 0, 0);
}
delete[] pixels;
}
Sleep(1);
}
void updateResolution() {
while (1) {
Sleep(4000);
hwnd = GetForegroundWindow(); // get handle of currently active window
hwnd = FindWindowA(0, "APB RELOADED");
RECT windowsize;
GetClientRect(hwnd, &windowsize);
HDC monitor = GetDC(hwnd);
int current = GetDeviceCaps(monitor, VERTRES);
int total = GetDeviceCaps(monitor, DESKTOPVERTRES);
screenWidth = (windowsize.right - windowsize.left) * total / current;
screenHeight = (windowsize.bottom - windowsize.top) * total / current;
a.x = screenWidth / 2 - width / 2;
a.y = screenHeight / 2 - height / 2;
b.x = screenWidth / 2 + width / 2;
b.y = screenHeight / 2 + height / 2;
Sleep(6000);
}
}
int main() {
printf("Ready");
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)updateResolution, 0, 0, 0);
Aim();
return 0;
}
По коду видно, что проект сыроват — например, память под массив pixels выделяется в цикле, а очистка идет не самым изящным образом. Я бы советовал переписать захват на DirectX или хотя бы оптимизировать цикл перебора пикселей, чтобы не ловить просадки FPS при большом FOV.
Инструкция:
Аим работает по зажатому SHIFT. В коде прописан поиск окна "APB RELOADED", так что если играете в оконном или полноэкранном в окне — должно подцепиться без проблем. Компилить лучше под x86/x64 в зависимости от билда игры, зависимости стандартные.
Для паблик-базы под допил вариант нормальный, особенно если прикрутить сюда нормальный фильтр цветов и сглаживание (smoothing), а то сейчас наводка может быть слишком резкой для BattlEye.