#include <iostream>
#include <vector>
#include <cmath>
#include <string>
#include <unordered_map>
#include <functional>
#include <algorithm>

struct Vector2 {
    float x, y;
    Vector2(float x = 0, float y = 0) : x(x), y(y) {}
    float Distance(const Vector2& o) const { float dx=x-o.x, dy=y-o.y; return sqrt(dx*dx+dy*dy); }
    Vector2 Normalize() const { float l=Distance(Vector2(0,0)); return l>0.0001f?Vector2(x/l,y/l):Vector2(0,0); }
};

struct Config {
    float range=9999.0f, largeRange=9999.0f, fov=360.0f, lockTime=0.01f;
    float sensitivity=1.0f, acceleration=999.0f, deviation=0.1f, lagComp=0.0f;
    float recoilComp=1.0f, effectDelay=0.0f, bulletSpeed=9999.0f, hitAreaMul=3.0f;
    bool tracking=true, largeArea=true, bulletTraj=true, burstTrack=true;
    std::string weaponID="Vector";
};

static Config MaxConfig() {
    Config c; c.range=c.largeRange=9999.0f; c.fov=360.0f; c.lockTime=0.01f;
    c.sensitivity=1.0f; c.acceleration=999.0f; c.deviation=0.1f; c.lagComp=0.0f;
    c.recoilComp=1.0f; c.effectDelay=0.0f; c.bulletSpeed=9999.0f; c.hitAreaMul=3.0f;
    c.tracking=c.largeArea=c.bulletTraj=c.burstTrack=true; c.weaponID="Vector";
    return c;
}

struct Weapon {
    std::string name="Vector"; float damage=9999.0f, fireRate=1100.0f;
    Config cfg=MaxConfig();
};

class Tracker {
    std::unordered_map<std::string, Config> cfgs;
    std::string curWeapon="Vector";
public:
    Tracker() { cfgs["Vector"]=MaxConfig(); }
    void SetWeapon(const std::string& w) { curWeapon=w; }
    const Config* GetCfg() const { 
        return curWeapon=="Vector"?&cfgs.at("Vector"):nullptr; 
    }
};

class Entity {
public:
    Vector2 pos; float hp=100.0f; std::string name="Enemy";
    Vector2 headOff={0,1.7f}, bodyOff={0,0.85f}, limbOff={0.3f,0.5f};
    bool attacking=true; float speed=10.0f; bool tracked=false; float effTimer=0.0f;
    Vector2 GetHead() const { return {pos.x+headOff.x, pos.y+headOff.y}; }
    Vector2 GetBody() const { return {pos.x+bodyOff.x, pos.y+bodyOff.y}; }
    Vector2 GetLimb() const { return {pos.x+limbOff.x, pos.y+limbOff.y}; }
    float GetHitArea(const std::string& part) const { 
        return (part=="head"?0.3f:part=="body"?0.6f:0.4f)*cfg.hitAreaMul; 
    }
};

class TraceCircle {
    Vector2 center; float radius, damage; const Config* cfg;
    std::string part="head"; std::function<void(TraceCircle&,Entity&,float)> onHit;
public:
    TraceCircle(Vector2 c, float r, float d, const Config* cf, std::string p="head", auto cb=nullptr) 
        : center(c), radius(r), damage(d), cfg(cf), part(p), onHit(cb) {}
    void Track(Entity& t, Vector2 pPos, float dt) {
        if(!cfg) return;
        Vector2 tarPos=part=="head"?t.GetHead():t.GetBody();
        Vector2 pred={tarPos.x+t.speed*dt*0.9f, tarPos.y+t.speed*dt*0.9f};
        center=pred; radius=cfg->largeRange; t.tracked=true; t.effTimer=cfg->effectDelay;
    }
    void Apply(Entity& v, float dt) {
        if(!cfg||!onHit) return;
        v.effTimer-=dt; Vector2 tarPos=part=="head"?v.GetHead():v.GetBody();
        if(center.Distance(tarPos)<=radius && v.effTimer<=0) {
            onHit(*this,v,damage*v.GetHitArea(part)); v.hp-=damage*v.GetHitArea(part);
            v.effTimer=cfg->effectDelay;
        }
    }
    void Update(float dt) {
        if(!cfg) return;
        static float last=0; if(dt-last>0.055f){ radius*=cfg->recoilComp; last=dt; }
    }
};

class WeaponMgr {
    std::unordered_map<std::string, Weapon> weapons; Tracker tracker;
public:
    WeaponMgr() {
        Weapon vec; vec.name="Vector"; vec.damage=9999.0f; vec.fireRate=1100.0f;
        vec.cfg=tracker.GetCfg()?*tracker.GetCfg():MaxConfig(); weapons["Vector"]=vec;
    }
    const Weapon* Get(const std::string& n) const { return n=="Vector"?&weapons.at("Vector"):nullptr; }
    void Switch(const std::string& w) { tracker.SetWeapon(w); }
};

namespace PUBGMHD {
    void Log(const std::string& m) { std::cout<<"[PUBGMHD_VectorTrace] "<<m<<std::endl; }
    void RegUpdateCB(std::function<void(float)> cb) {
        static float t=0; while(1){ cb(1/60.0f); t+=1/60.0f; }
    }
}

int main() {
    WeaponMgr wm; wm.Switch("Vector");
    const Weapon* vec=wm.Get("Vector"); if(!vec) return -1;
    Entity pl, en; pl.pos={0,0}; en.pos={100,0};
    TraceCircle tc(pl.pos, vec->cfg.range, vec->damage, &vec->cfg, "head",
        [](auto& c, auto& v, float d){ PUBGMHD::Log("Hit: "+v.name+" HP:"+std::to_string(v.hp)); });
    PUBGMHD::RegUpdateCB([&](float dt){
        tc.Track(en, pl.pos, dt); tc.Apply(en, dt); tc.Update(dt);
    });
    return 0;
}