Почему не происходит эмуляции в игре?

maras_

Участник
Автор темы
41
2
В общем накостылял код на плюсах но не пойму почему в самой игре.
main:
//
// CMakeProject2.cpp: определяет точку входа для приложения.
//
#include "CMakeProject2.h"
#include <opencv2/opencv.hpp>
#include <windows.h>
#include <vector>
#include <string>
#include <map>
#include <iostream>
#include <random> // Для случайных задержек
using namespace std;
using namespace cv;

// Отключение параллельных бэкендов OpenCV
static void disableOpenCVParallel() {
    cv::setNumThreads(1); // Ограничение до 1 потока
    cv::setUseOptimized(false); // Отключение оптимизаций, зависящих от параллелизма
}

string getExecutableDirectory() {
    char buffer[MAX_PATH];
    GetModuleFileNameA(NULL, buffer, MAX_PATH);
    string path(buffer);
    return path.substr(0, path.find_last_of("\\/")) + "\\photo\\";
}

const string template_dir = getExecutableDirectory();

// Коды клавиш с виртуальными кодами и скан-кодами
const map<string, pair<WORD, BYTE>> key_map = {
    {"F", {0x46, 0x21}},
    {"H", {0x48, 0x23}},
    {"Q", {0x51, 0x10}},
    {"R", {0x52, 0x13}},
    {"V", {0x56, 0x2F}},
    {"W", {0x57, 0x11}},
    {"B", {0x42, 0x30}},
    {"D", {0x44, 0x20}},
    {"Space", {0x20, 0x39}},
    {"Left Arrow", {0x25, 0x4B}},
    {"Right Arrow", {0x26, 0x4D}},
    {"Up Arrow", {0x27, 0x48}},
    {"Down Arrow", {0x28, 0x50}},
    {"Left Shift", {0xA0, 0x2A}}
};

// Функция для определения, является ли скан-код расширенным
bool isExtendedKey(BYTE scan) noexcept {
    return (scan == 0x4B || scan == 0x4D || scan == 0x48 || scan == 0x50 || scan == 0x2A);
}

// Функция эмуляции зажатия клавиши на 3 секунды
void simulateKeyHold(WORD vk, BYTE scan, HWND hwnd = NULL) {
    cout << " -> Эмуляция зажатия клавиши на 3 секунды..." << endl;
    DWORD extendedFlag = isExtendedKey(scan) ? KEYEVENTF_EXTENDEDKEY : 0;
    INPUT input[2] = { 0 };
    input[0].type = INPUT_KEYBOARD;
    input[0].ki.wVk = vk;
    input[0].ki.wScan = scan;
    input[0].ki.dwFlags = KEYEVENTF_SCANCODE | extendedFlag;
    input[1].type = INPUT_KEYBOARD;
    input[1].ki.wVk = vk;
    input[1].ki.wScan = scan;
    input[1].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP | extendedFlag;

    SendInput(1, &input[0], sizeof(INPUT)); // Нажатие
    Sleep(3000); // Удержание на 3 секунды
    SendInput(1, &input[1], sizeof(INPUT)); // Отпускание
    cout << " -> Зажатие завершено" << endl;
}

// Функция поиска окна игры
HWND findGameWindow() {
    const char* game_names[] = {
        "AMAZING3 online",
        "AMAZING3",
        "Amazing3",
        "Amazing 3",
        "AMAZING ONLINE",
        NULL
    };
    for (int i = 0; game_names[i] != NULL; i++) {
        HWND hwnd = FindWindowA(NULL, game_names[i]);
        if (hwnd) {
            cout << " -> Найдено окно игры: " << game_names[i] << endl;
            return hwnd;
        }
    }
    HWND hwnd = FindWindowA("UnityWndClass", NULL);
    if (hwnd) {
        cout << " -> Найдено окно Unity игры" << endl;
        return hwnd;
    }
    cout << " -> Окно игры не найдено" << endl;
    return NULL;
}

// Улучшенная функция активации окна игры
void activateGameWindow(HWND hwnd) {
    if (hwnd) {
        cout << " -> Активирую окно игры..." << endl;
        for (int attempt = 0; attempt < 3; attempt++) {
            ShowWindow(hwnd, SW_RESTORE);
            SetForegroundWindow(hwnd);
            SetActiveWindow(hwnd);
            SetFocus(hwnd);
            Sleep(200);
            if (GetForegroundWindow() == hwnd) {
                cout << " -> Фокус успешно установлен." << endl;
                return;
            }
            cout << " [!] Попытка " << attempt + 1 << "/3: Не удалось установить фокус." << endl;
        }
        cout << " [!] Предупреждение: Не удалось установить фокус на окно игры после 3 попыток." << endl;
    }
}

// Функция сравнения с порогом сходства
bool matchTemplateLowLevel(const Mat& screen, const Mat& template_img, double threshold = 0.3) noexcept {
    if (template_img.empty() || screen.empty()) {
        return false;
    }
    int result_cols = screen.cols - template_img.cols + 1;
    int result_rows = screen.rows - template_img.rows + 1;
    if (result_cols <= 0 || result_rows <= 0) {
        return false;
    }
    Mat result;
    try {
        result.create(result_rows, result_cols, CV_32FC1);
        matchTemplate(screen, template_img, result, TM_CCOEFF_NORMED);
        double minVal, maxVal;
        Point minLoc, maxLoc;
        minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);
        cout << "Совпадение для " << template_img.cols << "x" << template_img.rows << ": maxVal = " << maxVal << " at (" << maxLoc.x << ", " << maxLoc.y << ")" << endl;
        return maxVal > threshold;
    }
    catch (...) {
        cout << "[-] Ошибка в matchTemplateLowLevel" << endl;
        return false;
    }
}

// Захват всего экрана
Mat captureFullScreen() {
    int screenWidth = GetSystemMetrics(SM_CXSCREEN);
    int screenHeight = GetSystemMetrics(SM_CYSCREEN);
    HDC hScreenDC = GetDC(NULL);
    HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
    HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, screenWidth, screenHeight);
    HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemoryDC, hBitmap);
    BitBlt(hMemoryDC, 0, 0, screenWidth, screenHeight, hScreenDC, 0, 0, SRCCOPY | CAPTUREBLT);
    BITMAPINFO bmi = { 0 };
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = screenWidth;
    bmi.bmiHeader.biHeight = -screenHeight;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biCompression = BI_RGB;
    Mat screenMat(screenHeight, screenWidth, CV_8UC4);
    GetDIBits(hScreenDC, hBitmap, 0, screenHeight, screenMat.data, &bmi, DIB_RGB_COLORS);
    SelectObject(hMemoryDC, hOldBitmap);
    DeleteObject(hBitmap);
    DeleteDC(hMemoryDC);
    ReleaseDC(NULL, hScreenDC);
    Mat bgrScreen;
    cvtColor(screenMat, bgrScreen, COLOR_BGRA2BGR);
    return bgrScreen;
}

int main()
{
    cout << "=== Автоматизация добычи руды ===" << endl;
    cout << "Агрессивный режим нажатий клавиш" << endl;
    cout << "=================================" << endl;
    disableOpenCVParallel(); // Отключение параллельных бэкендов
    // Загрузка шаблонов
    vector<pair<Mat, string>> templates;
    vector<string> filenames = {
        "F.png", "H.png", "Q.png", "R.png", "V.png", "W.png",
        "B.png", "D.png", "Space.png",
        "Left Arrow.png", "Right Arrow.png", "Up Arrow.png", "Down Arrow.png",
        "Left Shift.png"
    };
    int loaded_templates = 0;
    cout << "Проверка загрузки шаблонов из: " << template_dir << endl;
    for (const auto& fname : filenames) {
        string path = template_dir + fname;
        Mat img = imread(path, IMREAD_COLOR);
        if (!img.empty()) {
            templates.push_back({ img, fname });
            cout << "[+] Загружен шаблон: " << fname << " (" << img.cols << "x" << img.rows << ")" << endl;
            loaded_templates++;
        }
        else {
            cout << "[-] Не удалось загрузить шаблон: " << fname << " (Проверьте путь: " << path << ")" << endl;
        }
    }
    cout << "Всего загружено шаблонов: " << loaded_templates << endl;
    cout << "=================================" << endl;
    if (loaded_templates == 0) {
        cout << "ОШИБКА: Не загружено ни одного шаблона! Убедитесь, что папка 'photo' с изображениями находится в директории исполняемого файла." << endl;
        return -1;
    }
    // Найти окно игры один раз
    HWND game_hwnd = findGameWindow();
    if (game_hwnd) {
        cout << "[i] Окно игры найдено, используем агрессивные методы" << endl;
    }
    else {
        cout << "[!] Окно игры не найдено, используем только глобальные методы" << endl;
    }
    int matches_found = 0;
    string last_key_pressed = "";
    // Основной цикл
    while (true) {
        static int frame_counter = 0;
        frame_counter++;
        // Захват экрана
        Mat screen = captureFullScreen();
        if (screen.empty()) {
            cout << "[-] Ошибка: Пустой захват экрана, пауза 1s" << endl;
            Sleep(1000);
            continue;
        }
        // Отладка каждые 100 кадров
        if (frame_counter % 100 == 0) {
            cout << "[i] Кадр " << frame_counter << ": " << screen.cols << "x" << screen.rows << endl;
        }
        // Поиск шаблонов
        bool new_key_detected = false;
        for (const auto& [template_img, filename] : templates) {
            if (matchTemplateLowLevel(screen, template_img, 0.3)) {
                size_t dot_pos = filename.find(".png");
                if (dot_pos != string::npos) {
                    string key_name = filename.substr(0, dot_pos);
                    if (key_map.find(key_name) != key_map.end()) {
                        if (key_name != last_key_pressed) {
                            matches_found++;
                            cout << "[***] НАЙДЕНА КНОПКА " << matches_found << ": " << key_name
                                << " (кадр " << frame_counter << ")" << endl;
                            activateGameWindow(game_hwnd);
                            auto key_pair = key_map.at(key_name);
                            for (int attempt = 1; attempt <= 3; attempt++) {
                                cout << " -> Попытка зажатия " << attempt << "/3..." << endl;
                                simulateKeyHold(key_pair.first, key_pair.second, game_hwnd);
                                Sleep(1000); // Задержка между попытками
                                // Проверка, не появилась ли новая кнопка
                                Mat new_screen = captureFullScreen();
                                bool other_key = false;
                                for (const auto& [new_template, new_filename] : templates) {
                                    if (new_filename != filename && matchTemplateLowLevel(new_screen, new_template, 0.3)) {
                                        other_key = true;
                                        break;
                                    }
                                }
                                if (other_key) {
                                    cout << " -> Обнаружена новая кнопка, прерывание повторений." << endl;
                                    break;
                                }
                            }
                            last_key_pressed = key_name;
                            new_key_detected = true;
                            Sleep(5000); // Задержка для обновления экрана
                        }
                    }
                }
            }
        }
        if (!new_key_detected) {
            Sleep(300); // Задержка, если нет новых совпадений
        }
    }
    return 0;
}
 

maras_

Участник
Автор темы
41
2
Проблема в том что код написан при помощи чат гпт судя по комментариям к каждой функциии
Разве коды для клавиш не выглядят следующим образом:
VK_F
VK_H
VK_Q
итд...
Изначальная версия была написана без гпт но гпт испытал все варианты эмуляции как цифрами так и разными способами