#include <windows.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <vector>
#include <string>
#include <algorithm>
#include <chrono>
#include <thread>
#include <atomic>
#include <mutex>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <unordered_map>
#include <deque>
#include <random>

#pragma comment(lib, "winmm.lib")

class HitRangeConfig {
private:
    std::string configPath = "HitRange.ini";
    std::unordered_map<std::string, std::unordered_map<std::string, std::string>> data;
    
    void trim(std::string& str) {
        str.erase(0, str.find_first_not_of(" \t\n\r"));
        str.erase(str.find_last_not_of(" \t\n\r") + 1);
    }
    
public:
    HitRangeConfig(const std::string& path = "HitRange.ini") : configPath(path) {
        loadConfig();
    }
    
    bool loadConfig() {
        std::ifstream file(configPath);
        if (!file.is_open()) {
            createDefaultConfig();
            return false;
        }
        
        data.clear();
        std::string currentSection;
        std::string line;
        
        while (std::getline(file, line)) {
            trim(line);
            
            if (line.empty() || line[0] == ';' || line[0] == '#') {
                continue;
            }
            
            if (line[0] == '[' && line.back() == ']') {
                currentSection = line.substr(1, line.length() - 2);
                data[currentSection];
            } else {
                size_t equalsPos = line.find('=');
                if (equalsPos != std::string::npos) {
                    std::string key = line.substr(0, equalsPos);
                    std::string value = line.substr(equalsPos + 1);
                    trim(key);
                    trim(value);
                    data[currentSection][key] = value;
                }
            }
        }
        
        file.close();
        return true;
    }
    
    void saveConfig() {
        std::ofstream file(configPath);
        for (const auto& section : data) {
            file << "[" << section.first << "]\n";
            for (const auto& entry : section.second) {
                file << entry.first << "=" << entry.second << "\n";
            }
            file << "\n";
        }
        file.close();
    }
    
    template<typename T>
    T getValue(const std::string& section, const std::string& key, T defaultValue) {
        auto secIt = data.find(section);
        if (secIt != data.end()) {
            auto keyIt = secIt->second.find(key);
            if (keyIt != secIt->second.end()) {
                std::stringstream ss(keyIt->second);
                T result;
                if (ss >> result) return result;
            }
        }
        return defaultValue;
    }
    
    template<typename T>
    void setValue(const std::string& section, const std::string& key, T value) {
        std::stringstream ss;
        ss << value;
        data[section][key] = ss.str();
    }
    
    void createDefaultConfig() {
        data["HitRange"]["Enable"] = "1";
        data["HitRange"]["HitChance"] = "100";
        data["HitRange"]["HeadHitRate"] = "100";
        data["HitRange"]["BodyHitRate"] = "100";
        data["HitRange"]["LegHitRate"] = "100";
        data["HitRange"]["ArmHitRate"] = "100";
        data["HitRange"]["AutoAimHitRate"] = "100";
        data["HitRange"]["ManualAimHitRate"] = "100";
        data["HitRange"]["ScopeHitRate"] = "100";
        data["HitRange"]["HipfireHitRate"] = "100";
        data["HitRange"]["MovingHitRate"] = "100";
        data["HitRange"]["JumpingHitRate"] = "100";
        data["HitRange"]["CrouchHitRate"] = "100";
        data["HitRange"]["ProneHitRate"] = "100";
        data["HitRange"]["VehicleHitRate"] = "100";
        data["HitRange"]["ParachuteHitRate"] = "100";
        data["HitRange"]["WaterHitRate"] = "100";
        
        data["HitArea"]["HeadRadius"] = "15.0";
        data["HitArea"]["NeckRadius"] = "20.0";
        data["HitArea"]["ChestRadius"] = "30.0";
        data["HitArea"]["StomachRadius"] = "25.0";
        data["HitArea"]["ArmRadius"] = "20.0";
        data["HitArea"]["LegRadius"] = "18.0";
        data["HitArea"]["FootRadius"] = "12.0";
        data["HitArea"]["HitboxExpansion"] = "1.5";
        data["HitArea"]["HitboxScale"] = "1.2";
        data["HitArea"]["HitboxOffsetX"] = "0.0";
        data["HitArea"]["HitboxOffsetY"] = "0.0";
        data["HitArea"]["HitboxOffsetZ"] = "0.0";
        
        data["HitDistance"]["MinHitDistance"] = "0.5";
        data["HitDistance"]["MaxHitDistance"] = "1000.0";
        data["HitDistance"]["CloseRangeHitRate"] = "100";
        data["HitDistance"]["MediumRangeHitRate"] = "100";
        data["HitDistance"]["LongRangeHitRate"] = "100";
        data["HitDistance"]["SniperRangeHitRate"] = "100";
        data["HitDistance"]["DynamicDistanceScaling"] = "1";
        data["HitDistance"]["DistanceFalloffStart"] = "300.0";
        data["HitDistance"]["DistanceFalloffEnd"] = "800.0";
        
        data["HitEffect"]["HitEffectStrength"] = "100";
        data["HitEffect"]["BloodEffectSize"] = "1.5";
        data["HitEffect"]["HitMarkerSize"] = "2.0";
        data["HitEffect"]["HitMarkerColorR"] = "255";
        data["HitEffect"]["HitMarkerColorG"] = "0";
        data["HitEffect"]["HitMarkerColorB"] = "0";
        data["HitEffect"]["HitSoundVolume"] = "100";
        data["HitEffect"]["CriticalHitEffect"] = "1";
        data["HitEffect"]["HeadshotEffect"] = "1";
        data["HitEffect"]["KillEffect"] = "1";
        data["HitEffect"]["MultiKillEffect"] = "1";
        
        data["HitPrediction"]["PredictionAccuracy"] = "100";
        data["HitPrediction"]["LeadTargetStrength"] = "1.2";
        data["HitPrediction"]["BulletGravityComp"] = "1.0";
        data["HitPrediction"]["WindCompensation"] = "0.0";
        data["HitPrediction"]["VelocityPrediction"] = "1.2";
        data["HitPrediction"]["AccelerationPrediction"] = "0.8";
        data["HitPrediction"]["JumpPrediction"] = "1.0";
        data["HitPrediction"]["ParachutePrediction"] = "1.0";
        data["HitPrediction"]["VehiclePrediction"] = "1.5";
        data["HitPrediction"]["PredictionSmoothing"] = "0.9";
        
        data["WeaponHit"]["AR_HitRate"] = "100";
        data["WeaponHit"]["SR_HitRate"] = "100";
        data["WeaponHit"]["SMG_HitRate"] = "100";
        data["WeaponHit"]["LMG_HitRate"] = "100";
        data["WeaponHit"]["SG_HitRate"] = "100";
        data["WeaponHit"]["Pistol_HitRate"] = "100";
        data["WeaponHit"]["SniperHeadshotRate"] = "100";
        data["WeaponHit"]["ShotgunPelletHit"] = "100";
        data["WeaponHit"]["MeleeHitRate"] = "100";
        data["WeaponHit"]["ThrowableHitRate"] = "100";
        data["WeaponHit"]["VehicleWeaponHitRate"] = "100";
        
        data["HitAssist"]["AutoCorrection"] = "1";
        data["HitAssist"]["CorrectionStrength"] = "0.8";
        data["HitAssist"]["StickyAim"] = "1";
        data["HitAssist"]["StickyStrength"] = "0.7";
        data["HitAssist"]["RecoilCompensation"] = "1";
        data["HitAssist"]["SpreadReduction"] = "1";
        data["HitAssist"]["BulletMagnetism"] = "1";
        data["HitAssist"]["MagnetismStrength"] = "0.6";
        data["HitAssist"]["HitPriority"] = "1";
        data["HitAssist"]["ForceHit"] = "0";
        
        data["HitVisual"]["ShowHitbox"] = "1";
        data["HitVisual"]["HitboxColorR"] = "255";
        data["HitVisual"]["HitboxColorG"] = "0";
        data["HitVisual"]["HitboxColorB"] = "0";
        data["HitVisual"]["HitboxAlpha"] = "60";
        data["HitVisual"]["ShowHitPoint"] = "1";
        data["HitVisual"]["HitPointSize"] = "8.0";
        data["HitVisual"]["ShowTrajectory"] = "1";
        data["HitVisual"]["TrajectoryColorR"] = "0";
        data["HitVisual"]["TrajectoryColorG"] = "255";
        data["HitVisual"]["TrajectoryColorB"] = "0";
        data["HitVisual"]["ShowDamage"] = "1";
        data["HitVisual"]["DamageColorR"] = "255";
        data["HitVisual"]["DamageColorG"] = "255";
        data["HitVisual"]["DamageColorB"] = "0";
        
        data["HitAdvanced"]["SmartHitDetection"] = "1";
        data["HitAdvanced"]["AdaptiveHitRate"] = "1";
        data["HitAdvanced"]["HitMemoryTime"] = "2.0";
        data["HitAdvanced"]["HitCooldown"] = "0.1";
        data["HitAdvanced"]["MultiHitEnabled"] = "1";
        data["HitAdvanced"]["PenetrationHit"] = "1";
        data["HitAdvanced"]["WallbangHit"] = "1";
        data["HitAdvanced"]["ThroughSmokeHit"] = "1";
        data["HitAdvanced"]["ThroughFlashHit"] = "1";
        data["HitAdvanced"]["InstantHit"] = "0";
        
        data["HitAntiCheat"]["HumanizeHitPattern"] = "1";
        data["HitAntiCheat"]["RandomMissChance"] = "0";
        data["HitAntiCheat"]["HitDelay"] = "0";
        data["HitAntiCheat"]["HitJitter"] = "0.0";
        data["HitAntiCheat"]["HitOffsetX"] = "0.0";
        data["HitAntiCheat"]["HitOffsetY"] = "0.0";
        data["HitAntiCheat"]["HitTimingRandom"] = "1";
        data["HitAntiCheat"]["HideHitData"] = "1";
        data["HitAntiCheat"]["EncryptHitInfo"] = "1";
        
        data["Hotkeys"]["ToggleHitRange"] = "F6";
        data["Hotkeys"]["ToggleHitbox"] = "F7";
        data["Hotkeys"]["ToggleHitEffect"] = "F8";
        data["Hotkeys"]["IncreaseHitRate"] = "NUMPAD+";
        data["Hotkeys"]["DecreaseHitRate"] = "NUMPAD-";
        data["Hotkeys"]["ResetHitConfig"] = "F9";
        data["Hotkeys"]["SaveHitConfig"] = "F10";
        data["Hotkeys"]["LoadHitConfig"] = "F11";
        data["Hotkeys"]["HitPanicKey"] = "F12";
        
        saveConfig();
    }
};

class Vector3 {
public:
    float x, y, z;
    
    Vector3() : x(0), y(0), z(0) {}
    Vector3(float x, float y, float z) : x(x), y(y), z(z) {}
    
    Vector3 operator+(const Vector3& other) const {
        return Vector3(x + other.x, y + other.y, z + other.z);
    }
    
    Vector3 operator-(const Vector3& other) const {
        return Vector3(x - other.x, y - other.y, z - other.z);
    }
    
    Vector3 operator*(float scalar) const {
        return Vector3(x * scalar, y * scalar, z * scalar);
    }
    
    float Length() const {
        return sqrtf(x * x + y * y + z * z);
    }
    
    float Distance(const Vector3& other) const {
        Vector3 diff = *this - other;
        return diff.Length();
    }
    
    Vector3 Normalized() const {
        float len = Length();
        if (len > 0.0001f) {
            return Vector3(x / len, y / len, z / len);
        }
        return *this;
    }
    
    static float Dot(const Vector3& a, const Vector3& b) {
        return a.x * b.x + a.y * b.y + a.z * b.z;
    }
    
    static Vector3 Cross(const Vector3& a, const Vector3& b) {
        return Vector3(
            a.y * b.z - a.z * b.y,
            a.z * b.x - a.x * b.z,
            a.x * b.y - a.y * b.x
        );
    }
};

class MemoryInterface {
private:
    HANDLE processHandle = nullptr;
    DWORD processId = 0;
    uintptr_t baseAddress = 0;
    
    DWORD GetProcessIdByName(const wchar_t* processName) {
        PROCESSENTRY32W entry;
        entry.dwSize = sizeof(PROCESSENTRY32W);
        
        HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
        DWORD pid = 0;
        
        if (Process32FirstW(snapshot, &entry)) {
            do {
                if (_wcsicmp(entry.szExeFile, processName) == 0) {
                    pid = entry.th32ProcessID;
                    break;
                }
            } while (Process32NextW(snapshot, &entry));
        }
        
        CloseHandle(snapshot);
        return pid;
    }
    
public:
    MemoryInterface() = default;
    
    bool Attach(const wchar_t* processName) {
        processId = GetProcessIdByName(processName);
        if (processId == 0) return false;
        
        processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
        if (!processHandle) return false;
        
        HMODULE hMods[1024];
        DWORD cbNeeded;
        if (EnumProcessModules(processHandle, hMods, sizeof(hMods), &cbNeeded)) {
            baseAddress = (uintptr_t)hMods[0];
        }
        
        return true;
    }
    
    void Detach() {
        if (processHandle) {
            CloseHandle(processHandle);
            processHandle = nullptr;
        }
    }
    
    template<typename T>
    T Read(uintptr_t address) {
        T value;
        ReadProcessMemory(processHandle, (LPCVOID)address, &value, sizeof(T), NULL);
        return value;
    }
    
    template<typename T>
    bool Write(uintptr_t address, T value) {
        return WriteProcessMemory(processHandle, (LPVOID)address, &value, sizeof(T), NULL);
    }
    
    bool IsAttached() const {
        return processHandle != nullptr;
    }
    
    uintptr_t GetBaseAddress() const {
        return baseAddress;
    }
    
    uintptr_t ReadChain(uintptr_t base, const std::vector<uintptr_t>& offsets) {
        uintptr_t result = Read<uintptr_t>(base);
        for (size_t i = 0; i < offsets.size() - 1; ++i) {
            result = Read<uintptr_t>(result + offsets[i]);
        }
        return result + offsets.back();
    }
};

class HitRangeSystem {
private:
    HitRangeConfig config;
    MemoryInterface memory;
    std::atomic<bool> enabled{true};
    std::atomic<bool> running{true};
    std::thread processingThread;
    std::mutex dataMutex;
    
    struct HitTarget {
        uint32_t id;
        Vector3 position;
        Vector3 velocity;
        Vector3 headPos;
        Vector3 chestPos;
        Vector3 pelvisPos;
        float health;
        float distance;
        bool isVisible;
        bool isKnocked;
        bool isTeammate;
        uint64_t lastUpdate;
    };
    
    std::unordered_map<uint32_t, HitTarget> targets;
    std::vector<uint32_t> targetQueue;
    
    std::random_device rd;
    std::mt19937 gen;
    std::uniform_real_distribution<float> dist;
    
public:
    HitRangeSystem() : gen(rd()), dist(0.0f, 1.0f) {
        Start();
    }
    
    ~HitRangeSystem() {
        Stop();
    }
    
    void Start() {
        running = true;
        processingThread = std::thread(&HitRangeSystem::ProcessLoop, this);
    }
    
    void Stop() {
        running = false;
        if (processingThread.joinable()) {
            processingThread.join();
        }
    }
    
    void SetEnabled(bool state) {
        enabled = state;
    }
    
    bool IsEnabled() const {
        return enabled;
    }
    
    void ReloadConfig() {
        config.loadConfig();
    }
    
    void SaveConfig() {
        config.saveConfig();
    }
    
private:
    void ProcessLoop() {
        while (running) {
            if (enabled) {
                UpdateTargets();
                ProcessHits();
                ApplyHitEffects();
            }
            
            std::this_thread::sleep_for(std::chrono::milliseconds(1));
        }
    }
    
    void UpdateTargets() {
        std::lock_guard<std::mutex> lock(dataMutex);
        
        targets.clear();
        targetQueue.clear();
        
        uint32_t localPlayer = GetLocalPlayer();
        if (localPlayer == 0) return;
        
        Vector3 localPos = GetPlayerPosition(localPlayer);
        uint32_t maxTargets = config.getValue<int>("System", "MaxTargets", 20);
        
        for (uint32_t i = 0; i < maxTargets; ++i) {
            uint32_t playerId = GetPlayerById(i);
            if (playerId == 0 || playerId == localPlayer) continue;
            
            if (!IsPlayerValid(playerId)) continue;
            
            HitTarget target;
            target.id = playerId;
            target.position = GetPlayerPosition(playerId);
            target.velocity = GetPlayerVelocity(playerId);
            target.health = GetPlayerHealth(playerId);
            target.distance = localPos.Distance(target.position);
            target.isVisible = IsPlayerVisible(playerId);
            target.isKnocked = IsPlayerKnocked(playerId);
            target.isTeammate = IsTeammate(playerId);
            target.lastUpdate = GetCurrentTime();
            
            target.headPos = GetBonePosition(playerId, 8);
            target.chestPos = GetBonePosition(playerId, 5);
            target.pelvisPos = GetBonePosition(playerId, 2);
            
            if (target.distance <= config.getValue<float>("HitDistance", "MaxHitDistance", 1000.0f) &&
                target.distance >= config.getValue<float>("HitDistance", "MinHitDistance", 0.5f)) {
                
                if (!target.isKnocked || !config.getValue<bool>("HitRange", "IgnoreKnocked", true)) {
                    if (!target.isTeammate || !config.getValue<bool>("HitRange", "IgnoreTeammate", true)) {
                        targets[playerId] = target;
                        targetQueue.push_back(playerId);
                    }
                }
            }
        }
    }
    
    void ProcessHits() {
        std::lock_guard<std::mutex> lock(dataMutex);
        
        if (targets.empty()) return;
        
        uint32_t localPlayer = GetLocalPlayer();
        if (localPlayer == 0) return;
        
        for (const auto& targetId : targetQueue) {
            auto it = targets.find(targetId);
            if (it == targets.end()) continue;
            
            const HitTarget& target = it->second;
            
            if (!target.isVisible && !config.getValue<bool>("HitAdvanced", "ThroughWallHit", false)) {
                continue;
            }
            
            if (IsShooting()) {
                ProcessHitForTarget(localPlayer, target);
            }
        }
    }
    
    void ProcessHitForTarget(uint32_t localPlayer, const HitTarget& target) {
        float hitChance = config.getValue<float>("HitRange", "HitChance", 100.0f);
        hitChance = AdjustHitChanceByDistance(target.distance, hitChance);
        hitChance = AdjustHitChanceByWeapon(hitChance);
        hitChance = AdjustHitChanceByMovement(hitChance, target);
        
        if (dist(gen) * 100.0f > hitChance) {
            if (config.getValue<bool>("HitAntiCheat", "RandomMissChance", 0) > 0) {
                return;
            }
        }
        
        Vector3 hitPoint = CalculateHitPoint(target);
        hitPoint = ApplyPrediction(hitPoint, target);
        hitPoint = ApplyCorrection(hitPoint, target);
        
        if (config.getValue<bool>("HitAssist", "ForceHit", 0)) {
            ForceHit(target.id, hitPoint);
        } else {
            SimulateHit(target.id, hitPoint);
        }
        
        ApplyHitEffect(target.id, hitPoint);
        UpdateHitStatistics(target.id);
    }
    
    Vector3 CalculateHitPoint(const HitTarget& target) {
        int priorityBone = config.getValue<int>("HitArea", "PriorityBone", 0);
        Vector3 basePoint;
        
        switch (priorityBone) {
            case 0: basePoint = target.headPos; break;
            case 1: basePoint = target.chestPos; break;
            case 2: basePoint = target.pelvisPos; break;
            default: basePoint = target.chestPos; break;
        }
        
        if (config.getValue<bool>("HitArea", "DynamicBoneSelection", true)) {
            basePoint = SelectDynamicBone(target);
        }
        
        float expansion = config.getValue<float>("HitArea", "HitboxExpansion", 1.5f);
        float offsetX = config.getValue<float>("HitArea", "HitboxOffsetX", 0.0f);
        float offsetY = config.getValue<float>("HitArea", "HitboxOffsetY", 0.0f);
        float offsetZ = config.getValue<float>("HitArea", "HitboxOffsetZ", 0.0f);
        
        Vector3 randomOffset(
            (dist(gen) * 2.0f - 1.0f) * expansion + offsetX,
            (dist(gen) * 2.0f - 1.0f) * expansion + offsetY,
            (dist(gen) * 2.0f - 1.0f) * expansion + offsetZ
        );
        
        if (config.getValue<bool>("HitAntiCheat", "HumanizeHitPattern", true)) {
            randomOffset = randomOffset * 0.3f;
        }
        
        return basePoint + randomOffset;
    }
    
    Vector3 SelectDynamicBone(const HitTarget& target) {
        float distance = target.distance;
        
        if (distance <= 50.0f) {
            int bone = config.getValue<int>("HitArea", "CloseRangeBone", 0);
            return GetBoneByIndex(target, bone);
        } else if (distance <= 200.0f) {
            int bone = config.getValue<int>("HitArea", "MediumRangeBone", 2);
            return GetBoneByIndex(target, bone);
        } else {
            int bone = config.getValue<int>("HitArea", "LongRangeBone", 2);
            return GetBoneByIndex(target, bone);
        }
    }
    
    Vector3 GetBoneByIndex(const HitTarget& target, int index) {
        switch (index) {
            case 0: return target.headPos;
            case 1: return target.chestPos;
            case 2: return target.pelvisPos;
            default: return target.chestPos;
        }
    }
    
    Vector3 ApplyPrediction(const Vector3& hitPoint, const HitTarget& target) {
        float predictionStrength = config.getValue<float>("HitPrediction", "LeadTargetStrength", 1.2f);
        float bulletSpeed = GetCurrentBulletSpeed();
        
        if (bulletSpeed <= 0) return hitPoint;
        
        float timeToTarget = target.distance / bulletSpeed;
        Vector3 predictedMovement = target.velocity * timeToTarget * predictionStrength;
        
        float gravityComp = config.getValue<float>("HitPrediction", "BulletGravityComp", 1.0f);
        predictedMovement.y -= 0.5f * 9.81f * timeToTarget * timeToTarget * gravityComp;
        
        float smoothing = config.getValue<float>("HitPrediction", "PredictionSmoothing", 0.9f);
        return hitPoint + predictedMovement * smoothing;
    }
    
    Vector3 ApplyCorrection(const Vector3& hitPoint, const HitTarget& target) {
        float correctionStrength = config.getValue<float>("HitAssist", "CorrectionStrength", 0.8f);
        
        if (!config.getValue<bool>("HitAssist", "AutoCorrection", true)) {
            return hitPoint;
        }
        
        Vector3 targetCenter = target.chestPos;
        Vector3 direction = targetCenter - hitPoint;
        
        float stickyStrength = config.getValue<float>("HitAssist", "StickyStrength", 0.7f);
        if (config.getValue<bool>("HitAssist", "StickyAim", true)) {
            direction = direction * stickyStrength;
        }
        
        float magnetism = config.getValue<float>("HitAssist", "MagnetismStrength", 0.6f);
        if (config.getValue<bool>("HitAssist", "BulletMagnetism", true)) {
            direction = direction * magnetism;
        }
        
        return hitPoint + direction * correctionStrength;
    }
    
    float AdjustHitChanceByDistance(float distance, float baseChance) {
        if (distance <= 50.0f) {
            return baseChance * (config.getValue<float>("HitDistance", "CloseRangeHitRate", 100.0f) / 100.0f);
        } else if (distance <= 200.0f) {
            return baseChance * (config.getValue<float>("HitDistance", "MediumRangeHitRate", 100.0f) / 100.0f);
        } else {
            return baseChance * (config.getValue<float>("HitDistance", "LongRangeHitRate", 100.0f) / 100.0f);
        }
    }
    
    float AdjustHitChanceByWeapon(float baseChance) {
        std::string weaponType = GetCurrentWeaponType();
        
        if (weaponType == "AR") {
            return baseChance * (config.getValue<float>("WeaponHit", "AR_HitRate", 100.0f) / 100.0f);
        } else if (weaponType == "SR") {
            return baseChance * (config.getValue<float>("WeaponHit", "SR_HitRate", 100.0f) / 100.0f);
        } else if (weaponType == "SMG") {
            return baseChance * (config.getValue<float>("WeaponHit", "SMG_HitRate", 100.0f) / 100.0f);
        } else if (weaponType == "LMG") {
            return baseChance * (config.getValue<float>("WeaponHit", "LMG_HitRate", 100.0f) / 100.0f);
        } else if (weaponType == "SG") {
            return baseChance * (config.getValue<float>("WeaponHit", "SG_HitRate", 100.0f) / 100.0f);
        } else if (weaponType == "Pistol") {
            return baseChance * (config.getValue<float>("WeaponHit", "Pistol_HitRate", 100.0f) / 100.0f);
        }
        
        return baseChance;
    }
    
    float AdjustHitChanceByMovement(float baseChance, const HitTarget& target) {
        float velocity = target.velocity.Length();
        
        if (velocity > 5.0f) {
            return baseChance * (config.getValue<float>("HitRange", "MovingHitRate", 100.0f) / 100.0f);
        }
        
        if (IsPlayerJumping(target.id)) {
            return baseChance * (config.getValue<float>("HitRange", "JumpingHitRate", 100.0f) / 100.0f);
        }
        
        if (IsPlayerCrouching(target.id)) {
            return baseChance * (config.getValue<float>("HitRange", "CrouchHitRate", 100.0f) / 100.0f);
        }
        
        if (IsPlayerProne(target.id)) {
            return baseChance * (config.getValue<float>("HitRange", "ProneHitRate", 100.0f) / 100.0f);
        }
        
        if (IsPlayerInVehicle(target.id)) {
            return baseChance * (config.getValue<float>("HitRange", "VehicleHitRate", 100.0f) / 100.0f);
        }
        
        if (IsPlayerParachuting(target.id)) {
            return baseChance * (config.getValue<float>("HitRange", "ParachuteHitRate", 100.0f) / 100.0f);
        }
        
        return baseChance;
    }
    
    void ForceHit(uint32_t targetId, const Vector3& hitPoint) {
        uintptr_t hitFunction = FindHitFunction();
        if (hitFunction == 0) return;
        
        typedef void(__fastcall* HitFunc)(uint32_t, Vector3*, float);
        HitFunc hit = (HitFunc)hitFunction;
        
        float damage = CalculateDamage(hitPoint);
        hit(targetId, &hitPoint, damage);
    }
    
    void SimulateHit(uint32_t targetId, const Vector3& hitPoint) {
        uintptr_t localPlayer = GetLocalPlayer();
        if (localPlayer == 0) return;
        
        Vector3 aimAngle = CalculateAimAngle(localPlayer, hitPoint);
        SetViewAngles(aimAngle);
        
        if (config.getValue<bool>("HitAdvanced", "InstantHit", false)) {
            SimulateInstantHit(targetId, hitPoint);
        } else {
            SimulateBulletHit(targetId, hitPoint);
        }
    }
    
    void ApplyHitEffect(uint32_t targetId, const Vector3& hitPoint) {
        if (!config.getValue<bool>("HitEffect", "EnableHitEffect", true)) {
            return;
        }
        
        float effectStrength = config.getValue<float>("HitEffect", "HitEffectStrength", 100.0f) / 100.0f;
        
        if (config.getValue<bool>("HitEffect", "CriticalHitEffect", true) && IsCriticalHit(hitPoint)) {
            PlayCriticalHitEffect(targetId, hitPoint, effectStrength);
        }
        
        if (config.getValue<bool>("HitEffect", "HeadshotEffect", true) && IsHeadshot(hitPoint)) {
            PlayHeadshotEffect(targetId, hitPoint, effectStrength);
        }
        
        if (config.getValue<bool>("HitEffect", "KillEffect", true) && IsKillShot(targetId)) {
            PlayKillEffect(targetId, hitPoint, effectStrength);
        }
        
        PlayBloodEffect(targetId, hitPoint, effectStrength);
        PlayHitSound(targetId, hitPoint, effectStrength);
        ShowHitMarker(targetId, hitPoint, effectStrength);
    }
    
    void UpdateHitStatistics(uint32_t targetId) {
        static uint32_t hitCount = 0;
        static uint32_t headshotCount = 0;
        static uint32_t killCount = 0;
        static uint64_t lastUpdate = 0;
        
        hitCount++;
        
        auto it = targets.find(targetId);
        if (it != targets.end() && IsHeadshot(it->second.headPos)) {
            headshotCount++;
        }
        
        if (IsPlayerDead(targetId)) {
            killCount++;
        }
        
        uint64_t currentTime = GetCurrentTime();
        if (currentTime - lastUpdate > 1000) {
            UpdateHitStatsDisplay(hitCount, headshotCount, killCount);
            lastUpdate = currentTime;
        }
    }
    
    uint32_t GetLocalPlayer() { return 0; }
    Vector3 GetPlayerPosition(uint32_t playerId) { return Vector3(); }
    Vector3 GetPlayerVelocity(uint32_t playerId) { return Vector3(); }
    float GetPlayerHealth(uint32_t playerId) { return 100.0f; }
    bool IsPlayerValid(uint32_t playerId) { return true; }
    bool IsPlayerVisible(uint32_t playerId) { return true; }
    bool IsPlayerKnocked(uint32_t playerId) { return false; }
    bool IsTeammate(uint32_t playerId) { return false; }
    uint32_t GetPlayerById(uint32_t index) { return index + 1; }
    uint64_t GetCurrentTime() { return GetTickCount64(); }
    Vector3 GetBonePosition(uint32_t playerId, uint32_t boneId) { return Vector3(); }
    bool IsShooting() { return (GetAsyncKeyState(VK_LBUTTON) & 0x8000) != 0; }
    float GetCurrentBulletSpeed() { return 880.0f; }
    std::string GetCurrentWeaponType() { return "AR"; }
    bool IsPlayerJumping(uint32_t playerId) { return false; }
    bool IsPlayerCrouching(uint32_t playerId) { return false; }
    bool IsPlayerProne(uint32_t playerId) { return false; }
    bool IsPlayerInVehicle(uint32_t playerId) { return false; }
    bool IsPlayerParachuting(uint32_t playerId) { return false; }
    uintptr_t FindHitFunction() { return 0; }
    float CalculateDamage(const Vector3& hitPoint) { return 100.0f; }
    Vector3 CalculateAimAngle(uint32_t fromPlayer, const Vector3& toPoint) { return Vector3(); }
    void SetViewAngles(const Vector3& angles) {}
    void SimulateInstantHit(uint32_t targetId, const Vector3& hitPoint) {}
    void SimulateBulletHit(uint32_t targetId, const Vector3& hitPoint) {}
    bool IsCriticalHit(const Vector3& hitPoint) { return dist(gen) > 0.8f; }
    bool IsHeadshot(const Vector3& hitPoint) { return dist(gen) > 0.7f; }
    bool IsKillShot(uint32_t targetId) { return false; }
    bool IsPlayerDead(uint32_t targetId) { return false; }
    void PlayCriticalHitEffect(uint32_t targetId, const Vector3& hitPoint, float strength) {}
    void PlayHeadshotEffect(uint32_t targetId, const Vector3& hitPoint, float strength) {}
    void PlayKillEffect(uint32_t targetId, const Vector3& hitPoint, float strength) {}
    void PlayBloodEffect(uint32_t targetId, const Vector3& hitPoint, float strength) {}
    void PlayHitSound(uint32_t targetId, const Vector3& hitPoint, float strength) {}
    void ShowHitMarker(uint32_t targetId, const Vector3& hitPoint, float strength) {}
    void UpdateHitStatsDisplay(uint32_t hits, uint32_t headshots, uint32_t kills) {}
};

class HotkeyManager {
private:
    HitRangeSystem& hitSystem;
    HitRangeConfig& config;
    
    struct HotkeyAction {
        int key;
        std::function<void()> action;
        bool pressed;
    };
    
    std::vector<HotkeyAction> hotkeys;
    std::thread hotkeyThread;
    std::atomic<bool> running{true};
    
public:
    HotkeyManager(HitRangeSystem& hs, HitRangeConfig& cfg) : hitSystem(hs), config(cfg) {
        SetupHotkeys();
        Start();
    }
    
    ~HotkeyManager() {
        Stop();
    }
    
    void Start() {
        running = true;
        hotkeyThread = std::thread(&HotkeyManager::HotkeyLoop, this);
    }
    
    void Stop() {
        running = false;
        if (hotkeyThread.joinable()) {
            hotkeyThread.join();
        }
    }
    
private:
    void SetupHotkeys() {
        hotkeys.push_back({VK_F6, [this]() { ToggleHitRange(); }, false});
        hotkeys.push_back({VK_F7, [this]() { ToggleHitbox(); }, false});
        hotkeys.push_back({VK_F8, [this]() { ToggleHitEffect(); }, false});
        hotkeys.push_back({VK_ADD, [this]() { IncreaseHitRate(); }, false});
        hotkeys.push_back({VK_SUBTRACT, [this]() { DecreaseHitRate(); }, false});
        hotkeys.push_back({VK_F9, [this]() { ResetConfig(); }, false});
        hotkeys.push_back({VK_F10, [this]() { SaveConfig(); }, false});
        hotkeys.push_back({VK_F11, [this]() { LoadConfig(); }, false});
        hotkeys.push_back({VK_F12, [this]() { PanicMode(); }, false});
    }
    
    void HotkeyLoop() {
        while (running) {
            for (auto& hotkey : hotkeys) {
                bool currentState = (GetAsyncKeyState(hotkey.key) & 0x8000) != 0;
                
                if (currentState && !hotkey.pressed) {
                    hotkey.action();
                    hotkey.pressed = true;
                } else if (!currentState) {
                    hotkey.pressed = false;
                }
            }
            
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
    
    void ToggleHitRange() {
        bool current = hitSystem.IsEnabled();
        hitSystem.SetEnabled(!current);
    }
    
    void ToggleHitbox() {
        bool current = config.getValue<bool>("HitVisual", "ShowHitbox", true);
        config.setValue("HitVisual", "ShowHitbox", !current);
        config.saveConfig();
    }
    
    void ToggleHitEffect() {
        bool current = config.getValue<bool>("HitEffect", "EnableHitEffect", true);
        config.setValue("HitEffect", "EnableHitEffect", !current);
        config.saveConfig();
    }
    
    void IncreaseHitRate() {
        float current = config.getValue<float>("HitRange", "HitChance", 100.0f);
        if (current < 100.0f) {
            config.setValue("HitRange", "HitChance", current + 5.0f);
            config.saveConfig();
        }
    }
    
    void DecreaseHitRate() {
        float current = config.getValue<float>("HitRange", "HitChance", 100.0f);
        if (current > 0.0f) {
            config.setValue("HitRange", "HitChance", current - 5.0f);
            config.saveConfig();
        }
    }
    
    void ResetConfig() {
        config.createDefaultConfig();
        config.loadConfig();
    }
    
    void SaveConfig() {
        config.saveConfig();
    }
    
    void LoadConfig() {
        config.loadConfig();
    }
    
    void PanicMode() {
        hitSystem.SetEnabled(false);
        config.setValue("HitRange", "HitChance", 0.0f);
        config.saveConfig();
    }
};

DWORD WINAPI MainThread(LPVOID lpParam) {
    HitRangeSystem hitSystem;
    HitRangeConfig config;
    HotkeyManager hotkeyManager(hitSystem, config);
    
    while (true) {
        if (GetAsyncKeyState(VK_END) & 1) {
            break;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
    
    return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
    if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
        DisableThreadLibraryCalls(hModule);
        CreateThread(nullptr, 0, MainThread, hModule, 0, nullptr);
    }
    return TRUE;
}

//命中范围第一人辞酱
