Qt写游戏脚本/辅助(仅供参考)

写游戏脚本/辅助的背景

去年找了一款传奇游戏玩,后续发现现在的传奇游戏都是氪金为主,除了活动时间以外大家都是挂机刷混沌神石,然后再通过混沌神石换灵符,灵符又是零氪党快速提升实力的唯一绝经,后面就萌生了用脚本来刷混沌神石的想法。然后就通过"按键精灵"写了一个自动挂机(切图)刷混沌神石的脚本。随着时间的推移,后面又陆陆续续增加了功能,比如固定时间的活动(魔龙宝藏,世界BOSS,行会试炼等)。也用了很长一段时间,中途还在游戏里面跟别人吵架了,被别人开着榜一的号连续24小时追杀了好长一段时间,因为挂机的时候被杀的话就一直躺着,如果是晚上睡觉之后被别人杀了就很伤...然后就继续优化脚本,增加角色死亡检测和死亡自动复活等功能。总之在游戏里面通过脚本跟别人各种斗智斗勇,但是随着时间的推移,游戏里面增加的地图也越来越多,需要用到脚本做的事情也越来越多。最主要是把脚本给别人用,同时还要控制辅助的使用时间(过期不给用)。。。越到后面越发觉得用"按键精灵"写的脚本性能和UI界面(UI界面固定大小,放不下太多东西)不够用,然后今年就用Qt重构了脚本,把脚本的功能都通过Qt来实现。

一、用Qt写游戏脚本/辅助的前提准备工作

  1. 通过Qt界面来配置游戏参数

毕竟辅助是给别人(小白)使用的,所以界面是必须要有的,用Qt写界面这是基本操作

  1. 对游戏窗口实现鼠标点击操作

对游戏窗口实现鼠标点击操作最简单的是在屏幕对应的坐标点击鼠标左键/右键。但是大部分玩家都是游戏双开甚至多开,所以就不能直接点击屏幕,而是要实现后台操作(毕竟不可能每个窗口要操作的时候都临时切换到顶层来点击屏幕)。后台操作游戏窗口就离不开窗口句柄,游戏多开的情况下需要精准找到各个游戏的窗口句柄(精准区分大小号),再通过游戏窗口句柄实现相对坐标系统的鼠标点击。

  1. 对游戏窗口实现按键(键盘)操作

找到窗口句柄后,再通过游戏窗口句柄实现对窗口的按键操作

  1. 对游戏窗口进行监测

对游戏窗口的数据进行检测和分析,比如人物死亡检测,通常是检测人物血条,也就是对某一坐标的颜色进行抓取和判断。还有就是活动期间的检测,比如某一时间段到活动了,简单一点来就是获取电脑本地时间。

  1. 对辅助的时间控制

辅助毕竟是给别人用的,如何实现对辅助的时间控制,比如过期后就用不了。最简单的就是设置一个日期,每次运行辅助的时候检测本地时间,到期后就不能用。但是这个有一弊端,电脑本地时间是可以调准的。那就得获取网络时间,并且还要能动态控制时间,比如上服务器动态给辅助设置有效期。还有就是如何精准知道是哪一个用户等。。。

二、用Qt写游戏辅助的实现

  1. 辅助UI界面的实现
  1. 找到游戏的所有窗口句柄

找到所有窗口句柄

cpp 复制代码
// 枚举所有顶层窗口
EnumWindows(EnumWindowsProc, 0);

筛选需要的游戏窗口句柄,并且放到list中

cpp 复制代码
// 枚举顶层窗口的回调函数
BOOL CALLBACK Widget::EnumWindowsProc(HWND hwnd, LPARAM lParam) {
    // 获取窗口标题
    int length = GetWindowTextLength(hwnd);
    if (length > 0) {
        TCHAR *buffer = new TCHAR[length + 1];
        GetWindowText(hwnd, buffer, length + 1);
        QString windowTitle = QString::fromWCharArray(buffer);
        delete[] buffer;

        if (windowTitle.startsWith("霸者xx")) {
            qDebug() << "hwnd:" << hwnd  << ", title:" << windowTitle;
            hwndList.append(hwnd);
            hwndNameList.append(captureHiddenWindow(hwnd));
        }
    }

    return TRUE;
}
  1. 通过窗口句柄实现后台鼠标点击
cpp 复制代码
//后台点击
void Worker::backgroundClick(MyPoint point)
{
    if (!IsWindow(hwnd)) {
        qDebug() << "backgroundClick: 窗口不存在";
        return;
    }
    LPARAM lParam = MAKELPARAM(point.getX(), point.getY());
    PostMessage(hwnd, WM_MOUSEMOVE, 0, lParam);
    PostMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, lParam);
    PostMessage(hwnd, WM_LBUTTONUP, 0, lParam);
}
  1. 通过窗口句柄实现后台按键操作
cpp 复制代码
//后台按键
void Worker::backgroundKeyPress(int keyCode)
{
    if (!IsWindow(hwnd)) {
        qDebug() << "backgroundKeyPress: 窗口不存在";
        return;
    }
    DWORD dwVKFkeydata; //lParam 参数值
    WORD dwScanCode = MapVirtualKey(keyCode, MAPVK_VK_TO_VSC);
    dwVKFkeydata = 1;
    dwVKFkeydata |= dwScanCode << 16;
    dwVKFkeydata |= 0 << 24;
    dwVKFkeydata |= 1 << 29;
    PostMessage(hwnd, WM_KEYDOWN, keyCode, dwVKFkeydata);

    dwVKFkeydata = 1;
    dwVKFkeydata |= dwScanCode << 16;
    dwVKFkeydata |= 0 << 24;
    dwVKFkeydata |= 1 << 29;
    dwVKFkeydata |= 3 << 30;
    PostMessage(hwnd, WM_KEYUP, keyCode, dwVKFkeydata);
}
  1. 通过窗口句柄检测目标坐标点的颜色
cpp 复制代码
/**
 * @brief checkPixelColor   根据窗口句柄检查某一坐标是否是某颜色
 * @param hwnd  窗口句柄
 * @param point 检查的坐标
 * @param color 目标颜色
 * @return
 */
bool Widget::checkPixelColor(HWND hwnd, QPoint point, QColor color)
{
    if (!IsWindow(hwnd)) {
        qDebug() << "窗口不存在";
        return false;
    }

    //获取窗口上下文
    HDC hdc = GetDC(hwnd);
    if (hdc == NULL) {
        qDebug() << "hdc获取失败";
        return false;
    }
    COLORREF colorREF = GetPixel(hdc, point.x(), point.y());

    //释放窗口上下文
    ReleaseDC(hwnd, hdc);

    unsigned char red = GetRValue(colorREF);
    unsigned char geen = GetGValue(colorREF);
    unsigned char blue = GetBValue(colorREF);
    qDebug() << "R:" << red << ", G:" << geen << ", B:" << blue;

    if ((red > color.red() - 5 && red < color.red() + 5) && (geen > color.green() - 5 && geen < color.green() + 5) && (blue > color.blue() - 5 && blue < color.blue() + 5)) {
        return true;
    }
    return false;
}

三、后话

自己写的辅助给别人用的话,如果还需要控制辅助使用时间,最好是能有一个服务器。没有服务器也能实现,比如自己在某个网页写了一篇文章,在这篇文章里面按一定的格式写上时间,然后辅助启动的时候去访问这个文章的链接,并且获取到所有内容,并且提取出对应格式的内容,然后进行对比时间是否过期...要更新辅助的使用时间那就更新一下文章(修改一下里面的时间)。。。

相关推荐
樱木Plus15 小时前
深拷贝(Deep Copy)和浅拷贝(Shallow Copy)
c++
blasit2 天前
笔记:Qt C++建立子线程做一个socket TCP常连接通信
c++·qt·tcp/ip
肆忆_3 天前
# 用 5 个问题学懂 C++ 虚函数(入门级)
c++
不想写代码的星星4 天前
虚函数表:C++ 多态背后的那个男人
c++
xiezhr4 天前
米哈游36岁程序员被曝复工当晚猝死出租屋内
游戏·程序员·游戏开发
端平入洛5 天前
delete又未完全delete
c++
端平入洛6 天前
auto有时不auto
c++
哇哈哈20217 天前
信号量和信号
linux·c++
多恩Stone7 天前
【C++入门扫盲1】C++ 与 Python:类型、编译器/解释器与 CPU 的关系
开发语言·c++·人工智能·python·算法·3d·aigc
蜡笔小马7 天前
21.Boost.Geometry disjoint、distance、envelope、equals、expand和for_each算法接口详解
c++·算法·boost