#include "cache.h"

void rbx::cache::threads::globals_cache() {
	auto base = rbx::task_scheduler(driver::roblox_base);
	while (true) {
		globals::g_datamodel = base.get_datamodel();
		globals::g_visual_engine = base.get_visual_engine();
		globals::g_players_service = globals::g_datamodel.get_players_service();
		globals::g_workspace = globals::g_datamodel.get_workspace();
		globals::g_camera = globals::g_workspace.get_current_camera();
		sleep_ms(500);
	}
}

void rbx::cache::threads::visuals_cache() {
	while (true) {
		auto curr_plrs = globals::g_players_service.get_active_players();

		{
			std::lock_guard<std::mutex> lock(mutex_v);
			targets_v.clear();

			auto lp = globals::g_players_service.get_local_player();
			auto lph = lp.get_model_instance().get_head();

			for (auto p : curr_plrs) {
				if (!p.self) continue;

				auto p_char = p.get_model_instance();
				auto p_head = p_char.get_head();
				auto p_hrp = p_char.get_humanoid_root_part();
				auto p_humanoid = p_char.get_humanoid();
				auto p_health = p.get_health();
				auto p_dist = lph.get_distance(p_head);

				// checks
				if (cheats::visuals::flags_vals[0] && p.self == lp.self) continue;
				if (cheats::visuals::flags_vals[1] && lp.is_teammate(p)) continue;
				if (cheats::visuals::flags_vals[2] && p_health <= 0) continue;
				if (cheats::visuals::flags_vals[3] && p_health < cheats::visuals::min_health) continue;
				if (cheats::visuals::flags_vals[4] && p_dist > cheats::visuals::max_distance) continue;

				std::vector<bone> bones;
				for (auto bone : p_char.get_children()) {
					auto cn = bone.get_class_name();
					if (cn == "Part" || cn == "MeshPart") {
						bones.push_back({ bone.get_name(), part(bone.self) });
					}
				}

				targets_v.push_back({
					p, p_humanoid, p_head, p_hrp,
					p.get_team(), p_health, p_dist,
					p.get_name(), p.get_display_name(),
					p.get_rig_type(), bones
				});
			}
		}

		sleep_ms(250);
	}
}

void rbx::cache::threads::combat_cache() {
	while (true) {
		auto curr_plrs = globals::g_players_service.get_active_players();

		{
			std::lock_guard<std::mutex> lock(mutex_c);
			targets_c.clear();

			auto lp = globals::g_players_service.get_local_player();
			auto lph = lp.get_head();

			for (auto p : curr_plrs) {
				if (!p.self) continue;

				auto p_char = p.get_model_instance();
				auto p_head = p_char.get_head();
				auto p_hrp = p_char.get_humanoid_root_part();
				auto p_humanoid = p_char.get_humanoid();
				auto p_health = p.get_health();
				auto p_dist = lph.get_distance(p_head);
				auto p_head_pos = p_head.get_part_position();

				POINT x;
				GetCursorPos(&x);
				ScreenToClient(globals::our_window, &x);
				auto p1 = vector2_t{ float(x.x), float(x.y) };
				auto p2 = globals::g_visual_engine.world_to_screen(p_head_pos);
				auto dx = p2.x - p1.x;
				auto dy = p2.y - p1.y;
				float d = sqrt( dx * dx + dy * dy );

				// checks
				if (cheats::combat::use_fov && d > cheats::combat::fov_radius) continue;
				if (cheats::combat::flags_vals[0] && lp.is_teammate(p)) continue;
				if (cheats::combat::flags_vals[1] && p_health <= 0) continue;
				if (cheats::combat::flags_vals[2] && p_health < cheats::combat::min_health) continue;
				if (cheats::combat::flags_vals[3] && p_dist > cheats::combat::max_distance) continue;

				targets_c.push_back({
					p, p_humanoid, p_head, p_hrp,
					p.get_team(), p_health, p_dist,
					p.get_name(), p.get_display_name(),
					p.get_rig_type()
				});
			}
		}

		sleep_ms(250);
	}
}