
bool FakeEdge(float& angle)
{
	float edge_dist = 128;
	Vector position = g_Local.vEye;
	float closest_distance = 100.0f;
	float radius = edge_dist + 0.1f;
	float step = M_PI * 2.0 / 8;

	for (float a = 0; a < (M_PI * 2.0); a += step)
	{
		Vector location(radius * cos(a) + position.x, radius * sin(a) + position.y, position.z);

		pmtrace_t tr;

		g_Engine.pEventAPI->EV_SetTraceHull(2);
		g_Engine.pEventAPI->EV_PlayerTrace(position, location, PM_GLASS_IGNORE, -1, &tr);

		float distance = position.Distance(tr.endpos);

		if (distance < closest_distance)
		{
			closest_distance = distance;
			angle = RAD2DEG(a);
		}
	}
	return closest_distance < edge_dist;
}

void AntiAim(struct usercmd_s* cmd)
{
	if (cvar.rage_active && g_Local.bAlive)
	{
		int m_Use = (cmd->buttons & IN_USE);
		int m_InAttack = (cmd->buttons & IN_ATTACK);

		if (!m_Use && !(m_InAttack && CanAttack()))
		{
			FixMoveStart(cmd);

			int id = NULL;
			float flDist = 8192.f;

			for (unsigned int i = 0; i < 33; i++)
			{
				if (i == g_Local.iIndex)
					continue;

				if (!g_Player[id].bAlive)
					continue;

				if (!cvar.rage_team && g_Player[i].iTeam == g_Local.iTeam)
					continue;

				if (g_Player[i].flDist < flDist || id == NULL)
				{
					flDist = g_Player[i].flDist;
					id = i;
				}
			}

			Vector vAngles = cmd->viewangles;

			if (id > 0)
				VectorAngles(g_Player[id].pEnt->origin - g_Local.vEye, vAngles);

			//Yaw
			if (g_Local.flVelocity2D > 0)
			{
				if (cvar.aa_yaw_while_running > 0)
				{
					if (cvar.aa_yaw_while_running == 1)
					{//180
						cmd->viewangles.y = vAngles[1] + 180;
					}
					else if (cvar.aa_yaw_while_running == 2)
					{//180 Jitter
						static bool jitter = false;

						if (jitter)
							cmd->viewangles.y = vAngles[1] + 180;
						else
							cmd->viewangles.y = vAngles[1];

						jitter = !jitter;
					}
					else if (cvar.aa_yaw_while_running == 3)
					{//Spin
						int spin = 30;
						cmd->viewangles.y = fmod(g_Engine.GetClientTime() * spin * 360.0f, 360.0f);
					}
					else if (cvar.aa_yaw_while_running == 4)
					{//Jitter
						static unsigned int m_side = 0;

						if (m_side == 0)
							cmd->viewangles.y = vAngles[1] + 0;
						else if (m_side == 1)
							cmd->viewangles.y = vAngles[1] + 90;
						else if (m_side == 2)
							cmd->viewangles.y = vAngles[1] + 180;
						else if (m_side >= 3) {
							cmd->viewangles.y = vAngles[1] + -90;
							m_side = 0;
						}

						m_side++;
					}
					else if (cvar.aa_yaw_while_running == 5) {//Sideway
						static bool jitter = false;

						if (jitter)
							cmd->viewangles.y = vAngles[1] + 90;
						else
							cmd->viewangles.y = vAngles[1] - 90;

						jitter = !jitter;
					}
					else if (cvar.aa_yaw_while_running == 6) {//Random
						cmd->viewangles.y = rand() % 361;
						if (cmd->viewangles.y > 180)
							cmd->viewangles.y -= 360;
					}
					else if (cvar.aa_yaw_while_running == 7) {//Static
						cmd->viewangles.y = vAngles[1] + cvar.aa_yaw_static;
					}
				}

				float angle = cmd->viewangles.y;

				if ((cvar.aa_edge == 2 || cvar.aa_edge == 3) && FakeEdge(angle))
					cmd->viewangles.y = angle;
			}
			else
			{
				if (cvar.aa_yaw > 0)
				{
					if (cvar.aa_yaw == 1)
					{//180
						cmd->viewangles.y = vAngles[1] + 180;
					}
					else if (cvar.aa_yaw == 2)
					{//180 Jitter
						static bool jitter = false;

						if (jitter)
							cmd->viewangles.y = vAngles[1] + 180;
						else
							cmd->viewangles.y = vAngles[1];

						jitter = !jitter;
					}
					else if (cvar.aa_yaw == 3)
					{//Spin
						int spin = 30;
						cmd->viewangles.y = fmod(g_Engine.GetClientTime() * spin * 360.0f, 360.0f);
					}
					else if (cvar.aa_yaw == 4)
					{//Jitter
						static unsigned int m_side = 0;

						if (m_side == 0)
							cmd->viewangles.y = vAngles[1] + 0;
						else if (m_side == 1)
							cmd->viewangles.y = vAngles[1] + 90;
						else if (m_side == 2)
							cmd->viewangles.y = vAngles[1] + 180;
						else if (m_side >= 3) {
							cmd->viewangles.y = vAngles[1] + -90;
							m_side = 0;
						}

						m_side++;
					}
					else if (cvar.aa_yaw == 5)
					{//Sideway
						static bool jitter = false;

						if (jitter)
							cmd->viewangles.y = vAngles[1] + 90;
						else
							cmd->viewangles.y = vAngles[1] - 90;

						jitter = !jitter;
					}
					else if (cvar.aa_yaw == 6)
					{//Random
						cmd->viewangles.y = rand() % 361;
						if (cmd->viewangles.y > 180)
							cmd->viewangles.y -= 360;
					}
					else if (cvar.aa_yaw == 7)
					{//Static
						cmd->viewangles.y = vAngles[1] + cvar.aa_yaw_static;
					}
				}

				float angle = cmd->viewangles.y;

				if ((cvar.aa_edge == 1 || cvar.aa_edge == 3 || cvar.aa_edge == 4) && FakeEdge(angle))
				{
					static float timer = g_Local.weapon.curtime;

					if (g_Local.weapon.curtime - timer > 3 && cvar.aa_edge == 4)
					{
						timer = g_Local.weapon.curtime;

						cmd->viewangles.y = angle + 180;
					}
					else {
						cmd->viewangles.y = angle;
					}
				}
			}

			//Roll
			if (g_Local.flVelocity2D > 0)
			{
				if (cvar.aa_roll_while_running > 0)
				{
					if (cvar.aa_roll_while_running == 1)
					{//180
						cmd->viewangles.z = 180;
					}
					else if (cvar.aa_roll_while_running == 2)
					{//180 Jitter
						static bool jitter = false;

						if (jitter)
							cmd->viewangles.z = 180;

						jitter = !jitter;
					}
					else if (cvar.aa_roll_while_running == 3)
					{//Spin
						int spin = 30;
						cmd->viewangles.z = fmod(g_Engine.GetClientTime() * spin * 360.0f, 360.0f);
					}
					else if (cvar.aa_roll_while_running == 4)
					{//Jitter
						static unsigned int m_side = 0;

						if (m_side == 1)
							cmd->viewangles.z = 90;
						else if (m_side == 2)
							cmd->viewangles.z = 180;
						else if (m_side >= 3) {
							cmd->viewangles.z = -90;
							m_side = 0;
						}

						m_side++;
					}
					else if (cvar.aa_roll_while_running == 5) {//Sideway
						static bool jitter = false;

						if (jitter)
							cmd->viewangles.z = 90;
						else
							cmd->viewangles.z = -90;

						jitter = !jitter;
					}
					else if (cvar.aa_roll_while_running == 6) {//Random
						cmd->viewangles.z = rand() % 361;
						if (cmd->viewangles.z > 180)
							cmd->viewangles.z -= 360;
					}
					else if (cvar.aa_roll_while_running == 7) {//Static
						cmd->viewangles.z = cvar.aa_yaw_static;
					}
				}

				float angle = cmd->viewangles.z;

				if ((cvar.aa_edge == 2 || cvar.aa_edge == 3) && FakeEdge(angle))
					cmd->viewangles.z = angle;
			}
			else
			{
				if (cvar.aa_roll > 0)
				{
					if (cvar.aa_roll == 1)
					{//180
						cmd->viewangles.z = 180;
					}
					else if (cvar.aa_roll == 2)
					{//180 Jitter
						static bool jitter = false;

						if (jitter)
							cmd->viewangles.z = 180;

						jitter = !jitter;
					}
					else if (cvar.aa_roll == 3)
					{//Spin
						int spin = 30;
						cmd->viewangles.z = fmod(g_Engine.GetClientTime() * spin * 360.0f, 360.0f);
					}
					else if (cvar.aa_roll == 4)
					{//Jitter
						static unsigned int m_side = 0;

						if (m_side == 1)
							cmd->viewangles.z = 90;
						else if (m_side == 2)
							cmd->viewangles.z = 180;
						else if (m_side >= 3) {
							cmd->viewangles.z = -90;
							m_side = 0;
						}

						m_side++;
					}
					else if (cvar.aa_roll == 5)
					{//Sideway
						static bool jitter = false;

						if (jitter)
							cmd->viewangles.z = 90;
						else
							cmd->viewangles.z = -90;

						jitter = !jitter;
					}
					else if (cvar.aa_roll == 6)
					{//Random
						cmd->viewangles.z = rand() % 361;
						if (cmd->viewangles.z > 180)
							cmd->viewangles.z -= 360;
					}
					else if (cvar.aa_roll == 7)
					{//Static
						cmd->viewangles.z = cvar.aa_roll_static;
					}
				}

				float angle = cmd->viewangles.z;

				if ((cvar.aa_edge == 1 || cvar.aa_edge == 3 || cvar.aa_edge == 4) && FakeEdge(angle))
				{
					static float timer = g_Local.weapon.curtime;

					if (g_Local.weapon.curtime - timer > 3 && cvar.aa_edge == 4)
					{
						timer = g_Local.weapon.curtime;

						cmd->viewangles.z = angle + 180;
					}
					else {
						cmd->viewangles.z = angle;
					}
				}
			}

			//Pitch
			if (cvar.aa_pitch > 0)
			{
				if (cvar.aa_pitch == 1)
				{//Fakedown
					cmd->viewangles.x = 180;
				}
				if (cvar.aa_pitch == 2)
				{//Random
					cmd->viewangles.x = rand() % 361;
					if (cmd->viewangles.x > 180)
						cmd->viewangles.x -= 360;
				}
			}

			FixMoveEnd(cmd);
		}
	}
}

void FakeLag(struct usercmd_s* cmd)
{
	if (cvar.rage_active && cvar.fakelag_active && g_Local.bAlive)
	{
		int m_InAttack = (cmd->buttons & IN_ATTACK);

		bool fakelag = false;

		if (!(m_InAttack && CanAttack()))
			fakelag = true;

		if (cvar.fakelag_while_shooting && m_InAttack && CanAttack())
			fakelag = true;

		if (cvar.fakelag_move == 0)//On land
		{
			if (g_Local.flVelocity2D > 0)
				fakelag = false;
		}
		else if (cvar.fakelag_move == 1)//On move
		{
			if (g_Local.flVelocity2D <= 0)
				fakelag = false;
		}
		else if (cvar.fakelag_move == 2)//In air
		{
			if (g_Local.flHeightorigin <= 0)
				fakelag = false;
		}

		if (fakelag)
		{
			static int choked = 0;
			static int good = 0;

			if (cvar.fakelag_type == 0)//Dynamic
			{
				if (choked < cvar.fakelag_limit)
				{
					bSendpacket(false);

					choked++;

					good = 0;
				}
				else {
					float one = cvar.fakelag_limit / 100;
					float tmp = one * cvar.fakelag_variance;

					good++;

					if (good > tmp) {
						choked = 0;
					}
				}
			}
			else if (cvar.fakelag_type == 1)//Maximum
			{
				choked++;

				if (choked > 0)
					bSendpacket(false);

				if (choked > cvar.fakelag_limit)
					choked = -1;//1 tick valid
			}
			else if (cvar.fakelag_type == 2)//Flucture
			{
				static bool jitter = false;

				if (jitter)
					bSendpacket(false);

				jitter = !jitter;
			}
			else if (cvar.fakelag_type == 3)//Break lag compensation
			{
				Vector velocity = g_Local.vVelocity;
				velocity.z = 0;

				float len = velocity.Length() * g_Local.flFrametime;

				if (len < 64.0f && velocity.Length() > 0.05f)
				{
					int need_choke = 64.0f / len;

					if (need_choke > cvar.fakelag_limit)
						need_choke = cvar.fakelag_limit;

					if (choked < need_choke)
					{
						bSendpacket(false);

						choked++;
					}
					else {
						choked = 0;
					}
				}
			}
		}
	}
}

