#include "aimbot.hpp"
#include <random>
#include <Windows.h>
#include <thread>
#include "../globals/globals.hpp"
#include "../../game/xorstr/xorstr.hpp"
#include <iostream>
#include <tuple>
#include <mutex>
#include <atomic>
#include <chrono>
#include <../features/player/playerClass.h>

#define _DEBUG(str) printf("%s\n", str);
std::random_device rd;
std::mt19937 rng(rd());

std::atomic<bool> loop_control(true);
std::atomic<bool> loop_running(true);
std::atomic<bool> stop_aimbot(false);
std::chrono::time_point<std::chrono::steady_clock> last_iteration_time;
std::mutex loop_mutex;
std::thread aimbot_thread;

float calc_dist(pulse::roblox::vector2_t a, pulse::roblox::vector2_t b) {
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

float calc_dist_vec3(pulse::roblox::vector3_t a, pulse::roblox::vector3_t b) {
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z));
}

pulse::roblox::vector3_t to_vector3(float a, float b, float c) {
    return { a, b, c };
}

pulse::roblox::vector3_t calc_vel(pulse::roblox::instance_t body_part) {
    auto start = std::chrono::high_resolution_clock::now();

    pulse::roblox::vector3_t old_pos = body_part.get_part_pos();
    //std::this_thread::sleep_for(std::chrono::milliseconds(1));
    pulse::roblox::vector3_t current_pos = body_part.get_part_pos();

    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<float> elapsed_seconds = end - start;

    pulse::roblox::vector3_t velocity = (current_pos - old_pos) / elapsed_seconds.count();

    return velocity;
}

void click() {
    INPUT input;
    input.type = INPUT_MOUSE;
    input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
    SendInput(1, &input, sizeof(input));
    input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
    SendInput(1, &input, sizeof(input));
}


static pulse::roblox::vector3_t lerp_vector3(const pulse::roblox::vector3_t& a, const pulse::roblox::vector3_t& b, float t)
{
    return {
        a.x + (b.x - a.x) * t,
        a.y + (b.y - a.y) * t,
        a.z + (b.z - a.z) * t
    };
}

static pulse::roblox::matrix3_t lerp_matrix3(const pulse::roblox::matrix3_t& a, const pulse::roblox::matrix3_t& b, float t)
{
    pulse::roblox::matrix3_t result{};
    for (int i = 0; i < 9; ++i) {
        result.data[i] = a.data[i] + (b.data[i] - a.data[i]) * t;
    }
    return result;
}


static pulse::roblox::vector3_t normalize(const pulse::roblox::vector3_t& vec) {
    float length = sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z);
    if (length != 0) {
        return { vec.x / length, vec.y / length, vec.z / length };
    }
    else {
        // dont divide by zero silly
        return vec;
    }
}

// cross product
static pulse::roblox::vector3_t crossProduct(const pulse::roblox::vector3_t& vec1, const pulse::roblox::vector3_t& vec2) {
    return {
        vec1.y * vec2.z - vec1.z * vec2.y,
        vec1.z * vec2.x - vec1.x * vec2.z,
        vec1.x * vec2.y - vec1.y * vec2.x
    };
}


static pulse::roblox::matrix3_t LookAtToMatrix(const pulse::roblox::vector3_t& cameraPosition, const pulse::roblox::vector3_t& targetPosition) {
    pulse::roblox::vector3_t forward = normalize(pulse::roblox::vector3_t{ (targetPosition.x - cameraPosition.x), (targetPosition.y - cameraPosition.y), (targetPosition.z - cameraPosition.z) }); // Calculate the forward direction
    pulse::roblox::vector3_t right = normalize(crossProduct({ 0, 1, 0 }, forward)); // Calculate the right direction
    pulse::roblox::vector3_t up = crossProduct(forward, right); // Calculate the up direction

    // Construct the transformation matrix
    pulse::roblox::matrix3_t lookAtMatrix{};
    lookAtMatrix.data[0] = (right.x * -1);  lookAtMatrix.data[1] = up.x;  lookAtMatrix.data[2] = -forward.x;
    lookAtMatrix.data[3] = right.y;  lookAtMatrix.data[4] = up.y;  lookAtMatrix.data[5] = -forward.y;
    lookAtMatrix.data[6] = (right.z * -1);  lookAtMatrix.data[7] = up.z;  lookAtMatrix.data[8] = -forward.z;

    return lookAtMatrix;
}



static void run(pulse::roblox::instance_t player, pulse::roblox::vector3_t resolved_velocity, pulse::roblox::vector3_t Characterpos) {
    POINT cursor_point;
    GetCursorPos(&cursor_point);
    ScreenToClient(globals::window_handle, &cursor_point);

    pulse::roblox::vector3_t part_pos_3d;

    auto& players = playerList;

    auto dimensions = globals::visualengine.get_dimensions();
    auto view_matrix = globals::visualengine.get_view_matrix();
    auto local_player = globals::LocalPlayer;
    float smoothness = ((static_cast<float>(101) - static_cast<float>(globals::smoothness)) / 100);
    pulse::roblox::instance_t workspace = globals::workspace;
    pulse::roblox::instance_t camera = workspace.get_camera();

    pulse::roblox::vector3_t camera_position = camera.get_camera_pos();
    pulse::roblox::matrix3_t camera_rotation = camera.get_camera_rotation();

    if (globals::prediction) {
        pulse::roblox::vector3_t velocity = globals::resolver ? resolved_velocity : player.get_part_velocity();
        pulse::roblox::vector3_t target_pos = player.get_part_pos();

        float prediction_x = globals::separate_predictions ? globals::prediction_x : globals::main_prediction;
        float prediction_y = globals::separate_predictions ? globals::prediction_y : globals::main_prediction;
        float prediction_z = globals::separate_predictions ? globals::prediction_x : globals::main_prediction;


        if (globals::autopred) {
            pulse::roblox::instance_t ping_data = globals::datamodel.find_first_child("Stats").find_first_child("PerformanceStats").find_first_child("Ping");
            float ping = ping_data.get_ping();
            float new_prediction = 0.1f + (ping / 2000) + ((ping / 1000) * (ping / 1500) * 1.025f);

            prediction_x = prediction_y = prediction_z = new_prediction;
        }

        pulse::roblox::vector3_t velocity_vector;

        if (globals::prediction_method == 0)
            velocity_vector = { velocity.x / prediction_x, velocity.y / prediction_y, velocity.z / prediction_z };
        else
            velocity_vector = { velocity.x * prediction_x, velocity.y * prediction_y, velocity.z * prediction_z };

        part_pos_3d = target_pos + velocity_vector;
    }
    else {
        part_pos_3d = player.get_part_pos();
    }

    auto part_pos = pulse::roblox::world_to_screen(part_pos_3d, dimensions, view_matrix);

    if (part_pos.x == -1)
        return;

    float dist = calc_dist(part_pos, { static_cast<float>(cursor_point.x), static_cast<float>(cursor_point.y) });

    pulse::roblox::vector2_t relative = { 0, 0 };

    if (globals::shake) {
        if (globals::shaketype == 0) {
            int shake_range_x = static_cast<int>(globals::shake_x * 10);
            int shake_range_y = static_cast<int>(globals::shake_y * 10);

            auto shake_x = (rand() & shake_range_x - (shake_range_x / 2));
            auto shake_y = (rand() & shake_range_y - (shake_range_y / 2));

            relative.x = (part_pos.x - cursor_point.x + shake_x) * globals::sensitivity / globals::smoothness_x;
            relative.y = (part_pos.y - cursor_point.y + shake_y) * globals::sensitivity / globals::smoothness_y;
        }
        else if (globals::shaketype == 0) {
            int shake_range = static_cast<int>(globals::shake_value * 10);
            auto shake = (rand() & shake_range - (shake_range / 2));

            relative.x = (part_pos.x - cursor_point.x + shake_range) * globals::sensitivity / globals::smoothness_x;
            relative.y = (part_pos.y - cursor_point.y + shake_range) * globals::sensitivity / globals::smoothness_y;
        }
    }
    else {
        relative.x = (part_pos.x - cursor_point.x) * globals::sensitivity / globals::smoothness_x;
        relative.y = (part_pos.y - cursor_point.y) * globals::sensitivity / globals::smoothness_y;
    }

    if (relative.x == -1 || relative.y == -1)
        return;

    float dist_to_deadzone = calc_dist({ static_cast<float>(cursor_point.x), static_cast<float>(cursor_point.y) },
        { static_cast<float>(cursor_point.x) + relative.x,
          static_cast<float>(cursor_point.y) + relative.y });

    if (globals::deadzone && dist_to_deadzone <= globals::deadzone_value)
        return;


    if (!globals::disable_outside_fov || dist <= globals::fov) {

        switch (globals::aimtype)
        {
        case 0: {
            static float current_dx = 0.0f;
            static float current_dy = 0.0f;

            current_dx += (relative.x - current_dx) * smoothness;
            current_dy += (relative.y - current_dy) * smoothness;

            INPUT input{};
            input.mi.time = 0;
            input.type = INPUT_MOUSE;
            input.mi.mouseData = 0;
            input.mi.dx = static_cast<LONG>(current_dx);
            input.mi.dy = static_cast<LONG>(current_dy);
            input.mi.dwFlags = MOUSEEVENTF_MOVE;
            SendInput(1, &input, sizeof(input));
            break;
        }
        case 1: {
            pulse::roblox::matrix3_t hit_matrix = LookAtToMatrix(camera_position, part_pos_3d);
            pulse::roblox::matrix3_t relative_matrix = lerp_matrix3(camera_rotation, hit_matrix, smoothness);
            camera.write_camera_rotation(relative_matrix);
            break;
        }
        }
    }
}

void pulse::roblox::watchdog() {
    while (true) {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        auto now = std::chrono::steady_clock::now();

        {
            std::lock_guard<std::mutex> guard(loop_mutex);
            if (loop_running && std::chrono::duration_cast<std::chrono::seconds>(now - last_iteration_time).count() > 2) {
                std::cout << "[Watchdog] -> Loop seems to be stuck. Restarting aimbot..." << std::endl;

                stop_aimbot = true;

                loop_control = false;
                std::this_thread::sleep_for(std::chrono::milliseconds(500));
                loop_control = true;
                last_iteration_time = now;

                if (aimbot_thread.joinable()) {
                    aimbot_thread.join();
                }

                stop_aimbot = false;
                aimbot_thread = std::thread([]() {
                    pulse::roblox::hook_aimbot();
                    });

                std::cout << "[Watchdog] -> Aimbot restarted." << std::endl;
            }
        }
    }
}

void pulse::roblox::hook_aimbot() {
    pulse::roblox::instance_t _saved_target;
    pulse::roblox::instance_t _target;
    pulse::roblox::instance_t _body_part;
    bool focus = false;
    bool _locked = false;
    pulse::roblox::vector3_t velocity = {};

    loop_running = true;
    std::thread velocity_calculation([&]() {

        while (!stop_aimbot) {
            std::this_thread::sleep_for(std::chrono::milliseconds(1));

            if (!globals::aimbot || !globals::aimbotkey.enabled || !globals::resolver || _target.self == 0)
                continue;

            pulse::roblox::instance_t _character = _target.get_model_instance();

            if (_character.self == 0)
                continue;

            pulse::roblox::instance_t _root_part = _character.find_first_child("HumanoidRootPart");

            if (_root_part.self == 0)
                continue;

            velocity = calc_vel(_root_part);
        }
        });


    while (!stop_aimbot) {
        while (loop_control) {
            {
                std::lock_guard<std::mutex> guard(loop_mutex);
                last_iteration_time = std::chrono::steady_clock::now();
            }

            if (globals::aimbot) {
                if (globals::is_focused) {
                    globals::aimbotkey.update();
                    pulse::roblox::vector3_t lastpos = { 3, 3, 3 };

                    if (globals::aimbotkey.enabled) {
                        if (!focus && globals::negro && _locked && _saved_target.self != 0 && globals::saved_player.self != 0) {
                            _body_part = _saved_target;
                            _target = globals::saved_player;
                        }
                        else {
                            if (!focus) {
                                focus = true;
                                auto [body_part, closest_player] = pulse::roblox::get_closest_player_to_cursor();
                                _target = closest_player;
                                _body_part = body_part;
                            }
                        }

                        if (_body_part.self != 0 && _body_part.get_part_pos().y > 0.1f) {
                            if (globals::autoresolve) {
                                pulse::roblox::vector3_t current_vel = _body_part.get_part_velocity();
                                float velocity_magnitude = std::sqrt((current_vel.x * current_vel.x) + (current_vel.y * current_vel.y) + (current_vel.z * current_vel.z));

                                bool velocity_exceeds_threshold = std::abs(current_vel.x) > globals::velocity_threshold ||
                                    std::abs(current_vel.y) > globals::velocity_threshold ||
                                    std::abs(current_vel.z) > globals::velocity_threshold;

                                globals::resolver = velocity_exceeds_threshold;
                            }

                            if (globals::saved_player.self != 0 && globals::healthcheck) {
                                auto character = globals::saved_player;
                                auto humanoid = character.find_first_child("Humanoid");
                            }

                            if (globals::saved_player.self != 0 && globals::knock_check) {
                                auto character = globals::saved_player.get_model_instance();
                                auto humanoid = character.find_first_child("Humanoid");
                            }

                            if (focus) {
                                run(_body_part, velocity, lastpos);
                            }

                            _saved_target = _body_part;
                            globals::saved_player = _target;
                            _locked = true;
                        }
                        else {
                            globals::saved_player = {};
                            _target = {};
                            _body_part = {};
                            _locked = false;
                            focus = false;
                        }
                    }
                    else {
                        globals::saved_player = {};
                        _target = {};
                        _body_part = {};
                        _locked = false;
                        focus = false;
                    }
                }

                if (globals::aimtype == 1 && globals::smoothcamlock)
                {

                }
                else
                {
                    std::this_thread::sleep_for(std::chrono::milliseconds(1));
                }

            }
            else {
                std::this_thread::sleep_for(std::chrono::milliseconds(1));
            }
        }
        loop_control = true;
    }

    loop_running = false;
}

i like this aimbot system but sadly its not mine, so i will give you my aimbot system and i want you to make my aimbot system work the same way this one works
note:
use the same code structer, do NOT play with the structer or add non-existing things out of this structure, make it fully functional and compatible with my project, keep my extra features and everything just copy how that other aimbot system works, heres mine:
#include "aim.hpp"

#include <random>
#include <Windows.h>
#include <thread>
#include "../Holder/Holder.hpp"
#include "../../other/xorstr/xorstr.hpp"


float calc_dist(hook::roblox::Vector2 first, hook::roblox::Vector2 sec)
{
	return sqrt((first.x - sec.x) * (first.x - sec.x) + (first.y - sec.y) * (first.y - sec.y));
}

bool is_within_deadzone(float x, float y) {
	float distance = sqrt(x * x + y * y);
	return distance <= niggaglobals::deadzone_value;
}

static hook::roblox::Matrix3 lookAtMatrix3(hook::roblox::Vector3& cameraPosition, const hook::roblox::Vector3& targetPosition) {
	hook::roblox::Vector3 forward = hook::roblox::Vector3(
		targetPosition.x - cameraPosition.x,
		targetPosition.y - cameraPosition.y,
		targetPosition.z - cameraPosition.z
	).normalize();

	hook::roblox::Vector3 right = hook::roblox::Vector3(0, 1, 0).cross(forward).normalize();
	hook::roblox::Vector3 up = forward.cross(right);

	hook::roblox::Matrix3 lookAtMatrix{};

	lookAtMatrix.data[0] = (right.x * -1);
	lookAtMatrix.data[1] = up.x;
	lookAtMatrix.data[2] = -forward.x;
	lookAtMatrix.data[3] = right.y;
	lookAtMatrix.data[4] = up.y;
	lookAtMatrix.data[5] = -forward.y;
	lookAtMatrix.data[6] = (right.z * -1);
	lookAtMatrix.data[7] = up.z;
	lookAtMatrix.data[8] = -forward.z;

	return lookAtMatrix;
}

hook::roblox::Matrix3 lerpMatrix3(const hook::roblox::Matrix3& start, const hook::roblox::Matrix3& end, float t) {
	hook::roblox::Matrix3 result;
	for (int i = 0; i < 9; ++i) {
		result.data[i] = start.data[i] + (end.data[i] - start.data[i]) * t;
	}

	return result;
}

hook::roblox::Vector2 AddVector2(hook::roblox::Vector2 first, hook::roblox::Vector2 sec)
{
	return
	{
		first.x + sec.x,
		first.y + sec.y
	};
}

hook::roblox::Vector3 AddVector3(hook::roblox::Vector3 first, hook::roblox::Vector3 sec)
{
	return
	{
		first.x + sec.x,
		first.y + sec.y,
		first.z + sec.z
	};
}

hook::roblox::Vector3 DivVector3(hook::roblox::Vector3 first, hook::roblox::Vector3 sec)
{
	return
	{
		first.x / sec.x,
		first.y / sec.y,
		first.z / sec.z
	};
}

hook::roblox::Vector3 SubVector3(hook::roblox::Vector3 first, hook::roblox::Vector3 sec)
{
	return
	{
		first.x - sec.x,
		first.y - sec.y,
		first.z - sec.z
	};
}

hook::roblox::Vector2 VectorSub(hook::roblox::Vector2 one, hook::roblox::Vector2 two)
{
	return { one.x - two.x, one.y - two.y };
}

hook::roblox::Vector3 ToVector3(float value)
{
	return { value, value , value };
}

hook::roblox::Vector3 CalculateVelocity(hook::roblox::rbx player)
{
	hook::roblox::Vector3 old_Position = player.GetPartPos();
	std::this_thread::sleep_for(std::chrono::milliseconds(100));
	hook::roblox::Vector3 current_Position = player.GetPartPos();
	return DivVector3((SubVector3(current_Position, old_Position)), ToVector3(0.100));
}

hook::roblox::rbx actualPlayer;

hook::roblox::rbx targetPlayer;
hook::roblox::rbx targetHumanoid;

hook::roblox::rbx lastPlayer;

void update_health(hook::roblox::rbx player, hook::roblox::rbx humanoid) {
	auto player_name = player.name();
	if (!humanoid.Address) return;
	float new_health = humanoid.GetHealth();

	if (lastPlayer.name() != player.name())
	{
		lastPlayer = player;

		niggaglobals::player_health[player_name] = new_health;

	}

	if (new_health != niggaglobals::player_health[player_name])
	{
		if (new_health < niggaglobals::player_health[player_name])
		{
			if (niggaglobals::aimbotkey.enabled || niggaglobals::aimbot)
			{
				niggaglobals::health_changed = true;
			}
		}

	}
	niggaglobals::player_health[player_name] = new_health;
	lastPlayer = player;
}

hook::roblox::rbx hook::roblox::GetClosestPlayerToCursor()
{
	POINT cursor_point;
	GetCursorPos(&cursor_point);
	ScreenToClient(FindWindowA(0, XorStr("Roblox")), &cursor_point);

	Vector2 cursor =
	{
		static_cast<float>(cursor_point.x),
		static_cast<float>(cursor_point.y)
	};

	hook::roblox::rbx closest_player;

	int min_dist = 9e9;
	std::string teamname;

	auto dimensions = niggaglobals::visualengine.getdimensions();
	auto viewmatrix = niggaglobals::visualengine.getviewmatrix();

	auto customplayers = niggaglobals::playerslocation;
	auto customplayerslist = customplayers.children();

	auto localplayer = customplayers.FindFirstChild(niggaglobals::localplayername); // find localplayer entry in list
	auto localplayerHead = localplayer.FindFirstChild("Head"); // and the lplrs head!"!! to avoid crases :money:

	for (auto player : customplayers.children())
	{
		if (niggaglobals::deadlines) {
			if (player.Address == localplayer.Address)
				continue;

			if (player.name() == localplayer.name())
			{
				continue;
			}

			auto humanoid = player.FindFirstChild("Humanoid");
			if (!humanoid.Address)
				continue;

			if (humanoid.GetHealth() <= 4 && niggaglobals::knock_check)
			{
				continue;
			}

			hook::roblox::rbx head;

			head = player.FindFirstChild("head");

			if (!head.Address)
				continue;

			Vector3 HeadPos3D = head.GetPartPos();

			auto HeadPos = hook::roblox::WorldToScreen(HeadPos3D, dimensions, viewmatrix);

			float dist = calc_dist(HeadPos, cursor);

			if ((!niggaglobals::disable_outside_fov || dist < niggaglobals::fov) && (min_dist > dist)) {
				closest_player = head;
				min_dist = dist;
			}
		}
		else {
			if (player.Address == localplayer.Address)
				continue;

			if (player.name() == localplayer.name())
			{
				continue;
			}


			auto character = player;

			auto humanoid = character.FindFirstChild("Humanoid");
			if (!humanoid.Address)
				continue;


			auto team = player.GetTeam();

			//if (niggaglobals::team_check && (team.Address == localplayer_team.Address))
			//	continue;

			if (humanoid.GetHealth() <= 4 && niggaglobals::knock_check)
			{
				continue;
			}

			hook::roblox::rbx head;

			head = character.FindFirstChild("HumanoidRootPart");

			std::string custom_aimpart_name = niggaglobals::aimparts[niggaglobals::aimpart];

			hook::roblox::rbx custom_aimpart = character.FindFirstChild(custom_aimpart_name);

			if (!custom_aimpart.Address)
				continue;

			if (!head.Address)
				continue;

			Vector3 HeadPos3D = head.GetPartPos();

			auto HeadPos = hook::roblox::WorldToScreen(HeadPos3D, dimensions, viewmatrix);

			float dist = calc_dist(HeadPos, cursor);

			if ((!niggaglobals::disable_outside_fov || dist < niggaglobals::fov) && (min_dist > dist)) {
				closest_player = custom_aimpart;
				actualPlayer = player;
				targetPlayer = player;
				targetHumanoid = humanoid;
				min_dist = dist;
			}
		}
	}
	return closest_player;
}

hook::roblox::Vector2 hook::roblox::GetRelativePlayerToPos(Vector2 closest_player)
{
	Vector2 ret = { 0, 0 };

	POINT cursor_point;
	GetCursorPos(&cursor_point);
	ScreenToClient(FindWindowA(0, XorStr("Roblox")), &cursor_point);
	Vector2 cursor_pos = { static_cast<float>(cursor_point.x),static_cast<float>(cursor_point.y) };

	ret.x = (closest_player.x - cursor_pos.x) * niggaglobals::sensitivity / niggaglobals::smoothness;
	ret.y = (closest_player.y - cursor_pos.y) * niggaglobals::sensitivity / niggaglobals::smoothness;

	return ret;
}


void run(hook::roblox::rbx player, hook::roblox::Vector3 resolvedVelocity)
{
	POINT cursor_pos;
	GetCursorPos(&cursor_pos);
	ScreenToClient(FindWindowA(0, "Roblox"), &cursor_pos);

	hook::roblox::Vector3 HeadPos3D;

	auto dimensions = niggaglobals::visualengine.getdimensions();
	auto viewmatrix = niggaglobals::visualengine.getviewmatrix();

	if (niggaglobals::prediction)
	{
		hook::roblox::Vector3 velocity = niggaglobals::resolver ? resolvedVelocity : player.GetPartVelocity();
		auto velocity_vec = DivVector3(velocity, { niggaglobals::prediction_x, niggaglobals::prediction_y, niggaglobals::prediction_x });
		HeadPos3D = AddVector3(player.GetPartPos(), velocity_vec);
	}
	else
	{
		HeadPos3D = player.GetPartPos();
	}



	auto HeadPos = hook::roblox::WorldToScreen(HeadPos3D, dimensions, viewmatrix);

	if (HeadPos.x == -1)
	{
		return;
	}

	float dist = calc_dist(HeadPos, { static_cast<float>(cursor_pos.x), static_cast<float>(cursor_pos.y) });

	float sens = niggaglobals::sensitivity;

	hook::roblox::Vector2 rel = { 0, 0 };

	if (niggaglobals::shake) {
		int shake_range = static_cast<int>(niggaglobals::shake_value * 10);
		rel.x = (HeadPos.x - cursor_pos.x + (rand() % shake_range - shake_range / 2)) * sens / .5;
		rel.y = (HeadPos.y - cursor_pos.y + (rand() % shake_range - shake_range / 2)) * sens / .5;

	}
	else {
		rel.x = (HeadPos.x - cursor_pos.x) * sens / niggaglobals::smoothness;
		rel.y = (HeadPos.y - cursor_pos.y) * sens / niggaglobals::smoothness;
	}

	if (rel.x == -1 || rel.y == -1)
		return;

	float distance_to_deadzone = calc_dist({ static_cast<float>(cursor_pos.x), static_cast<float>(cursor_pos.y) },
		{ static_cast<float>(cursor_pos.x) + rel.x,
		  static_cast<float>(cursor_pos.y) + rel.y });

	if (niggaglobals::deadzone && distance_to_deadzone <= niggaglobals::deadzone_value) {
		return;
	}

	hook::roblox::rbx camera = niggaglobals::datamodel.FindFirstChild("Workspace").FindFirstChild("Camera");
	hook::roblox::Vector3 cameraPosition = camera.getcamerapos();
	hook::roblox::Matrix3 cameraRotation = camera.getcamerarot();

	if (!niggaglobals::disable_outside_fov || dist <= niggaglobals::fov) {

		niggaglobals::targetinstance = actualPlayer;
		niggaglobals::target = true;

		switch (niggaglobals::aimbottype) {
		case 0:
			INPUT input;
			input.mi.time = 0;
			input.type = INPUT_MOUSE;
			input.mi.mouseData = 0;
			input.mi.dx = rel.x;
			input.mi.dy = rel.y;
			input.mi.dwFlags = MOUSEEVENTF_MOVE;
			SendInput(1, &input, sizeof(input));
			break;
		case 1:
			hook::roblox::Matrix3 HitMatrix = lookAtMatrix3(cameraPosition, HeadPos3D);
			hook::roblox::Matrix3 RelativeMatrix = lerpMatrix3(cameraRotation, HitMatrix, sens / niggaglobals::smoothness);
			camera.WriteCameraRotation(RelativeMatrix);
			break;
		}
	}

}



std::atomic<bool> run_velocity_calculation(true);

void hook::roblox::HookAimbot() {
	hook::roblox::rbx saved_player;
	bool is_aimboting = false;
	hook::roblox::Vector3 velocity;
	hook::roblox::rbx current_player;

	std::thread velocity_calculation([&]() {
		while (run_velocity_calculation) {
			std::this_thread::sleep_for(std::chrono::milliseconds(1));

			if (niggaglobals::resolver && current_player.Address) {
				velocity = CalculateVelocity(current_player);
			}
		}
		});

	std::thread health_update([&]() {
		while (run_velocity_calculation) {
			std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Adjust the frequency as needed
			update_health(targetPlayer, targetHumanoid);
		}
		});


	//std::thread magicbullet([&]() {


	//	

	//	while (10==1) // comment: 10==1 for temp disable, will implement l8r. working.
	//	{
	//		std::this_thread::sleep_for(std::chrono::milliseconds(10));

	//		if (niggaglobals::aimbotkey.enabled and niggaglobals::aimbot)
	//		{
	//			auto LocalPlayerInstance = niggaglobals::playerslocation.FindFirstChild(niggaglobals::localplayername);

	//			auto LocalPlayer = LocalPlayerInstance.FindFirstChild("HumanoidRootPart");
	//			auto target_pos = current_player.GetPartPos();
	//			auto originalpos = LocalPlayer.GetPartPos();
	//			Vector3 newpos = Vector3(target_pos.x, target_pos.y, target_pos.z);
	//			if (LocalPlayer.Address)
	//			{
	//				LocalPlayer.SetPartPos(target_pos);
	//				std::this_thread::sleep_for(std::chrono::milliseconds(100));
	//				LocalPlayer.SetPartPos(originalpos);
	//				std::this_thread::sleep_for(std::chrono::milliseconds(500));
	//			}
	//		}
	//	}
	//});

	std::thread orbit([&]() {
		auto start_time = std::chrono::high_resolution_clock::now();
		Vector3 previous_pos;
		bool first_run = true;

		// Parameters
		float radius = static_cast<float>(niggaglobals::orbitradius);
		float speed = static_cast<float>(niggaglobals::orbitspeed);
		float offset = static_cast<float>(niggaglobals::orbitoffset);

		// Time variables
		auto last_update_time = start_time;

		while (true) {
			auto current_time = std::chrono::high_resolution_clock::now();
			std::chrono::duration<float> delta_time = current_time - last_update_time;
			last_update_time = current_time;

			if (niggaglobals::aimbotkey.enabled && niggaglobals::aimbot && niggaglobals::orbit) {
				auto LocalPlayerInstance = niggaglobals::playerslocation.FindFirstChild(niggaglobals::localplayername);
				auto LocalPlayer = LocalPlayerInstance.FindFirstChild("HumanoidRootPart");

				auto target_cframe = current_player.getpartcframe(); // Assuming this method exists
				Vector3 target_pos = target_cframe.position; // Get the position from CFrame

				// Calculate angle based on elapsed time
				float time_elapsed = std::chrono::duration_cast<std::chrono::duration<float>>(current_time - start_time).count();
				float angle = speed * time_elapsed;
				float new_x = target_pos.x + radius * cos(angle);
				float new_z = target_pos.z + radius * sin(angle);
				Vector3 new_pos = { new_x, target_pos.y + offset, new_z };

				// Smooth movement using interpolation (lerp-like effect)
				if (!first_run) {
					float lerp_factor = 0.1f; // Adjust as needed
					new_pos = previous_pos + (new_pos - previous_pos) * lerp_factor;
				}

				// Apply the new position
				LocalPlayer.setpartcframe(new_pos);  // Assuming this method exists for setting position

				// Store the previous position for the next iteration
				previous_pos = new_pos;
				first_run = false;
			}

			// Ensure continuous running without sleep
		}
		});


	while (true) {

		std::this_thread::sleep_for(std::chrono::milliseconds(5));
		niggaglobals::aimbotkey.update();

		if (GetForegroundWindow() != FindWindowA(0, XorStr("Roblox")))
			continue;

		if (!niggaglobals::aimbotkey.enabled || !niggaglobals::aimbot) {
			is_aimboting = false;
			continue;
		}

		if (niggaglobals::sticky_aim && is_aimboting && saved_player.Address != 0) {
			current_player = saved_player;
		}
		else {
			current_player = GetClosestPlayerToCursor();
		}

		if (current_player.Address != 0 && current_player.GetPartPos().y > 0.1f) {
			run(current_player, velocity);
			saved_player = current_player;
			is_aimboting = true;
		}
		else {
			is_aimboting = false;
		}

	}


	run_velocity_calculation = false;
	if (orbit.joinable()) {
		orbit.join();
	}
	if (velocity_calculation.joinable()) {
		velocity_calculation.join();
	}
}