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;
}

三、后话

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

相关推荐
liulilittle16 分钟前
DDD领域驱动中瘦模型与富态模型的核心区别
开发语言·c++·算法·ddd·领域驱动·思想
铭哥的编程日记36 分钟前
《C++ string 完全指南:string的模拟实现》
c++
Yu_Lijing42 分钟前
MySQL进阶学习与初阶复习第二天
数据库·c++·学习·mysql
l1t1 小时前
开源嵌入式数组引擎TileDB的简单使用
c语言·数据库·c++
上海云盾第一敬业销售2 小时前
手游遇攻击为何要用游戏盾SDK?
游戏
“αβ”3 小时前
线程安全的单例模式
linux·服务器·开发语言·c++·单例模式·操作系统·vim
byte轻骑兵3 小时前
【Bluedroid】bta_av_sink_media_callback(BTA_AV_SINK_MEDIA_CFG_EVT)流程源码分析
android·c++·bluedroid
打码农的篮球4 小时前
C++模板
开发语言·c++
德迅云安全杨德俊4 小时前
应用加速游戏盾的安全作用
网络·安全·游戏·ddos
嶔某4 小时前
网络:基础概念
linux·服务器·网络·c++