2

我为名为 Assault Cube 的开源射击游戏编写了一个瞄准机器人。以下是部分源代码:

主要.h:

/*
    Control + 0 = enable aimbot
    Control + 9 = enable vacuum hack
*/

#include "stdafx.h"
#ifndef MAIN_H
#define MAIN_H
#include "Player.h"
#include "Constants.h"
#include "Calculations.h"
#include <math.h>

Player players[32]; // need to give access to this to Calculations

int main() {
    bool aimbotEnabled = false;
    bool vacEnabled = false;
    Player* closestTargetPointer = nullptr;
    // [Base + DF73C] = Player 1 base
    players[0] = Player(reinterpret_cast<char**>(Constants::baseAddress + 0xDF73C));
    char** extraPlayersBase = *(reinterpret_cast<char***>(Constants::baseAddress + 0xE5F00));

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

    while (true) {
        if (GetAsyncKeyState(VK_CONTROL)) {
            if (GetAsyncKeyState('0')) {
                aimbotEnabled = !aimbotEnabled;
                Sleep(500);
            } else if (GetAsyncKeyState('9')) {
                vacEnabled = !vacEnabled;
                Sleep(500);
            }
        }

        if (aimbotEnabled) {
            closestTargetPointer = Calculations::getClosestTarget();

            if (closestTargetPointer != nullptr) {
                players[0].setCrosshairX(Calculations::getCrosshairHorizontalAngle(players[0], *closestTargetPointer));
                players[0].setCrosshairY(Calculations::getCrosshairVerticalAngle(players[0], *closestTargetPointer));
            }
        }

        if (vacEnabled) {
            for (int i = 1; i < Calculations::getNumberOfPlayers(); i++) {
                players[i].setX(players[0].getX() + 10);
                players[i].setY(players[0].getY());
                players[i].setZ(players[0].getZ());
            }
        }

        Sleep(10);
    }
}
#endif

计算.h:

#include "stdafx.h"
#ifndef CALCULATIONS_H
#define CALCULATIONS_H
#include "Player.h"
#include "Constants.h"

namespace Calculations {
    /* Pythagorean's theorem applied twice for getting distance between two players in 3D space */
    float getDistanceBetween(Player one, Player two) {
        return sqrt(
                   (one.getX() - two.getX()) * (one.getX() - two.getX())
                   + (one.getY() - two.getY()) * (one.getY() - two.getY())
                   + (one.getZ() - two.getZ()) * (one.getZ() - two.getZ())
               );
    }

    int getNumberOfPlayers() {
        return *(reinterpret_cast<int*>(Constants::baseAddress + 0xE4E10));
    }

    Player* getClosestTarget() {
        float smallestDistance;
        int index = -1;

        for (int i = 1; i < getNumberOfPlayers(); i++) {
            if (players[i].getHP() > 0 && players[i].isVisible()) { // this is an error, because Calculations does not have access to the players array in Main
                float tempDistance = getDistanceBetween(players[0], players[i]);

                if (index == -1 || tempDistance < smallestDistance) {
                    smallestDistance = tempDistance;
                    index = i;
                }
            }
        }

        if (index == -1) {
            return nullptr;
        } else {
            return &players[index];
        }
    }

    float getCrosshairHorizontalAngle(Player me, Player target) {
        float deltaX = target.getX() - me.getX();
        float deltaY = me.getY() - target.getY();

        if (target.getX() > me.getX() && target.getY() < me.getY()) {
            return atanf(deltaX / deltaY) * 180.0f / Constants::pi;
        } else if (target.getX() > me.getX() && target.getY() > me.getY()) {
            return atanf(deltaX / deltaY) * 180.0f / Constants::pi + 180.0f;
        } else if (target.getX() < me.getX() && target.getY() > me.getY()) {
            return atanf(deltaX / deltaY) * 180.0f / Constants::pi - 180.0f;
        } else {
            return atanf(deltaX / deltaY) * 180.0f / Constants::pi + 360.0f;
        }
    }

    float getCrosshairVerticalAngle(Player me, Player target) {
        float deltaZ = target.getZ() - me.getZ();
        float dist = getDistanceBetween(me, target);
        return asinf(deltaZ / dist) * 180.0f / Constants::pi;
    }
}
#endif

错误:

1>  Calculations.h
1>Calculations.h(26): error C2065: 'players' : undeclared identifier
1>Calculations.h(26): error C2228: left of '.getHP' must have class/struct/union
1>Calculations.h(26): error C2228: left of '.isVisible' must have class/struct/union
1>Calculations.h(27): error C2065: 'players' : undeclared identifier
1>Calculations.h(39): error C2065: 'players' : undeclared identifier

所有这些错误都是因为 Calculations 无法访问 Main 中的 player 数组。有什么办法可以让计算访问玩家数组?

另外,如果我将 Calculations 设为命名空间的决定是否正确,请告诉我。

4

3 回答 3

3

在开头添加Calculations.h

extern Player players[32];

告诉编译器players在另一个位置/文件中获取定义。

extern关键字相当于声明而不定义。这是一种显式声明变量或强制声明没有定义的方法......

extern 关键字声明一个变量或函数,并指定它具有外部链接(它的名称在定义它的文件之外的文件中可见)。修改变量时,extern 指定变量具有静态持续时间(在程序开始时分配,在程序结束时释放)。变量或函数可以在另一个源文件中定义,或者稍后在同一文件中定义。默认情况下,文件范围内的变量和函数声明是外部的。

来源here(+examples)和here

最后一点:extern对于函数和变量的行为不同。更多

于 2013-06-15T02:36:46.043 回答
2

放:

extern Player players[32];

在第 26 行之前的某处Calculations.h

于 2013-06-15T02:36:34.047 回答
0

拥有一个全局播放器数组,就像使用 extern 关键字一样,当然不是一个好的设计决策。

更好的设计可能会定义一个世界对象,该对象知道当前存在的任何事物,并可以定义哪些信息可供哪个参与者使用。然后,玩家将查询这个世界对象以获取有关其周围环境的信息,并据此做出决定。

您可能希望将这个世界实现为单例,这样您就可以编写静态包装函数,静默地将对象提供给调用,避免到处查找世界对象的麻烦。

于 2013-06-15T07:30:45.157 回答