#include <Windows.h>
#include <vector>
#include <cmath>
#include <thread>

class GameReader {
private:
    HANDLE hProcess = 0;
    DWORD64 baseAddr = 0x30000000;
    
    template<typename T>
    T Read(DWORD64 addr) {
        T val;
        ReadProcessMemory(hProcess, (LPCVOID)addr, &val, sizeof(T), 0);
        return val;
    }
    
    template<typename T>
    void Write(DWORD64 addr, T val) {
        DWORD oldProtect;
        VirtualProtectEx(hProcess, (LPVOID)addr, sizeof(T), PAGE_EXECUTE_READWRITE, &oldProtect);
        WriteProcessMemory(hProcess, (LPVOID)addr, &val, sizeof(T), 0);
        VirtualProtectEx(hProcess, (LPVOID)addr, sizeof(T), oldProtect, &oldProtect);
    }
    
public:
    struct GamePlayer {
        float x, y, z;
        float hp, shield;
        int team;
        float distance;
    };
    
    struct GameEffect {
        float x, y, z;
        float radius;
        int type;
        float power;
    };
    
    bool Init() {
        HWND hwnd = FindWindowA(0, 0);
        DWORD pid = 0;
        GetWindowThreadProcessId(hwnd, &pid);
        hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
        return hProcess != 0;
    }
    
    std::vector<GamePlayer> GetAllPlayers() {
        std::vector<GamePlayer> players;
        DWORD64 playerList = Read<DWORD64>(baseAddr + 0x1000);
        int count = Read<int>(baseAddr + 0x1008);
        
        for (int i = 0; i < count; i++) {
            DWORD64 player = Read<DWORD64>(playerList + i * 0x8);
            if (!player) continue;
            
            GamePlayer p;
            p.x = Read<float>(player + 0x200);
            p.y = Read<float>(player + 0x204);
            p.z = Read<float>(player + 0x208);
            p.hp = Read<float>(player + 0x100);
            p.shield = Read<float>(player + 0x104);
            p.team = Read<int>(player + 0x300);
            
            players.push_back(p);
        }
        
        return players;
    }
    
    std::vector<GameEffect> GetAllEffects() {
        std::vector<GameEffect> effects;
        DWORD64 effectList = Read<DWORD64>(baseAddr + 0x3000);
        int count = Read<int>(baseAddr + 0x3008);
        
        for (int i = 0; i < count; i++) {
            DWORD64 effect = Read<DWORD64>(effectList + i * 0x10);
            if (!effect) continue;
            
            GameEffect e;
            e.x = Read<float>(effect + 0x20);
            e.y = Read<float>(effect + 0x24);
            e.z = Read<float>(effect + 0x28);
            e.radius = Read<float>(effect + 0x30);
            e.type = Read<int>(effect + 0x40);
            e.power = Read<float>(effect + 0x50);
            
            effects.push_back(e);
        }
        
        return effects;
    }
    
    void ExpandEffectRange(float multiplier) {
        auto effects = GetAllEffects();
        for (auto& effect : effects) {
            DWORD64 effectAddr = FindEffectAddress(effect.x, effect.y, effect.z);
            if (effectAddr) {
                float newRadius = effect.radius * multiplier;
                Write<float>(effectAddr + 0x30, newRadius);
            }
        }
    }
    
    void SetBulletRange(float range) {
        DWORD64 bulletRangeAddr = baseAddr + 0x4000;
        Write<float>(bulletRangeAddr, range);
        
        DWORD64 explosionRangeAddr = baseAddr + 0x4008;
        Write<float>(explosionRangeAddr, range * 2.0f);
    }
    
    void SetGrenadeRange(float range) {
        DWORD64 grenadeAddr1 = baseAddr + 0x5000;
        Write<float>(grenadeAddr1, range);
        
        DWORD64 grenadeAddr2 = baseAddr + 0x5008;
        Write<float>(grenadeAddr2, range * 1.5f);
    }
    
    void SetAoeRange(float range) {
        DWORD64 aoeAddr1 = baseAddr + 0x6000;
        Write<float>(aoeAddr1, range);
        
        DWORD64 aoeAddr2 = baseAddr + 0x6008;
        Write<float>(aoeAddr2, range * 1.2f);
        
        DWORD64 aoeAddr3 = baseAddr + 0x6010;
        Write<float>(aoeAddr3, range * 1.5f);
    }
    
    void SetFlashbangRange(float range) {
        DWORD64 flashAddr = baseAddr + 0x7000;
        Write<float>(flashAddr, range);
        
        DWORD64 flashDurAddr = baseAddr + 0x7008;
        Write<float>(flashDurAddr, 5.0f);
    }
    
    void SetSmokeRange(float range) {
        DWORD64 smokeAddr = baseAddr + 0x8000;
        Write<float>(smokeAddr, range);
    }
    
    void SetMolotovRange(float range) {
        DWORD64 fireAddr1 = baseAddr + 0x9000;
        Write<float>(fireAddr1, range);
        
        DWORD64 fireAddr2 = baseAddr + 0x9008;
        Write<float>(fireAddr2, range * 1.3f);
    }
    
    void SetWeaponRange(float range) {
        DWORD64 weaponAddr1 = baseAddr + 0xA000;
        Write<float>(weaponAddr1, range);
        
        DWORD64 weaponAddr2 = baseAddr + 0xA008;
        Write<float>(weaponAddr2, range * 2.0f);
        
        DWORD64 weaponAddr3 = baseAddr + 0xA010;
        Write<float>(weaponAddr3, range * 3.0f);
    }
    
    void SetDetectionRange(float range) {
        DWORD64 detectAddr1 = baseAddr + 0xB000;
        Write<float>(detectAddr1, range);
        
        DWORD64 detectAddr2 = baseAddr + 0xB008;
        Write<float>(detectAddr2, range);
    }
    
    void SetSoundRange(float range) {
        DWORD64 soundAddr = baseAddr + 0xC000;
        Write<float>(soundAddr, range);
    }
    
    void SetVisionRange(float range) {
        DWORD64 visionAddr = baseAddr + 0xD000;
        Write<float>(visionAddr, range);
    }
    
    void EnableSuperRange() {
        ExpandEffectRange(10.0f);
        SetBulletRange(1000.0f);
        SetGrenadeRange(500.0f);
        SetAoeRange(300.0f);
        SetFlashbangRange(200.0f);
        SetSmokeRange(400.0f);
        SetMolotovRange(250.0f);
        SetWeaponRange(2000.0f);
        SetDetectionRange(1000.0f);
        SetSoundRange(500.0f);
        SetVisionRange(1000.0f);
    }
    
private:
    DWORD64 FindEffectAddress(float x, float y, float z) {
        DWORD64 effectList = Read<DWORD64>(baseAddr + 0x3000);
        int count = Read<int>(baseAddr + 0x3008);
        
        for (int i = 0; i < count; i++) {
            DWORD64 effect = Read<DWORD64>(effectList + i * 0x10);
            if (!effect) continue;
            
            float ex = Read<float>(effect + 0x20);
            float ey = Read<float>(effect + 0x24);
            float ez = Read<float>(effect + 0x28);
            
            float dx = ex - x;
            float dy = ey - y;
            float dz = ez - z;
            
            if (dx*dx + dy*dy + dz*dz < 1.0f) {
                return effect;
            }
        }
        
        return 0;
    }
}
//二改死马
