Evilhack

From BigPackets Game Hacking Wiki

evilhack was a hack for America's Army in 2005/2006.

It was coded by evilbert.

Projectile Prediction

Here are the maths to the projectile prediction system it has

static CInt2 GetTrajectory(const double& Gravity, const double& Distance, const double& Height, const double& Velocity)
{
	double kd2 = (Gravity * Distance * Distance) / (2.0 * Velocity * Velocity);
	double a = kd2;
	double b = Distance;
	double c = Height + kd2;

	return CInt2(RadianToDegree(ATan2((b + sqrt((b * b) - (4 * a * c))), (2 * a))), RadianToDegree(ATan2((b - sqrt((b * b) - (4 * a * c))), (2 * a))));
}

static double GetMaxDistAngle(const double& Gravity, const double& Height, const double& Velocity)
{
	double e = 2 * Gravity * -Height / (Velocity * Velocity);
	return ACos(Sqrt((1 + e) / (2 + e)));
}

static double GetMaxDist(const double& Gravity, const double& Height, const double& Velocity)
{
	double e = 2 * Gravity * -Height / (Velocity * Velocity);
	double angl = GetMaxDistAngle(Gravity, Height, Velocity);

	return (Velocity * Velocity / Gravity) * (0.5 * Sin(2 * angl) + Cos(angl) * Sqrt(Sin(angl) * Sin(angl) + e));
}

static double GetTimeToDist(const double& HorizontalDistance, const double& Angle, const double& Velocity)
{
	double HorizontalVelocity = Cos(Angle) * Velocity;
	return HorizontalDistance / HorizontalVelocity;
}

Lead Prediction

Some usage, if you can understand it

GRAVITY = 9.8;
static const double TOLERANCE = 0.5;
static const double VEL203 = 250 * 0.3048;	//for m203 and gp-30
static const double VELRPG = 393 * 0.3048;	//for RPG-7 and AT-4 (300 m/s rocket burnout velocity for RPG-7 and 290 m/s muzzle velocity for AT-4 presumed to result in the same 950 fps) 120 m/s
static unsigned int OldTarget = -1;
static bool bHElevMode = false;
static bool bArty = false;
static bool bLeading = false;
static UINT_PTR pTimer = NULL;
static double OldTargetX = 0;
static double OldTargetY = 0;
static double OldTargetZ = 0;
static double OldTHeadingX = 0;
static double OldTHeadingZ = 0;
static unsigned int Coordinates = -1;
#define VIEWPORT_RADIUS_STANDING	-6.78f
#define VIEWPORT_RADIUS_PRONE		33.255f
#define CHANGERATE_TRIGGER		7.132f		//Trigger value for min target movement for LeadCalc, resolves to 5 meters per second
#define TRACKING_RANGE_GRENADE		30		//Min range of enabling lead calculation for grenades in meters
#define TRACKING_RANGE_BULLET		5		//Min range of enabling lead calculation for bullet weapons in meters	
#define SAMPLING_INTERVAL		77		//Time between target position saves in ms	
#define RESOLUTION			10		//Feedback loop resolution, max difference between time comparisons, in ms
#define	D3D2M	36.15
static void LeadCalc(D3DVECTOR Camera, bool bGrenade, unsigned int NearestPlayer, double *pTHeadingX, double *pTHeadingZ, double *pTargetX, double *pTargetY, double *pTargetZ)
{
	static double SChangeX = 0;
	static double SChangeY = 0;
	static double SChangeZ = 0;
	static double SDiffTime = 0;
	static double AimerTime = 0;

	double NowTime = 1;
	if (NowTime == -1)
		return;


	double distxy = 0;
	double distxyz = 0;
	double DiffTime = 0;
	double CompTime = 0;
	double CTITime = 0;


	//Get current current camera location and distance to target in meters
	distxy = sqrt(pow(fabs(*pTargetX - Camera.x), 2) + pow(fabs(*pTargetY - Camera.y), 2));
	distxyz = sqrt(pow(distxy, 2) + pow(fabs(*pTargetZ - Camera.z), 2));
	distxyz /= D3D2M;


	double TempWMx = *pTargetX;
	double TempWMy = *pTargetY;
	double TempWMz = *pTargetZ;
	DiffTime = NowTime - AimerTime;


	if (NearestPlayer != OldTarget || DiffTime > 500)	//Reset some stuff if new target or old data
	{
		AimerTime = NowTime;
		OldTargetX = *pTargetX;
		OldTargetY = *pTargetY;
		OldTargetZ = *pTargetZ;
		SDiffTime = 0;
		DiffTime = 0;
	}


	if (DiffTime > SAMPLING_INTERVAL)			//Store coordinates if sampling interval reached
	{
		SChangeX = *pTargetX - OldTargetX;
		SChangeY = *pTargetY - OldTargetY;
		SChangeZ = *pTargetZ - OldTargetZ;
		SDiffTime = DiffTime;
		OldTargetX = *pTargetX;
		OldTargetY = *pTargetY;
		OldTargetZ = *pTargetZ;
		AimerTime = NowTime;
	}


	bLeading = false;

	if (SDiffTime == 0)
		return;


	if (bGrenade)
	{
		//Check for lead calculation treshold values
		if ((sqrt(pow(fabs(SChangeX), 2) + pow(fabs(SChangeY), 2)) > SDiffTime / CHANGERATE_TRIGGER) && distxyz > TRACKING_RANGE_GRENADE)
		{
			double DiffX = 0;
			double DiffY = 0;
			double DiffZ = 0;
			double DiffXY = 0;
			double DistXYm = 0;
			double MyWMHx = 0;
			double MyWMHz = 0;
			double Velocity = 0;
			double FBLTime = 11;
			double OldCTITime = 0;
			double Trajectory[2] = { 0 };



			//Velocity = 28.8;
			Velocity = VEL203;





			//Add GetPing here
			while (FBLTime > RESOLUTION)	//Until feadback loop reaches required precission of 10 ms, < 1 meter
			{
				//Convert predicted target location to heading angle X
				DiffX = Camera.x - TempWMx;
				DiffY = Camera.y - TempWMy;
				DiffZ = Camera.z - TempWMz;
				DiffXY = sqrt(pow(DiffX, 2) + pow(DiffY, 2));


				/*if (GameInfo.m_StatusMovement == MOVEMENT_PRONE)
					MyWMHx = -(float)D3DXToDegree(atan2(DiffXY - VIEWPORT_RADIUS_PRONE, DiffZ)) + 180;
				else*/
					MyWMHx = -(float)D3DXToDegree(atan2(DiffXY + VIEWPORT_RADIUS_STANDING, DiffZ)) + 180;


				//Calculate horizontal distances in meters 
				DistXYm = sqrt(pow(fabs(DiffX), 2) + pow(fabs(DiffY), 2)) / D3D2M;

				//Get flighttime plus ping, compare it to true recorded sample interval
				GetTrajectory(DistXYm, fabs(DiffZ) / D3D2M, Velocity, *Trajectory);
				CTITime = (1000 * GetTimeToDist(DistXYm, D3DXToRadian(Trajectory[0] - MyWMHx), Velocity)) + (/*GameInfo.m_PingDelay*/10 / 2);
				CompTime = CTITime / SDiffTime;

				//Advance the target location with the current estimate for the command to impact time
				TempWMx = *pTargetX + (SChangeX * CompTime);
				TempWMy = *pTargetY + (SChangeY * CompTime);
				TempWMz = *pTargetZ + (SChangeZ * CompTime);

				//Get the total CTI time difference between previus iteration to see if we're close enough
				FBLTime = fabs(CTITime - OldCTITime);
				OldCTITime = CTITime;
			}
			//Z coordinate heading is not needed in the FBL, so leave it later to save a few cycles
			MyWMHz = (float)D3DXToDegree(atan2(DiffY, DiffX)) - 90;


			if (MyWMHz < -180)
				MyWMHz += 360;
			else if (MyWMHz > 180)
				MyWMHz -= 360;


			/*if (GameInfo.m_StatusMovement == MOVEMENT_PRONE)
				MyWMHz -= (float)((VIEWPORT_RADIUS_PRONE / 2 * 180) / (2 * D3DX_PI * DiffXY));*/


			*pTargetX = TempWMx;
			*pTargetY = TempWMy;
			*pTargetZ = TempWMz;
			*pTHeadingX = MyWMHx;
			*pTHeadingZ = MyWMHz;
			bLeading = true;
		}
	}
	else
	{
		//Check for lead calculation treshold values
		if ((sqrt(pow(fabs(SChangeX), 2) + pow(fabs(SChangeY), 2)) > SDiffTime / CHANGERATE_TRIGGER) && distxyz > TRACKING_RANGE_BULLET)
		{
			//Add GetPing here
			CompTime = (/*GameInfo.m_PingDelay*/10 / 2) / SDiffTime;
			TempWMx = *pTargetX + (SChangeX * CompTime);
			TempWMy = *pTargetY + (SChangeY * CompTime);
			TempWMz = *pTargetZ + (SChangeZ * CompTime);


			//Convert predicted target location to heading angles for aiming, creating a ghost aiming point
			double DiffX, DiffY, DiffZ, DiffXY, MyWMHx, MyWMHz;
			DiffX = Camera.x - TempWMx;
			DiffY = Camera.y - TempWMy;
			DiffZ = Camera.z - TempWMz;
			DiffXY = sqrt(pow(DiffX, 2) + pow(DiffY, 2));
			MyWMHz = (float)D3DXToDegree(atan2(DiffY, DiffX)) - 90;


			if (MyWMHz < -180)
				MyWMHz += 360;
			else if (MyWMHz > 180)
				MyWMHz -= 360;

			/*if (GameInfo.m_StatusMovement == MOVEMENT_PRONE)
			{
				MyWMHx = -(float)D3DXToDegree(atan2(DiffXY - VIEWPORT_RADIUS_PRONE, DiffZ)) + 180;
				MyWMHz -= (float)((VIEWPORT_RADIUS_PRONE / 2 * 180) / (2 * D3DX_PI * DiffXY));
			}
			else*/
				MyWMHx = -(float)D3DXToDegree(atan2(DiffXY + VIEWPORT_RADIUS_STANDING, DiffZ)) + 180;


			*pTHeadingX = MyWMHx;
			*pTHeadingZ = MyWMHz;
			bLeading = true;
		}
	}
}