首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于开源FPS游戏攻击立方体的Aimbot

用于开源FPS游戏攻击立方体的Aimbot
EN

Code Review用户
提问于 2013-05-23 02:02:13
回答 2查看 13K关注 0票数 12

实际上,我对C++非常陌生,尽管我以前用Java编程过。您认为我有什么方法可以提高可读性、可维护性和性能,并使其更面向对象吗?

代码语言:javascript
复制
/*
    Control + 0 = enable aimbot
*/

#include "stdafx.h"
#include <math.h>

const float pi = 3.14159265358979f;

/*
  * I am using int* as if it were the same thing as int**, int***, etc.
  * Another more elegant looking method is to use int as if it were int*, int**, etc
  * but it is more prone to undefined behaviour and I am more likely to get away with the first method.
  * See: http://stackoverflow.com/questions/16256158/dereferencing-a-double-level-pointer-results-in-different-behaviour-from-derefer
*/
int* getClosestPointer(int** basePointer, int offsets[], int levels) {
    for (int i = 0; i < levels; i++) {
        basePointer = (int**) (*basePointer + offsets[i] / sizeof(int));
    }
    return (int*) basePointer;
}

/*
  [Player base] = A
  [A + 34] = X
  [A + 38] = Y
  [A + 3C] = Z
  [A + 40] = Crosshair X
  [A + 44] = Crosshair Y
  [A + F4] = HP
  [A + 154] = Grenades
*/
int playerBaseXOffsets[] = { 0x34 };
int playerBaseYOffsets[] = { 0x38 };
int playerBaseZOffsets[] = { 0x3C };
int playerBaseCXOffsets[] = { 0x40 };
int playerBaseCYOffsets[] = { 0x44 };
int playerBaseHPOffsets[] = { 0xF4 };
int playerBaseAmmoOffsets[] = { 0x368, 0x14, 0 };
int playerBaseGrenadesOffsets[] = { 0x154 };

typedef struct Player {
    int** basePointer;
    float* xPointer;
    float* yPointer;
    float* zPointer;
    float* cXPointer;
    float* cYPointer;
    int* hpPointer;
    int* ammoPointer;
    int* grenadesPointer;

    Player() {
    }

    Player(int** basePtr) {
        basePointer = basePtr;
        xPointer = (float*) getClosestPointer(basePointer, playerBaseXOffsets, sizeof(playerBaseXOffsets) / sizeof(playerBaseXOffsets[0]));
        yPointer = (float*) getClosestPointer(basePointer, playerBaseYOffsets, sizeof(playerBaseYOffsets) / sizeof(playerBaseYOffsets[0]));
        zPointer = (float*) getClosestPointer(basePointer, playerBaseZOffsets, sizeof(playerBaseZOffsets) / sizeof(playerBaseZOffsets[0]));
        cXPointer = (float*) getClosestPointer(basePointer, playerBaseCXOffsets, sizeof(playerBaseCXOffsets) / sizeof(playerBaseCXOffsets[0]));
        cYPointer = (float*) getClosestPointer(basePointer, playerBaseCYOffsets, sizeof(playerBaseCYOffsets) / sizeof(playerBaseCYOffsets[0]));
        hpPointer = getClosestPointer(basePointer, playerBaseHPOffsets, sizeof(playerBaseHPOffsets) / sizeof(playerBaseHPOffsets[0]));
        ammoPointer = getClosestPointer(basePointer, playerBaseAmmoOffsets, sizeof(playerBaseAmmoOffsets) / sizeof(playerBaseAmmoOffsets[0]));
        grenadesPointer = getClosestPointer(basePointer, playerBaseGrenadesOffsets, sizeof(playerBaseGrenadesOffsets) / sizeof(playerBaseGrenadesOffsets[0]));
    }
} Player;

Player players[32] = { };

/* Pythagorean's theorem (flavour for 3D) */
float getDistanceBetween(Player one, Player two) {
    return sqrt(
        (*(one.xPointer)-*(two.xPointer))*(*(one.xPointer)-*(two.xPointer))
        + (*(one.yPointer)-*(two.yPointer))*(*(one.yPointer)-*(two.yPointer))
        + (*(one.zPointer)-*(two.zPointer))*(*(one.zPointer)-*(two.zPointer))
        );
}

int getNumberOfPlayers() {
    return *((int*) ((UINT) GetModuleHandleW(0) + 0xE4E10));
}

Player* getClosestTarget() {
    float smallestDistance;
    int index = -1;
    for (int i = 1; i < getNumberOfPlayers(); i++) {
        if (*(players[i].hpPointer) > 0) {
            float tempDistance = getDistanceBetween(players[0], players[i]);
            if (index == -1 || tempDistance < smallestDistance) {
                smallestDistance = tempDistance;
                index = i;
            }
        }
    }
    if (index == -1) {
        return NULL;
    } else {
        return &players[index];
    }
}

/* Gets the crosshair horizontal angle in degrees. */
float getCX(Player me, Player target) {
    float deltaX = *(target.xPointer) - *(me.xPointer);
    float deltaY = *(me.yPointer) - *(target.yPointer);
    if (*(target.xPointer) > *(me.xPointer) && *(target.yPointer) < *(me.yPointer)) {
        return atanf(deltaX/deltaY) * 180.0f / pi;
    } else if(*(target.xPointer) > *(me.xPointer) && *(target.yPointer) > *(me.yPointer)) {
        return atanf(deltaX/deltaY) * 180.0f / pi + 180.0f;
    } else if(*(target.xPointer) < *(me.xPointer) && *(target.yPointer) > *(me.yPointer)) {
        return atanf(deltaX/deltaY) * 180.0f / pi - 180.0f;
    } else {
        return atanf(deltaX/deltaY) * 180.0f / pi + 360.0f;
    }
}

/* Gets the crosshair vertical angle in degrees. */
float getCY(Player me, Player target) {
    float deltaZ = *(target.zPointer) - *(me.zPointer);
    float dist = getDistanceBetween(me, target);
    return asinf(deltaZ/dist) * 180.0f / pi;
}

int main() {
    bool aimbotEnabled = false;
    Player* closestTargetPointer = NULL;

    // [Base + DF73C] = Player 1 base
    players[0] = Player((int**) ((UINT) GetModuleHandleW(0) + 0xDF73C));
    int** extraPlayersBase = *((int***) ((UINT) GetModuleHandleW(0) + 0xE5F00));

    while (true) {
        // [Base + E5F00] = A
        // [A + 0,4,8...] = Player 2/3/4... base
        for (int i = 0; i < getNumberOfPlayers() - 1; i++) {
            players[i + 1] = Player(extraPlayersBase + i * 4 / sizeof(int*));
        }

        if (GetAsyncKeyState(VK_CONTROL) && GetAsyncKeyState('0')) {
            aimbotEnabled = !aimbotEnabled;
            Sleep(500);
        }

        if (aimbotEnabled) {
            closestTargetPointer = getClosestTarget();

            if (closestTargetPointer != NULL) {
                *(players[0].cXPointer) = getCX(players[0], *closestTargetPointer);
                *(players[0].cYPointer) = getCY(players[0], *closestTargetPointer);
            }
        }

        Sleep(10);
    }
}

DWORD WINAPI Main(LPVOID lpParam) {
    main();
    return S_OK;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved) {
    if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
        DisableThreadLibraryCalls(hModule);
        CreateThread(NULL, 0, &Main, NULL, 0, NULL);
    }
    return TRUE;
}
EN

回答 2

Code Review用户

发布于 2013-07-30 03:48:50

你的C++很像C。首先,我要利用C++:

  • 您几乎总是希望使用std::vector而不是数组。例如: std::vector播放器;players.reserve( 32 );这将创建一个足以容纳32 Players的向量。如果您需要更多的空间,当您添加更多的玩家时,该向量将自动增长。通过使用players.at(index)访问元素,您将得到范围检查。要获取vector中的元素数,可以使用players.size()而不是使用sizeof数组除法。
  • 您的struct类型胡枝子是C中的一个常见成语,因为在C中,需要用struct限定struct标识符才能使用它们:void foo(struct Bacon* bacon)。在C++中,您不必这样做。因此,我将把您对Player的定义更改为: class Player { public: // contents };
  • 通常应该封装Player中的变量。这意味着它们应该在类的private部分中定义(在public:之上)。如果您需要访问其他函数或类中的变量,则可以提供访问器函数: class Player { int** basePointer;public: int** getBasePointer() const {返回basePointer;};
  • 如果您真的想使用您的struct作为吊舱,我建议您在需要时制作成员const并复制一份。这不是必须的,但却减少了发生意外变化的可能性。
  • 简而言之,您的类( struct是类)可以而且很可能应该像类一样设计,而不是像POD那样设计。
  • 正如@Jamal所指出的,您可以使用enum作为偏移量:枚举偏移量{ playerBaseXOffset = 0x34,playerBaseYOffset = 0x38 /* . */ };如果希望以后有更多的偏移量,则使用std::vector:std::vector playerBaseXOffsets{ 0x34 };// C++11语法。注意最后一个示例中的{}。使用()代替编译,但意味着完全不同的东西!(它将默认构造0x34 =52个对象。)
  • 我不确定你的指针是否真的有必要。如果不是,我建议你避免这样做。它容易出错,一些潜在的错误很难找到。如果幸运的话,您可能会忘记取消指针的引用;如果没有,则会从违反严格的混叠规则获得未定义的行为。
  • 使用符号常数,而不是文字常量。例如: const std::size_t player_one_base_offset = 0xDF73C;Player0= Player((int**) ((int**)((Int) GetModuleHandleW(0) + player_one_base_offset));我相信您同意player_one_base_offset0xDF73C更可读性和可理解性。
  • 我通常会推荐C++风格的static_cast<type>(object),而不是C风格的(type)object转换,但在您的情况下,我认为它只会降低可读性而不会带来太大的好处。

最后,与代码无关的是:要么是毕达哥拉斯定理,要么是毕达哥拉斯定理。

票数 5
EN

Code Review用户

发布于 2013-07-29 22:49:13

  • 这是C++,而不是C,所以使用<cmath>而不是<math.h>
  • 使用更多的classes,这看起来更好,功能也更好,特别是因为它是一款游戏。例如,Player可以变成类而不是struct,这样就可以保持private。还应该有一个Game类来保存玩家的集合并处理游戏。您只需通过创建一个game在main()中启动游戏。请注意,main()不应该访问游戏中超出启动能力的任何内容。
  • 我同意@Lstor关于制作std::vector of Players的观点,这也允许您使用容器的迭代器访问每个玩家。如果有C++11,则有两个选项,取决于编译器是否支持基于范围的for-循环:如果它支持.用于(auto & player :player){ std::cout << player;}如果它没有.对于(auto = players.cbegin();iter != players.cend();++iter) { std::cout << * iter;}在您的游戏中,您将只对游戏类中的这个向量进行操作。这一点很重要,因为它不应该通过接口公开。您可以自由地定义显示函数(或重载operator<<),但不能破坏封装。
  • getCX()getCY()中的参数应该是const-ref,因为它们没有修改: float getCX(Player const& me,Player const& target) {} float getCY(Player const& me,Player const& target) {}
  • playerBaseOffsets看起来应该是const。我还喜欢比单个数组更简洁的东西,比如enum。还可以将其放入namespace中以避免名称冲突。
  • 特别应该使用STL来利用智能指针来代替原始指针(后者更像C)。除此之外,尽可能多地使用STL将大大地清理您的代码。对于一般的指针,如果您使用的是nullptr而不是NULL,则使用C++11。
  • 关于@Lstor的回答,请包含<cstddef>以便使用std::size_t
票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/26503

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档