2

I've written an aimbot for an open-source shooter called Assault Cube. Here is part of the source code:

Main.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

Calculations.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

Errors:

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

All these errors are because Calculations does not have access to the players array in Main. Is there any way I can give Calculations access to the players array?

Also, let me know if my decision of making Calculations a namespace was correct.

3 Answers3

3

Add at the beginning of Calculations.h

extern Player players[32];

to tell the compiler to get the definition of players in another location / file.

The extern keyword is equivalent to declare without defining. It is a way to explicitly declare a variable, or to force a declaration without a definition...

The extern keyword declares a variable or function and specifies that it has external linkage (its name is visible from files other than the one in which it's defined). When modifying a variable, extern specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends). The variable or function may be defined in another source file, or later in the same file. Declarations of variables and functions at file scope are external by default.

Source here (+examples) and here.

Last Note : extern doesn't behave the same for functions and variables. more.

Community
  • 1
  • 1
Gauthier Boaglio
  • 10,054
  • 5
  • 48
  • 85
2

Put:

extern Player players[32];

Somewhere before line 26 of Calculations.h.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
0

Having a global player array, as it would be with the extern keyword, is certainly not a good design decision.

A better design would probably define a world object that knows about anything that is currently in existence and could define what information is available to which actor. Players would then query this world object for information on their surrounding and make decisions based on that.

You might want to implement this world as a singleton, so that you can write static wrapper functions that silently supply the object to the calls, avoiding the hassle to look up the world object everywhere.

cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106