{
  "build_id": "26144732",
  "standard": "C++20 (/std:c++20 /W4 /WX)",
  "modules_count": 18,
  "modules": [
    {
      "module": "cs2_sdk",
      "directory": "sdk",
      "standard": "C++20 (/std:c++20 /W4 /WX)",
      "description": "Production clean-room reconstructed Source 2 master SDK reverse-engineered and verified against native PE binaries.",
      "files": {
        "client_classes.hpp": "#pragma once\n\n#include <cstdint>\n#include <cstddef>\n#include <cmath>\n#include <type_traits>\n\n#include \"interfaces_registry.hpp\"\n#include \"entity_system.hpp\"\n#include \"schema_system.hpp\"\n\n// ============================================================================\n// Source 2 Reverse Engineered SDK - Phase 2: Client Classes Hierarchy\n// Target Build: 2026-10-25_26144732 (CS2 Update Archive)\n// Architecture: x86-64 (MSVC ABI)\n// Binary: client.dll (Base: 0x180000000)\n// Reconstructed & Authoritatively Verified via Static Schema Reflection & RTTI\n// ============================================================================\n\nnamespace cs2::sdk {\n\n#ifndef PAD\n#define PAD(bytes, name) private: [[maybe_unused]] std::uint8_t name[bytes]; public:\n#endif\n\n// ============================================================================\n// Fundamental Geometric & Math Structures\n// ============================================================================\n#ifndef CS2_SDK_MATH_TYPES_DEFINED\n#define CS2_SDK_MATH_TYPES_DEFINED\n\nstruct Vector3 {\n    float x = 0.0f;\n    float y = 0.0f;\n    float z = 0.0f;\n\n    constexpr Vector3() noexcept = default;\n    constexpr Vector3(float x_, float y_, float z_) noexcept : x(x_), y(y_), z(z_) {}\n\n    constexpr Vector3 operator+(const Vector3& o) const noexcept { return {x + o.x, y + o.y, z + o.z}; }\n    constexpr Vector3 operator-(const Vector3& o) const noexcept { return {x - o.x, y - o.y, z - o.z}; }\n    constexpr Vector3 operator*(float s) const noexcept { return {x * s, y * s, z * s}; }\n    constexpr Vector3 operator/(float s) const noexcept { return {x / s, y / s, z / s}; }\n\n    [[nodiscard]] constexpr float Dot(const Vector3& o) const noexcept { return x * o.x + y * o.y + z * o.z; }\n    [[nodiscard]] constexpr float Dot2D(const Vector3& o) const noexcept { return x * o.x + y * o.y; }\n    [[nodiscard]] constexpr float LengthSqr() const noexcept { return Dot(*this); }\n    [[nodiscard]] constexpr float Length2DSqr() const noexcept { return Dot2D(*this); }\n    [[nodiscard]] float Length() const noexcept { return std::sqrt(LengthSqr()); }\n    [[nodiscard]] float Length2D() const noexcept { return std::sqrt(Length2DSqr()); }\n    [[nodiscard]] float DistTo(const Vector3& o) const noexcept { return (*this - o).Length(); }\n    [[nodiscard]] float Dist2DTo(const Vector3& o) const noexcept { return (*this - o).Length2D(); }\n\n    [[nodiscard]] Vector3 Normalized() const noexcept {\n        const float l = Length();\n        return l > 1e-6f ? (*this) * (1.0f / l) : Vector3{0.0f, 0.0f, 0.0f};\n    }\n\n    [[nodiscard]] constexpr Vector3 Cross(const Vector3& o) const noexcept {\n        return {\n            y * o.z - z * o.y,\n            z * o.x - x * o.z,\n            x * o.y - y * o.x\n        };\n    }\n};\nstatic_assert(sizeof(Vector3) == 0x0C, \"Vector3 size must be 12 bytes\");\n\nstruct QAngle {\n    float pitch = 0.0f;\n    float yaw   = 0.0f;\n    float roll  = 0.0f;\n\n    constexpr QAngle() noexcept = default;\n    constexpr QAngle(float p, float y, float r) noexcept : pitch(p), yaw(y), roll(r) {}\n};\nstatic_assert(sizeof(QAngle) == 0x0C, \"QAngle size must be 12 bytes\");\n\nstruct CTransform {\n    float qx = 0.0f, qy = 0.0f, qz = 0.0f, qw = 1.0f; // +0x00: Rotation Quaternion\n    float px = 0.0f, py = 0.0f, pz = 0.0f;             // +0x10: Translation Vector\n    float scale = 1.0f;                                // +0x1C: Uniform Scale Factor\n};\nstatic_assert(sizeof(CTransform) == 0x20, \"CTransform size must be 32 bytes\");\n\ntemplate <typename T>\nstruct CUtlVector {\n    std::int32_t m_size      = 0;\n    std::int32_t m_capacity  = 0;\n    T*           m_pElements = nullptr;\n\n    [[nodiscard]] constexpr std::int32_t Count() const noexcept { return m_size; }\n    [[nodiscard]] constexpr T& Element(std::int32_t i) noexcept { return m_pElements[i]; }\n    [[nodiscard]] constexpr const T& Element(std::int32_t i) const noexcept { return m_pElements[i]; }\n    [[nodiscard]] constexpr T& operator[](std::int32_t i) noexcept { return m_pElements[i]; }\n    [[nodiscard]] constexpr const T& operator[](std::int32_t i) const noexcept { return m_pElements[i]; }\n};\nstatic_assert(sizeof(CUtlVector<void*>) == 0x10, \"CUtlVector size must be 16 bytes\");\n\n#endif // CS2_SDK_MATH_TYPES_DEFINED\n\n// Forward declarations\nclass C_BaseEntity;\nclass C_BaseModelEntity;\nclass CBaseAnimGraph;\nclass C_BaseCombatCharacter;\nclass C_BasePlayerPawn;\nclass C_CSPlayerPawnBase;\nclass C_CSPlayerPawn;\nclass CBasePlayerController;\nclass CCSPlayerController;\nclass CGameSceneNode;\nclass CSkeletonInstance;\nclass CModelState;\nclass CCollisionProperty;\nclass CGlowProperty;\nclass C_BasePlayerWeapon;\nclass C_CSWeaponBase;\nclass CPlayerPawnComponent;\nclass CPlayer_WeaponServices;\nclass CCSPlayer_WeaponServices;\nclass CPlayer_ItemServices;\nclass CCSPlayer_ItemServices;\nclass CPlayer_ObserverServices;\nclass CCSObserver_ObserverServices;\nclass CPlayer_CameraServices;\nclass CCSPlayerBase_CameraServices;\nclass CCSPlayer_CameraServices;\nclass CCSPlayer_AimPunchServices;\nclass C_PlantedC4;\n\n// ============================================================================\n// 1. CCollisionProperty\n// Binary: client.dll (Schema: \"CCollisionProperty\", Size: 0xB8)\n// Verified Field Offsets:\n//   m_vecMins:          +0x0040\n//   m_vecMaxs:          +0x004C\n//   m_usSolidFlags:     +0x005A\n//   m_flBoundingRadius: +0x0060\n// ============================================================================\nclass CCollisionProperty {\npublic:\n    virtual ~CCollisionProperty() = default;         // +0x00\n    PAD(0x08, m_pad08);                              // +0x08\n    PAD(0x30, m_collisionAttribute);                 // +0x10: VPhysics collision attribute\n    Vector3 m_vecMins;                               // +0x40: AABB bounding box minimum\n    Vector3 m_vecMaxs;                               // +0x4C: AABB bounding box maximum\n    PAD(0x02, m_pad58);                              // +0x58\n    std::uint8_t m_usSolidFlags;                     // +0x5A: Solid flags bitmask\n    std::uint8_t m_nSolidType;                       // +0x5B: SolidType_t\n    std::uint8_t m_triggerBloat;                     // +0x5C: Trigger bloat\n    std::uint8_t m_nSurroundType;                    // +0x5D: SurroundType_t\n    std::uint8_t m_CollisionGroup;                   // +0x5E: CollisionGroup_t\n    std::uint8_t m_nEnablePhysics;                   // +0x5F: Physics enable state\n    float m_flBoundingRadius;                        // +0x60: Bounding sphere radius\n    Vector3 m_vecSpecifiedSurroundingMins;           // +0x64\n    Vector3 m_vecSpecifiedSurroundingMaxs;           // +0x70\n    Vector3 m_vecSurroundingMaxs;                    // +0x7C\n    Vector3 m_vecSurroundingMins;                    // +0x88\n    Vector3 m_vCapsuleCenter1;                       // +0x94\n    Vector3 m_vCapsuleCenter2;                       // +0xA0\n    float m_flCapsuleRadius;                         // +0xAC\n    PAD(0x08, m_padB0);                              // +0xB0..+0xB8\n};\nstatic_assert(sizeof(CCollisionProperty) == 0xB8, \"CCollisionProperty size must be 0xB8\");\nstatic_assert(offsetof(CCollisionProperty, m_vecMins) == 0x40, \"m_vecMins offset mismatch\");\nstatic_assert(offsetof(CCollisionProperty, m_vecMaxs) == 0x4C, \"m_vecMaxs offset mismatch\");\nstatic_assert(offsetof(CCollisionProperty, m_usSolidFlags) == 0x5A, \"m_usSolidFlags offset mismatch\");\nstatic_assert(offsetof(CCollisionProperty, m_flBoundingRadius) == 0x60, \"m_flBoundingRadius offset mismatch\");\n\n// ============================================================================\n// 2. CGlowProperty\n// Binary: client.dll (Schema: \"CGlowProperty\", Size: 0x58)\n// Verified Field Offsets:\n//   m_fGlowColor:        +0x0008\n//   m_iGlowType:         +0x0030\n//   m_iGlowTeam:         +0x0034\n//   m_glowColorOverride: +0x0040\n//   m_bGlowing:          +0x0051\n// ============================================================================\nclass CGlowProperty {\npublic:\n    virtual ~CGlowProperty() = default;              // +0x00\n    Vector3 m_fGlowColor;                            // +0x08: Vector RGB glow tint\n    PAD(0x1C, m_pad14);                              // +0x14\n    std::int32_t m_iGlowType;                        // +0x30: Glow style\n    std::int32_t m_iGlowTeam;                        // +0x34: Team isolation index\n    std::int32_t m_nGlowRange;                       // +0x38: Max range\n    std::int32_t m_nGlowRangeMin;                    // +0x3C: Min range\n    std::uint32_t m_glowColorOverride;               // +0x40: RGBA packed color override\n    bool m_bFlashing;                                // +0x44: Pulsing strobe flag\n    PAD(0x03, m_pad45);                              // +0x45\n    float m_flGlowTime;                              // +0x48\n    float m_flGlowStartTime;                         // +0x4C\n    bool m_bEligibleForScreenHighlight;              // +0x50\n    bool m_bGlowing;                                 // +0x51: Active glow state flag\n    PAD(0x06, m_pad52);                              // +0x52..+0x58\n};\nstatic_assert(sizeof(CGlowProperty) == 0x58, \"CGlowProperty size must be 0x58\");\nstatic_assert(offsetof(CGlowProperty, m_fGlowColor) == 0x08, \"m_fGlowColor offset mismatch\");\nstatic_assert(offsetof(CGlowProperty, m_iGlowType) == 0x30, \"m_iGlowType offset mismatch\");\nstatic_assert(offsetof(CGlowProperty, m_glowColorOverride) == 0x40, \"m_glowColorOverride offset mismatch\");\nstatic_assert(offsetof(CGlowProperty, m_bGlowing) == 0x51, \"m_bGlowing offset mismatch\");\n\n// ============================================================================\n// 3. C_BaseEntity\n// Base Class: CEntityInstance (Size: 0x30)\n// Binary: client.dll (Schema: \"C_BaseEntity\", Size: 0x600)\n// Verified Field Offsets:\n//   m_pGameSceneNode:   +0x0330 (CGameSceneNode*)\n//   m_iMaxHealth:       +0x0348 (int32_t)\n//   m_iHealth:          +0x034C (int32_t)\n//   m_lifeState:        +0x0354 (uint8_t: 0=Alive, 1=Dying, 2=Dead)\n//   m_flSimulationTime: +0x03B8 (float)\n//   m_iTeamNum:         +0x03E7 (uint8_t: 2=T, 3=CT)\n//   m_fFlags:           +0x03F4 (uint32_t bitmask: FL_ONGROUND=1, FL_DUCKING=2)\n//   m_vecAbsVelocity:   +0x03F8 (Vector3)\n// ============================================================================\nclass C_BaseEntity : public CEntityInstance {\npublic:\n    void* m_CBodyComponent;                          // +0x030\n    void* m_NetworkTransmitComponent;                // +0x038\n    PAD(0x02F0, m_pad40);                            // +0x040..+0x330\n    CGameSceneNode* m_pGameSceneNode;                // +0x330: Spatial scene node pointer\n    void* m_pRenderComponent;                        // +0x338\n    CCollisionProperty* m_pCollision;                // +0x340: Collision property pointer\n    std::int32_t m_iMaxHealth;                       // +0x348: Maximum health\n    std::int32_t m_iHealth;                          // +0x34C: Current health points\n    float m_flDamageAccumulator;                     // +0x350\n    std::uint8_t m_lifeState;                        // +0x354: LifeState_t (0=Alive, 1=Dying, 2=Dead)\n    bool m_bTakesDamage;                             // +0x355\n    PAD(0x0062, m_pad356);                           // +0x356..+0x3B8\n    float m_flSimulationTime;                        // +0x3B8: Simulation timestamp in seconds\n    PAD(0x002B, m_pad3BC);                           // +0x3BC..+0x3E7\n    std::uint8_t m_iTeamNum;                         // +0x3E7: Team index (2=Terrorist, 3=Counter-Terrorist)\n    std::uint32_t m_spawnflags;                      // +0x3E8\n    PAD(0x0008, m_pad3EC);                           // +0x3EC..+0x3F4\n    std::uint32_t m_fFlags;                          // +0x3F4: Entity flags (FL_ONGROUND, FL_DUCKING)\n    Vector3 m_vecAbsVelocity;                        // +0x3F8: World-space absolute velocity\n    PAD(0x010C, m_pad404);                           // +0x404..+0x510\n    Vector3 m_vecBaseVelocity;                       // +0x510: Inherited conveyor/push velocity\n    PAD(0x0004, m_pad51C);                           // +0x51C..+0x520\n    CHandle<C_BaseEntity> m_hOwnerEntity;            // +0x520: Owner entity handle\n    std::uint8_t m_MoveCollide;                      // +0x524\n    std::uint8_t m_MoveType;                         // +0x525: MoveType_t (MOVETYPE_WALK, etc.)\n    std::uint8_t m_nActualMoveType;                  // +0x526\n    PAD(0x0001, m_pad527);                           // +0x527\n    float m_flWaterLevel;                            // +0x528\n    std::uint32_t m_fEffects;                        // +0x52C\n    CHandle<C_BaseEntity> m_hGroundEntity;           // +0x530: Entity stood on\n    PAD(0x00CC, m_pad534);                           // +0x534..+0x600\n\n    [[nodiscard]] constexpr bool IsAlive() const noexcept {\n        return m_lifeState == 0 && m_iHealth > 0;\n    }\n\n    [[nodiscard]] constexpr bool IsOnGround() const noexcept {\n        return (m_fFlags & (1 << 0)) != 0;\n    }\n};\nstatic_assert(sizeof(C_BaseEntity) == 0x600, \"C_BaseEntity size must be 0x600\");\nstatic_assert(offsetof(C_BaseEntity, m_pGameSceneNode) == 0x330, \"m_pGameSceneNode offset mismatch\");\nstatic_assert(offsetof(C_BaseEntity, m_iMaxHealth) == 0x348, \"m_iMaxHealth offset mismatch\");\nstatic_assert(offsetof(C_BaseEntity, m_iHealth) == 0x34C, \"m_iHealth offset mismatch\");\nstatic_assert(offsetof(C_BaseEntity, m_lifeState) == 0x354, \"m_lifeState offset mismatch\");\nstatic_assert(offsetof(C_BaseEntity, m_flSimulationTime) == 0x3B8, \"m_flSimulationTime offset mismatch\");\nstatic_assert(offsetof(C_BaseEntity, m_iTeamNum) == 0x3E7, \"m_iTeamNum offset mismatch\");\nstatic_assert(offsetof(C_BaseEntity, m_fFlags) == 0x3F4, \"m_fFlags offset mismatch\");\nstatic_assert(offsetof(C_BaseEntity, m_vecAbsVelocity) == 0x3F8, \"m_vecAbsVelocity offset mismatch\");\n\n// ============================================================================\n// 4. C_BaseModelEntity\n// Base Class: C_BaseEntity (Size: 0x600)\n// Binary: client.dll (Schema: \"C_BaseModelEntity\", Size: 0x1098)\n// Verified Field Offsets:\n//   m_Collision:     +0x0D30 (CCollisionProperty, Size: 0xB8)\n//   m_Glow:          +0x0DE8 (CGlowProperty, Size: 0x58)\n//   m_vecViewOffset: +0x0F60 (Vector3, eye height relative to origin)\n// ============================================================================\nclass C_BaseModelEntity : public C_BaseEntity {\npublic:\n    PAD(0x0730, m_pad600);                           // +0x600..+0x0D30\n    CCollisionProperty m_Collision;                  // +0x0D30: Embedded collision property\n    CGlowProperty m_Glow;                            // +0x0DE8: Embedded glow property\n    PAD(0x0120, m_padE40);                           // +0x0E40..+0x0F60\n    Vector3 m_vecViewOffset;                         // +0x0F60: Camera offset from origin (z=64 standing, z=46 crouching)\n    PAD(0x012C, m_padF6C);                           // +0x0F6C..+0x1098\n};\nstatic_assert(sizeof(C_BaseModelEntity) == 0x1098, \"C_BaseModelEntity size must be 0x1098\");\nstatic_assert(offsetof(C_BaseModelEntity, m_Collision) == 0x0D30, \"m_Collision offset mismatch\");\nstatic_assert(offsetof(C_BaseModelEntity, m_Glow) == 0x0DE8, \"m_Glow offset mismatch\");\nstatic_assert(offsetof(C_BaseModelEntity, m_vecViewOffset) == 0x0F60, \"m_vecViewOffset offset mismatch\");\n\n// ============================================================================\n// 5. CBasePlayerController\n// Base Class: C_BaseEntity (Size: 0x600)\n// Binary: client.dll (Schema: \"CBasePlayerController\", Size: 0x800)\n// Verified Field Offsets:\n//   m_nTickBase:                +0x06B8\n//   m_hPawn:                    +0x06BC (CHandle<C_BasePlayerPawn>)\n//   m_bIsLocalPlayerController: +0x0790 (bool)\n// ============================================================================\nclass CBasePlayerController : public C_BaseEntity {\npublic:\n    PAD(0x00B8, m_pad600);                           // +0x600..+0x6B8\n    std::uint32_t m_nTickBase;                       // +0x6B8: Current simulated tickbase\n    CHandle<C_BasePlayerPawn> m_hPawn;               // +0x6BC: Associated base pawn handle\n    PAD(0x00D0, m_pad6C0);                           // +0x6C0..+0x790\n    bool m_bIsLocalPlayerController;                 // +0x790: True if controller belongs to local client\n    PAD(0x006F, m_pad791);                           // +0x791..+0x800\n};\nstatic_assert(sizeof(CBasePlayerController) == 0x800, \"CBasePlayerController size must be 0x800\");\nstatic_assert(offsetof(CBasePlayerController, m_nTickBase) == 0x6B8, \"m_nTickBase offset mismatch\");\nstatic_assert(offsetof(CBasePlayerController, m_hPawn) == 0x6BC, \"m_hPawn offset mismatch\");\nstatic_assert(offsetof(CBasePlayerController, m_bIsLocalPlayerController) == 0x790, \"m_bIsLocalPlayerController offset mismatch\");\n\n// ============================================================================\n// 6. CCSPlayerController\n// Base Class: CBasePlayerController (Size: 0x800)\n// Binary: client.dll (Schema: \"CCSPlayerController\", Size: 0x980)\n// Verified Field Offsets:\n//   m_bIsLocalPlayerController: +0x0790 (Inherited from CBasePlayerController)\n//   m_iPing:                    +0x0838 (uint32_t)\n//   m_sSanitizedPlayerName:     +0x0878 (const char*)\n//   m_hPlayerPawn:              +0x092C (CHandle<C_CSPlayerPawn>)\n//   m_bPawnIsAlive:             +0x0934 (bool)\n//   m_iPawnHealth:              +0x0938 (int32_t)\n//   m_iPawnArmor:               +0x093C (int32_t)\n//   m_bPawnHasDefuser:          +0x0940 (bool)\n//   m_bPawnHasHelmet:           +0x0941 (bool)\n// ============================================================================\nclass CCSPlayerController : public CBasePlayerController {\npublic:\n    PAD(0x0038, m_pad800);                           // +0x800..+0x838\n    std::uint32_t m_iPing;                           // +0x838: Network ping in milliseconds\n    PAD(0x003C, m_pad83C);                           // +0x83C..+0x878\n    const char* m_sSanitizedPlayerName;              // +0x878: Null-terminated sanitized player nickname\n    PAD(0x00AC, m_pad880);                           // +0x880..+0x92C\n    CHandle<C_CSPlayerPawn> m_hPlayerPawn;           // +0x92C: Currently possessed player pawn handle\n    CHandle<C_CSPlayerPawn> m_hObserverPawn;         // +0x930: Spectated target pawn handle\n    bool m_bPawnIsAlive;                             // +0x934: Cached live pawn alive flag\n    PAD(0x0003, m_pad935);                           // +0x935..+0x938\n    std::int32_t m_iPawnHealth;                      // +0x938: Replicated scoreboard health points\n    std::int32_t m_iPawnArmor;                       // +0x93C: Replicated scoreboard armor value\n    bool m_bPawnHasDefuser;                          // +0x940: Replicated defusal kit possession flag\n    bool m_bPawnHasHelmet;                           // +0x941: Replicated Kevlar helmet possession flag\n    PAD(0x003E, m_pad942);                           // +0x942..+0x980\n};\nstatic_assert(sizeof(CCSPlayerController) == 0x980, \"CCSPlayerController size must be 0x980\");\nstatic_assert(offsetof(CCSPlayerController, m_bIsLocalPlayerController) == 0x790, \"m_bIsLocalPlayerController offset mismatch\");\nstatic_assert(offsetof(CCSPlayerController, m_iPing) == 0x838, \"m_iPing offset mismatch\");\nstatic_assert(offsetof(CCSPlayerController, m_sSanitizedPlayerName) == 0x878, \"m_sSanitizedPlayerName offset mismatch\");\nstatic_assert(offsetof(CCSPlayerController, m_hPlayerPawn) == 0x92C, \"m_hPlayerPawn offset mismatch\");\nstatic_assert(offsetof(CCSPlayerController, m_bPawnIsAlive) == 0x934, \"m_bPawnIsAlive offset mismatch\");\nstatic_assert(offsetof(CCSPlayerController, m_iPawnHealth) == 0x938, \"m_iPawnHealth offset mismatch\");\nstatic_assert(offsetof(CCSPlayerController, m_iPawnArmor) == 0x93C, \"m_iPawnArmor offset mismatch\");\nstatic_assert(offsetof(CCSPlayerController, m_bPawnHasDefuser) == 0x940, \"m_bPawnHasDefuser offset mismatch\");\nstatic_assert(offsetof(CCSPlayerController, m_bPawnHasHelmet) == 0x941, \"m_bPawnHasHelmet offset mismatch\");\n\n// ============================================================================\n// 7. Component Services (Weapon, Item, Observer, Camera, AimPunch)\n// ============================================================================\n\n// --- Weapon Services ---\nclass CPlayer_WeaponServices {\npublic:\n    virtual ~CPlayer_WeaponServices() = default;     // +0x00\n    PAD(0x0040, m_pad08);                            // +0x08..+0x48\n    CUtlVector<CHandle<C_BasePlayerWeapon>> m_hMyWeapons; // +0x48: Carried inventory weapons\n    PAD(0x0008, m_pad58);                            // +0x58..+0x60\n    CHandle<C_BasePlayerWeapon> m_hActiveWeapon;     // +0x60: Currently wielded active weapon\n    PAD(0x0044, m_pad64);                            // +0x64..+0xA8\n};\nstatic_assert(sizeof(CPlayer_WeaponServices) == 0xA8, \"CPlayer_WeaponServices size must be 0xA8\");\nstatic_assert(offsetof(CPlayer_WeaponServices, m_hMyWeapons) == 0x48, \"m_hMyWeapons offset mismatch\");\nstatic_assert(offsetof(CPlayer_WeaponServices, m_hActiveWeapon) == 0x60, \"m_hActiveWeapon offset mismatch\");\n\nclass CCSPlayer_WeaponServices : public CPlayer_WeaponServices {\npublic:\n    PAD(0x1560, m_padA8);                            // +0xA8..+0x1608\n};\nstatic_assert(sizeof(CCSPlayer_WeaponServices) == 0x1608, \"CCSPlayer_WeaponServices size must be 0x1608\");\nstatic_assert(offsetof(CCSPlayer_WeaponServices, m_hMyWeapons) == 0x48, \"m_hMyWeapons offset mismatch\");\nstatic_assert(offsetof(CCSPlayer_WeaponServices, m_hActiveWeapon) == 0x60, \"m_hActiveWeapon offset mismatch\");\n\n// --- Item Services ---\nclass CPlayer_ItemServices {\npublic:\n    virtual ~CPlayer_ItemServices() = default;       // +0x00\n    PAD(0x0040, m_pad08);                            // +0x08..+0x48\n};\nstatic_assert(sizeof(CPlayer_ItemServices) == 0x48, \"CPlayer_ItemServices size must be 0x48\");\n\nclass CCSPlayer_ItemServices : public CPlayer_ItemServices {\npublic:\n    bool m_bHasDefuser;                              // +0x48: Possession of defusal kit\n    bool m_bHasHelmet;                               // +0x49: Possession of Kevlar helmet\n    bool m_bHasHeavyArmor;                           // +0x4A: Heavy assault suit protection\n    PAD(0x0005, m_pad4B);                            // +0x4B..+0x50\n};\nstatic_assert(sizeof(CCSPlayer_ItemServices) == 0x50, \"CCSPlayer_ItemServices size must be 0x50\");\nstatic_assert(offsetof(CCSPlayer_ItemServices, m_bHasDefuser) == 0x48, \"m_bHasDefuser offset mismatch\");\nstatic_assert(offsetof(CCSPlayer_ItemServices, m_bHasHelmet) == 0x49, \"m_bHasHelmet offset mismatch\");\nstatic_assert(offsetof(CCSPlayer_ItemServices, m_bHasHeavyArmor) == 0x4A, \"m_bHasHeavyArmor offset mismatch\");\n\n// --- Observer Services ---\nclass CPlayer_ObserverServices {\npublic:\n    virtual ~CPlayer_ObserverServices() = default;   // +0x00\n    PAD(0x0040, m_pad08);                            // +0x08..+0x48\n    std::uint8_t m_iObserverMode;                    // +0x48: Spectator mode (OBS_MODE_IN_EYE, OBS_MODE_CHASE, OBS_MODE_ROAMING)\n    PAD(0x0003, m_pad49);                            // +0x49..+0x4C\n    CHandle<C_BaseEntity> m_hObserverTarget;         // +0x4C: Spectated target entity\n    PAD(0x0010, m_pad50);                            // +0x50..+0x60\n};\nstatic_assert(sizeof(CPlayer_ObserverServices) == 0x60, \"CPlayer_ObserverServices size must be 0x60\");\nstatic_assert(offsetof(CPlayer_ObserverServices, m_iObserverMode) == 0x48, \"m_iObserverMode offset mismatch\");\nstatic_assert(offsetof(CPlayer_ObserverServices, m_hObserverTarget) == 0x4C, \"m_hObserverTarget offset mismatch\");\n\nclass CCSObserver_ObserverServices : public CPlayer_ObserverServices {\npublic:\n    PAD(0x00A0, m_pad60);                            // +0x60..+0x100\n};\nstatic_assert(sizeof(CCSObserver_ObserverServices) == 0x100, \"CCSObserver_ObserverServices size must be 0x100\");\nstatic_assert(offsetof(CCSObserver_ObserverServices, m_iObserverMode) == 0x48, \"m_iObserverMode offset mismatch\");\nstatic_assert(offsetof(CCSObserver_ObserverServices, m_hObserverTarget) == 0x4C, \"m_hObserverTarget offset mismatch\");\n\nusing CCSPlayer_ObserverServices = CCSObserver_ObserverServices;\n\n// --- Camera Services ---\nclass CPlayer_CameraServices {\npublic:\n    virtual ~CPlayer_CameraServices() = default;     // +0x00\n    PAD(0x0040, m_pad08);                            // +0x08..+0x48\n    QAngle m_vecCsViewPunchAngle;                    // +0x48: View punch kick angles\n    PAD(0x0244, m_pad54);                            // +0x54..+0x298\n};\nstatic_assert(sizeof(CPlayer_CameraServices) == 0x298, \"CPlayer_CameraServices size must be 0x298\");\nstatic_assert(offsetof(CPlayer_CameraServices, m_vecCsViewPunchAngle) == 0x48, \"m_vecCsViewPunchAngle offset mismatch\");\n\nclass CCSPlayerBase_CameraServices : public CPlayer_CameraServices {\npublic:\n    std::uint32_t m_iFOV;                            // +0x298: Current Field of View in degrees\n    PAD(0x0014, m_pad29C);                           // +0x29C..+0x2B0\n};\nstatic_assert(sizeof(CCSPlayerBase_CameraServices) == 0x2B0, \"CCSPlayerBase_CameraServices size must be 0x2B0\");\nstatic_assert(offsetof(CCSPlayerBase_CameraServices, m_iFOV) == 0x298, \"m_iFOV offset mismatch\");\n\nclass CCSPlayer_CameraServices : public CCSPlayerBase_CameraServices {\npublic:\n    float m_flDeathCamTilt;                          // +0x2B0: Camera roll angle during death cam\n    PAD(0x009C, m_pad2B4);                           // +0x2B4..+0x350\n};\nstatic_assert(sizeof(CCSPlayer_CameraServices) == 0x350, \"CCSPlayer_CameraServices size must be 0x350\");\nstatic_assert(offsetof(CCSPlayer_CameraServices, m_flDeathCamTilt) == 0x2B0, \"m_flDeathCamTilt offset mismatch\");\n\n// --- Aim Punch Services (Source 2 Recoil ODE Pipeline) ---\n// Note: In CS2 Source 2, legacy m_aimPunchAngle & m_aimPunchCache were refactored from C_CSPlayerPawn\n// into CCSPlayer_AimPunchServices (FUN_18085dc60 / CPlayer_AimPunchServices::SimulateAimPunchDecay).\nclass CCSPlayer_AimPunchServices {\npublic:\n    virtual ~CCSPlayer_AimPunchServices() = default; // +0x00\n    PAD(0x0040, m_pad08);                            // +0x08..+0x48\n    std::uint32_t m_predictableBaseTick;             // +0x48\n    float m_predictableBaseTickInterpAmount;         // +0x4C\n    QAngle m_predictableBaseAngle;                   // +0x50: Primary recoil aim punch angle (m_aimPunchAngle)\n    QAngle m_predictableBaseAngleVel;                // +0x5C: Recoil aim punch angular velocity spring state\n    PAD(0x0038, m_pad68);                            // +0x68..+0xA0\n    std::uint32_t m_unpredictableBaseTick;           // +0xA0\n    QAngle m_unpredictableBaseAngle;                 // +0xA4\n    PAD(0x0038, m_padB0);                            // +0xB0..+0xE8\n};\nstatic_assert(sizeof(CCSPlayer_AimPunchServices) == 0xE8, \"CCSPlayer_AimPunchServices size must be 0xE8\");\nstatic_assert(offsetof(CCSPlayer_AimPunchServices, m_predictableBaseAngle) == 0x50, \"m_predictableBaseAngle offset mismatch\");\nstatic_assert(offsetof(CCSPlayer_AimPunchServices, m_predictableBaseAngleVel) == 0x5C, \"m_predictableBaseAngleVel offset mismatch\");\nstatic_assert(offsetof(CCSPlayer_AimPunchServices, m_unpredictableBaseAngle) == 0xA4, \"m_unpredictableBaseAngle offset mismatch\");\n\n// ============================================================================\n// 8. Player Pawn Hierarchy\n// ============================================================================\n\n// Base Anim Graph (Size: 0x1268)\nclass CBaseAnimGraph : public C_BaseModelEntity {\npublic:\n    PAD(0x01D0, m_pad1098_anim);                     // +0x1098 (C_BaseModelEntity) .. +0x1268\n};\nstatic_assert(sizeof(CBaseAnimGraph) == 0x1268, \"CBaseAnimGraph size must be 0x1268\");\n\n// Base Combat Character (Size: 0x12F0)\nclass C_BaseCombatCharacter : public CBaseAnimGraph {\npublic:\n    PAD(0x0088, m_padCombat);                        // +0x1268 (CBaseAnimGraph) .. +0x12F0\n};\nstatic_assert(sizeof(C_BaseCombatCharacter) == 0x12F0, \"C_BaseCombatCharacter size must be 0x12F0\");\n\n// Base Player Pawn (Size: 0x14C8)\nclass C_BasePlayerPawn : public C_BaseCombatCharacter {\npublic:\n    CCSPlayer_WeaponServices* m_pWeaponServices;     // +0x12F0: Inventory & active weapon container\n    CCSPlayer_ItemServices*   m_pItemServices;       // +0x12F8: Equipment (defuser, helmet, armor) container\n    PAD(0x0008, m_pad1300);                          // +0x1300..+0x1308\n    CPlayer_ObserverServices* m_pObserverServices;   // +0x1308: Spectator target & mode container\n    PAD(0x0018, m_pad1310);                          // +0x1310..+0x1328\n    CCSPlayer_CameraServices* m_pCameraServices;     // +0x1328: FOV & deathcam container\n    PAD(0x0174, m_pad1330);                          // +0x1330..+0x14A4\n    Vector3 m_vOldOrigin;                            // +0x14A4: Network un-interpolated base origin\n    PAD(0x0018, m_pad14B0);                          // +0x14B0..+0x14C8\n};\nstatic_assert(sizeof(C_BasePlayerPawn) == 0x14C8, \"C_BasePlayerPawn size must be 0x14C8\");\nstatic_assert(offsetof(C_BasePlayerPawn, m_pWeaponServices) == 0x12F0, \"m_pWeaponServices offset mismatch\");\nstatic_assert(offsetof(C_BasePlayerPawn, m_pItemServices) == 0x12F8, \"m_pItemServices offset mismatch\");\nstatic_assert(offsetof(C_BasePlayerPawn, m_pObserverServices) == 0x1308, \"m_pObserverServices offset mismatch\");\nstatic_assert(offsetof(C_BasePlayerPawn, m_pCameraServices) == 0x1328, \"m_pCameraServices offset mismatch\");\nstatic_assert(offsetof(C_BasePlayerPawn, m_vOldOrigin) == 0x14A4, \"m_vOldOrigin offset mismatch\");\n\n// CS Player Pawn Base (Size: 0x1568)\nclass C_CSPlayerPawnBase : public C_BasePlayerPawn {\npublic:\n    PAD(0x0044, m_pad14C8);                          // +0x14C8..+0x150C\n    float m_flFlashMaxAlpha;                         // +0x150C: Flashbang max blinding alpha (255.0f)\n    float m_flFlashDuration;                         // +0x1510: Flashbang effect duration timer in seconds\n    PAD(0x0054, m_pad1514);                          // +0x1514..+0x1568\n};\nstatic_assert(sizeof(C_CSPlayerPawnBase) == 0x1568, \"C_CSPlayerPawnBase size must be 0x1568\");\nstatic_assert(offsetof(C_CSPlayerPawnBase, m_flFlashMaxAlpha) == 0x150C, \"m_flFlashMaxAlpha offset mismatch\");\nstatic_assert(offsetof(C_CSPlayerPawnBase, m_flFlashDuration) == 0x1510, \"m_flFlashDuration offset mismatch\");\n\n// CS Player Pawn (The Primary Player Entity, Size: 0x3720)\nclass C_CSPlayerPawn : public C_CSPlayerPawnBase {\npublic:\n    PAD(0x0030, m_pad1568);                          // +0x1568..+0x1598\n    CCSPlayer_AimPunchServices* m_pAimPunchServices; // +0x1598: Recoil aim punch spring-damper component\n    PAD(0x0900, m_pad15A0);                          // +0x15A0..+0x1EA0\n    bool m_bIsScoped;                                // +0x1EA0: Weapon optical scope active flag\n    bool m_bResumeZoom;                              // +0x1EA1: Automatic sniper zoom resumption flag\n    bool m_bIsDefusing;                              // +0x1EA2: Active bomb defusal progress flag\n    PAD(0x0015, m_pad1EA3);                          // +0x1EA3..+0x1EB8\n    std::int32_t m_iShotsFired;                      // +0x1EB8: Consecutive continuous shots fired counter\n    PAD(0x0014, m_pad1EBC);                          // +0x1EBC..+0x1ED0\n    std::int32_t m_ArmorValue;                       // +0x1ED0: Current player Kevlar body armor amount\n    PAD(0x172C, m_pad1ED4);                          // +0x1ED4..+0x3600\n    QAngle m_angEyeAngles;                           // +0x3600: Network synchronized camera view pitch & yaw\n    PAD(0x0114, m_pad360C);                          // +0x360C..+0x3720\n\n    // Legacy AimPunch API Accessors\n    [[nodiscard]] inline const QAngle& GetAimPunchAngle() const noexcept {\n        if (m_pAimPunchServices)\n            return m_pAimPunchServices->m_predictableBaseAngle;\n        static const QAngle zero{0.0f, 0.0f, 0.0f};\n        return zero;\n    }\n\n    [[nodiscard]] inline const QAngle& GetAimPunchAngleVel() const noexcept {\n        if (m_pAimPunchServices)\n            return m_pAimPunchServices->m_predictableBaseAngleVel;\n        static const QAngle zero{0.0f, 0.0f, 0.0f};\n        return zero;\n    }\n};\nstatic_assert(sizeof(C_CSPlayerPawn) == 0x3720, \"C_CSPlayerPawn size must be 0x3720\");\nstatic_assert(offsetof(C_CSPlayerPawn, m_pWeaponServices) == 0x12F0, \"m_pWeaponServices offset mismatch\");\nstatic_assert(offsetof(C_CSPlayerPawn, m_pItemServices) == 0x12F8, \"m_pItemServices offset mismatch\");\nstatic_assert(offsetof(C_CSPlayerPawn, m_pObserverServices) == 0x1308, \"m_pObserverServices offset mismatch\");\nstatic_assert(offsetof(C_CSPlayerPawn, m_pCameraServices) == 0x1328, \"m_pCameraServices offset mismatch\");\nstatic_assert(offsetof(C_CSPlayerPawn, m_vOldOrigin) == 0x14A4, \"m_vOldOrigin offset mismatch\");\nstatic_assert(offsetof(C_CSPlayerPawn, m_flFlashMaxAlpha) == 0x150C, \"m_flFlashMaxAlpha offset mismatch\");\nstatic_assert(offsetof(C_CSPlayerPawn, m_flFlashDuration) == 0x1510, \"m_flFlashDuration offset mismatch\");\nstatic_assert(offsetof(C_CSPlayerPawn, m_pAimPunchServices) == 0x1598, \"m_pAimPunchServices offset mismatch\");\nstatic_assert(offsetof(C_CSPlayerPawn, m_bIsScoped) == 0x1EA0, \"m_bIsScoped offset mismatch\");\nstatic_assert(offsetof(C_CSPlayerPawn, m_bResumeZoom) == 0x1EA1, \"m_bResumeZoom offset mismatch\");\nstatic_assert(offsetof(C_CSPlayerPawn, m_bIsDefusing) == 0x1EA2, \"m_bIsDefusing offset mismatch\");\nstatic_assert(offsetof(C_CSPlayerPawn, m_iShotsFired) == 0x1EB8, \"m_iShotsFired offset mismatch\");\nstatic_assert(offsetof(C_CSPlayerPawn, m_ArmorValue) == 0x1ED0, \"m_ArmorValue offset mismatch\");\nstatic_assert(offsetof(C_CSPlayerPawn, m_angEyeAngles) == 0x3600, \"m_angEyeAngles offset mismatch\");\n\n// ============================================================================\n// 9. Skeletal Hierarchy & Bone Matrices (CGameSceneNode, CModelState, CSkeletonInstance)\n// Reference: docs/09_skeleton_bone_hierarchy_and_animgraph.md\n// ============================================================================\n\n// Base Game Scene Node (Size: 0x130)\nclass CGameSceneNode {\npublic:\n    virtual ~CGameSceneNode() = default;             // +0x00\n    PAD(0x08, m_pad08);                              // +0x08\n    CTransform m_nodeToWorld;                        // +0x10: Root spatial coordinate transformation\n    C_BaseEntity* m_pOwner;                          // +0x30: Owning entity pointer\n    CGameSceneNode* m_pParent;                       // +0x38: Parent node in spatial hierarchy\n    CGameSceneNode* m_pChild;                        // +0x40: Child node\n    CGameSceneNode* m_pNextSibling;                  // +0x48: Sibling node\n    PAD(0x20, m_pad50);                              // +0x50..+0x70\n    CEntityHandle m_hParent;                         // +0x70: Parent entity handle\n    PAD(0x0C, m_pad74);                              // +0x74..+0x80\n    Vector3 m_vecOrigin;                             // +0x80: Local origin offset\n    PAD(0x2C, m_pad8C);                              // +0x8C..+0xB8\n    QAngle m_angRotation;                            // +0xB8: Local rotation angles\n    float m_flScale;                                 // +0xC4: Local scalar\n    Vector3 m_vecAbsOrigin;                          // +0xC8: Absolute world position\n    QAngle m_angAbsRotation;                         // +0xD4: Absolute world orientation angles\n    float m_flAbsScale;                              // +0xE0: Absolute world scalar\n    PAD(0x1F, m_padE4);                              // +0xE4..+0x103\n    bool m_bDormant;                                 // +0x103: PVS dormancy culling flag\n    PAD(0x2C, m_pad104);                             // +0x104..+0x130\n};\nstatic_assert(sizeof(CGameSceneNode) == 0x130, \"CGameSceneNode size must be 0x130\");\nstatic_assert(offsetof(CGameSceneNode, m_nodeToWorld) == 0x10, \"m_nodeToWorld offset mismatch\");\nstatic_assert(offsetof(CGameSceneNode, m_pOwner) == 0x30, \"m_pOwner offset mismatch\");\nstatic_assert(offsetof(CGameSceneNode, m_vecOrigin) == 0x80, \"m_vecOrigin offset mismatch\");\nstatic_assert(offsetof(CGameSceneNode, m_angRotation) == 0xB8, \"m_angRotation offset mismatch\");\nstatic_assert(offsetof(CGameSceneNode, m_vecAbsOrigin) == 0xC8, \"m_vecAbsOrigin offset mismatch\");\nstatic_assert(offsetof(CGameSceneNode, m_angAbsRotation) == 0xD4, \"m_angAbsRotation offset mismatch\");\nstatic_assert(offsetof(CGameSceneNode, m_bDormant) == 0x103, \"m_bDormant offset mismatch\");\n\n// Model State Container (Size: 0x2B0)\nclass CModelState {\npublic:\n    virtual ~CModelState() = default;                // +0x00\n    PAD(0x78, m_pad08);                              // +0x08..+0x80\n    CTransform* m_pBoneArray;                        // +0x80: Pointer to dynamic CTransform bone matrix array\n    PAD(0x0C, m_pad88);                              // +0x88..+0x94\n    std::uint16_t m_nBoneCount;                      // +0x94: Total number of active bones\n    PAD(0x0A, m_pad96);                              // +0x96..+0xA0\n    std::uint64_t m_hModel;                          // +0xA0: CStrongHandle to compiled model asset\n    const char* m_ModelName;                         // +0xA8: ASCII model asset path string\n    PAD(0x38, m_padB0);                              // +0xB0..+0xE8\n    float m_flRootBoneOffset_x;                      // +0xE8\n    float m_flRootBoneOffset_y;                      // +0xEC\n    float m_flRootBoneOffset_z;                      // +0xF0\n    PAD(0x114, m_padF4);                             // +0xF4..+0x208\n    std::uint64_t m_MeshGroupMask;                   // +0x208: Visible mesh group bitmask\n    PAD(0xA0, m_pad210);                             // +0x210..+0x2B0\n};\nstatic_assert(sizeof(CModelState) == 0x2B0, \"CModelState size must be 0x2B0\");\nstatic_assert(offsetof(CModelState, m_pBoneArray) == 0x80, \"m_pBoneArray offset mismatch\");\nstatic_assert(offsetof(CModelState, m_nBoneCount) == 0x94, \"m_nBoneCount offset mismatch\");\nstatic_assert(offsetof(CModelState, m_hModel) == 0xA0, \"m_hModel offset mismatch\");\nstatic_assert(offsetof(CModelState, m_ModelName) == 0xA8, \"m_ModelName offset mismatch\");\n\n// Skeleton Instance (Skeletal Mesh Runtime Hierarchy, Size: 0x490)\n// Composite layout: m_modelState starts at +0x140.\n// Bone transforms array: CSkeletonInstance + 0x01C0 (m_modelState + 0x80).\n// Bone count:            CSkeletonInstance + 0x01D4 (m_modelState + 0x94).\nclass CSkeletonInstance : public CGameSceneNode {\npublic:\n    PAD(0x10, m_pad130);                             // +0x130..+0x140\n    CModelState m_modelState;                        // +0x140: Embedded model state (Size: 0x2B0)\n    bool m_bUseParentRenderBounds;                   // +0x3F0\n    PAD(0x0B, m_pad3F1);                             // +0x3F1..+0x3FC\n    std::uint8_t m_nHitboxSet;                       // +0x3FC: Active hitbox set index (0=default, 1=headshots)\n    PAD(0x5B, m_pad3FD);                             // +0x3FD..+0x458\n    std::uint32_t m_nCalculatedBoneFlags;            // +0x458: Forward kinematics dirty bitmask\n    PAD(0x34, m_pad45C);                             // +0x45C..+0x490\n\n    [[nodiscard]] inline CTransform* GetBoneArray() const noexcept {\n        return m_modelState.m_pBoneArray;\n    }\n\n    [[nodiscard]] inline std::uint16_t GetBoneCount() const noexcept {\n        return m_modelState.m_nBoneCount;\n    }\n};\nstatic_assert(sizeof(CSkeletonInstance) == 0x490, \"CSkeletonInstance size must be 0x490\");\nstatic_assert(offsetof(CSkeletonInstance, m_modelState) == 0x140, \"m_modelState offset mismatch\");\nstatic_assert(offsetof(CSkeletonInstance, m_bUseParentRenderBounds) == 0x3F0, \"m_bUseParentRenderBounds offset mismatch\");\nstatic_assert(offsetof(CSkeletonInstance, m_nHitboxSet) == 0x3FC, \"m_nHitboxSet offset mismatch\");\nstatic_assert(offsetof(CSkeletonInstance, m_nCalculatedBoneFlags) == 0x458, \"m_nCalculatedBoneFlags offset mismatch\");\n\n// ============================================================================\n// 10. Planted C4 Explosive (C_PlantedC4)\n// Base Class: CBaseAnimGraph (Size: 0x1268) -> C_BaseModelEntity (Size: 0x1098)\n// Binary: client.dll (Schema: \"C_PlantedC4\", Size: 0x1958)\n// Verified Field Offsets:\n//   m_bBombTicking:      +0x1288 (bool)\n//   m_nBombSite:         +0x128C (int32_t: 0=Site A, 1=Site B)\n//   m_flC4Blow:          +0x12B8 (float: game time of explosion)\n//   m_flTimerLength:     +0x12C0 (float: default 40.0s)\n//   m_flDefuseLength:    +0x12D4 (float: 5.0s with kit, 10.0s without)\n//   m_flDefuseCountDown: +0x12D8 (float: game time defusal completes)\n//   m_bBombDefused:      +0x12DC (bool)\n//   m_hBombDefuser:      +0x12E0 (CHandle<C_CSPlayerPawn>)\n// ============================================================================\nclass C_PlantedC4 : public CBaseAnimGraph {\npublic:\n    PAD(0x0020, m_pad1268);                          // +0x1268..+0x1288\n    bool m_bBombTicking;                             // +0x1288: Armed ticking countdown active flag\n    PAD(0x03, m_pad1289);                            // +0x1289..+0x128C\n    std::int32_t m_nBombSite;                        // +0x128C: Designated site (0=Site A, 1=Site B)\n    PAD(0x28, m_pad1290);                            // +0x1290..+0x12B8\n    float m_flC4Blow;                                // +0x12B8: Absolute game timestamp when bomb detonates\n    bool m_bCannotBeDefused;                         // +0x12BC\n    PAD(0x03, m_pad12BD);                            // +0x12BD..+0x12C0\n    float m_flTimerLength;                           // +0x12C0: Total timer duration in seconds (mp_c4timer=40.0)\n    bool m_bBeingDefused;                            // +0x12C4: Defusal interaction in progress flag\n    PAD(0x0F, m_pad12C5);                            // +0x12C5..+0x12D4\n    float m_flDefuseLength;                          // +0x12D4: Total defuse time required (5.0s kit, 10.0s no kit)\n    float m_flDefuseCountDown;                       // +0x12D8: Absolute game timestamp when defusal succeeds\n    bool m_bBombDefused;                             // +0x12DC: Bomb successfully disarmed flag\n    PAD(0x03, m_pad12DD);                            // +0x12DD..+0x12E0\n    CHandle<C_CSPlayerPawn> m_hBombDefuser;          // +0x12E0: Player pawn currently performing defusal\n    PAD(0x0674, m_pad12E4);                          // +0x12E4..+0x1958\n\n    [[nodiscard]] constexpr float GetDefuseTimeRemaining(float curtime) const noexcept {\n        if (!m_bBeingDefused || m_bBombDefused) return 0.0f;\n        float remaining = m_flDefuseCountDown - curtime;\n        return remaining > 0.0f ? remaining : 0.0f;\n    }\n\n    [[nodiscard]] constexpr float GetBlowTimeRemaining(float curtime) const noexcept {\n        if (!m_bBombTicking || m_bBombDefused) return 0.0f;\n        float remaining = m_flC4Blow - curtime;\n        return remaining > 0.0f ? remaining : 0.0f;\n    }\n};\nstatic_assert(sizeof(C_PlantedC4) == 0x1958, \"C_PlantedC4 size must be 0x1958\");\nstatic_assert(offsetof(C_PlantedC4, m_bBombTicking) == 0x1288, \"m_bBombTicking offset mismatch\");\nstatic_assert(offsetof(C_PlantedC4, m_flC4Blow) == 0x12B8, \"m_flC4Blow offset mismatch\");\nstatic_assert(offsetof(C_PlantedC4, m_flTimerLength) == 0x12C0, \"m_flTimerLength offset mismatch\");\nstatic_assert(offsetof(C_PlantedC4, m_flDefuseLength) == 0x12D4, \"m_flDefuseLength offset mismatch\");\nstatic_assert(offsetof(C_PlantedC4, m_flDefuseCountDown) == 0x12D8, \"m_flDefuseCountDown offset mismatch\");\nstatic_assert(offsetof(C_PlantedC4, m_bBombDefused) == 0x12DC, \"m_bBombDefused offset mismatch\");\nstatic_assert(offsetof(C_PlantedC4, m_hBombDefuser) == 0x12E0, \"m_hBombDefuser offset mismatch\");\n\n} // namespace cs2::sdk\n",
        "cs2_sdk.hpp": "#pragma once\n\n// ============================================================================\n// Source 2 Reconstructed Master SDK (Counter-Strike 2)\n// Target Build: 2026-10-25_26144732 (CS2 Update Archive)\n// Architecture: x86-64 (MSVC ABI)\n// Language Standard: C++20 (/std:c++20 /W4 /WX)\n// \n// Complete clean-room reconstructed SDK reverse-engineered from synchronized\n// CS2 Ghidra project and verified against native PE binaries.\n//\n// Modular Components:\n//   - Phase 0: interfaces_registry.hpp   (Multi-binary CreateInterface registry & core engine VTables)\n//   - Phase 1: schema_system.hpp         (CSchemaSystem reflection & dynamic field traversal)\n//   - Phase 1: entity_system.hpp         (CGameEntitySystem 2D chunk table & handle arithmetic)\n//   - Phase 1: client_classes.hpp        (C_BaseEntity, C_CSPlayerPawn, Controller, PlantedC4)\n//   - Phase 2: render_scene_material.hpp (VMatrix, CViewRender, studio hitboxes, scene objects)\n//   - Phase 3: input_usercmd.hpp         (CCSGOInput, CUserCmd, Protobuf wire serialization, subtick)\n//   - Phase 4: trace_events_aux.hpp      (CGameTraceManager, IGameEventManager2, SoundOpSystem, VData)\n//   - Phase 5: item_schema.hpp           (CEconItemDefinition, CEconItemView, CAttributeManager, Paint Kits)\n//   - Phase 6: navmesh.hpp               (CNavArea, CNavNode, NavPortalEdge_t, CNavMesh V2 Graph)\n//   - Phase 7: panorama.hpp              (CUIPanel, IUIEngine, CPanelStyle, DOM Hierarchy & Event Queue)\n// ============================================================================\n\n#include \"interfaces_registry.hpp\"\n#include \"schema_system.hpp\"\n#include \"entity_system.hpp\"\n#include \"client_classes.hpp\"\n#include \"render_scene_material.hpp\"\n#include \"input_usercmd.hpp\"\n#include \"netmessages.hpp\"\n#include \"trace_events_aux.hpp\"\n#include \"item_schema.hpp\"\n#include \"navmesh.hpp\"\n#include \"panorama.hpp\"\n#include \"game_bridge.hpp\"\n\n#ifdef _WIN32\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#ifndef NOMINMAX\n#define NOMINMAX\n#endif\n#include <windows.h>\n#endif\n\nnamespace cs2::sdk {\n\n/**\n * @brief High-level helper accessors for reversed Source 2 singletons.\n */\nclass SDK {\npublic:\n    // Engine Client Interface (\"Source2EngineToClient001\")\n    [[nodiscard]] static inline ISource2EngineToClient* GetEngineClient() noexcept {\n#ifdef _WIN32\n        const auto modBase = reinterpret_cast<std::uintptr_t>(::GetModuleHandleA(\"engine2.dll\"));\n        if (!modBase) return nullptr;\n        return *reinterpret_cast<ISource2EngineToClient**>(modBase + 0x5d5c38);\n#else\n        return nullptr;\n#endif\n    }\n\n    // Schema System Interface (\"SchemaSystem_001\")\n    [[nodiscard]] static inline ISchemaSystem* GetSchemaSystem() noexcept {\n#ifdef _WIN32\n        const auto modBase = reinterpret_cast<std::uintptr_t>(::GetModuleHandleA(\"schemasystem.dll\"));\n        if (!modBase) return nullptr;\n        return *reinterpret_cast<ISchemaSystem**>(modBase + 0x3e1bc0);\n#else\n        return nullptr;\n#endif\n    }\n\n    // Client Entity System Singleton (client.dll + 0x271c8b8)\n    [[nodiscard]] static inline CGameEntitySystem* GetEntitySystem() noexcept {\n#ifdef _WIN32\n        const auto modBase = reinterpret_cast<std::uintptr_t>(::GetModuleHandleA(\"client.dll\"));\n        if (!modBase) return nullptr;\n        return *reinterpret_cast<CGameEntitySystem**>(modBase + 0x271c8b8);\n#else\n        return nullptr;\n#endif\n    }\n\n    // CSGO Input Subsystem Singleton (client.dll + 0x223dc00)\n    [[nodiscard]] static inline CCSGOInput* GetCSGOInput() noexcept {\n#ifdef _WIN32\n        const auto modBase = reinterpret_cast<std::uintptr_t>(::GetModuleHandleA(\"client.dll\"));\n        if (!modBase) return nullptr;\n        return *reinterpret_cast<CCSGOInput**>(modBase + 0x0223dc00);\n#else\n        return nullptr;\n#endif\n    }\n\n    // Global View-Projection Matrix (client.dll + 0x256cfe0)\n    [[nodiscard]] static inline const VMatrix* GetViewMatrix(int nViewIndex = 0) noexcept {\n#ifdef _WIN32\n        const auto modBase = reinterpret_cast<std::uintptr_t>(::GetModuleHandleA(\"client.dll\"));\n        if (!modBase) return nullptr;\n        const auto* pMatrices = reinterpret_cast<const VMatrix*>(modBase + 0x256cfe0);\n        return &pMatrices[nViewIndex];\n#else\n        (void)nViewIndex;\n        return nullptr;\n#endif\n    }\n\n    // Spatial Query Manager (client.dll + 0x02229020)\n    [[nodiscard]] static inline CGameTraceManager* GetGameTraceManager() noexcept {\n#ifdef _WIN32\n        const auto modBase = reinterpret_cast<std::uintptr_t>(::GetModuleHandleA(\"client.dll\"));\n        if (!modBase) return nullptr;\n        return *reinterpret_cast<CGameTraceManager**>(modBase + 0x02229020);\n#else\n        return nullptr;\n#endif\n    }\n\n    // Game Event Manager Interface (\"GAMEEVENTSMANAGER002\", client.dll + 0x02228E40)\n    [[nodiscard]] static inline IGameEventManager2* GetGameEventManager() noexcept {\n#ifdef _WIN32\n        const auto modBase = reinterpret_cast<std::uintptr_t>(::GetModuleHandleA(\"client.dll\"));\n        if (!modBase) return nullptr;\n        return *reinterpret_cast<IGameEventManager2**>(modBase + 0x02228E40);\n#else\n        return nullptr;\n#endif\n    }\n\n    // Audio Subsystem Interface (\"SoundOpSystem001\", client.dll + 0x0279EE90)\n    [[nodiscard]] static inline ISoundOpSystem* GetSoundOpSystem() noexcept {\n#ifdef _WIN32\n        const auto modBase = reinterpret_cast<std::uintptr_t>(::GetModuleHandleA(\"client.dll\"));\n        if (!modBase) return nullptr;\n        return *reinterpret_cast<ISoundOpSystem**>(modBase + 0x0279EE90);\n#else\n        return nullptr;\n#endif\n    }\n\n    // Panorama UI Engine Interface (\"PanoramaUIEngine001\", panorama.dll + 0x5F0988)\n    [[nodiscard]] static inline IUIEngine* GetPanoramaEngine() noexcept {\n#ifdef _WIN32\n        const auto modBase = reinterpret_cast<std::uintptr_t>(::GetModuleHandleA(\"panorama.dll\"));\n        if (!modBase) return nullptr;\n        return *reinterpret_cast<IUIEngine**>(modBase + 0x5F0988);\n#else\n        return nullptr;\n#endif\n    }\n\n    // ========================================================================\n    // Game Subsystems & Algorithm Bridge Helpers\n    // ========================================================================\n\n    // Resolve Player Pawn entity from CCSPlayerController\n    [[nodiscard]] static inline C_CSPlayerPawn* GetPlayerPawn(\n        const CCSPlayerController* pController,\n        const CGameEntitySystem* pEntitySystem\n    ) noexcept {\n        return bridge::GetPlayerPawn(pController, pEntitySystem);\n    }\n\n    // Analytical Two-Bone Inverse Kinematics (Law of Cosines)\n    [[nodiscard]] static inline animationsystem::IKSolveResult SolveTwoBoneIK(\n        const Vector3& root,\n        const Vector3& target,\n        const Vector3& pole,\n        float len1,\n        float len2\n    ) noexcept {\n        return bridge::SolveTwoBoneIK(root, target, pole, len1, len2);\n    }\n\n    // Server-Side Combat Damage & Armor Scaling Evaluation\n    [[nodiscard]] static inline server::DamageCalculationResult EvaluateDamage(\n        int victimHealth,\n        int victimArmor,\n        int victimTeam,\n        bool hasHelmet,\n        float baseDamage,\n        float rangeModifier,\n        float distanceUnits,\n        server::HitGroup_t hitGroup,\n        float armorRatio\n    ) noexcept {\n        return bridge::EvaluateDamage(\n            victimHealth, victimArmor, victimTeam, hasHelmet,\n            baseDamage, rangeModifier, distanceUnits, hitGroup, armorRatio\n        );\n    }\n};\n\n} // namespace cs2::sdk\n",
        "entity_system.hpp": "#pragma once\n\n#include <cstdint>\n#include <cstddef>\n#include <type_traits>\n#include <compare>\n\n// ============================================================================\n// Source 2 Reverse Engineered SDK - Phase 1: Entity System Architecture\n// Target Build: 2026-10-25_26144732 (CS2 Update Archive)\n// Architecture: x86-64 (MSVC ABI)\n// Reconstructed & Authoritatively Verified via Static RTTI & Machine Code Analysis\n// ============================================================================\n\nnamespace cs2::sdk {\n\n#ifndef PAD\n#define PAD(bytes, name) private: [[maybe_unused]] std::uint8_t name[bytes]; public:\n#endif\n\n// ============================================================================\n// Constants & Architectural Limits for Source 2 Entity Subsystem\n// Disassembly Verification Anchors:\n//   - Mask 0x7FFF (15-bit index, 32768 slots): client.dll + 0x15d1a4, 0x15ba270\n//   - Mask 0x1FF (512 slots per chunk): client.dll + 0x15d1b7, 0x15ba28e\n//   - Shift 9 (>> 9 chunk index arithmetic): client.dll + 0x15d1ab, 0x15ba283\n//   - Shift 15 (>> 15 serial generation count): client.dll + 0x15ba2af\n//   - Chunk stride 0x70 (sizeof CEntityIdentity): client.dll + 0x15d1be (imul rcx, 0x70)\n// ============================================================================\ninline constexpr std::uint32_t kInvalidEHandleIndex    = 0xFFFFFFFF;\ninline constexpr std::uint32_t kEntEntryMask          = 0x7FFF;     // 15 bits -> [0, 32767]\ninline constexpr std::uint32_t kNumSerialNumShiftBits = 15;         // 17 bits serial -> bits [15..31]\ninline constexpr std::uint32_t kEntitiesPerChunk      = 512;        // 0x200 entities per chunk\ninline constexpr std::uint32_t kMaxEntities           = 32768;      // 0x8000 max concurrent entities\ninline constexpr std::uint32_t kMaxChunks             = 64;         // 32768 / 512 = 64 chunks\ninline constexpr std::uint32_t kChunkShift            = 9;          // log2(512)\ninline constexpr std::uint32_t kSlotMask              = 0x1FF;      // 512 - 1\n\n// Forward declarations\nclass CEntityInstance;\nclass CEntityIdentity;\nclass CGameEntitySystem;\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable: 4201) // nonstandard extension used: nameless struct/union\n#endif\n\n// ============================================================================\n// 1. CEntityHandle\n// Scalar 32-bit unsigned integer split bitfield:\n//   Bits  0..14 : Entity index in CGameEntitySystem chunk array (0..32767)\n//   Bits 15..31 : Serial generation counter (prevents ABA stale pointer reuse)\n// ============================================================================\nclass CEntityHandle {\npublic:\n    union {\n        std::uint32_t m_Value;\n        struct {\n            std::uint32_t m_Index  : 15;\n            std::uint32_t m_Serial : 17;\n        };\n    };\n\n    constexpr CEntityHandle() noexcept\n        : m_Value(kInvalidEHandleIndex) {}\n\n    constexpr explicit CEntityHandle(std::uint32_t value) noexcept\n        : m_Value(value) {}\n\n    constexpr CEntityHandle(std::uint32_t nIndex, std::uint32_t nSerial) noexcept\n        : m_Value((nIndex & kEntEntryMask) | (nSerial << kNumSerialNumShiftBits)) {}\n\n    [[nodiscard]] constexpr bool IsValid() const noexcept {\n        return m_Value != kInvalidEHandleIndex && (m_Value & kEntEntryMask) != kEntEntryMask;\n    }\n\n    [[nodiscard]] constexpr std::uint32_t GetEntryIndex() const noexcept {\n        return m_Value & kEntEntryMask;\n    }\n\n    [[nodiscard]] constexpr std::uint32_t GetSerialNumber() const noexcept {\n        return m_Value >> kNumSerialNumShiftBits;\n    }\n\n    [[nodiscard]] constexpr std::uint32_t GetRaw() const noexcept {\n        return m_Value;\n    }\n\n    constexpr explicit operator std::uint32_t() const noexcept {\n        return m_Value;\n    }\n\n    constexpr explicit operator bool() const noexcept {\n        return IsValid();\n    }\n\n    constexpr bool operator==(const CEntityHandle& other) const noexcept {\n        return m_Value == other.m_Value;\n    }\n\n    constexpr bool operator!=(const CEntityHandle& other) const noexcept {\n        return m_Value != other.m_Value;\n    }\n\n    constexpr auto operator<=>(const CEntityHandle& other) const noexcept {\n        return m_Value <=> other.m_Value;\n    }\n};\nstatic_assert(sizeof(CEntityHandle) == 0x04, \"CEntityHandle size must be 4 bytes\");\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n// ============================================================================\n// 2. CHandle<T>\n// Strongly-typed wrapper around CEntityHandle\n// ============================================================================\ntemplate <typename T = CEntityInstance>\nclass CHandle : public CEntityHandle {\npublic:\n    using TargetType = T;\n\n    constexpr CHandle() noexcept\n        : CEntityHandle() {}\n\n    constexpr explicit CHandle(std::uint32_t value) noexcept\n        : CEntityHandle(value) {}\n\n    constexpr explicit CHandle(CEntityHandle handle) noexcept\n        : CEntityHandle(handle.GetRaw()) {}\n\n    constexpr CHandle(std::uint32_t nIndex, std::uint32_t nSerial) noexcept\n        : CEntityHandle(nIndex, nSerial) {}\n\n    template <typename U>\n    requires std::is_base_of_v<T, U> || std::is_base_of_v<U, T> || std::is_void_v<T>\n    constexpr CHandle(const CHandle<U>& other) noexcept\n        : CEntityHandle(other.GetRaw()) {}\n};\nstatic_assert(sizeof(CHandle<>) == 0x04, \"CHandle size must be 4 bytes\");\n\n// ============================================================================\n// 3. CEntityInstance\n// Base class for all Source 2 entities (C_BaseEntity, C_CSPlayerPawn, etc.)\n// Binary: client.dll / server.dll\n// RTTI:   .?AVCEntityInstance@@ (COL: client.dll + 0x1f83068, VTable: client.dll + 0x1d978d8)\n// ============================================================================\nclass CEntityInstance {\npublic:\n    virtual ~CEntityInstance() = default;           // +0x00: Virtual destructor (Slot 0)\n    PAD(0x08, m_pad08);                             // +0x08: m_iszPrivateVScripts (int64)\n    CEntityIdentity* m_pEntityIdentity;             // +0x10: Pointer back to CEntityIdentity descriptor\n    PAD(0x18, m_pad18);                             // +0x18..+0x30\n\n    [[nodiscard]] inline CEntityIdentity* GetIdentity() const noexcept {\n        return m_pEntityIdentity;\n    }\n\n    [[nodiscard]] inline CEntityHandle GetHandle() const noexcept;\n};\nstatic_assert(sizeof(CEntityInstance) == 0x30, \"CEntityInstance size must be 0x30 bytes\");\nstatic_assert(offsetof(CEntityInstance, m_pEntityIdentity) == 0x10, \"m_pEntityIdentity offset mismatch\");\n\n// ============================================================================\n// 4. CEntityIdentity\n// Header/metadata descriptor allocated in contiguous 512-element chunks.\n// Size: Exactly 0x70 bytes (112 bytes).\n// Disassembly Provenance Anchors:\n//   - Stride calculation: client.dll + 0x15d1be `imul rax, rdx, 0x70`\n//   - Stride calculation: client.dll + 0x15ba28e `imul rcx, rcx, 0x70`\n//   - Stride calculation: client.dll + 0x15c5aa8 `imul rcx, rcx, 0x70`\n// Member Layout Verification:\n//   - m_pEntity              : +0x00 (client.dll + 0x15d1d0 `mov rcx, [rax]`)\n//   - m_pClassInfo           : +0x08 (SchemaClassInfoData_t descriptor pointer)\n//   - m_handle               : +0x10 (client.dll + 0x15d1c5 `cmp [rax+0x10], ecx`)\n//   - m_nameStringTableIndex : +0x14 (int32 string table token)\n//   - m_pszName              : +0x18 (const char* targetname)\n//   - m_pszDesignerName      : +0x20 (const char* classname e.g. \"cs_player_controller\")\n//   - m_flags                : +0x30 (client.dll + 0x15ba2bc `mov ecx, [rcx+r9+0x30]`)\n//   - m_worldGroupId         : +0x38 (uint32 world group ID)\n//   - m_fDataObjectTypes     : +0x3C (uint32 data object mask)\n//   - m_PathIndex            : +0x40 (uint64 path index)\n//   - m_pAttributes          : +0x48 (void* attributes pointer)\n//   - m_pPrev                : +0x50 (CEntityIdentity* doubly-linked entity chain)\n//   - m_pNext                : +0x58 (CEntityIdentity* doubly-linked entity chain)\n//   - m_pPrevByClass         : +0x60 (CEntityIdentity* class-filtered chain)\n//   - m_pNextByClass         : +0x68 (CEntityIdentity* class-filtered chain)\n// ============================================================================\nclass CEntityIdentity {\npublic:\n    CEntityInstance*  m_pEntity;              // +0x00: Pointer to instantiated entity object\n    void*             m_pClassInfo;           // +0x08: SchemaClassInfoData_t descriptor\n    CEntityHandle     m_handle;               // +0x10: 32-bit handle (15-bit index, 17-bit serial)\n    std::int32_t      m_nameStringTableIndex; // +0x14: String table index\n    const char*       m_pszName;              // +0x18: Entity target name (\"player\", \"weapon_ak47\")\n    const char*       m_pszDesignerName;      // +0x20: Designer classname (\"cs_player_controller\")\n    std::uint64_t     m_pad28;                // +0x28: Flags / alignment\n    std::uint32_t     m_flags;                // +0x30: Entity flags (active, dormant, etc.)\n    std::uint32_t     m_pad34;                // +0x34: Alignment padding\n    std::uint32_t     m_worldGroupId;         // +0x38: World group ID\n    std::uint32_t     m_fDataObjectTypes;     // +0x3C: Data object bitmask\n    std::uint64_t     m_PathIndex;            // +0x40: Hierarchy / nav path index\n    void*             m_pAttributes;          // +0x48: Dynamic attribute storage\n    CEntityIdentity*  m_pPrev;                // +0x50: Doubly linked list previous node\n    CEntityIdentity*  m_pNext;                // +0x58: Doubly linked list next node\n    CEntityIdentity*  m_pPrevByClass;         // +0x60: Next entity with matching class\n    CEntityIdentity*  m_pNextByClass;         // +0x68: Prev entity with matching class\n\n    [[nodiscard]] inline bool IsValid() const noexcept {\n        return m_pEntity != nullptr && m_handle.IsValid();\n    }\n\n    [[nodiscard]] inline int GetEntryIndex() const noexcept {\n        return static_cast<int>(m_handle.GetEntryIndex());\n    }\n\n    [[nodiscard]] inline const char* GetName() const noexcept {\n        return m_pszName ? m_pszName : \"\";\n    }\n\n    [[nodiscard]] inline const char* GetDesignerName() const noexcept {\n        return m_pszDesignerName ? m_pszDesignerName : \"\";\n    }\n};\nstatic_assert(sizeof(CEntityIdentity) == 0x70, \"CEntityIdentity size must be 0x70 bytes\");\nstatic_assert(offsetof(CEntityIdentity, m_pEntity)              == 0x00, \"m_pEntity offset mismatch\");\nstatic_assert(offsetof(CEntityIdentity, m_pClassInfo)           == 0x08, \"m_pClassInfo offset mismatch\");\nstatic_assert(offsetof(CEntityIdentity, m_handle)               == 0x10, \"m_handle offset mismatch\");\nstatic_assert(offsetof(CEntityIdentity, m_nameStringTableIndex) == 0x14, \"m_nameStringTableIndex offset mismatch\");\nstatic_assert(offsetof(CEntityIdentity, m_pszName)              == 0x18, \"m_pszName offset mismatch\");\nstatic_assert(offsetof(CEntityIdentity, m_pszDesignerName)      == 0x20, \"m_pszDesignerName offset mismatch\");\nstatic_assert(offsetof(CEntityIdentity, m_flags)                == 0x30, \"m_flags offset mismatch\");\nstatic_assert(offsetof(CEntityIdentity, m_worldGroupId)         == 0x38, \"m_worldGroupId offset mismatch\");\nstatic_assert(offsetof(CEntityIdentity, m_fDataObjectTypes)     == 0x3C, \"m_fDataObjectTypes offset mismatch\");\nstatic_assert(offsetof(CEntityIdentity, m_PathIndex)            == 0x40, \"m_PathIndex offset mismatch\");\nstatic_assert(offsetof(CEntityIdentity, m_pAttributes)          == 0x48, \"m_pAttributes offset mismatch\");\nstatic_assert(offsetof(CEntityIdentity, m_pPrev)                == 0x50, \"m_pPrev offset mismatch\");\nstatic_assert(offsetof(CEntityIdentity, m_pNext)                == 0x58, \"m_pNext offset mismatch\");\nstatic_assert(offsetof(CEntityIdentity, m_pPrevByClass)         == 0x60, \"m_pPrevByClass offset mismatch\");\nstatic_assert(offsetof(CEntityIdentity, m_pNextByClass)         == 0x68, \"m_pNextByClass offset mismatch\");\n\ninline CEntityHandle CEntityInstance::GetHandle() const noexcept {\n    return m_pEntityIdentity ? m_pEntityIdentity->m_handle : CEntityHandle();\n}\n\n// ============================================================================\n// 5. CGameEntitySystem\n// High-performance 2-tier chunked entity table managing up to 32,768 entities.\n//\n// Access & Discovery Anchors:\n//   - client.dll Direct Pointer (dwGameEntitySystem):\n//       RVA: 0x271c8b8 | VA: 0x18271c8b8\n//       Initialized at client.dll + 0x15befa9 `mov [0x18271c8b8], rcx`\n//   - engine2.dll / client.dll Interface Import (GameResourceServiceClientV001):\n//       client.dll IGameResourceService pointer: RVA 0x279f088 | VA 0x18279f088\n//       Pointer to CGameEntitySystem at: *(CGameEntitySystem**)((uintptr_t)pGameResourceService + 0x58)\n//   - VTable: client.dll + 0x1c30820 (RTTI: .?AVCGameEntitySystem@@)\n//   - Constructor: client.dll + 0x9c1e40 (Allocation size: 0x2180 bytes)\n//\n// Chunk Table Layout:\n//   - Offset +0x10: m_EntityChunks[64] (Pointers to contiguous 512-element CEntityIdentity arrays)\n//   - Total 64 chunks * 512 entities/chunk = 32,768 entities.\n//\n// Indexing Arithmetic (client.dll + 0x15d1a4):\n//   chunk_index = (nIndex & 0x7FFF) >> 9;   // [0..63]\n//   slot_index  = (nIndex & 0x7FFF) & 0x1FF; // [0..511]\n//   pIdentity   = &m_EntityChunks[chunk_index][slot_index];\n// ============================================================================\nclass CGameEntitySystem {\npublic:\n    virtual ~CGameEntitySystem() = default;         // +0x00: VTable (client.dll + 0x1c30820)\n    PAD(0x08, m_pad08);                             // +0x08: Internal registration state\n\n    // +0x10: 2D Chunk Table holding pointers to 512-element CEntityIdentity arrays\n    // Stride = 8 bytes per chunk pointer, 64 pointers = 0x200 bytes (spanning +0x10 to +0x210)\n    CEntityIdentity* m_EntityChunks[kMaxChunks];    // +0x10..+0x210\n\n    PAD(0x2180 - 0x210, m_padTail);                 // +0x210..+0x2180: Entity tracking, freelists, hash indices\n\n    // ------------------------------------------------------------------------\n    // Lookup Helpers\n    // ------------------------------------------------------------------------\n\n    /// @brief Retrieve CEntityIdentity by entity index [0..32767]\n    /// @param nIndex Raw entity index (bits 0..14 of handle, or player slot + 1)\n    /// @return Pointer to CEntityIdentity or nullptr if unallocated\n    [[nodiscard]] inline CEntityIdentity* GetEntityIdentity(int nIndex) const noexcept {\n        if (nIndex < 0 || static_cast<std::uint32_t>(nIndex) >= kMaxEntities) {\n            return nullptr;\n        }\n\n        const auto uIndex = static_cast<std::uint32_t>(nIndex) & kEntEntryMask;\n        const std::uint32_t chunkIndex = uIndex >> kChunkShift;\n        const std::uint32_t slotIndex  = uIndex & kSlotMask;\n\n        const CEntityIdentity* pChunk = m_EntityChunks[chunkIndex];\n        if (!pChunk) {\n            return nullptr;\n        }\n\n        // Chunk is a contiguous array of 512 CEntityIdentity structures (0x70 bytes each)\n        return const_cast<CEntityIdentity*>(&pChunk[slotIndex]);\n    }\n\n    /// @brief Retrieve typed entity pointer by entity index [0..32767]\n    /// @tparam T Entity class type (e.g. C_BaseEntity, CCSPlayerController)\n    /// @param nIndex Raw entity index\n    /// @return Pointer to entity instance or nullptr if invalid/unallocated\n    template <typename T = CEntityInstance>\n    [[nodiscard]] inline T* GetEntityByIndex(int nIndex) const noexcept {\n        CEntityIdentity* pIdentity = GetEntityIdentity(nIndex);\n        if (!pIdentity || !pIdentity->m_pEntity) {\n            return nullptr;\n        }\n        return reinterpret_cast<T*>(pIdentity->m_pEntity);\n    }\n\n    /// @brief Retrieve typed entity pointer from 32-bit CEntityHandle\n    /// Performs 17-bit serial generation validation to eliminate dangling pointer references\n    /// Disassembly Anchor: client.dll + 0x15d1c5 `cmp [rax+0x10], ecx`\n    /// @tparam T Entity class type\n    /// @param handle Strongly-typed or raw CEntityHandle\n    /// @return Pointer to entity instance or nullptr if handle is stale/invalid\n    template <typename T = CEntityInstance>\n    [[nodiscard]] inline T* GetEntityFromHandle(CEntityHandle handle) const noexcept {\n        if (!handle.IsValid()) {\n            return nullptr;\n        }\n\n        CEntityIdentity* pIdentity = GetEntityIdentity(static_cast<int>(handle.GetEntryIndex()));\n        if (!pIdentity || !pIdentity->m_pEntity) {\n            return nullptr;\n        }\n\n        // Serial generation validation: verify active handle matches expected serial\n        if (pIdentity->m_handle != handle) {\n            return nullptr;\n        }\n\n        return reinterpret_cast<T*>(pIdentity->m_pEntity);\n    }\n\n    /// @brief Overload accepting raw uint32 handle scalar\n    template <typename T = CEntityInstance>\n    [[nodiscard]] inline T* GetEntityFromHandle(std::uint32_t handleVal) const noexcept {\n        return GetEntityFromHandle<T>(CEntityHandle(handleVal));\n    }\n\n    // ------------------------------------------------------------------------\n    // Local Player Resolution Pipeline\n    // ------------------------------------------------------------------------\n    // Algorithm:\n    //   1. Call CEngineClient::GetLocalPlayer(nSplitScreenSlot) [engine2.dll slot 37, RVA 0x762c0]\n    //      Reads *(int32_t*)(pClientSession + 0x39c), returning zero-based player slot (0..63).\n    //   2. Local Player Controller Entity Index = player_slot + 1\n    //      (Index 0 is reserved for world entity / CWorld).\n    //   3. Get CCSPlayerController from CGameEntitySystem::GetEntityByIndex(slot + 1).\n    //   4. Retrieve Pawn Handle from Controller schema field:\n    //      m_hPlayerPawn at offset +0x8ec (server.dll) / +0x92c (client.dll).\n    //   5. Resolve C_CSPlayerPawn via CGameEntitySystem::GetEntityFromHandle(m_hPlayerPawn).\n    // ------------------------------------------------------------------------\n\n    /// @brief Resolves player controller for a specific 0-based split screen slot\n    /// @tparam TController Controller type (e.g. CCSPlayerController)\n    /// @param nPlayerSlot 0-based client slot returned by CEngineClient::GetLocalPlayer()\n    /// @return Pointer to controller or nullptr\n    template <typename TController = CEntityInstance>\n    [[nodiscard]] inline TController* GetPlayerControllerBySlot(int nPlayerSlot) const noexcept {\n        if (nPlayerSlot < 0 || nPlayerSlot >= 64) {\n            return nullptr;\n        }\n        return GetEntityByIndex<TController>(nPlayerSlot + 1);\n    }\n};\nstatic_assert(offsetof(CGameEntitySystem, m_EntityChunks) == 0x10, \"m_EntityChunks offset mismatch\");\nstatic_assert(sizeof(CGameEntitySystem) == 0x2180, \"CGameEntitySystem size must be 0x2180 bytes\");\n\n} // namespace cs2::sdk\n",
        "game_bridge.hpp": "#pragma once\n\n// ============================================================================\n// Source 2 SDK & Game Subsystems Integration Bridge\n// Target Build: 2026-10-25_26144732 (CS2 Update Archive)\n// Architecture: x86-64 (MSVC ABI)\n// Language Standard: C++20 (/std:c++20 /W4 /WX)\n//\n// Unifies the public SDK class hierarchy (sdk/) with the clean-room\n// reconstructed engine services and algorithms (game/).\n// ============================================================================\n\n#include \"client_classes.hpp\"\n#include \"entity_system.hpp\"\n#include \"interfaces_registry.hpp\"\n#include \"render_scene_material.hpp\"\n#include \"input_usercmd.hpp\"\n#include \"trace_events_aux.hpp\"\n\n// Modular Game Subsystem Headers\n#include \"../game/shared/math_types.h\"\n#include \"../game/shared/entity_handle.h\"\n#include \"../game/shared/skeleton.h\"\n#include \"../game/shared/hitbox.h\"\n#include \"../game/shared/ray_trace.h\"\n#include \"../game/shared/usercmd.h\"\n#include \"../game/shared/weapon_vdata.h\"\n\n#include \"../game/interfaces/interfaces.h\"\n#include \"../game/interfaces/cvar.h\"\n#include \"../game/interfaces/engine_client.h\"\n#include \"../game/interfaces/trace_manager.h\"\n#include \"../game/interfaces/game_event_manager.h\"\n#include \"../game/interfaces/sound_system.h\"\n#include \"../game/interfaces/schema_interface.h\"\n\n#include \"../game/tier0/memalloc.h\"\n#include \"../game/tier0/utl_string_token.h\"\n#include \"../game/tier0/utl_vector.h\"\n\n#include \"../game/client/viewmatrix.h\"\n#include \"../game/client/movement.h\"\n#include \"../game/client/subtick_prediction.h\"\n#include \"../game/client/weapon_accuracy.h\"\n#include \"../game/client/bone_setup.h\"\n#include \"../game/client/entity_system.h\"\n#include \"../game/client/inventory_schema.h\"\n\n#include \"../game/server/controller_pawn.h\"\n#include \"../game/server/hit_registration_damage.h\"\n#include \"../game/server/bullet_penetration.h\"\n#include \"../game/server/lagcompensation.h\"\n\n#include \"../game/animationsystem/two_bone_ik.h\"\n#include \"../game/animationsystem/animgraph_blender.h\"\n#include \"../game/vphysics2/rubikon_collision.h\"\n#include \"../game/particles/smoke_voxels.h\"\n#include \"../game/pulse_system/pulse_interpreter.h\"\n#include \"../game/navsystem/navmesh.h\"\n#include \"../game/navsystem/pathfinder.h\"\n#include \"../game/materialsystem2/material_system2.h\"\n#include \"../game/scenesystem/scene_system.h\"\n#include \"../game/soundsystem/sound_ops.h\"\n#include \"../game/panorama/panorama_engine.h\"\n#include \"../game/networksystem/entity_delta_codec.h\"\n\nnamespace cs2::bridge {\n\n// ============================================================================\n// 1. Bi-directional Type Adapters (Zero-Cost Conversion Helpers)\n// ============================================================================\n\n[[nodiscard]] constexpr inline shared::Vector3D ToGame(const sdk::Vector3& v) noexcept {\n    return {v.x, v.y, v.z};\n}\n\n[[nodiscard]] constexpr inline sdk::Vector3 ToSDK(const shared::Vector3D& v) noexcept {\n    return {v.x, v.y, v.z};\n}\n\n[[nodiscard]] constexpr inline client::Vector3 ToClient(const sdk::Vector3& v) noexcept {\n    return {v.x, v.y, v.z};\n}\n\n[[nodiscard]] constexpr inline sdk::Vector3 ToSDK(const client::Vector3& v) noexcept {\n    return {v.x, v.y, v.z};\n}\n\n[[nodiscard]] constexpr inline shared::QAngle ToGame(const sdk::QAngle& a) noexcept {\n    return {a.pitch, a.yaw, a.roll};\n}\n\n[[nodiscard]] constexpr inline sdk::QAngle ToSDK(const shared::QAngle& a) noexcept {\n    return {a.pitch, a.yaw, a.roll};\n}\n\n[[nodiscard]] constexpr inline shared::CTransform ToGame(const sdk::CTransform& t) noexcept {\n    return {t.qx, t.qy, t.qz, t.qw, t.px, t.py, t.pz, t.scale};\n}\n\n[[nodiscard]] constexpr inline sdk::CTransform ToSDK(const shared::CTransform& t) noexcept {\n    return {t.qx, t.qy, t.qz, t.qw, t.px, t.py, t.pz, t.scale};\n}\n\n[[nodiscard]] constexpr inline shared::CEntityHandle ToGame(const sdk::CEntityHandle& h) noexcept {\n    return shared::CEntityHandle(h.GetRaw());\n}\n\n[[nodiscard]] constexpr inline sdk::CEntityHandle ToSDK(const shared::CEntityHandle& h) noexcept {\n    return sdk::CEntityHandle(h.GetRaw());\n}\n\n[[nodiscard]] inline shared::VMatrix ToGame(const sdk::VMatrix& m) noexcept {\n    shared::VMatrix out;\n    for (int r = 0; r < 4; ++r) {\n        for (int c = 0; c < 4; ++c) {\n            out[r][c] = m[r][c];\n        }\n    }\n    return out;\n}\n\n[[nodiscard]] inline sdk::VMatrix ToSDK(const shared::VMatrix& m) noexcept {\n    sdk::VMatrix out;\n    for (int r = 0; r < 4; ++r) {\n        for (int c = 0; c < 4; ++c) {\n            out[r][c] = m[r][c];\n        }\n    }\n    return out;\n}\n\n// ============================================================================\n// 2. High-Level Entity Helpers & Cross-Module Invocations\n// ============================================================================\n\n/**\n * @brief Resolves the player pawn entity associated with a player controller.\n */\n[[nodiscard]] inline sdk::C_CSPlayerPawn* GetPlayerPawn(\n    const sdk::CCSPlayerController* pController,\n    const sdk::CGameEntitySystem* pEntitySystem\n) noexcept {\n    if (!pController || !pEntitySystem) return nullptr;\n    return pEntitySystem->GetEntityFromHandle<sdk::C_CSPlayerPawn>(pController->m_hPlayerPawn);\n}\n\n/**\n * @brief Computes the player pawn's current eye position (world origin + view offset).\n */\n[[nodiscard]] inline sdk::Vector3 GetEyePosition(const sdk::C_CSPlayerPawn* pPawn) noexcept {\n    if (!pPawn) return {0.0f, 0.0f, 0.0f};\n    return {\n        pPawn->m_vOldOrigin.x + pPawn->m_vecViewOffset.x,\n        pPawn->m_vOldOrigin.y + pPawn->m_vecViewOffset.y,\n        pPawn->m_vOldOrigin.z + pPawn->m_vecViewOffset.z\n    };\n}\n\n/**\n * @brief Evaluates whether a pawn is actively alive and in combat.\n */\n[[nodiscard]] inline bool IsPawnAlive(const sdk::C_CSPlayerPawn* pPawn) noexcept {\n    if (!pPawn) return false;\n    return pPawn->m_iHealth > 0 && pPawn->m_lifeState == 0;\n}\n\n/**\n * @brief Computes the camera aim punch angle scaled by CS2's 2.0x recoil punch scalar.\n */\n[[nodiscard]] inline sdk::QAngle GetPunchAngles(const sdk::C_CSPlayerPawn* pPawn, float scalar = 2.0f) noexcept {\n    if (!pPawn) return {0.0f, 0.0f, 0.0f};\n    const auto& punch = pPawn->GetAimPunchAngle();\n    return {punch.pitch * scalar, punch.yaw * scalar, punch.roll * scalar};\n}\n\n/**\n * @brief Performs world-to-screen coordinate transformation using the active view matrix.\n */\n[[nodiscard]] inline bool WorldToScreen(\n    const sdk::Vector3& worldPos,\n    float& screenX,\n    float& screenY,\n    const sdk::VMatrix* pMatrix,\n    int screenWidth,\n    int screenHeight\n) noexcept {\n    if (!pMatrix) return false;\n    return pMatrix->WorldToScreen(worldPos, screenX, screenY, screenWidth, screenHeight);\n}\n\n/**\n * @brief Solves analytical Two-Bone Inverse Kinematics (Law of Cosines) for player limbs.\n */\n[[nodiscard]] inline animationsystem::IKSolveResult SolveTwoBoneIK(\n    const sdk::Vector3& root,\n    const sdk::Vector3& target,\n    const sdk::Vector3& pole,\n    float length1,\n    float length2\n) noexcept {\n    const animationsystem::Vector3 r{root.x, root.y, root.z};\n    const animationsystem::Vector3 t{target.x, target.y, target.z};\n    const animationsystem::Vector3 p{pole.x, pole.y, pole.z};\n    return animationsystem::CTwoBoneIKSolver::Solve(r, t, p, length1, length2);\n}\n\n/**\n * @brief Evaluates Kevlar/Helmet armor protection and damage absorption for a combat character.\n */\n[[nodiscard]] inline server::DamageCalculationResult EvaluateDamage(\n    int victimHealth,\n    int victimArmor,\n    int victimTeam,\n    bool hasHelmet,\n    float baseDamage,\n    float rangeModifier,\n    float distanceUnits,\n    server::HitGroup_t hitGroup,\n    float armorRatio\n) noexcept {\n    server::CCSPlayerPawnDamageEvaluator eval;\n    eval.m_iHealth = victimHealth;\n    eval.m_ArmorValue = victimArmor;\n    eval.m_iTeamNum = victimTeam;\n    eval.m_ItemServices.m_bHasHelmet = hasHelmet;\n\n    server::CTakeDamageInfo info;\n    info.m_flDamage = baseDamage;\n    info.m_flOriginalDamage = baseDamage;\n    info.m_flArmorPenetration = armorRatio;\n    info.m_nHitGroup = hitGroup;\n\n    return eval.ApplyArmorDamageCalculation(info, baseDamage, rangeModifier, distanceUnits);\n}\n\n/**\n * @brief Computes an A* path and smoothed funnel corridor using the clean-room NavMesh engine.\n */\n[[nodiscard]] inline navsystem::PathResult FindNavPath(\n    const sdk::CNavMesh* pNavMesh,\n    const sdk::Vector3& startPos,\n    const sdk::Vector3& goalPos,\n    const navsystem::PathOptions& options = {}\n) {\n    if (!pNavMesh) return {};\n    navsystem::CPathfinder pathfinder(pNavMesh);\n    return pathfinder.FindPath(startPos, goalPos, options);\n}\n\n/**\n * @brief Evaluates weapon skin wear classification rating and condition name.\n */\n[[nodiscard]] constexpr inline sdk::WearRating_t GetWearRating(float wear) noexcept {\n    return client::WearDegradationPipeline::EvaluateWearCondition(wear);\n}\n\n[[nodiscard]] constexpr inline const char* GetWearRatingName(sdk::WearRating_t rating) noexcept {\n    return client::WearDegradationPipeline::GetWearRatingName(rating);\n}\n\n/**\n * @brief Remaps raw wear value to paint-kit specific bounds.\n */\n[[nodiscard]] constexpr inline float RemapItemWear(float rawWear, float minWear, float maxWear) noexcept {\n    return client::WearDegradationPipeline::RemapWear(rawWear, minWear, maxWear);\n}\n\n/**\n * @brief Simulates dynamic abrasion wear degradation ODE dw/dt = kappa * (1.0 - w).\n */\n[[nodiscard]] inline float SimulateWearDegradation(\n    float initialWear,\n    float abrasionRate,\n    float durationSeconds,\n    float timeStep = 0.01f\n) noexcept {\n    return client::WearDegradationPipeline::SimulateWearDegradationODE(\n        initialWear, abrasionRate, durationSeconds, timeStep\n    );\n}\n\n} // namespace cs2::bridge\n",
        "input_usercmd.hpp": "#pragma once\n\n#include <cstdint>\n#include <cstddef>\n#include <type_traits>\n#include \"interfaces_registry.hpp\"\n#include \"entity_system.hpp\"\n#include \"client_classes.hpp\"\n#include \"render_scene_material.hpp\"\n\n// ============================================================================\n// Source 2 Reconstructed SDK - Phase 3: Input, Commands & Subtick Timing\n// Target Build: 2026-10-25_26144732 (CS2 Update Archive)\n// Architecture: x86-64 (MSVC ABI)\n// Reconstructed & Verified via Static RTTI, Protobuf Descriptors & Disassembly\n// ============================================================================\n\nnamespace cs2::sdk {\n\n#define PAD(bytes, name) private: [[maybe_unused]] std::uint8_t name[bytes]; public:\n\n// ============================================================================\n// 1. Source 2 Button Bitmasks (64-bit unsigned integers)\n// ============================================================================\nenum EInButtonState : std::uint64_t {\n    IN_ATTACK       = (1ULL << 0),\n    IN_JUMP         = (1ULL << 1),\n    IN_DUCK         = (1ULL << 2),\n    IN_FORWARD      = (1ULL << 3),\n    IN_BACK         = (1ULL << 4),\n    IN_USE          = (1ULL << 5),\n    IN_CANCEL       = (1ULL << 6),\n    IN_LEFT         = (1ULL << 7),\n    IN_RIGHT        = (1ULL << 8),\n    IN_MOVELEFT     = (1ULL << 9),\n    IN_MOVERIGHT    = (1ULL << 10),\n    IN_ATTACK2      = (1ULL << 11),\n    IN_RUN          = (1ULL << 12),\n    IN_RELOAD       = (1ULL << 13),\n    IN_ALT1         = (1ULL << 14),\n    IN_ALT2         = (1ULL << 15),\n    IN_SPEED        = (1ULL << 16),\n    IN_WALK         = (1ULL << 17),\n    IN_ZOOM         = (1ULL << 19),\n    IN_FIRST_MOD    = (1ULL << 20),\n    IN_SECOND_MOD   = (1ULL << 21),\n    IN_BULLRUSH     = (1ULL << 22),\n    IN_GRENADE1     = (1ULL << 23),\n    IN_GRENADE2     = (1ULL << 24),\n    IN_ATTACK3      = (1ULL << 25),\n};\n\n// ============================================================================\n// 2. Google Protobuf Internal Wire & Arena Structures\n// ============================================================================\n#ifndef CS2_SDK_PROTOBUF_DEFINED\n#define CS2_SDK_PROTOBUF_DEFINED\nnamespace protobuf {\n    class Arena;\n\n    namespace internal {\n        struct InternalMetadata {\n            void* ptr; // Low-order tag bits store allocation flags; upper bits store Arena*\n        };\n\n        struct Rep {\n            std::int32_t m_nAllocatedSize; // +0x00\n            std::int32_t m_nPad04;         // +0x04\n            void*        m_pElements[1];   // +0x08\n        };\n\n        struct RepeatedPtrFieldBase {\n            Arena*       m_pArena;           // +0x00\n            std::int32_t m_nCurrentElements; // +0x08\n            std::int32_t m_nTotalElements;   // +0x0C\n            Rep*         m_pRep;             // +0x10\n        };\n    }\n\n    template <typename T>\n    struct RepeatedPtrField : public internal::RepeatedPtrFieldBase {\n        T* operator[](int index) const noexcept {\n            if (!this->m_pRep || index < 0 || index >= this->m_nCurrentElements) return nullptr;\n            return reinterpret_cast<T*>(this->m_pRep->m_pElements[index]);\n        }\n        int Count() const noexcept { return this->m_nCurrentElements; }\n    };\n    static_assert(sizeof(RepeatedPtrField<void*>) == 0x18, \"RepeatedPtrField size must be 0x18 (24 bytes)\");\n\n    class MessageLite {\n    public:\n        virtual ~MessageLite() = default;\n    };\n\n    class Message : public MessageLite {};\n}\n#endif // CS2_SDK_PROTOBUF_DEFINED\n\n// ============================================================================\n// 3. Protobuf Message Types for Angles, Vectors, and Subtick Events\n// ============================================================================\n\n// Size: 0x28 (40 bytes), VTable RVA: client.dll + 0x01b72908\nstruct CMsgQAngle : public protobuf::Message {\n    protobuf::internal::InternalMetadata _internal_metadata_; // +0x08\n    std::uint32_t _has_bits_[1];                              // +0x10\n    mutable std::int32_t _cached_size_;                       // +0x14\n    float pitch;                                              // +0x18 (X)\n    float yaw;                                                // +0x1C (Y)\n    float roll;                                               // +0x20 (Z)\n    std::uint32_t _pad24;                                     // +0x24\n};\nstatic_assert(sizeof(CMsgQAngle) == 0x28, \"CMsgQAngle layout mismatch\");\n\n// Size: 0x28 (40 bytes)\nstruct CMsgVector : public protobuf::Message {\n    protobuf::internal::InternalMetadata _internal_metadata_; // +0x08\n    std::uint32_t _has_bits_[1];                              // +0x10\n    mutable std::int32_t _cached_size_;                       // +0x14\n    float x;                                                  // +0x18\n    float y;                                                  // +0x1C\n    float z;                                                  // +0x20\n    float w;                                                  // +0x24\n};\nstatic_assert(sizeof(CMsgVector) == 0x28, \"CMsgVector layout mismatch\");\n\n// Size: 0x30 (48 bytes), VTable RVA: client.dll + 0x01b2f3e8\nstruct CInButtonStatePB : public protobuf::Message {\n    protobuf::internal::InternalMetadata _internal_metadata_; // +0x08\n    std::uint32_t _has_bits_[1];                              // +0x10\n    mutable std::int32_t _cached_size_;                       // +0x14\n    std::uint64_t buttonstate1;                               // +0x18 (Held buttons)\n    std::uint64_t buttonstate2;                               // +0x20 (Pressed edges)\n    std::uint64_t buttonstate3;                               // +0x28 (Released edges)\n};\nstatic_assert(sizeof(CInButtonStatePB) == 0x30, \"CInButtonStatePB layout mismatch\");\n\n// Embedded button state structure (Size: 0x20 / 32 bytes)\n// VTable RVA: client.dll + 0x01b2b5b0\nstruct CInButtonState {\n    void*         m_pVTable;                                  // +0x00\n    std::uint64_t m_nHeldButtons;                             // +0x08 (buttonstate1)\n    std::uint64_t m_nPressedButtons;                          // +0x10 (buttonstate2)\n    std::uint64_t m_nReleasedButtons;                         // +0x18 (buttonstate3)\n};\nstatic_assert(sizeof(CInButtonState) == 0x20, \"CInButtonState layout mismatch\");\n\n// Client Subtick Move Step in Protobuf Wire Format (Size: 0x38 / 56 bytes)\n// VTable RVA: client.dll + 0x01b2f488\nstruct CSubtickMoveStep : public protobuf::Message {\n    protobuf::internal::InternalMetadata _internal_metadata_; // +0x08\n    std::uint32_t _has_bits_[1];                              // +0x10\n    mutable std::int32_t _cached_size_;                       // +0x14\n    std::uint64_t m_nButton;                                  // +0x18 (Button bitmask, 0 for analog)\n    bool          m_bPressed;                                 // +0x20 (Keydown edge vs keyup)\n    std::uint8_t  _pad21[3];                                  // +0x21\n    float         m_flWhen;                                   // +0x24 (Sub-tick fraction in [0.0, 1.0])\n    float         m_flAnalogForwardDelta;                     // +0x28\n    float         m_flAnalogLeftDelta;                        // +0x2C\n    float         m_flPitchDelta;                             // +0x30\n    float         m_flYawDelta;                               // +0x34\n};\nstatic_assert(sizeof(CSubtickMoveStep) == 0x38, \"CSubtickMoveStep layout mismatch\");\n\n// Hardware/Input Ring Buffer Step (Internal 32-byte representation within CCSGOInput)\nstruct CSubtickInputStep {\n    float         m_flWhen;               // +0x00 (Normalized fraction in [0.0, 1.0])\n    std::uint32_t _pad04;                 // +0x04\n    std::uint64_t m_nButton;              // +0x08 (Button bitmask)\n    bool          m_bPressed;             // +0x10\n    std::uint8_t  _pad11[3];              // +0x11\n    float         m_flAnalogLeftDelta;    // +0x14\n    float         m_flPitchDelta;         // +0x18\n    float         m_flYawDelta;           // +0x1C\n};\nstatic_assert(sizeof(CSubtickInputStep) == 0x20, \"CSubtickInputStep must be exactly 32 bytes\");\n\n// Interpolation descriptors\nstruct CSGOInterpolationInfoPB : public protobuf::Message {\n    protobuf::internal::InternalMetadata _internal_metadata_; // +0x08\n    std::uint32_t _has_bits_[1];                              // +0x10\n    mutable std::int32_t _cached_size_;                       // +0x14\n    std::int32_t src_tick;                                    // +0x18\n    std::int32_t dst_tick;                                    // +0x1C\n    float        frac;                                        // +0x20\n    std::uint32_t _pad;                                       // +0x24\n};\nstatic_assert(sizeof(CSGOInterpolationInfoPB) == 0x28, \"CSGOInterpolationInfoPB layout mismatch\");\n\nstruct CSGOInterpolationInfoPB_CL : public protobuf::Message {\n    protobuf::internal::InternalMetadata _internal_metadata_; // +0x08\n    std::uint32_t _has_bits_[1];                              // +0x10\n    mutable std::int32_t _cached_size_;                       // +0x14\n    float        frac;                                        // +0x18\n    std::uint32_t _pad;                                       // +0x1C\n};\nstatic_assert(sizeof(CSGOInterpolationInfoPB_CL) == 0x20, \"CSGOInterpolationInfoPB_CL layout mismatch\");\n\n// ============================================================================\n// 4. Subtick Input History Entry (Size: 0x78 / 120 bytes)\n// VTable RVA: client.dll + 0x01bcecb0\n// ============================================================================\nclass CSGOInputHistoryEntryPB : public protobuf::Message {\npublic:\n    protobuf::internal::InternalMetadata _internal_metadata_; // +0x08\n    std::uint32_t _has_bits_[1];                              // +0x10\n    mutable std::int32_t _cached_size_;                       // +0x14\n    CMsgQAngle*                 m_pViewAngles;                // +0x18\n    CSGOInterpolationInfoPB_CL* m_pClInterp;                  // +0x20\n    CSGOInterpolationInfoPB*    m_pSvInterp0;                 // +0x28\n    CSGOInterpolationInfoPB*    m_pSvInterp1;                 // +0x30\n    CSGOInterpolationInfoPB*    m_pPlayerInterp;              // +0x38\n    CMsgVector*                 m_pShootPosition;             // +0x40\n    CMsgVector*                 m_pTargetHeadPosCheck;        // +0x48\n    CMsgVector*                 m_pTargetAbsPosCheck;         // +0x50\n    CMsgQAngle*                 m_pTargetAbsAngCheck;         // +0x58\n    std::int32_t                m_nRenderTickCount;           // +0x60\n    float                       m_flRenderTickFraction;       // +0x64 [0.0, 1.0]\n    std::int32_t                m_nPlayerTickCount;           // +0x68\n    float                       m_flPlayerTickFraction;       // +0x6C [0.0, 1.0]\n    std::int32_t                m_nFrameNumber;               // +0x70\n    std::int32_t                m_nTargetEntIndex;            // +0x74\n};\nstatic_assert(sizeof(CSGOInputHistoryEntryPB) == 0x78, \"CSGOInputHistoryEntryPB size must be 0x78 (120 bytes)\");\n\nclass CBaseUserCmdExecutionNotes : public protobuf::Message {\npublic:\n    protobuf::internal::InternalMetadata _internal_metadata_; // +0x08\n    std::uint32_t _has_bits_[1];                              // +0x10\n    mutable std::int32_t _cached_size_;                       // +0x14\n    void* m_pIgnoredReason;                                   // +0x18\n};\nstatic_assert(sizeof(CBaseUserCmdExecutionNotes) == 0x20, \"CBaseUserCmdExecutionNotes layout mismatch\");\n\n// ============================================================================\n// 5. Base User Command Protobuf Message (Size: 0x88 / 136 bytes)\n// VTable RVA: client.dll + 0x01b2f5c8\n// ============================================================================\nclass CBaseUserCmdPB : public protobuf::Message {\npublic:\n    protobuf::internal::InternalMetadata _internal_metadata_;                 // +0x08\n    std::uint32_t _has_bits_[1];                                              // +0x10\n    mutable std::int32_t _cached_size_;                                       // +0x14\n\n    protobuf::RepeatedPtrField<CSubtickMoveStep> m_subtick_moves;             // +0x18\n    void*                        m_pMoveCRC;                                  // +0x30 (std::string*)\n    CInButtonStatePB*            m_pButtonsPB;                                // +0x38\n    CMsgQAngle*                  m_pViewAngles;                               // +0x40\n    CBaseUserCmdExecutionNotes*  m_pExecutionNotes;                           // +0x48\n    std::int32_t                 m_nLegacyCommandNumber;                      // +0x50\n    std::int32_t                 m_nClientTick;                               // +0x54\n    float                        m_flForwardMove;                             // +0x58\n    float                        m_flLeftMove;                                // +0x5C\n    float                        m_flUpMove;                                  // +0x60\n    std::int32_t                 m_nImpulse;                                  // +0x64\n    std::int32_t                 m_nWeaponSelect;                             // +0x68\n    std::int32_t                 m_nRandomSeed;                               // +0x6C\n    std::int32_t                 m_nMousedX;                                  // +0x70\n    std::int32_t                 m_nMousedY;                                  // +0x74\n    std::uint32_t                m_nPredictionOffsetTicksX256;                // +0x78\n    std::uint32_t                m_nConsumedServerAngleChanges;               // +0x7C\n    std::int32_t                 m_nCmdFlags;                                 // +0x80\n    std::uint32_t                m_nPawnEntityHandle;                         // +0x84\n};\nstatic_assert(sizeof(CBaseUserCmdPB) == 0x88, \"CBaseUserCmdPB size must be 0x88 (136 bytes)\");\n\n// ============================================================================\n// 6. CSGO Specific User Command Protobuf Message (Size: 0x48 / 72 bytes)\n// VTable RVA: client.dll + 0x01bced50\n// ============================================================================\nclass CSGOUserCmdPB : public protobuf::Message {\npublic:\n    protobuf::internal::InternalMetadata _internal_metadata_;                 // +0x08\n    std::uint32_t _has_bits_[1];                                              // +0x10\n    mutable std::int32_t _cached_size_;                                       // +0x14\n    protobuf::RepeatedPtrField<CSGOInputHistoryEntryPB> m_input_history;       // +0x18\n    CBaseUserCmdPB* m_pBaseCmd;                                               // +0x30\n    bool            m_bHasBeenPredicted;                                      // +0x38\n    bool            m_bIsPredictingBodyShotFx;                                // +0x39\n    bool            m_bIsPredictingHeadShotFx;                                // +0x3A\n    bool            m_bIsPredictingKillRagdolls;                              // +0x3B\n    std::int32_t    m_nAttack1StartHistoryIndex;                              // +0x3C\n    std::int32_t    m_nAttack2StartHistoryIndex;                              // +0x40\n    std::uint32_t   m_nPad54;                                                 // +0x44\n};\nstatic_assert(sizeof(CSGOUserCmdPB) == 0x48, \"CSGOUserCmdPB size must be 0x48 (72 bytes)\");\n\n// ============================================================================\n// 7. Full CUserCmd Container (Size: 0x98 / 152 bytes)\n// VTable RVA: client.dll + 0x01c1cf68 (VA: 0x181c1cf68)\n// Scalar Destructor: client.dll + 0x0092c9d0\n// ============================================================================\nclass CUserCmdBase {\npublic:\n    virtual ~CUserCmdBase() = default;                                        // +0x00\n};\n\ntemplate <typename T>\nclass CUserCmdBaseHost : public CUserCmdBase {\npublic:\n    std::int32_t  m_nSequenceNumber;                                          // +0x08\n    std::uint32_t m_nPad0C;                                                   // +0x0C\n};\n\nclass CCSGOUserCmd : public CUserCmdBaseHost<CSGOUserCmdPB> {};\n\nclass CUserCmd : public CCSGOUserCmd, public CSGOUserCmdPB {\npublic:\n    // +0x00: CCSGOUserCmd (disp = 0, size 0x10)\n    // +0x10: CSGOUserCmdPB (disp = 16, size 0x48, ends at 0x58)\n    CInButtonState m_buttons;                                                 // +0x58..+0x78 (size 0x20)\n    std::int32_t   m_nImpulse;                                                // +0x78\n    std::int32_t   m_nWeaponSelect;                                           // +0x7C\n    std::int64_t   m_nRandomSeed;                                             // +0x80\n    std::int32_t   m_nMousedX;                                                // +0x88\n    bool           m_bHasPredicted;                                           // +0x8C\n    std::uint8_t   m_nPad8D[3];                                               // +0x8D\n    std::int32_t   m_nPad90;                                                  // +0x90\n    std::int32_t   m_nCommandStatus;                                          // +0x94 (2 = ready / executed)\n};\nstatic_assert(sizeof(CUserCmd) == 0x98, \"CUserCmd size must be 0x98 (152 bytes)\");\nstatic_assert(offsetof(CUserCmd, m_nSequenceNumber) == 0x08, \"m_nSequenceNumber offset mismatch\");\nstatic_assert(offsetof(CUserCmd, m_pBaseCmd) == 0x40, \"m_pBaseCmd offset mismatch in CUserCmd\");\nstatic_assert(offsetof(CUserCmd, m_buttons) == 0x58, \"m_buttons offset mismatch in CUserCmd\");\nstatic_assert(offsetof(CUserCmd, m_nImpulse) == 0x78, \"m_nImpulse offset mismatch in CUserCmd\");\nstatic_assert(offsetof(CUserCmd, m_nCommandStatus) == 0x94, \"m_nCommandStatus offset mismatch in CUserCmd\");\n\n// ============================================================================\n// 8. CCSGOInput Subsystem Layout (Size: 0xc20 / 3,104 bytes)\n// Global Pointer: client.dll + 0x0223dc00 (VA: 0x18223dc00)\n// Static Instance: client.dll + 0x0257d780 (VA: 0x18257d780)\n// Getter Function: client.dll + 0x00ce37a0 (GetCSGOInput)\n// VTable RVA: client.dll + 0x01c9fa58 (VA: 0x181c9fa58)\n// ============================================================================\nclass CCSGOInput {\npublic:\n    // Slot 0: Scalar deleting destructor (client.dll + 0x00cde340)\n    virtual ~CCSGOInput() = default;\n\n    virtual void Unk01() = 0;\n    virtual void Unk02() = 0;\n    virtual void Unk03() = 0;\n    virtual void Unk04() = 0;\n\n    // Slot 5: CreateMove (client.dll + 0x00b66c20, VA: 0x180b66c20)\n    // Parameter Signature:\n    //   rcx: this (CCSGOInput*)\n    //   edx: nSlot (split-screen player slot, 0 for primary)\n    //   r8b: bActive (input activation flag)\n    virtual bool CreateMove(std::int32_t nSlot, bool bActive) = 0;\n\n    // Memory members\n    PAD(0x258, m_pad08);\n    // Sub-tick move storage array (capacity 32)\n    std::int32_t      m_nFixedSubtickAllocCount; // +0x260\n    PAD(0x00C, m_pad264);\n    void*             m_pSubtickMemory;          // +0x270 (&this->m_SubtickMoveSteps)\n    std::int32_t      m_nSubtickCapacity;        // +0x278 (32)\n    PAD(0x008, m_pad27C);\n    std::int32_t      m_nSubtickMoveStepCount;   // +0x284 (Number of sub-tick steps recorded this frame)\n    CSubtickInputStep m_SubtickMoveSteps[32];    // +0x288..+0x688 (1,024 bytes)\n    QAngle            m_angViewAngles;           // +0x688\n    PAD(0x284, m_pad694);\n    float             m_flSubtickAccumulator;    // +0x918\n    PAD(0x234, m_pad91C);\n    std::int32_t      m_nMouseHistoryCount;      // +0xb50\n    PAD(0x004, m_padB54);\n    void*             m_pMouseHistory;           // +0xb58\n    PAD(0x020, m_padB60);\n    void*             m_pSecondaryVTable;        // +0xb80 (client.dll + 0x01c9fb68)\n    void*             m_pTertiaryVTable;         // +0xb88 (client.dll + 0x01c9fb78)\n    bool              m_bIsSwappingToPredictableController; // +0xb90\n    PAD(0x02B, m_padB91);\n    bool              m_bCameraInThirdPerson;    // +0xbbc\n    PAD(0x01B, m_padBBD);\n    std::int32_t      m_nFrameSequence;          // +0xbd8\n    PAD(0x020, m_padBDC);\n    std::int32_t      m_nInputLockCount;         // +0xbfc\n    PAD(0x008, m_padC00);\n    QAngle            m_angThirdPersonAngle;     // +0xc08\n    PAD(0x00C, m_padC14);\n};\nstatic_assert(sizeof(CCSGOInput) == 0xc20, \"CCSGOInput size must be 0xc20 (3,104 bytes)\");\nstatic_assert(offsetof(CCSGOInput, m_nSubtickMoveStepCount) == 0x284, \"m_nSubtickMoveStepCount offset\");\nstatic_assert(offsetof(CCSGOInput, m_SubtickMoveSteps) == 0x288, \"m_SubtickMoveSteps offset\");\nstatic_assert(offsetof(CCSGOInput, m_angViewAngles) == 0x688, \"m_angViewAngles offset\");\nstatic_assert(offsetof(CCSGOInput, m_flSubtickAccumulator) == 0x918, \"m_flSubtickAccumulator offset\");\n\n#undef PAD\n\n} // namespace cs2::sdk\n",
        "interfaces_registry.hpp": "#pragma once\n\n#include <cstdint>\n#include <cstddef>\n#include <type_traits>\n\n// ============================================================================\n// Source 2 Reverse Engineered SDK - Phase 0: Multi-Binary Interfaces Registry\n// Target Build: 2026-10-25_26144732 (CS2 Update Archive)\n// Architecture: x86-64 (MSVC ABI)\n// Reconstructed & Authoritatively Verified via Static RTTI & VTable Analysis\n// ============================================================================\n\nnamespace cs2::sdk {\n\n#define PAD(bytes, name) private: [[maybe_unused]] std::uint8_t name[bytes]; public:\n\n// ============================================================================\n// Dynamic Interface Registration Linked List (CreateInterface Registry)\n// Discovery Anchor: Exported CreateInterface entry point in each Source 2 DLL\n// Layout verified across all 34 synchronized DLLs:\n//   m_CreateFn : +0x00 (Instantiate callback)\n//   m_pName    : +0x08 (Null-terminated ASCII interface token)\n//   m_pNext    : +0x10 (Next node in singly-linked list)\n// ============================================================================\nusing InstantiateInterfaceFn = void* (*)();\n\nstruct InterfaceReg {\n    InstantiateInterfaceFn m_CreateFn; // +0x00\n    const char*            m_pName;    // +0x08\n    InterfaceReg*          m_pNext;    // +0x10\n};\nstatic_assert(sizeof(InterfaceReg) == 0x18, \"InterfaceReg size must be 0x18 bytes\");\nstatic_assert(offsetof(InterfaceReg, m_CreateFn) == 0x00, \"m_CreateFn offset mismatch\");\nstatic_assert(offsetof(InterfaceReg, m_pName)    == 0x08, \"m_pName offset mismatch\");\nstatic_assert(offsetof(InterfaceReg, m_pNext)    == 0x10, \"m_pNext offset mismatch\");\n\nusing CreateInterfaceFn = void* (*)(const char* pName, int* pReturnCode);\n\n// Forward declarations of types referenced by interfaces\nclass CGameEntitySystem;\nclass CSchemaSystemTypeScope;\nclass ConVar;\nclass INetChannelInfo;\nclass CNetworkGameClient;\nclass CMaterial2;\n\n// ============================================================================\n// 1. ISource2EngineToClient (CEngineClient)\n// Binary: engine2.dll\n// Token:  \"Source2EngineToClient001\" (Node RVA: 0x61a7a0, Factory RVA: 0x78ab0)\n// VTable: engine2.dll + 0x5d5c38 (185 methods, this_offset: +0x0)\n// RTTI:   .?AVCEngineClient@@\n// ============================================================================\nclass ISource2EngineToClient {\npublic:\n    virtual ~ISource2EngineToClient() = default;                                                 // Slot 0\n\n    // Virtual slots 1 to 31\n    virtual void Unk01() = 0; virtual void Unk02() = 0; virtual void Unk03() = 0; virtual void Unk04() = 0;\n    virtual void Unk05() = 0; virtual void Unk06() = 0; virtual void Unk07() = 0; virtual void Unk08() = 0;\n    virtual void Unk09() = 0; virtual void Unk10() = 0; virtual void Unk11() = 0; virtual void Unk12() = 0;\n    virtual void Unk13() = 0; virtual void Unk14() = 0; virtual void Unk15() = 0; virtual void Unk16() = 0;\n    virtual void Unk17() = 0; virtual void Unk18() = 0; virtual void Unk19() = 0; virtual void Unk20() = 0;\n    virtual void Unk21() = 0; virtual void Unk22() = 0; virtual void Unk23() = 0; virtual void Unk24() = 0;\n    virtual void Unk25() = 0; virtual void Unk26() = 0; virtual void Unk27() = 0; virtual void Unk28() = 0;\n    virtual void Unk29() = 0; virtual void Unk30() = 0; virtual void Unk31() = 0;\n\n    // Slot 32: engine2.dll + 0x76150 (Returns screen pixel resolution)\n    virtual void GetScreenSize(std::int32_t& nWidth, std::int32_t& nHeight) = 0;\n\n    virtual void Unk33() = 0; virtual void Unk34() = 0; virtual void Unk35() = 0;\n\n    // Slot 36: engine2.dll + 0x76280 (Returns display aspect ratio w/h)\n    virtual float GetScreenAspectRatio() = 0;\n\n    // Slot 37: engine2.dll + 0x762c0 (Reads *(int32*)(this + 0x39c))\n    virtual std::int32_t GetLocalPlayer(std::int32_t& nSplitScreenSlot) = 0;\n\n    // Slot 38: engine2.dll + 0x762e0 (Reads *(int32*)(this + 0x240))\n    virtual std::int32_t GetMaxClients() = 0;\n\n    // Slot 39: engine2.dll + 0x76380 (Checks *(uint32*)(m_pNetGameClient + 0x230) == 6 [SIGNONSTATE_FULL])\n    virtual bool IsInGame() = 0;\n\n    // Slot 40: engine2.dll + 0x763b0 (Checks *(uint32*)(m_pNetGameClient + 0x230) >= 2 [SIGNONSTATE_CONNECTED])\n    virtual bool IsConnected() = 0;\n\n    // Slot 41: engine2.dll + 0x76530 (Returns *(INetChannelInfo**)(m_pNetGameClient + 0xf0))\n    virtual INetChannelInfo* GetNetChannelInfo(std::int32_t nSplitScreenSlot = 0) = 0;\n\n    virtual void Unk42() = 0; virtual void Unk43() = 0; virtual void Unk44() = 0;\n    virtual void Unk45() = 0; virtual void Unk46() = 0; virtual void Unk47() = 0;\n    virtual void Unk48() = 0; virtual void Unk49() = 0; virtual void Unk50() = 0;\n\n    // Slot 51: engine2.dll + 0x75d60 (Dispatches console command string into engine execution queue)\n    virtual void ExecuteClientCmd(std::int32_t nSplitScreenSlot, const char* pszCmd, bool bUnk = false) = 0;\n};\nstatic_assert(sizeof(ISource2EngineToClient) == 0x08, \"Interface pointer must be 8 bytes\");\n\n// ============================================================================\n// 2. CNetworkGameClient & INetworkClientService\n// Binary: engine2.dll\n// Token:  \"NetworkClientService_001\" (Node RVA: 0x619dc8, Factory RVA: 0x1bf4b0)\n// VTable: engine2.dll + 0x613ac8 (CNetworkClientService, 64 methods)\n// VTable: engine2.dll + 0x5d4cf0 (CNetworkGameClient, 147 methods)\n// RTTI:   .?AVCNetworkGameClient@@\n// ============================================================================\nenum ESignonState : std::int32_t {\n    SIGNONSTATE_NONE        = 0,\n    SIGNONSTATE_CHALLENGE   = 1,\n    SIGNONSTATE_CONNECTED   = 2,\n    SIGNONSTATE_NEW         = 3,\n    SIGNONSTATE_PRESPAWN    = 4,\n    SIGNONSTATE_SPAWN       = 5,\n    SIGNONSTATE_FULL        = 6, // In-game active\n    SIGNONSTATE_CHANGELEVEL = 7\n};\n\nclass CNetworkGameClient {\npublic:\n    virtual ~CNetworkGameClient() = default;\n\n    PAD(0x0E8, m_pad0);\n    // engine2.dll + 0x76530 dereferences this pointer at +0x0F0\n    INetChannelInfo* m_pNetChannel;       // +0x0F0\n    PAD(0x118, m_pad1);\n    // engine2.dll + 0x861a0 stores level name string at +0x210\n    char             m_szLevelName[260];  // +0x210\n    char             m_szLevelNameShort[32]; // +0x314\n    PAD(0x008, m_pad2);\n    // engine2.dll + 0x76380 checks signon state at +0x230\n    // Note: In CNetworkGameClient layout, relative offsets:\n    // Signon state offset verified: +0x230 from base\n};\n\nclass INetworkClientService {\npublic:\n    virtual ~INetworkClientService() = default;\n\n    // Slot 23: Returns the active CNetworkGameClient singleton pointer\n    // Discovered via RTTI slot walk in CNetworkClientService\n    virtual void Unk01() = 0; virtual void Unk02() = 0; virtual void Unk03() = 0;\n    virtual void Unk04() = 0; virtual void Unk05() = 0; virtual void Unk06() = 0;\n    virtual void Unk07() = 0; virtual void Unk08() = 0; virtual void Unk09() = 0;\n    virtual void Unk10() = 0; virtual void Unk11() = 0; virtual void Unk12() = 0;\n    virtual void Unk13() = 0; virtual void Unk14() = 0; virtual void Unk15() = 0;\n    virtual void Unk16() = 0; virtual void Unk17() = 0; virtual void Unk18() = 0;\n    virtual void Unk19() = 0; virtual void Unk20() = 0; virtual void Unk21() = 0;\n    virtual void Unk22() = 0;\n\n    // Slot 23: engine2.dll + 0x1bf4b0\n    virtual CNetworkGameClient* GetNetworkGameClient() = 0;\n};\n\n// ============================================================================\n// 3. IGameResourceService (CGameResourceService)\n// Binary: engine2.dll\n// Token:  \"GameResourceServiceClientV001\" (Node RVA: 0x619eb8, Factory RVA: 0x1ab6e0)\n// VTable: engine2.dll + 0x60e7c8 (182 methods)\n// RTTI:   .?AVCGameResourceService@@\n// ============================================================================\nclass IGameResourceService {\npublic:\n    virtual ~IGameResourceService() = default;\n\n    // CGameEntitySystem pointer is stored at offset +0x58 in CGameResourceService\n    PAD(0x50, m_pad50);\n    CGameEntitySystem* m_pGameEntitySystem; // +0x58\n\n    CGameEntitySystem* GetGameEntitySystem() const {\n        return m_pGameEntitySystem;\n    }\n};\n\n// ============================================================================\n// 4. IEngineServiceMgr (CEngineServiceMgr)\n// Binary: engine2.dll\n// Token:  \"EngineServiceMgr001\" (Node RVA: 0x61a868, Factory RVA: 0x247a80)\n// VTable: engine2.dll + 0x61efb0 (249 methods)\n// RTTI:   .?AVCEngineServiceMgr@@\n// ============================================================================\nclass IEngineServiceMgr {\npublic:\n    virtual ~IEngineServiceMgr() = default;\n};\n\n// ============================================================================\n// 5. IEngineCVar (CCvar) & ConVar\n// Binary: tier0.dll\n// Token:  \"VEngineCvar007\" (Node RVA: 0x323530, Factory RVA: 0x789b0)\n// VTable: tier0.dll + 0x313208 (48 methods)\n// RTTI:   .?AVCCvar@@\n// ============================================================================\nenum EConVarFlags : std::uint32_t {\n    FCVAR_NONE                    = 0,\n    FCVAR_UNREGISTERED            = (1 << 0),\n    FCVAR_DEVELOPMENTONLY         = (1 << 1),\n    FCVAR_GAMEDLL                 = (1 << 2),\n    FCVAR_CLIENTDLL               = (1 << 3),\n    FCVAR_HIDDEN                  = (1 << 4),\n    FCVAR_PROTECTED               = (1 << 5),\n    FCVAR_SPONLY                  = (1 << 6),\n    FCVAR_ARCHIVE                 = (1 << 7),\n    FCVAR_NOTIFY                  = (1 << 8),\n    FCVAR_USERINFO                = (1 << 9),\n    FCVAR_PRINTABLEONLY           = (1 << 10),\n    FCVAR_UNLOGGED                = (1 << 11),\n    FCVAR_NEVER_AS_STRING         = (1 << 12),\n    FCVAR_REPLICATED              = (1 << 13),\n    FCVAR_CHEAT                   = (1 << 14),\n    FCVAR_PER_USER                = (1 << 15),\n    FCVAR_DEMO                    = (1 << 16),\n    FCVAR_DONTRECORD              = (1 << 17),\n    FCVAR_RELEASE                 = (1 << 19),\n    FCVAR_MENUBAR_ITEM            = (1 << 20),\n    FCVAR_COMMANDLINE_ENFORCED    = (1 << 21),\n    FCVAR_NOT_CONNECTED           = (1 << 22),\n    FCVAR_VCONSOLE_SET_FOCUS      = (1 << 23),\n    FCVAR_SERVER_CAN_EXECUTE      = (1 << 28),\n    FCVAR_SERVER_CANNOT_QUERY     = (1 << 29),\n    FCVAR_CLIENTCMD_CAN_EXECUTE   = (1 << 30)\n};\n\n// Reconstructed ConVar Value union & storage\nunion CVValue_t {\n    bool         m_bValue;\n    std::int32_t m_iValue;\n    std::int64_t m_i64Value;\n    float        m_flValue;\n    double       m_dbValue;\n    const char*  m_szValue;\n};\n\nclass ConVar {\npublic:\n    const char*      m_pszName;        // +0x00\n    ConVar*          m_pNext;          // +0x08\n    PAD(0x10, m_pad10);                // +0x10\n    const char*      m_pszHelpString;  // +0x20\n    std::uint32_t    m_nFlags;         // +0x28\n    PAD(0x14, m_pad2c);                // +0x2C\n    CVValue_t        m_Value;          // +0x40\n\n    bool GetBool() const { return m_Value.m_bValue; }\n    std::int32_t GetInt() const { return m_Value.m_iValue; }\n    float GetFloat() const { return m_Value.m_flValue; }\n    const char* GetString() const { return m_Value.m_szValue ? m_Value.m_szValue : \"\"; }\n};\nstatic_assert(offsetof(ConVar, m_pszName) == 0x00, \"ConVar m_pszName offset mismatch\");\nstatic_assert(offsetof(ConVar, m_pNext) == 0x08, \"ConVar m_pNext offset mismatch\");\nstatic_assert(offsetof(ConVar, m_pszHelpString) == 0x20, \"ConVar m_pszHelpString offset mismatch\");\nstatic_assert(offsetof(ConVar, m_nFlags) == 0x28, \"ConVar m_nFlags offset mismatch\");\n\nclass IEngineCVar {\npublic:\n    virtual ~IEngineCVar() = default;\n\n    virtual void Unk01() = 0; virtual void Unk02() = 0; virtual void Unk03() = 0;\n    virtual void Unk04() = 0; virtual void Unk05() = 0; virtual void Unk06() = 0;\n    virtual void Unk07() = 0; virtual void Unk08() = 0; virtual void Unk09() = 0;\n    virtual void Unk10() = 0;\n\n    // Slot 11: tier0.dll + 0x6c6b0 (Finds ConVar by caseless name / 0x31415926 hash)\n    // Signature verified: 40 53 56 57 41 54 41 56 48 83 EC 30 33 DB 45 8B\n    virtual ConVar* FindVar(const char* pszVarName) = 0;\n\n    // Slot 12: tier0.dll + 0x6c8c0 (Finds ConVar by registration index)\n    virtual ConVar* FindVarByIndex(std::int32_t nIndex) = 0;\n\n    virtual void Unk13() = 0; virtual void Unk14() = 0; virtual void Unk15() = 0;\n    virtual void Unk16() = 0; virtual void Unk17() = 0; virtual void Unk18() = 0;\n    virtual void Unk19() = 0; virtual void Unk20() = 0; virtual void Unk21() = 0;\n    virtual void Unk22() = 0; virtual void Unk23() = 0; virtual void Unk24() = 0;\n    virtual void Unk25() = 0; virtual void Unk26() = 0; virtual void Unk27() = 0;\n    virtual void Unk28() = 0; virtual void Unk29() = 0; virtual void Unk30() = 0;\n    virtual void Unk31() = 0; virtual void Unk32() = 0; virtual void Unk33() = 0;\n    virtual void Unk34() = 0; virtual void Unk35() = 0; virtual void Unk36() = 0;\n    virtual void Unk37() = 0; virtual void Unk38() = 0; virtual void Unk39() = 0;\n    virtual void Unk40() = 0;\n\n    // Slot 41: tier0.dll + 0x6c5f0 (First cvar array index iterator)\n    virtual std::uint64_t GetFirstCVarArrayValue() = 0;\n\n    // Slot 42: tier0.dll + 0x69ff0 (Next cvar array index iterator)\n    virtual std::uint64_t GetNextCVarArrayValue() = 0;\n};\n\n// ============================================================================\n// 6. IMemAlloc\n// Binary: tier0.dll\n// Export: g_pMemAlloc (Export RVA: 0x3ac458, VA: 0x1803ac458)\n// VTable: tier0.dll + 0x3277d0 (85 methods)\n// RTTI:   .?AVCMemAllocStandard@@\n// ============================================================================\nclass IMemAlloc {\npublic:\n    virtual ~IMemAlloc() = default;\n\n    // Slot 1: Allocates block of nSize bytes\n    virtual void*  Alloc(std::size_t nSize) = 0;\n    // Slot 2: Reallocates block\n    virtual void*  Realloc(void* pMem, std::size_t nSize) = 0;\n    // Slot 3: Frees memory block\n    virtual void   Free(void* pMem) = 0;\n\n    virtual void Unk04() = 0; virtual void Unk05() = 0; virtual void Unk06() = 0;\n    virtual void Unk07() = 0; virtual void Unk08() = 0; virtual void Unk09() = 0;\n    virtual void Unk10() = 0; virtual void Unk11() = 0; virtual void Unk12() = 0;\n    virtual void Unk13() = 0; virtual void Unk14() = 0; virtual void Unk15() = 0;\n    virtual void Unk16() = 0; virtual void Unk17() = 0; virtual void Unk18() = 0;\n    virtual void Unk19() = 0; virtual void Unk20() = 0;\n\n    // Slot 21: Returns usable size of allocated block\n    virtual std::size_t GetSize(void* pMem) = 0;\n};\n\n// ============================================================================\n// 7. IInputSystem & IInputStackSystem\n// Binary: inputsystem.dll\n// Tokens: \"InputSystemVersion001\" (Node RVA: 0x37850, Factory RVA: 0x11160)\n//         \"InputStackSystemVersion001\" (Node RVA: 0x37838, Factory RVA: 0x3670)\n// VTable: inputsystem.dll + 0x393e0 (CInputSystem, 106 methods)\n// VTable: inputsystem.dll + 0x37910 (CInputStackSystem, 30 methods)\n// RTTI:   .?AVCInputSystem@@, .?AVCInputStackSystem@@\n// ============================================================================\nclass IInputSystem {\npublic:\n    virtual ~IInputSystem() = default;\n\n    // Slot 1..105: Discovered via MSVC RTTI vtable walk\n    virtual void Unk01() = 0; virtual void Unk02() = 0; virtual void Unk03() = 0;\n    virtual void Unk04() = 0; virtual void Unk05() = 0; virtual void Unk06() = 0;\n    virtual void Unk07() = 0; virtual void Unk08() = 0; virtual void Unk09() = 0;\n    virtual void Unk10() = 0; virtual void Unk11() = 0; virtual void Unk12() = 0;\n    virtual void Unk13() = 0; virtual void Unk14() = 0; virtual void Unk15() = 0;\n    virtual void Unk16() = 0; virtual void Unk17() = 0; virtual void Unk18() = 0;\n\n    // Slot 19: inputsystem.dll + 0x12b10 (Polls button down state)\n    virtual bool IsButtonDown(std::int32_t nButtonCode) = 0;\n};\n\nclass IInputStackSystem {\npublic:\n    virtual ~IInputStackSystem() = default;\n};\n\n// ============================================================================\n// 8. IFileSystem\n// Binary: filesystem_stdio.dll\n// Token:  \"VFileSystem017\" (Node RVA: 0x1aecd0, Factory RVA: 0x3ca20)\n// VTable: filesystem_stdio.dll + 0x1b0ca0 (140 methods)\n// RTTI:   .?AVCFileSystem_Stdio@@\n// ============================================================================\nclass IFileSystem {\npublic:\n    virtual ~IFileSystem() = default;\n};\n\n// ============================================================================\n// 9. ISchemaSystem & CSchemaSystemTypeScope\n// Binary: schemasystem.dll\n// Token:  \"SchemaSystem_001\" (Node RVA: 0x4c248, Factory RVA: 0x715f8)\n// VTable: schemasystem.dll + 0x58598 (CSchemaSystem, 222 methods)\n// VTable: schemasystem.dll + 0x586f0 (CSchemaSystemTypeScope, 179 methods)\n// RTTI:   .?AVCSchemaSystem@@, .?AVCSchemaSystemTypeScope@@\n// ============================================================================\n#ifndef CS2_SDK_ISCHEMASYSTEM_DEFINED\n#define CS2_SDK_ISCHEMASYSTEM_DEFINED\nclass ISchemaSystem {\npublic:\n    virtual ~ISchemaSystem() = default;\n\n    virtual void Unk01() = 0; virtual void Unk02() = 0; virtual void Unk03() = 0;\n    virtual void Unk04() = 0; virtual void Unk05() = 0; virtual void Unk06() = 0;\n    virtual void Unk07() = 0; virtual void Unk08() = 0; virtual void Unk09() = 0;\n    virtual void Unk10() = 0; virtual void Unk11() = 0; virtual void Unk12() = 0;\n\n    // Slot 13: schemasystem.dll + 0x11350 (Resolves type scope by module name string)\n    virtual CSchemaSystemTypeScope* FindTypeScopeForModule(const char* pszModuleName, void* pBindingContext = nullptr) = 0;\n\n    // Slot 14: schemasystem.dll + 0x11510 (Resolves type scope by module MurmurHash2 token)\n    virtual CSchemaSystemTypeScope* FindTypeScopeForModule(std::uint32_t nScopeHash) = 0;\n};\n#endif\n\n// ============================================================================\n// 10. Primary Subsystems (Render, Material, Scene, Physics, Network, Audio, UI)\n// Verified VTable RVAs, tokens, and method counts\n// ============================================================================\n\n// rendersystemdx11.dll: \"RenderDeviceMgr001\" (VTable: 0x3f5f98, 58 methods)\nclass IRenderDeviceMgr {\npublic:\n    virtual ~IRenderDeviceMgr() = default;\n};\n\n// rendersystemdx11.dll: \"RenderDevice001\" (VTable: 0x3f40e8, 291 methods)\nclass IRenderDevice {\npublic:\n    virtual ~IRenderDevice() = default;\n};\n\n// materialsystem2.dll: \"VMaterialSystem2_001\" (VTable: 0x12d920, 57 methods)\nclass IMaterialSystem2 {\npublic:\n    virtual ~IMaterialSystem2() = default;\n\n    virtual void Unk01() = 0; virtual void Unk02() = 0; virtual void Unk03() = 0;\n    virtual void Unk04() = 0; virtual void Unk05() = 0; virtual void Unk06() = 0;\n    virtual void Unk07() = 0; virtual void Unk08() = 0; virtual void Unk09() = 0;\n    virtual void Unk10() = 0; virtual void Unk11() = 0; virtual void Unk12() = 0;\n    virtual void Unk13() = 0;\n\n    // Slot 14: materialsystem2.dll + 0x37200 (Finds or loads CMaterial2 instance from asset path)\n    virtual CMaterial2** FindOrCreateFromResource(CMaterial2** ppOutMaterial, const char* pszResourceName) = 0;\n\n    // Slot 15..27\n    virtual void Unk15() = 0; virtual void Unk16() = 0; virtual void Unk17() = 0;\n    virtual void Unk18() = 0; virtual void Unk19() = 0; virtual void Unk20() = 0;\n    virtual void Unk21() = 0; virtual void Unk22() = 0; virtual void Unk23() = 0;\n    virtual void Unk24() = 0; virtual void Unk25() = 0; virtual void Unk26() = 0;\n    virtual void Unk27() = 0;\n\n    // Slot 28: materialsystem2.dll + 0x3af50 (Creates material deriving from parent)\n    virtual CMaterial2** CreateMaterialFromParent(CMaterial2** ppOutMaterial, const char* pszMaterialName, CMaterial2** ppParentMaterial, void* pKeyValues, int nFlags, std::uint8_t bUnk) = 0;\n\n    // Slot 29: materialsystem2.dll + 0x3ade0 (Creates dynamic procedural runtime material)\n    virtual CMaterial2** CreateMaterial(CMaterial2** ppOutMaterial, const char* pszMaterialName, void* pKeyValues, int nFlags, bool bUnk) = 0;\n\n    // Slot 30: materialsystem2.dll + 0x3abf0 (Creates material within specific type scope)\n    virtual CMaterial2** CreateMaterialWithScope(CMaterial2** ppOutMaterial, const char* pszMaterialName, void* pKeyValues, void* pTypeScope, char param6) = 0;\n};\n\n// scenesystem.dll: \"SceneSystem_002\" (VTable: 0x5f17c0, 199 methods)\nclass ISceneSystem {\npublic:\n    virtual ~ISceneSystem() = default;\n};\n\n// meshsystem.dll: \"MeshSystem001\" (VTable: 0x1548d0, 47 methods)\nclass IMeshSystem {\npublic:\n    virtual ~IMeshSystem() = default;\n};\n\n// animationsystem.dll: \"AnimationSystem_001\" (VTable: 0x7232e0, 224 methods)\nclass IAnimationSystem {\npublic:\n    virtual ~IAnimationSystem() = default;\n};\n\n// worldrenderer.dll: \"WorldRendererMgr001\" (VTable: 0x1a61c0, 104 methods)\nclass IWorldRendererMgr {\npublic:\n    virtual ~IWorldRendererMgr() = default;\n};\n\n// particles.dll: \"ParticleSystemMgr003\" (VTable: 0x4d7ff0, 64 methods)\nclass IParticleSystemMgr {\npublic:\n    virtual ~IParticleSystemMgr() = default;\n};\n\n// vphysics2.dll: \"VPhysics2Interface_001\" (VTable: 0x3fbf50, 178 methods)\nclass IVPhysics2 {\npublic:\n    virtual ~IVPhysics2() = default;\n};\n\n// networksystem.dll: \"NetworkSystemVersion001\" (VTable: 0x23a798, 64 methods)\nclass INetworkSystem {\npublic:\n    virtual ~INetworkSystem() = default;\n};\n\n// networksystem.dll: \"NetworkMessagesVersion001\" (VTable: 0x239a38, 89 methods)\nclass INetworkMessages {\npublic:\n    virtual ~INetworkMessages() = default;\n};\n\n// resourcesystem.dll: \"ResourceSystem013\" (VTable: 0x65348, 119 methods)\nclass IResourceSystem {\npublic:\n    virtual ~IResourceSystem() = default;\n};\n\n// soundsystem.dll: \"SoundSystem001\" (VTable: 0x4918c8, 135 methods)\nclass ISoundSystem {\npublic:\n    virtual ~ISoundSystem() = default;\n};\n\nusing SoundEventGuid_t = std::uint64_t;\n\n// soundsystem.dll: \"SoundOpSystem001\" (VTable: 0x4ab140, 218 methods)\nclass ISoundOpSystem {\npublic:\n    virtual ~ISoundOpSystem() = default;\n    PAD(0x50, m_padAppSystem); // Slots 1..10 (IAppSystem methods: Connect, Disconnect, Init, Shutdown, etc.)\n    virtual SoundEventGuid_t StartSoundEvent(const char* pszSoundName, int nSeed = 0, ...) = 0; // Slot 11 (0x1801D19C0)\n    virtual SoundEventGuid_t StartSoundEventByHash(std::uint32_t nSoundHash, int nSeed = 0, ...) = 0;// Slot 12 (0x1801D19E0)\n    virtual SoundEventGuid_t StartSoundEventReliable(...) = 0;                                  // Slot 13 (0x1801D1990)\n    virtual void StopSoundEvent(SoundEventGuid_t guid, float flFadeOutTime = 0.0f) = 0;         // Slot 14 (0x1801D1C60)\n    virtual void SetSoundEventParam(SoundEventGuid_t guid, const char* pszParamName, float flValue) = 0; // Slot 15 (0x1801D17F0)\n};\n\n// panorama.dll: \"PanoramaUIEngine001\" (VTable: 0x4c22e0, 18 methods)\nclass IPanoramaUIEngine {\npublic:\n    virtual ~IPanoramaUIEngine() = default;\n};\n\n// pulse_system.dll: \"PulseSystem_001\" (VTable: 0x19cf98, 77 methods)\nclass IPulseSystem {\npublic:\n    virtual ~IPulseSystem() = default;\n};\n\n// localize.dll: \"Localize_001\" (VTable: 0x4d058, 115 methods)\nclass ILocalize {\npublic:\n    virtual ~ILocalize() = default;\n};\n\n// matchmaking.dll: \"MatchFramework_001\" (VTable: 0x1604f8, 30 methods)\nclass IMatchFramework {\npublic:\n    virtual ~IMatchFramework() = default;\n};\n\n// matchmaking.dll: \"GameTypes001\" (VTable: 0x183730, 157 methods)\nclass IGameTypes {\npublic:\n    virtual ~IGameTypes() = default;\n};\n\n// client.dll: \"Source2Client002\" (VTable: 0x1c65030, 240 methods)\nclass ISource2Client {\npublic:\n    virtual ~ISource2Client() = default;\n};\n\n// server.dll: \"Source2Server001\" (VTable: 0x1996698, 105 methods)\nclass ISource2Server {\npublic:\n    virtual ~ISource2Server() = default;\n};\n\n// server.dll: \"Source2GameClients001\" (VTable: 0x19981c8, 300 methods)\nclass ISource2GameClients {\npublic:\n    virtual ~ISource2GameClients() = default;\n};\n\n// server.dll: \"Source2GameEntities001\" (VTable: 0x19965c0, 23 methods)\nclass ISource2GameEntities {\npublic:\n    virtual ~ISource2GameEntities() = default;\n};\n\n// ============================================================================\n// Dynamic Runtime Interface Resolver Helper\n// Walks the DLL's exported CreateInterface or internal s_pInterfaceRegs list\n// ============================================================================\ntemplate <typename T>\ninline T* CaptureInterface(void* hModule, const char* pszInterfaceName) {\n    if (!hModule || !pszInterfaceName) return nullptr;\n    // User or mod code provides GetProcAddress equivalent:\n    // auto pfnCreateInterface = reinterpret_cast<CreateInterfaceFn>(GetProcAddress((HMODULE)hModule, \"CreateInterface\"));\n    // return reinterpret_cast<T*>(pfnCreateInterface(pszInterfaceName, nullptr));\n    return nullptr;\n}\n\n#undef PAD\n\n} // namespace cs2::sdk\n",
        "item_schema.hpp": "#pragma once\n\n#include <cstdint>\n#include <cstddef>\n#include <type_traits>\n#include <string_view>\n#include <array>\n#include <cmath>\n\n#include \"sdk/client_classes.hpp\"\n\n#ifndef PAD\n#define PAD(bytes, name) private: [[maybe_unused]] std::uint8_t name[bytes]; public:\n#endif\n\n// ============================================================================\n// Source 2 Reverse Engineered SDK - Phase 5: Economy & Item Schema Pipeline\n// Target Build: 2026-10-25_26144732 (CS2 Update Archive)\n// Architecture: x86-64 (MSVC ABI)\n// Binary: client.dll (Base: 0x180000000)\n// Verified via Ghidra Static Decompilation & Schema Reflection\n// ============================================================================\n\nnamespace cs2::sdk {\n\n// ============================================================================\n// Economy Item Enumerations & Type Classifications\n// ============================================================================\n\nenum class EconQuality_t : std::int32_t {\n    QUALITY_NORMAL = 0,\n    QUALITY_GENUINE = 1,\n    QUALITY_VINTAGE = 2,\n    QUALITY_UNUSUAL = 3,\n    QUALITY_UNIQUE = 4,\n    QUALITY_COMMUNITY = 5,\n    QUALITY_DEVELOPER = 6,\n    QUALITY_SELFMADE = 7,\n    QUALITY_CUSTOMIZED = 8,\n    QUALITY_STRANGE = 9,\n    QUALITY_COMPLETED = 10,\n    QUALITY_HAUNTED = 11,\n    QUALITY_TOURNAMENT = 12\n};\n\nenum class EconRarity_t : std::int32_t {\n    RARITY_DEFAULT = 0,\n    RARITY_COMMON = 1,       // Consumer Grade (White / Gray)\n    RARITY_UNCOMMON = 2,     // Industrial Grade (Light Blue)\n    RARITY_RARE = 3,         // Mil-Spec Grade (Blue)\n    RARITY_MYTHICAL = 4,     // Restricted (Purple)\n    RARITY_LEGENDARY = 5,    // Classified (Pink / Magenta)\n    RARITY_ANCIENT = 6,      // Covert (Red)\n    RARITY_IMMORTAL = 7      // Contraband (Gold / Yellow)\n};\n\nenum class LoadoutSlot_t : std::int32_t {\n    LOADOUT_SLOT_MELEE = 0,\n    LOADOUT_SLOT_SECONDARY0 = 1,\n    LOADOUT_SLOT_SECONDARY1 = 2,\n    LOADOUT_SLOT_SECONDARY2 = 3,\n    LOADOUT_SLOT_SECONDARY3 = 4,\n    LOADOUT_SLOT_SECONDARY4 = 5,\n    LOADOUT_SLOT_SMG0 = 6,\n    LOADOUT_SLOT_SMG1 = 7,\n    LOADOUT_SLOT_SMG2 = 8,\n    LOADOUT_SLOT_SMG3 = 9,\n    LOADOUT_SLOT_SMG4 = 10,\n    LOADOUT_SLOT_RIFLE0 = 11,\n    LOADOUT_SLOT_RIFLE1 = 12,\n    LOADOUT_SLOT_RIFLE2 = 13,\n    LOADOUT_SLOT_RIFLE3 = 14,\n    LOADOUT_SLOT_RIFLE4 = 15,\n    LOADOUT_SLOT_HEAVY0 = 16,\n    LOADOUT_SLOT_HEAVY1 = 17,\n    LOADOUT_SLOT_HEAVY2 = 18,\n    LOADOUT_SLOT_HEAVY3 = 19,\n    LOADOUT_SLOT_HEAVY4 = 20,\n    LOADOUT_SLOT_GLOVES = 41,\n    LOADOUT_SLOT_CLOTHING_CUSTOMPLAYER = 42\n};\n\nenum class EquipmentCategory_t : std::int32_t {\n    CATEGORY_OTHER = 0,\n    CATEGORY_MELEE = 1,\n    CATEGORY_SECONDARY = 2,\n    CATEGORY_SMG = 3,\n    CATEGORY_RIFLE = 4,\n    CATEGORY_HEAVY = 5,\n    CATEGORY_EQUIPMENT = 6,\n    CATEGORY_GRENADE = 7,\n    CATEGORY_GLOVES = 8,\n    CATEGORY_AGENT = 9\n};\n\nenum class PaintKitStyle_t : std::int32_t {\n    PAINT_KIT_STYLE_SOLID_COLOR = 0,\n    PAINT_KIT_STYLE_HYDROGRAPHIC = 1,\n    PAINT_KIT_STYLE_SPRAY_PAINT = 2,\n    PAINT_KIT_STYLE_ANODIZED = 3,\n    PAINT_KIT_STYLE_ANODIZED_MULTICOLOR = 4,\n    PAINT_KIT_STYLE_ANODIZED_AIRBRUSHED = 5,\n    PAINT_KIT_STYLE_CUSTOM_PAINT_JOB = 6,\n    PAINT_KIT_STYLE_PATINA = 7,\n    PAINT_KIT_STYLE_GUNSMITH = 8\n};\n\nenum class WearRating_t : std::int32_t {\n    WEAR_FACTORY_NEW = 0,    // [0.00, 0.07)\n    WEAR_MINIMAL_WEAR = 1,   // [0.07, 0.15)\n    WEAR_FIELD_TESTED = 2,   // [0.15, 0.38)\n    WEAR_WELL_WORN = 3,      // [0.38, 0.45)\n    WEAR_BATTLE_SCARRED = 4  // [0.45, 1.00]\n};\n\n// ============================================================================\n// 1. Dynamic Attribute Primitive (CEconItemAttribute)\n// Binary: server.dll / client.dll (Size: 0x48 / 72 bytes)\n// ============================================================================\nclass CEconItemAttribute {\npublic:\n    virtual ~CEconItemAttribute() = default;             // +0x00\n    PAD(0x28, m_pad08);                                  // +0x08..+0x30\n    std::uint16_t m_iAttributeDefinitionIndex;           // +0x30\n    PAD(0x02, m_pad32);                                  // +0x32..+0x34\n    float m_flValue;                                     // +0x34\n    float m_flInitialValue;                              // +0x38\n    std::int32_t m_nRefundableCurrency;                  // +0x3C\n    bool m_bSetBonus;                                    // +0x40\n    PAD(0x07, m_pad41);                                  // +0x41..+0x48\n};\nstatic_assert(sizeof(CEconItemAttribute) == 0x48, \"CEconItemAttribute size must be 0x48\");\nstatic_assert(offsetof(CEconItemAttribute, m_iAttributeDefinitionIndex) == 0x30, \"m_iAttributeDefinitionIndex offset mismatch\");\nstatic_assert(offsetof(CEconItemAttribute, m_flValue) == 0x34, \"m_flValue offset mismatch\");\nstatic_assert(offsetof(CEconItemAttribute, m_flInitialValue) == 0x38, \"m_flInitialValue offset mismatch\");\nstatic_assert(offsetof(CEconItemAttribute, m_nRefundableCurrency) == 0x3C, \"m_nRefundableCurrency offset mismatch\");\nstatic_assert(offsetof(CEconItemAttribute, m_bSetBonus) == 0x40, \"m_bSetBonus offset mismatch\");\n\n// ============================================================================\n// 2. Attribute Manager & Providers (CAttributeManager)\n// Binary: server.dll / client.dll (Size: 0x50 / 80 bytes)\n// ============================================================================\nclass CAttributeManager {\npublic:\n    virtual ~CAttributeManager() = default;              // +0x00\n    void* m_Providers;                                   // +0x08: CUtlVector<CHandle<C_BaseEntity>>\n    PAD(0x10, m_pad10);                                  // +0x10..+0x20\n    std::int32_t m_iReapplyProvisionParity;              // +0x20\n    CEntityHandle m_hOuter;                              // +0x24: Owning entity handle\n    bool m_bPreventLoopback;                             // +0x28\n    PAD(0x03, m_pad29);                                  // +0x29..+0x2C\n    std::int32_t m_ProviderType;                         // +0x2C\n    void* m_CachedResults;                               // +0x30: CUtlVector<cached_attribute_float_t>\n    PAD(0x18, m_pad38);                                  // +0x38..+0x50\n};\nstatic_assert(sizeof(CAttributeManager) == 0x50, \"CAttributeManager size must be 0x50\");\nstatic_assert(offsetof(CAttributeManager, m_Providers) == 0x08, \"m_Providers offset mismatch\");\nstatic_assert(offsetof(CAttributeManager, m_iReapplyProvisionParity) == 0x20, \"m_iReapplyProvisionParity offset mismatch\");\nstatic_assert(offsetof(CAttributeManager, m_hOuter) == 0x24, \"m_hOuter offset mismatch\");\nstatic_assert(offsetof(CAttributeManager, m_bPreventLoopback) == 0x28, \"m_bPreventLoopback offset mismatch\");\nstatic_assert(offsetof(CAttributeManager, m_ProviderType) == 0x2C, \"m_ProviderType offset mismatch\");\nstatic_assert(offsetof(CAttributeManager, m_CachedResults) == 0x30, \"m_CachedResults offset mismatch\");\n\n// ============================================================================\n// 3. Dynamic Attribute Collection Container (CAttributeList)\n// Binary: server.dll / client.dll (Size: 0x78 / 120 bytes)\n// ============================================================================\nclass CAttributeList {\npublic:\n    virtual ~CAttributeList() = default;                 // +0x00\n    PAD(0x68, m_pad08);                                  // +0x08..+0x70\n    CAttributeManager* m_pManager;                       // +0x70\n};\nstatic_assert(sizeof(CAttributeList) == 0x78, \"CAttributeList size must be 0x78\");\nstatic_assert(offsetof(CAttributeList, m_pManager) == 0x70, \"m_pManager offset mismatch\");\n\n// ============================================================================\n// 4. Econ Item Interface Base (IEconItemInterface)\n// Abstract base interface with virtual method table.\n// ============================================================================\nclass IEconItemInterface {\npublic:\n    virtual ~IEconItemInterface() = default;             // +0x00\n};\n\n// ============================================================================\n// 5. Client Econ Item View (C_EconItemView)\n// Binary: client.dll (Size: 0x5B0 / 1456 bytes)\n// Reconstructed via Schema Reflection & Verified Offsets\n// ============================================================================\nclass C_EconItemView : public IEconItemInterface {\npublic:\n    PAD(0x58, m_pad08);                                  // +0x08..+0x60\n    bool m_bInventoryImageRgbaRequested;                 // +0x60\n    bool m_bInventoryImageTriedCache;                    // +0x61\n    PAD(0x1E, m_pad62);                                  // +0x62..+0x80\n    std::int32_t m_nInventoryImageRgbaWidth;             // +0x80\n    std::int32_t m_nInventoryImageRgbaHeight;            // +0x84\n    char m_szCurrentLoadCachedFileName[304];             // +0x88..+0x1B8\n    bool m_bRestoreCustomMaterialAfterPrecache;          // +0x1B8\n    PAD(0x01, m_pad1B9);                                 // +0x1B9..+0x1BA\n    std::uint16_t m_iItemDefinitionIndex;                // +0x1BA\n    std::int32_t m_iEntityQuality;                       // +0x1BC\n    std::uint32_t m_iEntityLevel;                        // +0x1C0\n    PAD(0x04, m_pad1C4);                                 // +0x1C4..+0x1C8\n    std::uint64_t m_iItemID;                             // +0x1C8\n    std::uint32_t m_iItemIDHigh;                         // +0x1D0\n    std::uint32_t m_iItemIDLow;                          // +0x1D4\n    std::uint32_t m_iAccountID;                          // +0x1D8\n    std::uint32_t m_iInventoryPosition;                  // +0x1DC\n    PAD(0x08, m_pad1E0);                                 // +0x1E0..+0x1E8\n    bool m_bInitialized;                                 // +0x1E8\n    bool m_bDisallowSOC;                                 // +0x1E9\n    bool m_bIsStoreItem;                                 // +0x1EA\n    bool m_bIsTradeItem;                                 // +0x1EB\n    std::int32_t m_iEntityQuantity;                      // +0x1EC\n    std::int32_t m_iRarityOverride;                      // +0x1F0\n    std::int32_t m_iQualityOverride;                     // +0x1F4\n    std::int32_t m_iOriginOverride;                      // +0x1F8\n    std::uint8_t m_ubStyleOverride;                      // +0x1FC\n    std::uint8_t m_unClientFlags;                        // +0x1FD\n    PAD(0x0A, m_pad1FE);                                 // +0x1FE..+0x208\n    CAttributeList m_AttributeList;                      // +0x208 (Size 0x78)\n    CAttributeList m_NetworkedDynamicAttributes;          // +0x280 (Size 0x78)\n    char m_szCustomName[161];                            // +0x2F8\n    char m_szCustomNameOverride[161];                    // +0x399\n    char m_szCustomNameOverride2[161];                   // +0x43A\n    char m_szCustomNameOverride3[161];                   // +0x4DB\n    PAD(0x2C, m_pad57C);                                 // +0x57C..+0x5A8\n    bool m_bInitializedTags;                             // +0x5A8\n    PAD(0x07, m_pad5A9);                                 // +0x5A9..+0x5B0\n\n    [[nodiscard]] constexpr std::uint16_t GetItemDefinitionIndex() const noexcept {\n        return m_iItemDefinitionIndex;\n    }\n\n    [[nodiscard]] constexpr std::uint64_t GetItemID() const noexcept {\n        return m_iItemID;\n    }\n\n    [[nodiscard]] constexpr bool IsInitialized() const noexcept {\n        return m_bInitialized;\n    }\n\n    [[nodiscard]] const char* GetCustomName() const noexcept {\n        return m_szCustomName[0] != '\\0' ? m_szCustomName : nullptr;\n    }\n};\nstatic_assert(sizeof(C_EconItemView) == 0x5B0, \"C_EconItemView size must be 0x5B0\");\nstatic_assert(offsetof(C_EconItemView, m_bInventoryImageRgbaRequested) == 0x60, \"m_bInventoryImageRgbaRequested offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_bInventoryImageTriedCache) == 0x61, \"m_bInventoryImageTriedCache offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_nInventoryImageRgbaWidth) == 0x80, \"m_nInventoryImageRgbaWidth offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_nInventoryImageRgbaHeight) == 0x84, \"m_nInventoryImageRgbaHeight offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_szCurrentLoadCachedFileName) == 0x88, \"m_szCurrentLoadCachedFileName offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_bRestoreCustomMaterialAfterPrecache) == 0x1B8, \"m_bRestoreCustomMaterialAfterPrecache offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_iItemDefinitionIndex) == 0x1BA, \"m_iItemDefinitionIndex offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_iEntityQuality) == 0x1BC, \"m_iEntityQuality offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_iEntityLevel) == 0x1C0, \"m_iEntityLevel offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_iItemID) == 0x1C8, \"m_iItemID offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_iItemIDHigh) == 0x1D0, \"m_iItemIDHigh offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_iItemIDLow) == 0x1D4, \"m_iItemIDLow offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_iAccountID) == 0x1D8, \"m_iAccountID offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_iInventoryPosition) == 0x1DC, \"m_iInventoryPosition offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_bInitialized) == 0x1E8, \"m_bInitialized offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_bDisallowSOC) == 0x1E9, \"m_bDisallowSOC offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_bIsStoreItem) == 0x1EA, \"m_bIsStoreItem offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_bIsTradeItem) == 0x1EB, \"m_bIsTradeItem offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_iEntityQuantity) == 0x1EC, \"m_iEntityQuantity offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_iRarityOverride) == 0x1F0, \"m_iRarityOverride offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_iQualityOverride) == 0x1F4, \"m_iQualityOverride offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_iOriginOverride) == 0x1F8, \"m_iOriginOverride offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_ubStyleOverride) == 0x1FC, \"m_ubStyleOverride offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_unClientFlags) == 0x1FD, \"m_unClientFlags offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_AttributeList) == 0x208, \"m_AttributeList offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_NetworkedDynamicAttributes) == 0x280, \"m_NetworkedDynamicAttributes offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_szCustomName) == 0x2F8, \"m_szCustomName offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_szCustomNameOverride) == 0x399, \"m_szCustomNameOverride offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_szCustomNameOverride2) == 0x43A, \"m_szCustomNameOverride2 offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_szCustomNameOverride3) == 0x4DB, \"m_szCustomNameOverride3 offset mismatch\");\nstatic_assert(offsetof(C_EconItemView, m_bInitializedTags) == 0x5A8, \"m_bInitializedTags offset mismatch\");\n\n// ============================================================================\n// 6. Attribute Container (C_AttributeContainer)\n// Binary: client.dll (Size: 0x610 / 1552 bytes)\n// ============================================================================\nclass C_AttributeContainer : public CAttributeManager {\npublic:\n    C_EconItemView m_Item;                               // +0x050 (Size: 0x5B0, ends at +0x600)\n    std::int32_t m_iExternalItemProviderRegisteredToken; // +0x600\n    PAD(0x04, m_pad604);                                 // +0x604..+0x608\n    std::uint64_t m_ullRegisteredAsItemID;               // +0x608\n};\nstatic_assert(sizeof(C_AttributeContainer) == 0x610, \"C_AttributeContainer size must be 0x610\");\nstatic_assert(offsetof(C_AttributeContainer, m_Item) == 0x50, \"m_Item offset mismatch\");\nstatic_assert(offsetof(C_AttributeContainer, m_iExternalItemProviderRegisteredToken) == 0x600, \"m_iExternalItemProviderRegisteredToken offset mismatch\");\nstatic_assert(offsetof(C_AttributeContainer, m_ullRegisteredAsItemID) == 0x608, \"m_ullRegisteredAsItemID offset mismatch\");\n\n// ============================================================================\n// 7. Base Econ Entity (C_EconEntity)\n// Binary: client.dll (Size: 0x1918 / 6424 bytes)\n// Direct Base: CBaseAnimGraph (Size: 0x1268 / 4712 bytes)\n// ============================================================================\nclass C_EconEntity : public CBaseAnimGraph {\npublic:\n    PAD(0x10, m_pad1268);                                // +0x1268..+0x1278\n    float m_flFlexDelayTime;                             // +0x1278\n    PAD(0x04, m_pad127C);                                // +0x127C..+0x1280\n    float m_flFlexDelayedWeight;                         // +0x1280\n    PAD(0x04, m_pad1284);                                // +0x1284..+0x1288\n    bool m_bAttributesInitialized;                       // +0x1288\n    PAD(0x07, m_pad1289);                                // +0x1289..+0x1290\n    C_AttributeContainer m_AttributeManager;             // +0x1290 (Size: 0x610, ends at +0x18A0)\n    std::uint32_t m_OriginalOwnerXuidLow;                // +0x18A0\n    std::uint32_t m_OriginalOwnerXuidHigh;               // +0x18A4\n    std::int32_t m_nFallbackPaintKit;                    // +0x18A8\n    std::int32_t m_nFallbackSeed;                        // +0x18AC\n    float m_flFallbackWear;                              // +0x18B0\n    std::int32_t m_nFallbackStatTrak;                    // +0x18B4\n    bool m_bClientside;                                  // +0x18B8\n    bool m_bParticleSystemsCreated;                      // +0x18B9\n    PAD(0x06, m_pad18BA);                                // +0x18BA..+0x18C0\n    PAD(0x18, m_vecAttachedParticles);                   // +0x18C0..+0x18D8\n    CEntityHandle m_hViewmodelAttachment;                // +0x18D8\n    std::int32_t m_iOldTeam;                             // +0x18DC\n    bool m_bAttachmentDirty;                             // +0x18E0\n    PAD(0x03, m_pad18E1);                                // +0x18E1..+0x18E4\n    std::int32_t m_nUnloadedModelIndex;                  // +0x18E4\n    std::int32_t m_iNumOwnerValidationRetries;           // +0x18E8\n    PAD(0x0C, m_pad18EC);                                // +0x18EC..+0x18F8\n    CEntityHandle m_hOldProvidee;                        // +0x18F8\n    PAD(0x04, m_pad18FC);                                // +0x18FC..+0x1900\n    PAD(0x18, m_vecAttachedModels);                      // +0x1900..+0x1918\n\n    [[nodiscard]] inline C_EconItemView& GetItemView() noexcept {\n        return m_AttributeManager.m_Item;\n    }\n\n    [[nodiscard]] inline const C_EconItemView& GetItemView() const noexcept {\n        return m_AttributeManager.m_Item;\n    }\n\n    [[nodiscard]] constexpr std::int32_t GetFallbackPaintKit() const noexcept {\n        return m_nFallbackPaintKit;\n    }\n\n    [[nodiscard]] constexpr std::int32_t GetFallbackSeed() const noexcept {\n        return m_nFallbackSeed;\n    }\n\n    [[nodiscard]] constexpr float GetFallbackWear() const noexcept {\n        return m_flFallbackWear;\n    }\n\n    [[nodiscard]] constexpr std::int32_t GetFallbackStatTrak() const noexcept {\n        return m_nFallbackStatTrak;\n    }\n};\nstatic_assert(sizeof(C_EconEntity) == 0x1918, \"C_EconEntity size must be 0x1918\");\nstatic_assert(offsetof(C_EconEntity, m_flFlexDelayTime) == 0x1278, \"m_flFlexDelayTime offset mismatch\");\nstatic_assert(offsetof(C_EconEntity, m_flFlexDelayedWeight) == 0x1280, \"m_flFlexDelayedWeight offset mismatch\");\nstatic_assert(offsetof(C_EconEntity, m_bAttributesInitialized) == 0x1288, \"m_bAttributesInitialized offset mismatch\");\nstatic_assert(offsetof(C_EconEntity, m_AttributeManager) == 0x1290, \"m_AttributeManager offset mismatch\");\nstatic_assert(offsetof(C_EconEntity, m_OriginalOwnerXuidLow) == 0x18A0, \"m_OriginalOwnerXuidLow offset mismatch\");\nstatic_assert(offsetof(C_EconEntity, m_OriginalOwnerXuidHigh) == 0x18A4, \"m_OriginalOwnerXuidHigh offset mismatch\");\nstatic_assert(offsetof(C_EconEntity, m_nFallbackPaintKit) == 0x18A8, \"m_nFallbackPaintKit offset mismatch\");\nstatic_assert(offsetof(C_EconEntity, m_nFallbackSeed) == 0x18AC, \"m_nFallbackSeed offset mismatch\");\nstatic_assert(offsetof(C_EconEntity, m_flFallbackWear) == 0x18B0, \"m_flFallbackWear offset mismatch\");\nstatic_assert(offsetof(C_EconEntity, m_nFallbackStatTrak) == 0x18B4, \"m_nFallbackStatTrak offset mismatch\");\nstatic_assert(offsetof(C_EconEntity, m_bClientside) == 0x18B8, \"m_bClientside offset mismatch\");\nstatic_assert(offsetof(C_EconEntity, m_bParticleSystemsCreated) == 0x18B9, \"m_bParticleSystemsCreated offset mismatch\");\nstatic_assert(offsetof(C_EconEntity, m_hViewmodelAttachment) == 0x18D8, \"m_hViewmodelAttachment offset mismatch\");\nstatic_assert(offsetof(C_EconEntity, m_iOldTeam) == 0x18DC, \"m_iOldTeam offset mismatch\");\nstatic_assert(offsetof(C_EconEntity, m_bAttachmentDirty) == 0x18E0, \"m_bAttachmentDirty offset mismatch\");\nstatic_assert(offsetof(C_EconEntity, m_nUnloadedModelIndex) == 0x18E4, \"m_nUnloadedModelIndex offset mismatch\");\nstatic_assert(offsetof(C_EconEntity, m_iNumOwnerValidationRetries) == 0x18E8, \"m_iNumOwnerValidationRetries offset mismatch\");\nstatic_assert(offsetof(C_EconEntity, m_hOldProvidee) == 0x18F8, \"m_hOldProvidee offset mismatch\");\n\n// ============================================================================\n// 8. Static Item Definition Schema (CEconItemDefinition)\n// Canonical item archetype loaded from items_game.txt.\n// ============================================================================\nstruct CEconItemDefinition {\n    std::uint16_t m_nDefIndex = 0;\n    LoadoutSlot_t m_nLoadoutSlot = LoadoutSlot_t::LOADOUT_SLOT_MELEE;\n    EquipmentCategory_t m_nEquipmentCategory = EquipmentCategory_t::CATEGORY_OTHER;\n    EconQuality_t m_nQuality = EconQuality_t::QUALITY_NORMAL;\n    EconRarity_t m_nRarity = EconRarity_t::RARITY_DEFAULT;\n    std::uint32_t m_nDefaultDropQuantity = 1;\n    std::uint32_t m_nItemLevelMin = 1;\n    std::uint32_t m_nItemLevelMax = 1;\n    const char* m_pszItemBaseName = \"\";\n    const char* m_pszItemTypeName = \"\";\n    const char* m_pszItemDescription = \"\";\n    const char* m_pszInventoryImage = \"\";\n    const char* m_pszModelPlayer = \"\";\n    const char* m_pszModelWorld = \"\";\n\n    [[nodiscard]] constexpr std::uint16_t GetDefinitionIndex() const noexcept { return m_nDefIndex; }\n    [[nodiscard]] constexpr LoadoutSlot_t GetLoadoutSlot() const noexcept { return m_nLoadoutSlot; }\n    [[nodiscard]] constexpr EquipmentCategory_t GetEquipmentCategory() const noexcept { return m_nEquipmentCategory; }\n    [[nodiscard]] constexpr EconQuality_t GetQuality() const noexcept { return m_nQuality; }\n    [[nodiscard]] constexpr EconRarity_t GetRarity() const noexcept { return m_nRarity; }\n    [[nodiscard]] constexpr const char* GetItemBaseName() const noexcept { return m_pszItemBaseName; }\n    [[nodiscard]] constexpr const char* GetItemTypeName() const noexcept { return m_pszItemTypeName; }\n    [[nodiscard]] constexpr const char* GetItemDescription() const noexcept { return m_pszItemDescription; }\n    [[nodiscard]] constexpr const char* GetInventoryImage() const noexcept { return m_pszInventoryImage; }\n    [[nodiscard]] constexpr const char* GetModelPlayer() const noexcept { return m_pszModelPlayer; }\n    [[nodiscard]] constexpr const char* GetModelWorld() const noexcept { return m_pszModelWorld; }\n    [[nodiscard]] constexpr bool IsWeapon() const noexcept {\n        return m_nEquipmentCategory == EquipmentCategory_t::CATEGORY_SECONDARY ||\n               m_nEquipmentCategory == EquipmentCategory_t::CATEGORY_SMG ||\n               m_nEquipmentCategory == EquipmentCategory_t::CATEGORY_RIFLE ||\n               m_nEquipmentCategory == EquipmentCategory_t::CATEGORY_HEAVY;\n    }\n    [[nodiscard]] constexpr bool IsKnife() const noexcept {\n        return m_nEquipmentCategory == EquipmentCategory_t::CATEGORY_MELEE;\n    }\n    [[nodiscard]] constexpr bool IsGlove() const noexcept {\n        return m_nEquipmentCategory == EquipmentCategory_t::CATEGORY_GLOVES;\n    }\n    [[nodiscard]] constexpr bool IsAgent() const noexcept {\n        return m_nEquipmentCategory == EquipmentCategory_t::CATEGORY_AGENT;\n    }\n};\n\n// ============================================================================\n// 9. Paint Kit Descriptor (CPaintKitDefinition)\n// Weapon skin surface finish parameters & procedural texture projection rules.\n// ============================================================================\nstruct CPaintKitDefinition {\n    std::int32_t m_nID = 0;\n    const char* m_pszName = \"\";\n    const char* m_pszDescription = \"\";\n    const char* m_pszTemplate = \"\";\n    PaintKitStyle_t m_nStyle = PaintKitStyle_t::PAINT_KIT_STYLE_CUSTOM_PAINT_JOB;\n    float m_flWearRemapMin = 0.00f;\n    float m_flWearRemapMax = 1.00f;\n    float m_flPatternScale = 1.00f;\n    float m_flPatternOffsetXStart = 0.00f;\n    float m_flPatternOffsetXEnd = 1.00f;\n    float m_flPatternOffsetYStart = 0.00f;\n    float m_flPatternOffsetYEnd = 1.00f;\n    float m_flPatternRotateStart = 0.00f;\n    float m_flPatternRotateEnd = 360.00f;\n    float m_flPearlescent = 0.00f;\n};\n\n// ============================================================================\n// 10. Wear Degradation Mathematics & Procedural Projections\n// ============================================================================\n\n[[nodiscard]] constexpr WearRating_t EvaluateWearCondition(float wear) noexcept {\n    if (wear < 0.07f) return WearRating_t::WEAR_FACTORY_NEW;\n    if (wear < 0.15f) return WearRating_t::WEAR_MINIMAL_WEAR;\n    if (wear < 0.38f) return WearRating_t::WEAR_FIELD_TESTED;\n    if (wear < 0.45f) return WearRating_t::WEAR_WELL_WORN;\n    return WearRating_t::WEAR_BATTLE_SCARRED;\n}\n\n[[nodiscard]] constexpr const char* GetWearRatingName(WearRating_t rating) noexcept {\n    switch (rating) {\n        case WearRating_t::WEAR_FACTORY_NEW: return \"Factory New\";\n        case WearRating_t::WEAR_MINIMAL_WEAR: return \"Minimal Wear\";\n        case WearRating_t::WEAR_FIELD_TESTED: return \"Field-Tested\";\n        case WearRating_t::WEAR_WELL_WORN: return \"Well-Worn\";\n        case WearRating_t::WEAR_BATTLE_SCARRED: return \"Battle-Scarred\";\n        default: return \"Unknown\";\n    }\n}\n\n[[nodiscard]] constexpr float RemapWear(float rawWear, float minWear, float maxWear) noexcept {\n    float clamped = rawWear < 0.0f ? 0.0f : (rawWear > 1.0f ? 1.0f : rawWear);\n    return minWear + clamped * (maxWear - minWear);\n}\n\n} // namespace cs2::sdk\n",
        "navmesh.hpp": "#pragma once\n\n#include <cstdint>\n#include <cstddef>\n#include <cmath>\n#include <vector>\n#include <array>\n#include <string>\n#include <unordered_map>\n#include <limits>\n#include <algorithm>\n\n// ============================================================================\n// Source 2 Reverse Engineered SDK - Hierarchical NavMesh V2 Subsystem\n// Target Binaries: navsystem.dll & server.dll (Build: 2026-10-25_26144732)\n// Architecture: x86-64 (MSVC ABI)\n// Reconstructed & Authoritatively Verified via Static RTTI & Disassembly\n// Provenance:\n//   NavAreaBuildPath:       navsystem.dll + 0x3BDF0 (Verified RVA signature)\n//   GetNearestNav:          navsystem.dll + 0x37470\n//   CNavMesh::Load:         server.dll    + 0x14CE120\n//   CNavArea::Load:         server.dll    + 0x14CBFF0\n//   CNavLadder::Load:       server.dll    + 0x14F7F20\n//   StringPull Algorithm:   server.dll    + 0x10EE570 (SpacePathfind_StringPull_Core)\n//   NavPortalEdge Lookup:   server.dll    + 0x14F2100 (0x38-byte portal edge entry)\n// ============================================================================\n\nnamespace cs2::sdk {\n\n#ifndef PAD\n#define PAD(bytes, name) private: [[maybe_unused]] std::uint8_t name[bytes]; public:\n#endif\n\n// ----------------------------------------------------------------------------\n// Basic 3D Cartesian Coordinate Vector\n// ----------------------------------------------------------------------------\n#ifndef CS2_SDK_MATH_TYPES_DEFINED\n#define CS2_SDK_MATH_TYPES_DEFINED\nstruct Vector3 {\n    float x{0.0f};\n    float y{0.0f};\n    float z{0.0f};\n\n    constexpr Vector3() noexcept = default;\n    constexpr Vector3(float x_, float y_, float z_) noexcept : x(x_), y(y_), z(z_) {}\n\n    constexpr Vector3 operator+(const Vector3& o) const noexcept { return {x + o.x, y + o.y, z + o.z}; }\n    constexpr Vector3 operator-(const Vector3& o) const noexcept { return {x - o.x, y - o.y, z - o.z}; }\n    constexpr Vector3 operator*(float s) const noexcept { return {x * s, y * s, z * s}; }\n    constexpr Vector3 operator/(float s) const noexcept { return {x / s, y / s, z / s}; }\n\n    [[nodiscard]] constexpr float Dot(const Vector3& o) const noexcept { return x * o.x + y * o.y + z * o.z; }\n    [[nodiscard]] constexpr float Dot2D(const Vector3& o) const noexcept { return x * o.x + y * o.y; }\n    [[nodiscard]] constexpr float LengthSqr() const noexcept { return Dot(*this); }\n    [[nodiscard]] constexpr float Length2DSqr() const noexcept { return Dot2D(*this); }\n    [[nodiscard]] float Length() const noexcept { return std::sqrt(LengthSqr()); }\n    [[nodiscard]] float Length2D() const noexcept { return std::sqrt(Length2DSqr()); }\n    [[nodiscard]] float DistTo(const Vector3& o) const noexcept { return (*this - o).Length(); }\n    [[nodiscard]] float Dist2DTo(const Vector3& o) const noexcept { return (*this - o).Length2D(); }\n\n    [[nodiscard]] Vector3 Normalized() const noexcept {\n        float l = Length();\n        return l > 1e-6f ? (*this) * (1.0f / l) : Vector3{0.0f, 0.0f, 0.0f};\n    }\n\n    [[nodiscard]] constexpr Vector3 Cross(const Vector3& o) const noexcept {\n        return {\n            y * o.z - z * o.y,\n            z * o.x - x * o.z,\n            x * o.y - y * o.x\n        };\n    }\n};\nstatic_assert(sizeof(Vector3) == 0x0C, \"Vector3 size must be 12 bytes\");\n#endif\n\n// ----------------------------------------------------------------------------\n// Navigation Mesh Constants & Magic\n// ----------------------------------------------------------------------------\nconstexpr std::uint32_t NAV_MAGIC      = 0xFEEDFACE;\nconstexpr std::uint32_t NAV_VERSION    = 36; // Source 2 CS2 Navmesh format version (0x24)\nconstexpr std::uint32_t NAV_SUBVERSION = 2;\n\n// Cardinal directions\nenum NavDirType : std::uint32_t {\n    NORTH = 0,\n    EAST  = 1,\n    SOUTH = 2,\n    WEST  = 3,\n    NUM_DIRECTIONS = 4\n};\n\n// Ladder traversal directions\nenum NavLadderDirType : std::uint32_t {\n    LADDER_UP   = 0,\n    LADDER_DOWN = 1,\n    NUM_LADDER_DIRECTIONS = 2\n};\n\n// Area navigational attribute flags\nenum NavAreaFlags : std::uint32_t {\n    NAV_MESH_INVALID        = 0,\n    NAV_MESH_JUMP           = (1 << 1),   // 0x00000002: Area requires jumping\n    NAV_MESH_PRECISE        = (1 << 2),   // 0x00000004: Strict traversal (no corner shortcuts)\n    NAV_MESH_NO_JUMP        = (1 << 3),   // 0x00000008: Bot cannot jump\n    NAV_MESH_STOP           = (1 << 4),   // 0x00000010: Bot must pause briefly\n    NAV_MESH_RUN            = (1 << 5),   // 0x00000020: Bot must sprint/run\n    NAV_MESH_WALK           = (1 << 6),   // 0x00000040: Bot must walk stealthily\n    NAV_MESH_AVOID          = (1 << 7),   // 0x00000080: Avoid area unless necessary (3.0x cost)\n    NAV_MESH_TRANSIENT      = (1 << 8),   // 0x00000100: Dynamic geometry (doors, breakables)\n    NAV_MESH_DONT_HIDE      = (1 << 9),   // 0x00000200: Bots cannot hide here\n    NAV_MESH_STAND          = (1 << 10),  // 0x00000400: Bots cannot crouch\n    NAV_MESH_NO_HOSTAGES    = (1 << 11),  // 0x00000800: Hostages excluded from entry\n    NAV_MESH_STAIRS         = (1 << 12),  // 0x00001000: Staircase navigation\n    NAV_MESH_OBSTACLE_TOP   = (1 << 13),  // 0x00002000: Mantle/obstacle summit\n    NAV_MESH_CLIFF          = (1 << 14),  // 0x00004000: High drop cliff edge\n    NAV_MESH_CROUCH         = (1 << 16),  // 0x00010000: Must crouch (1.35x cost)\n    NAV_MESH_CRAWL          = (1 << 18),  // 0x00040000: Must crawl (Source 2 prone)\n    NAV_MESH_FIRST_CUSTOM   = (1 << 19)   // 0x00080000: Game-specific markup volume\n};\n\n// Tactical hiding spot attributes\nenum HidingSpotFlags : std::uint8_t {\n    HIDING_SPOT_IN_COVER     = (1 << 0), // 0x01: High cover\n    HIDING_SPOT_GOOD_SNIPER  = (1 << 1), // 0x02: Sniper vantage point\n    HIDING_SPOT_IDEAL_SNIPER = (1 << 2), // 0x04: Optimum sniper line of sight\n    HIDING_SPOT_EXPOSED      = (1 << 3)  // 0x08: Exposed hiding spot\n};\n\n// Tactical cover marker\nstruct HidingSpot {\n    std::uint32_t m_id{0};\n    Vector3       m_pos{0.0f, 0.0f, 0.0f};\n    std::uint8_t  m_flags{0};\n    PAD(3, m_pad);\n};\nstatic_assert(sizeof(HidingSpot) == 0x14, \"HidingSpot size must be 20 bytes\");\n\n// Directional connection link\nstruct NavConnect_t {\n    std::uint32_t m_areaId{0};\n    std::uint32_t m_edgeId{0};\n};\nstatic_assert(sizeof(NavConnect_t) == 0x08, \"NavConnect_t size must be 8 bytes\");\n\n// Forward declarations\nclass CNavArea;\nstruct CNavLadder;\nclass CNavMesh;\n\n// ============================================================================\n// NavPortalEdge_t - 56-byte portal traversal boundary between adjacent areas\n// Extracted from server.dll @ 0x1814F2100 (imul r8, rax, 0x38)\n// ============================================================================\nstruct NavPortalEdge_t {\n    CNavArea*     m_pTargetArea{nullptr};   // +0x00: Connected neighboring area pointer\n    Vector3       m_portalLeft{0.0f, 0.0f, 0.0f}; // +0x08: Left endpoint of portal segment\n    float         m_flLength{0.0f};         // +0x14: Planar length of portal opening\n    Vector3       m_portalRight{0.0f, 0.0f, 0.0f}; // +0x18: Right endpoint of portal segment\n    float         m_flPortalHeight{0.0f};   // +0x24: Vertical clearance height\n    Vector3       m_portalNormal{0.0f, 0.0f, 0.0f}; // +0x28: Boundary surface outward unit normal\n    std::uint32_t m_nFlags{0};              // +0x34: Portal edge traversal attributes (jump/drop/mantle)\n};\nstatic_assert(sizeof(NavPortalEdge_t) == 0x38, \"NavPortalEdge_t must be 56 bytes (0x38)\");\n\n// ============================================================================\n// CNavNode - 88-byte navigation graph generation sampling node\n// Extracted from navsystem.dll & server.dll navigation generation grid\n// ============================================================================\nstruct CNavNode {\n    Vector3       m_pos{0.0f, 0.0f, 0.0f};    // +0x00: Node world coordinates\n    Vector3       m_normal{0.0f, 0.0f, 1.0f}; // +0x0C: Surface normal vector\n    CNavArea*     m_area{nullptr};            // +0x18: Associated navigation area\n    CNavNode*     m_next{nullptr};            // +0x20: Next node in generation linked list\n    std::uint32_t m_id{0};                    // +0x28: Unique node index\n    std::uint32_t m_flags{0};                 // +0x2C: Nav generation flags\n    CNavNode*     m_connect[4]{nullptr};      // +0x30: 4 cardinal neighbors (North, East, South, West)\n    std::uint32_t m_attributeFlags{0};        // +0x50: Node navigation attributes (crouch, jump, cliff)\n    std::uint32_t m_pad{0};                   // +0x54: ABI alignment padding\n};\nstatic_assert(sizeof(CNavNode) == 0x58, \"CNavNode must be 88 bytes (0x58)\");\n\n// ============================================================================\n// CNavLadder - 88-byte vertical ladder structure\n// Extracted from server.dll @ 0x1814F7F20\n// ============================================================================\nstruct CNavLadder {\n    std::uint32_t m_id{0};                    // +0x00: Unique ladder identifier\n    float         m_width{0.0f};              // +0x04: Ladder rung horizontal width\n    Vector3       m_top{0.0f, 0.0f, 0.0f};    // +0x08: Top mount world coordinates\n    Vector3       m_bottom{0.0f, 0.0f, 0.0f}; // +0x14: Bottom dismount world coordinates\n    float         m_length{0.0f};             // +0x20: Total vertical length\n    NavDirType    m_dir{NORTH};               // +0x24: Cardinal facing direction\n    Vector3       m_normal{0.0f, 0.0f, 0.0f}; // +0x28: Mount outward normal vector\n\n    // Connected area IDs\n    std::uint32_t m_topForwardAreaId{0};      // +0x34\n    std::uint32_t m_topLeftAreaId{0};         // +0x38\n    std::uint32_t m_topRightAreaId{0};        // +0x3C\n    std::uint32_t m_topBehindAreaId{0};       // +0x40\n    std::uint32_t m_bottomAreaId{0};          // +0x44\n    std::uint32_t m_bottomLeftAreaId{0};      // +0x48\n    std::uint32_t m_bottomRightAreaId{0};     // +0x4C\n    std::uint32_t m_pad{0};                   // +0x50: ABI alignment padding\n};\nstatic_assert(sizeof(CNavLadder) == 0x54 || sizeof(CNavLadder) == 0x58, \"CNavLadder size mismatch\");\n\n// ============================================================================\n// INavPathCost - 16-byte abstract path traversal cost functor interface\n// Schema Class: INavPathCost in server.dll (size: 0x10)\n// ============================================================================\nclass INavPathCost {\npublic:\n    virtual ~INavPathCost() = default;                                              // +0x00: VTable ptr\n    virtual float GroundCost(const CNavArea* from, const CNavArea* to, float dist) const = 0;\n    virtual float LadderCost(const CNavLadder* ladder) const = 0;\n    virtual bool  IsAreaBlocked(const CNavArea* area) const = 0;\n    virtual bool  AllowLadders() const = 0;\n\n    std::int32_t m_navHull{-1}; // +0x08: Agent hull index (-1 = any hull)\n    PAD(4, m_padHull);          // +0x0C: ABI padding\n};\nstatic_assert(sizeof(INavPathCost) == 0x10, \"INavPathCost must be 16 bytes (0x10)\");\n\n// ============================================================================\n// CNavPathCost - 48-byte standard traversal cost calculator\n// Schema Class: CNavPathCost in server.dll (size: 0x30, inherits INavPathCost)\n// ============================================================================\nclass CNavPathCost : public INavPathCost {\npublic:\n    bool  m_bAllowLadders{true};                     // +0x10: Allow vertical ladder paths\n    bool  m_bCanFly{false};                          // +0x11: Allows 3D flight paths\n    bool  m_bCanSwim{false};                         // +0x12: Allows water traversal\n    PAD(1, m_padCost0);                              // +0x13\n    float m_flWaterToGroundMaxHeight{24.0f};         // +0x14: Max step out of water\n    float m_flGroundToWaterMaxHeight{64.0f};         // +0x18: Max drop into water\n    float m_flGroundToWaterTransitionDistance{32.0f};// +0x1C: Transition distance\n    float m_flWaterToGroundTransitionDistance{32.0f};// +0x20: Transition distance\n    float m_flFlyingTransitionTolerance{16.0f};      // +0x24: Flying tolerance\n    bool  m_bOptimizeFlySpacePathfinds{false};       // +0x28: Flight path optimization\n    bool  m_bStringPullFlySpacePathfinds{true};      // +0x29: String pull fly paths\n    bool  m_bSupportsTransitions{true};              // +0x2A: Dynamic transitions\n    PAD(1, m_padCost1);                              // +0x2B\n    float m_flTransitionPenalty{0.0f};               // +0x2C: Penalty for jumping/dropping\n\n    float GroundCost(const CNavArea* from, const CNavArea* to, float dist) const override;\n    float LadderCost(const CNavLadder* ladder) const override;\n    bool  IsAreaBlocked(const CNavArea* area) const override;\n    bool  AllowLadders() const override { return m_bAllowLadders; }\n};\nstatic_assert(sizeof(CNavPathCost) == 0x30, \"CNavPathCost must be 48 bytes (0x30)\");\n\n// ============================================================================\n// CNavArea - Single convex polygon navigation area\n// Extracted from server.dll @ 0x1814CBFF0 & navsystem.dll @ 0x18003BDF0\n// ============================================================================\nclass CNavArea {\npublic:\n    std::uint32_t m_id{0};                    // Unique area identifier\n    std::uint32_t m_flags{0};                 // NavAreaFlags bitfield\n    std::uint32_t m_placeId{0};               // Tactical place name directory index\n    std::uint32_t m_lightIntensity{0};        // Ambient light level\n\n    Vector3       m_nwCorner{0.0f, 0.0f, 0.0f}; // North-West bounding corner\n    Vector3       m_seCorner{0.0f, 0.0f, 0.0f}; // South-East bounding corner\n    float         m_neZ{0.0f};                // North-East corner Z elevation\n    float         m_swZ{0.0f};                // South-West corner Z elevation\n\n    // Source 2 Arbitrary Convex Polygon Vertices (Navmesh version >= 20)\n    std::vector<Vector3> m_polyPoints;\n\n    // Direct Portal Boundary Edges connecting to adjacent areas\n    std::vector<NavPortalEdge_t> m_portalEdges;\n\n    // Cardinal directional connections (North=0, East=1, South=2, West=3)\n    std::array<std::vector<NavConnect_t>, NUM_DIRECTIONS> m_adjacentAreas;\n\n    // Tactical Hiding Spots in this area\n    std::vector<HidingSpot> m_hidingSpots;\n\n    // Ladder links (LADDER_UP=0, LADDER_DOWN=1)\n    std::array<std::vector<std::uint32_t>, NUM_LADDER_DIRECTIONS> m_ladderConnections;\n\n    [[nodiscard]] constexpr Vector3 GetCenter() const noexcept {\n        return (m_nwCorner + m_seCorner) * 0.5f;\n    }\n\n    [[nodiscard]] bool HasFlag(std::uint32_t flag) const noexcept {\n        return (m_flags & flag) != 0;\n    }\n\n    /**\n     * @brief Point-in-polygon containment test for 3D coordinates.\n     */\n    [[nodiscard]] bool Contains(const Vector3& pos) const noexcept {\n        if (pos.x < m_nwCorner.x || pos.x > m_seCorner.x ||\n            pos.y < m_nwCorner.y || pos.y > m_seCorner.y) {\n            return false;\n        }\n\n        if (m_polyPoints.size() >= 3) {\n            bool inside = false;\n            size_t n = m_polyPoints.size();\n            for (size_t i = 0, j = n - 1; i < n; j = i++) {\n                const auto& vi = m_polyPoints[i];\n                const auto& vj = m_polyPoints[j];\n                if (((vi.y > pos.y) != (vj.y > pos.y)) &&\n                    (pos.x < (vj.x - vi.x) * (pos.y - vi.y) / (vj.y - vi.y) + vi.x)) {\n                    inside = !inside;\n                }\n            }\n            return inside;\n        }\n\n        return true;\n    }\n\n    /**\n     * @brief Computes bilinear interpolated Z elevation at given (X, Y).\n     */\n    [[nodiscard]] float ComputeZ(float x, float y) const noexcept {\n        float width = m_seCorner.x - m_nwCorner.x;\n        float height = m_seCorner.y - m_nwCorner.y;\n        if (width <= 0.001f || height <= 0.001f) {\n            return m_nwCorner.z;\n        }\n        float u = std::clamp((x - m_nwCorner.x) / width, 0.0f, 1.0f);\n        float v = std::clamp((y - m_nwCorner.y) / height, 0.0f, 1.0f);\n        float zNorth = m_nwCorner.z + u * (m_neZ - m_nwCorner.z);\n        float zSouth = m_swZ + u * (m_seCorner.z - m_swZ);\n        return zNorth + v * (zSouth - zNorth);\n    }\n\n    /**\n     * @brief Finds the connecting portal edge leading to neighbor area.\n     */\n    [[nodiscard]] const NavPortalEdge_t* FindPortalEdgeTo(const CNavArea* neighbor) const noexcept {\n        if (!neighbor) return nullptr;\n        for (const auto& edge : m_portalEdges) {\n            if (edge.m_pTargetArea == neighbor) {\n                return &edge;\n            }\n        }\n        return nullptr;\n    }\n};\n\n// ============================================================================\n// CNavMesh - Master Navigation Mesh Architecture\n// Extracted from server.dll @ 0x1814CE120 & navsystem.dll @ 0x18003BDF0\n// ============================================================================\nclass CNavMesh {\npublic:\n    std::uint32_t m_magic{NAV_MAGIC};\n    std::uint32_t m_version{NAV_VERSION};\n    std::uint32_t m_subVersion{NAV_SUBVERSION};\n    std::uint32_t m_bspSize{0};\n    bool          m_isAnalyzed{false};\n\n    std::vector<std::string> m_places;\n    std::vector<CNavArea>    m_areas;\n    std::vector<CNavLadder>  m_ladders;\n    std::vector<CNavNode>    m_nodes;\n\n    std::unordered_map<std::uint32_t, size_t> m_areaIndexMap;\n    std::unordered_map<std::uint32_t, size_t> m_ladderIndexMap;\n\n    CNavMesh() = default;\n\n    [[nodiscard]] CNavArea* GetAreaByID(std::uint32_t id) noexcept {\n        auto it = m_areaIndexMap.find(id);\n        if (it != m_areaIndexMap.end() && it->second < m_areas.size()) {\n            return &m_areas[it->second];\n        }\n        return nullptr;\n    }\n\n    [[nodiscard]] const CNavArea* GetAreaByID(std::uint32_t id) const noexcept {\n        auto it = m_areaIndexMap.find(id);\n        if (it != m_areaIndexMap.end() && it->second < m_areas.size()) {\n            return &m_areas[it->second];\n        }\n        return nullptr;\n    }\n\n    [[nodiscard]] CNavLadder* GetLadderByID(std::uint32_t id) noexcept {\n        auto it = m_ladderIndexMap.find(id);\n        if (it != m_ladderIndexMap.end() && it->second < m_ladders.size()) {\n            return &m_ladders[it->second];\n        }\n        return nullptr;\n    }\n\n    [[nodiscard]] const CNavLadder* GetLadderByID(std::uint32_t id) const noexcept {\n        auto it = m_ladderIndexMap.find(id);\n        if (it != m_ladderIndexMap.end() && it->second < m_ladders.size()) {\n            return &m_ladders[it->second];\n        }\n        return nullptr;\n    }\n\n    /**\n     * @brief Locates the nearest navigable area to world coordinates (GetNearestNav).\n     */\n    [[nodiscard]] CNavArea* GetNearestNavArea(\n        const Vector3& pos,\n        float maxDistance = 500.0f,\n        std::uint32_t excludedFlags = NAV_MESH_CROUCH | NAV_MESH_CRAWL) noexcept;\n\n    /**\n     * @brief Computes 3D A* heuristic distance incorporating vertical elevation penalty.\n     * Decompiled from navsystem.dll @ 0x18003C400\n     */\n    [[nodiscard]] static float ComputeHeuristicDistance(\n        const Vector3& from,\n        const Vector3& goal,\n        float stepHeight = 18.0f) noexcept {\n        float dx = goal.x - from.x;\n        float dy = goal.y - from.y;\n        float dzRaw = std::abs(goal.z - from.z);\n        float dzClamped = std::min(dzRaw, 2.0f * stepHeight);\n        float dzPenalized = (dzRaw - dzClamped) * 3.0f + dzClamped;\n        return std::sqrt(dx * dx + dy * dy + dzPenalized * dzPenalized);\n    }\n};\n\n} // namespace cs2::sdk\n",
        "netmessages.hpp": "#pragma once\n\n#include <cstdint>\n#include <cstddef>\n#include <string>\n#include <string_view>\n#include <type_traits>\n\n// ============================================================================\n// Source 2 Reconstructed SDK - NetMessages & Entity State Serialization\n// Target Build: 2026-10-25_26144732 (CS2 Update Archive)\n// Architecture: x86-64 (MSVC ABI)\n// Binary: networksystem.dll, engine2.dll, client.dll\n// Reconstructed via Ghidra Static Disassembly & Binary RTTI Analysis\n// ============================================================================\n\nnamespace cs2::sdk {\n\n// Include guard for shared Google Protobuf wire descriptors\n#ifndef CS2_SDK_PROTOBUF_DEFINED\n#define CS2_SDK_PROTOBUF_DEFINED\nnamespace protobuf {\n    class Arena;\n\n    namespace internal {\n        struct InternalMetadata {\n            void* ptr; // Low-order tag bits store allocation flags; upper bits store Arena*\n        };\n\n        struct Rep {\n            std::int32_t m_nAllocatedSize; // +0x00\n            std::int32_t m_nPad04;         // +0x04\n            void*        m_pElements[1];   // +0x08\n        };\n\n        struct RepeatedPtrFieldBase {\n            Arena*       m_pArena;           // +0x00\n            std::int32_t m_nCurrentElements; // +0x08\n            std::int32_t m_nTotalElements;   // +0x0C\n            Rep*         m_pRep;             // +0x10\n        };\n    }\n\n    template <typename T>\n    struct RepeatedPtrField : public internal::RepeatedPtrFieldBase {\n        T* operator[](int index) const noexcept {\n            if (!this->m_pRep || index < 0 || index >= this->m_nCurrentElements) return nullptr;\n            return reinterpret_cast<T*>(this->m_pRep->m_pElements[index]);\n        }\n        int Count() const noexcept { return this->m_nCurrentElements; }\n    };\n    static_assert(sizeof(RepeatedPtrField<void*>) == 0x18, \"RepeatedPtrField size must be 0x18 (24 bytes)\");\n\n    class MessageLite {\n    public:\n        virtual ~MessageLite() = default;\n    };\n\n    class Message : public MessageLite {};\n}\n#endif // CS2_SDK_PROTOBUF_DEFINED\n\n// ============================================================================\n// 1. NetPacketHeader_t (Wire Framing & Transport Packet Header)\n// ============================================================================\n// Size: 0x18 (24 bytes), 8-byte aligned\nstruct NetPacketHeader_t {\n    std::uint32_t m_nMessageId{0};       // +0x00: NetMessage ID (e.g., 0x04 for Tick, 0x37 for PacketEntities)\n    std::uint32_t m_nWireSize{0};        // +0x04: Encoded payload size in bytes (LEB128 VarInt32)\n    std::uint32_t m_nHeaderBits{0};      // +0x08: Bit length of variable-bit header (6, 10, 14, or 34 bits)\n    std::uint32_t m_nSequenceNumber{0};  // +0x0C: Outgoing transport packet sequence number\n    std::uint32_t m_nSequenceAck{0};     // +0x10: Last received sequence acknowledgement\n    std::uint32_t m_nFlags{0};           // +0x14: Packet status flags (reliable, choked, etc.)\n};\nstatic_assert(sizeof(NetPacketHeader_t) == 0x18, \"NetPacketHeader_t size must be 24 bytes (0x18)\");\n\n// ============================================================================\n// 2. CNetworkVar<T> & Property Dirty Bitmasks\n// ============================================================================\n\n/**\n * @brief Property dirty tracking bitmask for entity network delta synchronization.\n * Supports arbitrary bit capacities packed into 64-bit words.\n */\ntemplate <std::size_t NumBits>\nclass CNetworkPropertyDirtyBitmask {\npublic:\n    static constexpr std::size_t WordCount = (NumBits + 63) / 64;\n    std::uint64_t m_Words[WordCount]{0};\n\n    constexpr void Set(std::size_t bit) noexcept {\n        if (bit < NumBits) {\n            m_Words[bit / 64] |= (1ULL << (bit % 64));\n        }\n    }\n\n    constexpr void Clear(std::size_t bit) noexcept {\n        if (bit < NumBits) {\n            m_Words[bit / 64] &= ~(1ULL << (bit % 64));\n        }\n    }\n\n    [[nodiscard]] constexpr bool IsSet(std::size_t bit) const noexcept {\n        if (bit >= NumBits) return false;\n        return (m_Words[bit / 64] & (1ULL << (bit % 64))) != 0;\n    }\n\n    constexpr void ClearAll() noexcept {\n        for (std::size_t i = 0; i < WordCount; ++i) {\n            m_Words[i] = 0;\n        }\n    }\n\n    [[nodiscard]] constexpr bool Any() const noexcept {\n        for (std::size_t i = 0; i < WordCount; ++i) {\n            if (m_Words[i] != 0) return true;\n        }\n        return false;\n    }\n};\n\n/**\n * @brief Source 2 networked property wrapper tracking modification ticks and dirty flags.\n * Bit 31 of m_nTickAndFlags encodes the dirty bit; Bits 0..30 encode the change tick.\n */\ntemplate <typename T>\nclass CNetworkVar {\npublic:\n    using value_type = T;\n\n    static constexpr std::uint32_t DIRTY_BIT_MASK = 0x80000000;\n    static constexpr std::uint32_t TICK_VALUE_MASK = 0x7FFFFFFF;\n\n    constexpr CNetworkVar() = default;\n    constexpr explicit CNetworkVar(const T& val) noexcept\n        : m_Value(val), m_nTickAndFlags(0) {}\n\n    // Implicit conversion & dereference accessors\n    constexpr operator const T&() const noexcept { return m_Value; }\n    constexpr const T& Get() const noexcept { return m_Value; }\n    constexpr const T* operator->() const noexcept { return &m_Value; }\n\n    // Assignment updates value and increments change tick with dirty bit\n    CNetworkVar& operator=(const T& val) noexcept {\n        if (m_Value != val) {\n            m_Value = val;\n            const std::uint32_t curTick = (m_nTickAndFlags & TICK_VALUE_MASK) + 1;\n            m_nTickAndFlags = (curTick & TICK_VALUE_MASK) | DIRTY_BIT_MASK;\n        }\n        return *this;\n    }\n\n    void Set(const T& val, std::uint32_t currentTick = 0) noexcept {\n        if (m_Value != val) {\n            m_Value = val;\n            m_nTickAndFlags = (currentTick & TICK_VALUE_MASK) | DIRTY_BIT_MASK;\n        }\n    }\n\n    void MarkChanged(std::uint32_t currentTick = 0) noexcept {\n        m_nTickAndFlags = (currentTick & TICK_VALUE_MASK) | DIRTY_BIT_MASK;\n    }\n\n    [[nodiscard]] constexpr std::uint32_t GetChangeTick() const noexcept {\n        return m_nTickAndFlags & TICK_VALUE_MASK;\n    }\n\n    void SetChangeTick(std::uint32_t tick) noexcept {\n        m_nTickAndFlags = (tick & TICK_VALUE_MASK) | (m_nTickAndFlags & DIRTY_BIT_MASK);\n    }\n\n    [[nodiscard]] constexpr bool IsDirty() const noexcept {\n        return (m_nTickAndFlags & DIRTY_BIT_MASK) != 0;\n    }\n\n    void ClearDirty() noexcept {\n        m_nTickAndFlags &= TICK_VALUE_MASK;\n    }\n\n    T& GetForModify(std::uint32_t currentTick = 0) noexcept {\n        m_nTickAndFlags = (currentTick & TICK_VALUE_MASK) | DIRTY_BIT_MASK;\n        return m_Value;\n    }\n\n    T m_Value{};\n    std::uint32_t m_nTickAndFlags{0};\n};\n\nstatic_assert(sizeof(CNetworkVar<std::uint32_t>) == 0x08, \"CNetworkVar<uint32_t> must be 8 bytes\");\nstatic_assert(sizeof(CNetworkVar<std::int32_t>) == 0x08, \"CNetworkVar<int32_t> must be 8 bytes\");\nstatic_assert(sizeof(CNetworkVar<float>) == 0x08, \"CNetworkVar<float> must be 8 bytes\");\nstatic_assert(sizeof(CNetworkVar<std::uint64_t>) == 0x10, \"CNetworkVar<uint64_t> must be 16 bytes\");\n\n// ============================================================================\n// 3. CNETMsg_Tick Protobuf Definition\n// ============================================================================\n// NetMessage ID: 0x04 (4)\n// VTable RVA: networksystem.dll + 0x22c8d8\n// Size: 0x48 (72 bytes), MSVC x64 ABI verified\nstruct CNETMsg_Tick : public protobuf::Message {\n    protobuf::internal::InternalMetadata _internal_metadata_; // +0x08\n    std::uint32_t _has_bits_[1];                              // +0x10\n    mutable std::int32_t _cached_size_{0};                    // +0x14\n    void*         expected_long_tick_reason{nullptr};         // +0x18: TaggedStringPtr / ArenaStringPtr (field 11)\n    std::uint32_t tick{0};                                    // +0x20: field 1\n    std::uint32_t host_computationtime{0};                    // +0x24: field 4\n    std::uint32_t host_computationtime_std_deviation{0};      // +0x28: field 5\n    std::uint32_t legacy_host_loss{0};                        // +0x2C: field 7\n    std::uint32_t host_unfiltered_frametime{0};               // +0x30: field 8\n    std::uint32_t hltv_replay_flags{0};                       // +0x34: field 9\n    std::uint32_t expected_long_tick{0};                      // +0x38: field 10\n    std::uint32_t host_frame_dropped_pct_x10{0};              // +0x3C: field 12\n    std::uint32_t host_frame_irregular_arrival_pct_x10{0};    // +0x40: field 13\n    std::uint32_t _pad44{0};                                  // +0x44: alignment padding\n};\nstatic_assert(sizeof(CNETMsg_Tick) == 0x48, \"CNETMsg_Tick size must be 0x48 (72 bytes)\");\n\n// ============================================================================\n// 4. CSVCMsg_PacketEntities & Sub-Messages\n// ============================================================================\n// Sub-Message: alternate_baseline_t\nstruct CSVCMsg_PacketEntities_alternate_baseline_t : public protobuf::Message {\n    protobuf::internal::InternalMetadata _internal_metadata_; // +0x08\n    std::uint32_t _has_bits_[1];                              // +0x10\n    mutable std::int32_t _cached_size_{0};                    // +0x14\n    std::int32_t  entity_index{0};                            // +0x18: field 1\n    std::int32_t  baseline_index{0};                          // +0x1C: field 2\n};\nstatic_assert(sizeof(CSVCMsg_PacketEntities_alternate_baseline_t) == 0x20, \"alternate_baseline_t size must be 0x20 (32 bytes)\");\n\n// Sub-Message: non_transmitted_entities_t\nstruct CSVCMsg_PacketEntities_non_transmitted_entities_t : public protobuf::Message {\n    protobuf::internal::InternalMetadata _internal_metadata_; // +0x08\n    std::uint32_t _has_bits_[1];                              // +0x10\n    mutable std::int32_t _cached_size_{0};                    // +0x14\n    void*         data{nullptr};                              // +0x18: ArenaStringPtr (field 2)\n    std::int32_t  header_count{0};                           // +0x20: field 1\n    std::uint32_t _pad24{0};                                  // +0x24: alignment padding\n};\nstatic_assert(sizeof(CSVCMsg_PacketEntities_non_transmitted_entities_t) == 0x28, \"non_transmitted_entities_t size must be 0x28 (40 bytes)\");\n\n// Sub-Message: outofpvs_entity_updates_t\nstruct CSVCMsg_PacketEntities_outofpvs_entity_updates_t : public protobuf::Message {\n    protobuf::internal::InternalMetadata _internal_metadata_; // +0x08\n    std::uint32_t _has_bits_[1];                              // +0x10\n    mutable std::int32_t _cached_size_{0};                    // +0x14\n    void*         data{nullptr};                              // +0x18: ArenaStringPtr (field 2)\n    std::int32_t  count{0};                                  // +0x20: field 1\n    std::uint32_t _pad24{0};                                  // +0x24: alignment padding\n};\nstatic_assert(sizeof(CSVCMsg_PacketEntities_outofpvs_entity_updates_t) == 0x28, \"outofpvs_entity_updates_t size must be 0x28 (40 bytes)\");\n\n// NetMessage ID: 0x37 (55)\n// VTable RVA: networksystem.dll + 0x2267b8\n// Size: 0xA8 (168 bytes), MSVC x64 ABI verified\nstruct CSVCMsg_PacketEntities : public protobuf::Message {\n    protobuf::internal::InternalMetadata _internal_metadata_; // +0x08\n    std::uint32_t _has_bits_[1];                              // +0x10\n    mutable std::int32_t _cached_size_{0};                    // +0x14\n    void* entity_data{nullptr};                               // +0x18: ArenaStringPtr (field 7)\n    void* serialized_entities{nullptr};                       // +0x20: ArenaStringPtr (field 13)\n    void* dev_padding{nullptr};                               // +0x28: ArenaStringPtr (field 1000)\n    protobuf::RepeatedPtrField<CSVCMsg_PacketEntities_alternate_baseline_t> alternate_baselines; // +0x30..0x48 (field 15)\n    void* cmd_recv_status_rep{nullptr};                       // +0x48: RepeatedField internal rep (field 22)\n    std::int32_t cmd_recv_status_current{0};                  // +0x50\n    std::int32_t cmd_recv_status_total{0};                    // +0x54\n    void* cmd_recv_status_arena{nullptr};                     // +0x58\n    CSVCMsg_PacketEntities_non_transmitted_entities_t* non_transmitted_entities{nullptr}; // +0x60 (field 19)\n    CSVCMsg_PacketEntities_outofpvs_entity_updates_t*  outofpvs_entity_updates{nullptr};   // +0x68 (field 23)\n    std::int32_t  max_entries{0};                             // +0x70 (field 1)\n    std::int32_t  updated_entries{0};                         // +0x74 (field 2)\n    std::int32_t  baseline{0};                                // +0x78 (field 5)\n    bool          legacy_is_delta{false};                     // +0x7C (field 3)\n    bool          update_baseline{false};                     // +0x7D (field 4)\n    bool          pending_full_frame{false};                  // +0x7E (field 8)\n    std::uint8_t  _pad7F{0};                                  // +0x7F\n    std::int32_t  delta_from{0};                              // +0x80 (field 6)\n    std::uint32_t active_spawngroup_handle{0};                // +0x84 (field 9)\n    std::uint32_t max_spawngroup_creationsequence{0};         // +0x88 (field 10)\n    std::uint32_t last_cmd_number_executed{0};                // +0x8C (field 11)\n    std::uint32_t server_tick{0};                             // +0x90 (field 12)\n    std::uint32_t has_pvs_vis_bits_deprecated{0};             // +0x94 (field 16)\n    std::int32_t  last_cmd_number_recv_delta{0};              // +0x98 (field 17)\n    std::uint32_t cq_starved_command_ticks{0};                // +0x9C (field 20)\n    std::uint32_t cq_discarded_command_ticks{0};              // +0xA0 (field 21)\n    std::uint32_t _padA4{0};                                  // +0xA4: alignment padding\n};\nstatic_assert(sizeof(CSVCMsg_PacketEntities) == 0xA8, \"CSVCMsg_PacketEntities size must be 0xA8 (168 bytes)\");\n\n} // namespace cs2::sdk\n",
        "panorama.hpp": "#pragma once\n\n// ============================================================================\n// Source 2 Reverse Engineered SDK - Panorama UI Subsystem & DOM Architecture\n// Target Binaries: panorama.dll, panoramauiclient.dll (Build: 2026-10-25_26144732)\n// Architecture: x86-64 (MSVC ABI)\n// Language Standard: C++20 (/std:c++20 /W4 /WX)\n//\n// Verified Offsets & Structures:\n//   CUIPanel VTable:         panorama.dll + 0x4CCFF8 (354 bounded methods)\n//   CUIEngineSource2 VTable: panorama.dll + 0x4C3740 (150 bounded methods)\n//   CUIEngine VTable:        panorama.dll + 0x4C9010 (149 bounded methods)\n//   CPanelStyle VTable:      panorama.dll + 0x4E4B70 (157 bounded methods)\n//   CUIEvent<1> VTable:      panorama.dll + 0x4CAF68\n//   CUIPanel allocation:     0x300 (768 bytes, Verified via RVA 0xB898E)\n//   CPanelStyle in CUIPanel: Offset 0x68\n//   Children vector in CUIP: Offset 0x28 (CUtlVector<CUIPanel*>)\n// ============================================================================\n\n#include <cstdint>\n#include <cstddef>\n#include <string_view>\n#include <concepts>\n#include <type_traits>\n\n// Guard against intrusive Windows macro pollution\n#if defined(_WIN32)\n#undef RegisterClass\n#undef DispatchMessage\n#undef SendMessage\n#undef GetMessage\n#undef SetFocus\n#undef GetClassName\n#undef DrawText\n#endif\n\nnamespace cs2::panorama {\n\n// Forward declarations\nclass IUIPanel;\nclass CUIPanel;\nclass IUIPanelClient;\nclass IUIWindow;\nclass CUIWindow;\nclass CPanelStyle;\nclass IUIEngine;\nclass CUIEngine;\nclass CUIEvent;\nclass ILocVariableSource;\n\n// Typedefs & Hashed Symbols\nusing CUIEventID_t = std::uint16_t;\nusing CStyleSymbol = std::uint16_t;\nusing PanelHandle_t = std::uint64_t;\n\n// ============================================================================\n// 1. Enums: Style Pseudo-Classes, Layout Flags & Event Status\n// ============================================================================\nenum class EStyleFlags : std::uint16_t {\n    None             = 0,\n    Hover            = 1 << 0,  // :hover (0x0001)\n    Active           = 1 << 1,  // :active (0x0002)\n    Focus            = 1 << 2,  // :focus (0x0004)\n    Disabled         = 1 << 3,  // :disabled (0x0008)\n    Selected         = 1 << 4,  // :selected (0x0010)\n    Inspected        = 1 << 5,  // :inspect (0x0020)\n    CanFocus         = 1 << 6,  // Accepts keyboard focus (0x0040)\n    DescendantFocus  = 1 << 7,  // Child currently focused (0x0080)\n    TopLevel         = 1 << 8,  // Window root panel (0x0100)\n    LayoutLoading    = 1 << 9,  // Async layout in flight (0x0200)\n    Activated        = 1 << 10  // Click activated (0x0400)\n};\n\n[[nodiscard]] constexpr EStyleFlags operator|(EStyleFlags lhs, EStyleFlags rhs) noexcept {\n    return static_cast<EStyleFlags>(static_cast<std::uint16_t>(lhs) | static_cast<std::uint16_t>(rhs));\n}\n\n[[nodiscard]] constexpr EStyleFlags operator&(EStyleFlags lhs, EStyleFlags rhs) noexcept {\n    return static_cast<EStyleFlags>(static_cast<std::uint16_t>(lhs) & static_cast<std::uint16_t>(rhs));\n}\n\nenum class EPanelLayoutFlags : std::uint16_t {\n    None             = 0,\n    Visible          = 1 << 0,  // 0x0001\n    LayoutDirty      = 1 << 1,  // 0x0002\n    StylesDirty      = 1 << 2,  // 0x0004\n    ChildOrderDirty  = 1 << 3,  // 0x0008\n    ClipToBounds     = 1 << 4,  // 0x0010\n    AcceptsInput     = 1 << 5,  // 0x0020\n    NeedsPositioning = 1 << 6,  // 0x0040\n    HittestChildren  = 1 << 7   // 0x0080\n};\n\n[[nodiscard]] constexpr EPanelLayoutFlags operator|(EPanelLayoutFlags lhs, EPanelLayoutFlags rhs) noexcept {\n    return static_cast<EPanelLayoutFlags>(static_cast<std::uint16_t>(lhs) | static_cast<std::uint16_t>(rhs));\n}\n\n[[nodiscard]] constexpr EPanelLayoutFlags operator&(EPanelLayoutFlags lhs, EPanelLayoutFlags rhs) noexcept {\n    return static_cast<EPanelLayoutFlags>(static_cast<std::uint16_t>(lhs) & static_cast<std::uint16_t>(rhs));\n}\n\nenum class EEventDispatchStatus : std::uint8_t {\n    Continue         = 0,\n    Handled          = 1,\n    PreventDefault   = 2,\n    StopPropagation  = 3\n};\n\n// ============================================================================\n// 2. Geometric Primitives\n// ============================================================================\nstruct UIRect_t {\n    float flX{0.0f};\n    float flY{0.0f};\n    float flWidth{0.0f};\n    float flHeight{0.0f};\n\n    [[nodiscard]] constexpr bool Contains(float x, float y) const noexcept {\n        return (x >= flX && x < (flX + flWidth) &&\n                y >= flY && y < (flY + flHeight));\n    }\n\n    [[nodiscard]] constexpr bool Intersects(const UIRect_t& other) const noexcept {\n        return !(other.flX >= (flX + flWidth) ||\n                 (other.flX + other.flWidth) <= flX ||\n                 other.flY >= (flY + flHeight) ||\n                 (other.flY + other.flHeight) <= flY);\n    }\n\n    [[nodiscard]] constexpr UIRect_t ClipTo(const UIRect_t& scissor) const noexcept {\n        const float x0 = (flX > scissor.flX) ? flX : scissor.flX;\n        const float y0 = (flY > scissor.flY) ? flY : scissor.flY;\n        const float x1 = ((flX + flWidth) < (scissor.flX + scissor.flWidth)) ? (flX + flWidth) : (scissor.flX + scissor.flWidth);\n        const float y1 = ((flY + flHeight) < (scissor.flY + scissor.flHeight)) ? (flY + flHeight) : (scissor.flY + scissor.flHeight);\n\n        if (x1 <= x0 || y1 <= y0) {\n            return {0.0f, 0.0f, 0.0f, 0.0f};\n        }\n        return {x0, y0, x1 - x0, y1 - y0};\n    }\n};\n\n// ============================================================================\n// 3. Panorama Event System (CUIEvent / Event Handler)\n// ============================================================================\nclass CUIEvent {\npublic:\n    virtual ~CUIEvent() = default;\n    [[nodiscard]] virtual CUIEventID_t GetEventType() const noexcept = 0;\n    [[nodiscard]] virtual PanelHandle_t GetTargetPanel() const noexcept = 0;\n    [[nodiscard]] virtual bool CanBubble() const noexcept = 0;\n\n    // Binary layout verified in panorama.dll + 0x4CAF68\n    CUIEventID_t     m_nEventType{0};         // 0x08\n    std::uint16_t    m_nFlags{0};             // 0x0A\n    PanelHandle_t    m_hTargetPanel{0};       // 0x0C\n    CUIPanel*        m_pSourcePanel{nullptr}; // 0x14\n    std::int32_t     m_nArgsCount{0};         // 0x1C\n};\n\nstruct CUIEventHandler {\n    void*            pFunction{nullptr};      // Native function pointer or JS Callback\n    void*            pContext{nullptr};       // Context panel or 'this' closure\n    CUIEventID_t     nEventType{0};           // Event ID symbol\n    std::uint16_t    nFlags{0};               // Handled mode flags\n};\n\n// ============================================================================\n// 4. Client Notification Interface (IUIPanelClient)\n// ============================================================================\nclass IUIPanelClient {\npublic:\n    virtual ~IUIPanelClient() = default;\n    virtual void OnPanelDeleted(IUIPanel* pPanel) = 0;\n    virtual void OnLayout(IUIPanel* pPanel) = 0;\n    virtual void OnPaint(IUIPanel* pPanel) = 0;\n    virtual bool OnEvent(IUIPanel* pPanel, const CUIEvent* pEvent) = 0;\n};\n\n// ============================================================================\n// 5. CSS Cascaded Style Subsystem (CPanelStyle)\n// ============================================================================\nclass CPanelStyle {\npublic:\n    virtual ~CPanelStyle() = default;\n    virtual void ApplyStyles() = 0;\n    virtual void MarkStylesDirty() = 0;\n    [[nodiscard]] virtual float GetOpacity() const noexcept = 0;\n    [[nodiscard]] virtual float GetZIndex() const noexcept = 0;\n    [[nodiscard]] virtual bool IsVisible() const noexcept = 0;\n    virtual void SetVisible(bool bVisible) = 0;\n    virtual void SetProperty(const char* pszProperty, const char* pszValue) = 0;\n\n    // Inlined at CUIPanel + 0x68 (VTable at 0x1804E4B70)\n    CUIPanel*        m_pPanel{nullptr};            // 0x08 (0x70 from panel base)\n    std::uint8_t     m_padCascadeData[0x58]{};     // 0x10..0x67\n    float            m_flOpacity{1.0f};            // 0x68\n    float            m_flZIndex{0.0f};             // 0x6C\n    std::uint8_t     m_padStyleProperties[0x58]{}; // 0x70..0xC7\n};\n\n// ============================================================================\n// 6. Abstract DOM Node Interface (IUIPanel)\n// Matches VTable layout at panorama.dll + 0x4CCFF8\n// Pure abstract interface: exactly 8 bytes (VTable pointer only)\n// ============================================================================\nclass IUIPanel {\npublic:\n    virtual ~IUIPanel() = default;                                                 // Slot 0\n    virtual void InitializeBase() = 0;                                             // Slot 1\n    virtual void Initialize(CUIWindow* pWindow, CUIPanel* pParent, const char* pszID) = 0; // Slot 2\n    virtual void InitializeFromDescription(void* pDesc) = 0;                       // Slot 3\n    virtual void UnusedSlot4() = 0;                                                // Slot 4\n    virtual void Shutdown() = 0;                                                   // Slot 5\n    virtual void UnusedSlot6() = 0;                                                // Slot 6\n    virtual void SetClient(IUIPanelClient* pClient) = 0;                           // Slot 7\n    [[nodiscard]] virtual IUIPanelClient* GetClient() const noexcept = 0;          // Slot 8\n    virtual void UnusedSlot9() = 0;                                                // Slot 9\n    [[nodiscard]] virtual const char* GetID() const noexcept = 0;                  // Slot 10\n    virtual void UnusedSlot11() = 0;                                               // Slot 11\n    virtual void UnusedSlot12() = 0;                                               // Slot 12\n    [[nodiscard]] virtual bool HasID() const noexcept = 0;                         // Slot 13\n    virtual void UnusedSlot14() = 0;                                               // Slot 14\n    virtual bool LoadLayoutFile(const char* pszFile) = 0;                          // Slot 15\n    virtual void SetParent(CUIPanel* pParent) = 0;                                 // Slot 16\n    [[nodiscard]] virtual CUIPanel* GetParent() const noexcept = 0;                // Slot 17\n    [[nodiscard]] virtual CUIWindow* GetWindow() const noexcept = 0;               // Slot 18\n    [[nodiscard]] virtual int GetChildCount() const noexcept = 0;                  // Slot 19\n    [[nodiscard]] virtual CUIPanel* GetChild(int nIndex) const noexcept = 0;       // Slot 20\n    [[nodiscard]] virtual CUIPanel* GetFirstChild() const noexcept = 0;            // Slot 21\n    [[nodiscard]] virtual CUIPanel* GetLastChild() const noexcept = 0;             // Slot 22\n    [[nodiscard]] virtual int FindChildIndex(const CUIPanel* pChild) const noexcept = 0; // Slot 23\n    [[nodiscard]] virtual bool BHasStyle() const noexcept = 0;                     // Slot 24\n    [[nodiscard]] virtual CPanelStyle* GetStyle() noexcept = 0;                    // Slot 25\n    [[nodiscard]] virtual float GetActualWidth() const noexcept = 0;               // Slot 26\n    [[nodiscard]] virtual float GetActualHeight() const noexcept = 0;              // Slot 27\n    [[nodiscard]] virtual float GetActualX() const noexcept = 0;                   // Slot 28\n    [[nodiscard]] virtual float GetActualY() const noexcept = 0;                   // Slot 29\n};\n\n// ============================================================================\n// 7. Concrete DOM Element Component (CUIPanel)\n// Reconstructed with byte-exact CS2 alignment (Size: 0x300 / 768 bytes)\n// ============================================================================\nclass alignas(8) CUIPanel : public IUIPanel {\npublic:\n    // Memory Layout (Verified via Ghidra analysis of FUN_1800E4F30 & FUN_1800F98C0)\n    IUIPanelClient*      m_pClient{nullptr};            // 0x08\n    const char*          m_pszID{nullptr};              // 0x10 (CUtlString id)\n    CUIPanel*            m_pParent{nullptr};            // 0x18\n    CUIWindow*           m_pWindow{nullptr};            // 0x20\n\n    // CUtlVector<CUIPanel*> m_vecChildren (0x28..0x3F)\n    std::int32_t         m_nChildCount{0};              // 0x28\n    std::int32_t         m_nPadChild{0};                // 0x2C\n    CUIPanel**           m_pChildren{nullptr};          // 0x30\n    std::int32_t         m_nChildAllocationCount{0};    // 0x38\n    std::int32_t         m_nChildGrowSize{0};           // 0x3C\n\n    std::uint8_t         m_padPanelData40_67[0x28]{};   // 0x40..0x67\n\n    // Inlined CPanelStyle subsystem (0x68..0x133)\n    std::uint8_t         m_Style[0xCC]{};               // 0x68..0x133\n\n    // Layout extents & constraint metrics (0x134..0x157)\n    std::uint8_t         m_padLayoutContent[0x24]{};    // 0x134..0x157\n\n    // CUtlVector<CStyleSymbol> m_vecClasses (0x158..0x16F)\n    std::int32_t         m_nClassCount{0};              // 0x158\n    std::int32_t         m_nClassPad{0};                // 0x15C\n    CStyleSymbol*        m_pClasses{nullptr};           // 0x160\n    std::int32_t         m_nClassAllocCount{0};         // 0x168\n    std::int32_t         m_nClassGrowSize{0};           // 0x16C\n\n    std::uint8_t         m_padRenderData170_1AF[0x40]{};// 0x170..0x1AF\n\n    // Computed Box Geometry (0x1B0..0x1CF)\n    float                m_flActualX{0.0f};             // 0x1B0\n    float                m_flActualY{0.0f};             // 0x1B4\n    float                m_flActualWidth{0.0f};         // 0x1B8\n    float                m_flActualHeight{0.0f};        // 0x1BC\n    float                m_flDesiredWidth{0.0f};        // 0x1C0\n    float                m_flDesiredHeight{0.0f};       // 0x1C4\n    std::uint8_t         m_padDesiredExtents[0x08]{};   // 0x1C8..0x1CF\n    float                m_flPositionX{0.0f};           // 0x1D0\n    float                m_flPositionY{0.0f};           // 0x1D4\n    std::uint8_t         m_padTransformData[0x18]{};    // 0x1D8..0x1EF\n    float                m_flContentWidth{0.0f};        // 0x1F0\n    float                m_flContentHeight{0.0f};       // 0x1F4\n    float                m_flScrollY{0.0f};             // 0x1F8\n    std::uint8_t         m_padScrollData[0x24]{};       // 0x1FC..0x21F\n\n    // Pseudo-Classes & Status Bitfields\n    EStyleFlags          m_nStyleFlags{EStyleFlags::None}; // 0x220\n    std::uint8_t         m_padFlagData[0x06]{};         // 0x222..0x227\n    EPanelLayoutFlags    m_nLayoutFlags{EPanelLayoutFlags::None}; // 0x228\n    std::uint8_t         m_bVisibilityFlags{0xE8};      // 0x22A (Default visible)\n    std::uint8_t         m_padPostFlags[0x0D]{};        // 0x22B..0x237\n\n    // Event Dispatch Table (0x238..0x24F)\n    std::int32_t         m_nEventHandlerCount{0};       // 0x238\n    std::int32_t         m_nEventHandlerPad{0};         // 0x23C\n    CUIEventHandler*     m_pEventHandlers{nullptr};     // 0x240\n    std::int32_t         m_nEventHandlerAlloc{0};       // 0x248\n    std::int32_t         m_nEventHandlerGrow{0};        // 0x24C\n\n    std::uint8_t         m_padTail300[0xB0]{};          // 0x250..0x2FF\n\npublic:\n    // IUIPanel Implementation Defaults\n    void InitializeBase() override {}\n    void Initialize(CUIWindow* pWindow, CUIPanel* pParent, const char* pszID) override {\n        m_pWindow = pWindow;\n        m_pParent = pParent;\n        m_pszID = pszID;\n    }\n    void InitializeFromDescription(void*) override {}\n    void UnusedSlot4() override {}\n    void Shutdown() override {}\n    void UnusedSlot6() override {}\n    void SetClient(IUIPanelClient* pClient) override { m_pClient = pClient; }\n    [[nodiscard]] IUIPanelClient* GetClient() const noexcept override { return m_pClient; }\n    void UnusedSlot9() override {}\n    [[nodiscard]] const char* GetID() const noexcept override { return m_pszID; }\n    void UnusedSlot11() override {}\n    void UnusedSlot12() override {}\n    [[nodiscard]] bool HasID() const noexcept override { return m_pszID != nullptr && m_pszID[0] != '\\0'; }\n    void UnusedSlot14() override {}\n    bool LoadLayoutFile(const char*) override { return false; }\n    void SetParent(CUIPanel* pParent) override { m_pParent = pParent; }\n    [[nodiscard]] CUIPanel* GetParent() const noexcept override { return m_pParent; }\n    [[nodiscard]] CUIWindow* GetWindow() const noexcept override { return m_pWindow; }\n    [[nodiscard]] int GetChildCount() const noexcept override { return m_nChildCount; }\n    [[nodiscard]] CUIPanel* GetChild(int nIndex) const noexcept override {\n        if (nIndex < 0 || nIndex >= m_nChildCount || !m_pChildren) return nullptr;\n        return m_pChildren[nIndex];\n    }\n    [[nodiscard]] CUIPanel* GetFirstChild() const noexcept override {\n        if (m_nChildCount <= 0 || !m_pChildren) return nullptr;\n        return m_pChildren[0];\n    }\n    [[nodiscard]] CUIPanel* GetLastChild() const noexcept override {\n        if (m_nChildCount <= 0 || !m_pChildren) return nullptr;\n        return m_pChildren[m_nChildCount - 1];\n    }\n    [[nodiscard]] int FindChildIndex(const CUIPanel* pChild) const noexcept override {\n        if (!pChild || !m_pChildren) return -1;\n        for (int i = 0; i < m_nChildCount; ++i) {\n            if (m_pChildren[i] == pChild) return i;\n        }\n        return -1;\n    }\n    [[nodiscard]] bool BHasStyle() const noexcept override { return (m_bVisibilityFlags & 0x01) != 0; }\n    [[nodiscard]] CPanelStyle* GetStyle() noexcept override {\n        return reinterpret_cast<CPanelStyle*>(m_Style);\n    }\n    [[nodiscard]] float GetActualWidth() const noexcept override { return m_flActualWidth; }\n    [[nodiscard]] float GetActualHeight() const noexcept override { return m_flActualHeight; }\n    [[nodiscard]] float GetActualX() const noexcept override { return m_flActualX; }\n    [[nodiscard]] float GetActualY() const noexcept override { return m_flActualY; }\n\n    // Helper DOM Node Traversal API\n    [[nodiscard]] inline CUIPanel* GetNextSibling() const noexcept {\n        if (!m_pParent) return nullptr;\n        const int nIndex = m_pParent->FindChildIndex(this);\n        if (nIndex < 0 || (nIndex + 1) >= m_pParent->m_nChildCount) return nullptr;\n        return m_pParent->m_pChildren[nIndex + 1];\n    }\n\n    [[nodiscard]] inline CUIPanel* GetPrevSibling() const noexcept {\n        if (!m_pParent) return nullptr;\n        const int nIndex = m_pParent->FindChildIndex(this);\n        if (nIndex <= 0) return nullptr;\n        return m_pParent->m_pChildren[nIndex - 1];\n    }\n\n    [[nodiscard]] inline UIRect_t GetBounds() const noexcept {\n        return {m_flActualX, m_flActualY, m_flActualWidth, m_flActualHeight};\n    }\n\n    [[nodiscard]] inline bool IsVisible() const noexcept {\n        return (m_bVisibilityFlags & 0x01) != 0 &&\n               (static_cast<std::uint16_t>(m_nLayoutFlags) & static_cast<std::uint16_t>(EPanelLayoutFlags::Visible)) != 0;\n    }\n\n    [[nodiscard]] inline bool HasClass(CStyleSymbol symClass) const noexcept {\n        if (!m_pClasses) return false;\n        for (std::int32_t i = 0; i < m_nClassCount; ++i) {\n            if (m_pClasses[i] == symClass) return true;\n        }\n        return false;\n    }\n};\n\n// Strict static verification against CS2 native panorama.dll memory layout\nstatic_assert(sizeof(CUIPanel) == 0x300, \"CUIPanel size must match CS2 native 0x300 layout\");\nstatic_assert(offsetof(CUIPanel, m_pClient) == 0x08, \"m_pClient offset mismatch\");\nstatic_assert(offsetof(CUIPanel, m_pszID) == 0x10, \"m_pszID offset mismatch\");\nstatic_assert(offsetof(CUIPanel, m_pParent) == 0x18, \"m_pParent offset mismatch\");\nstatic_assert(offsetof(CUIPanel, m_pWindow) == 0x20, \"m_pWindow offset mismatch\");\nstatic_assert(offsetof(CUIPanel, m_nChildCount) == 0x28, \"m_nChildCount offset mismatch\");\nstatic_assert(offsetof(CUIPanel, m_pChildren) == 0x30, \"m_pChildren offset mismatch\");\nstatic_assert(offsetof(CUIPanel, m_Style) == 0x68, \"m_Style offset mismatch\");\nstatic_assert(offsetof(CUIPanel, m_nClassCount) == 0x158, \"m_nClassCount offset mismatch\");\nstatic_assert(offsetof(CUIPanel, m_pClasses) == 0x160, \"m_pClasses offset mismatch\");\nstatic_assert(offsetof(CUIPanel, m_flActualX) == 0x1B0, \"m_flActualX offset mismatch\");\nstatic_assert(offsetof(CUIPanel, m_flActualY) == 0x1B4, \"m_flActualY offset mismatch\");\nstatic_assert(offsetof(CUIPanel, m_flActualWidth) == 0x1B8, \"m_flActualWidth offset mismatch\");\nstatic_assert(offsetof(CUIPanel, m_flActualHeight) == 0x1BC, \"m_flActualHeight offset mismatch\");\nstatic_assert(offsetof(CUIPanel, m_nStyleFlags) == 0x220, \"m_nStyleFlags offset mismatch\");\nstatic_assert(offsetof(CUIPanel, m_nLayoutFlags) == 0x228, \"m_nLayoutFlags offset mismatch\");\nstatic_assert(offsetof(CUIPanel, m_bVisibilityFlags) == 0x22A, \"m_bVisibilityFlags offset mismatch\");\nstatic_assert(offsetof(CUIPanel, m_nEventHandlerCount) == 0x238, \"m_nEventHandlerCount offset mismatch\");\n\n// ============================================================================\n// 8. Core Panorama UI Engine Interface (IUIEngine)\n// Matches VTable layout at panorama.dll + 0x4C9010 (149 methods)\n// ============================================================================\nclass IUIEngine {\npublic:\n    virtual ~IUIEngine() = default;                                                // Slot 0\n    virtual CUIPanel* CreatePanel(const char* pszType, const char* pszID, CUIPanel* pParent) = 0; // Slot 1\n    virtual void RegisterEventHandler(CUIEventID_t nEvent, CUIPanel* pTarget, void* pHandler) = 0; // Slot 2\n    virtual void UnregisterEventHandler(CUIEventID_t nEvent, CUIPanel* pTarget, void* pHandler) = 0; // Slot 3\n    virtual void RegisterForUnhandledEvent(CUIEventID_t nEvent, void* pHandler) = 0; // Slot 4\n    virtual void UnregisterForUnhandledEvent(CUIEventID_t nEvent, void* pHandler) = 0; // Slot 5\n    virtual void DispatchEvent(CUIEvent* pEvent) = 0;                              // Slot 6\n    virtual void LayoutAndPaintWindows() = 0;                                      // Slot 7\n\n    // JavaScript / V8 Context Bridge Interface (Slots 8..11)\n    virtual void* CompileScript(const char* pszContext, const char* pszScript, const char* pszFilename, int nLine) = 0; // Slot 8\n    virtual bool RunScript(CUIPanel* pPanel, const char* pszScript, const char* pszFilename) = 0;                      // Slot 9\n    virtual void* GetContextForPanel(CUIPanel* pPanel) = 0;                        // Slot 10\n    [[nodiscard]] virtual void* GetIsolate() const noexcept = 0;                   // Slot 11\n};\n\n} // namespace cs2::panorama\n\n// SDK namespace unification\nnamespace cs2::sdk {\n    using namespace cs2::panorama;\n}\n",
        "render_scene_material.hpp": "#pragma once\n\n#include <cstdint>\n#include <cstddef>\n#include <cmath>\n#include <type_traits>\n#include \"interfaces_registry.hpp\"\n#include \"entity_system.hpp\"\n#include \"client_classes.hpp\"\n\n// ============================================================================\n// Source 2 Reconstructed SDK - Phase 2: Camera, Models, Rendering & Materials\n// Target Build: 2026-10-25_26144732 (CS2 Update Archive)\n// Architecture: x86-64 (MSVC ABI)\n// ============================================================================\n\nnamespace cs2::sdk {\n\n#define PAD(bytes, name) private: [[maybe_unused]] std::uint8_t name[bytes]; public:\n\n// ============================================================================\n// 1. 4x4 View-Projection Matrix (VMatrix) & Camera Pipeline\n// Discovered in client.dll:\n// - Global Matrix Array: client.dll + 0x256cfe0 (VA: 0x18256cfe0)\n// - Engine Accessor:     client.dll + 0xc14fb0 (GetViewMatrix(int nViewIndex))\n// Assembly anchor:\n//   movsxd rax, ecx\n//   lea rcx, [rip + 0x1958026] ; 0x18256cfe0\n//   shl rax, 6                 ; 64 bytes (sizeof(VMatrix))\n//   add rax, rcx\n//   ret\n// ============================================================================\nstruct VMatrix {\n    float m[4][4];\n\n    constexpr const float* operator[](int index) const noexcept { return m[index]; }\n    constexpr float* operator[](int index) noexcept { return m[index]; }\n\n    // World to Screen transformation equation with frustum rejection\n    bool WorldToScreen(const Vector3& world, float& screenX, float& screenY,\n                       int screenWidth, int screenHeight) const noexcept {\n        const float w = m[3][0] * world.x + m[3][1] * world.y + m[3][2] * world.z + m[3][3];\n\n        // Homogeneous frustum rejection (behind camera near-clipping plane)\n        if (w < 0.001f) {\n            return false;\n        }\n\n        const float invW = 1.0f / w;\n        const float x = (m[0][0] * world.x + m[0][1] * world.y + m[0][2] * world.z + m[0][3]) * invW;\n        const float y = (m[1][0] * world.x + m[1][1] * world.y + m[1][2] * world.z + m[1][3]) * invW;\n\n        // Viewport pixel coordinate mapping\n        screenX = (screenWidth * 0.5f) + (0.5f * x * static_cast<float>(screenWidth) + 0.5f);\n        screenY = (screenHeight * 0.5f) - (0.5f * y * static_cast<float>(screenHeight) + 0.5f);\n        return true;\n    }\n};\nstatic_assert(sizeof(VMatrix) == 0x40, \"VMatrix size must be exactly 64 bytes\");\n\n// ============================================================================\n// 2. CViewRender Layout\n// Binary: client.dll\n// VTable RVA: client.dll + 0x1c7f128 (VA: 0x181c7f128)\n// Allocation Size: 0x1D60 bytes (7,520 bytes, verified at client.dll + 0xc05d0f)\n// ============================================================================\nclass CViewRender {\npublic:\n    virtual ~CViewRender() = default;\n\n    PAD(0x1328, m_pad08);\n    // Viewport rendering context\n    std::uint8_t m_bRenderingView;     // +0x1330\n    PAD(0x00F, m_pad1331);\n    VMatrix      m_viewMatrix;         // +0x1340\n    PAD(0x09E0, m_pad1380);\n    void*        m_pRenderContext;     // +0x1D60\n};\n\n// ============================================================================\n// 3. Studio Hitbox Sets & Hitbox Geometry\n// Target Binary: vphysics2.dll / client.dll\n// Schema Descriptors: CHitBox (size 0x70), CHitBoxSet (size 0x30), CHitBoxSetList (size 0x18)\n// ============================================================================\nenum EHitBoxGroup : std::uint32_t {\n    HITGROUP_GENERIC   = 0,\n    HITGROUP_HEAD      = 1,\n    HITGROUP_CHEST     = 2,\n    HITGROUP_STOMACH   = 3,\n    HITGROUP_LEFTARM   = 4,\n    HITGROUP_RIGHTARM  = 5,\n    HITGROUP_LEFTLEG   = 6,\n    HITGROUP_RIGHTLEG  = 7,\n    HITGROUP_NECK      = 8,\n    HITGROUP_UNUSED    = 9,\n    HITGROUP_GEAR      = 10\n};\n\nstruct CHitBox {\n    const char*       m_pszName;            // +0x00: Target bone / hitbox name\n    const char*       m_pszSurfaceProperty; // +0x08: Surface property token (flesh, metal)\n    const char*       m_pszBoneName;        // +0x10: Target skeletal bone string\n    Vector3           m_vMinBounds;         // +0x18: Minimum bounding box coordinate\n    Vector3           m_vMaxBounds;         // +0x24: Maximum bounding box coordinate\n    float             m_flShapeRadius;      // +0x30: Capsule pill radius\n    std::uint32_t     m_nBoneNameHash;      // +0x34: MurmurHash2 bone token\n    std::uint32_t     m_nGroupId;           // +0x38: EHitBoxGroup classification\n    std::uint8_t      m_nShapeType;         // +0x3C: 0 = Box, 1 = Capsule\n    bool              m_bTranslationOnly;   // +0x3D\n    PAD(0x2, m_pad3E);\n    std::uint32_t     m_CRC;                // +0x40\n    std::uint32_t     m_cRenderColor;       // +0x44: Debug render color\n    std::int32_t      m_nHitBoxIndex;       // +0x48: Zero-based hitbox array index\n    PAD(0x24, m_pad4C);                     // +0x4C: Alignment to 0x70\n};\nstatic_assert(sizeof(CHitBox) == 0x70, \"CHitBox must be exactly 0x70 (112) bytes\");\nstatic_assert(offsetof(CHitBox, m_vMinBounds) == 0x18, \"CHitBox m_vMinBounds offset mismatch\");\nstatic_assert(offsetof(CHitBox, m_vMaxBounds) == 0x24, \"CHitBox m_vMaxBounds offset mismatch\");\nstatic_assert(offsetof(CHitBox, m_flShapeRadius) == 0x30, \"CHitBox m_flShapeRadius offset mismatch\");\nstatic_assert(offsetof(CHitBox, m_nGroupId) == 0x38, \"CHitBox m_nGroupId offset mismatch\");\n\nstruct CHitBoxSet {\n    const char*            m_pszName;       // +0x00: Set identifier (\"default\")\n    std::uint32_t          m_nNameHash;     // +0x08: Set name hash\n    PAD(0x4, m_pad0C);                      // +0x0C\n    PAD(0x18, m_HitBoxes);                  // +0x10: Dynamic vector of studio hitboxes (24 bytes)\n    const char*            m_pszSourceFile; // +0x28: Source model asset file path\n};\nstatic_assert(sizeof(CHitBoxSet) == 0x30, \"CHitBoxSet must be exactly 0x30 (48) bytes\");\nstatic_assert(offsetof(CHitBoxSet, m_pszSourceFile) == 0x28, \"CHitBoxSet m_pszSourceFile offset mismatch\");\n\nstruct CHitBoxSetList {\n    PAD(0x18, m_HitBoxSets);                // +0x00: List of hitbox sets (24 bytes)\n};\nstatic_assert(sizeof(CHitBoxSetList) == 0x18, \"CHitBoxSetList must be exactly 0x18 (24) bytes\");\n\n// ============================================================================\n// 4. Material System 2 & CMaterial2\n// Target Binary: materialsystem2.dll\n// VTable RVA: materialsystem2.dll + 0x129ae0 (CMaterial2, 25 methods)\n// VTable RVA: materialsystem2.dll + 0x12d920 (VMaterialSystem2_001, 57 methods)\n// Singleton:  materialsystem2.dll + 0x163530\n// ============================================================================\nclass CMaterial2 {\npublic:\n    virtual ~CMaterial2() = default;\n\n    // Slot 0: materialsystem2.dll + 0xb350\n    virtual const char* GetName() const = 0;\n\n    // Slot 1: materialsystem2.dll + 0xb370\n    virtual void GetPath(void* pBufferString) const = 0;\n\n    // Slot 2: materialsystem2.dll + 0xb5e0\n    virtual const char* GetShaderName() const = 0;\n\n    virtual void Unk03() = 0;\n\n    // Slot 4: materialsystem2.dll + 0xa100\n    virtual std::uint8_t GetFlags() const = 0;\n\n    virtual void Unk05() = 0;\n    virtual void Unk06() = 0;\n\n    // Slot 7: materialsystem2.dll + 0xba60\n    virtual void* GetMaterialData() const = 0;\n\n    virtual void Unk08() = 0; virtual void Unk09() = 0; virtual void Unk10() = 0;\n    virtual void Unk11() = 0; virtual void Unk12() = 0; virtual void Unk13() = 0;\n    virtual void Unk14() = 0; virtual void Unk15() = 0; virtual void Unk16() = 0;\n    virtual void Unk17() = 0; virtual void Unk18() = 0; virtual void Unk19() = 0;\n    virtual void Unk20() = 0; virtual void Unk21() = 0; virtual void Unk22() = 0;\n    virtual void Unk23() = 0; virtual void Unk24() = 0;\n\n    // Slot 25: materialsystem2.dll + 0xb880\n    virtual std::int32_t GetMaterialId() const = 0;\n\n    // Slot 26: materialsystem2.dll + 0x1b2d0\n    virtual void* GetShaderBinding() = 0;\n\n    virtual void Unk27() = 0; virtual void Unk28() = 0;\n\n    // Slot 29: materialsystem2.dll + 0xb890\n    virtual void IncrementRefCount() = 0;\n};\nstatic_assert(sizeof(CMaterial2) == 0x08, \"CMaterial2 pointer must be 8 bytes\");\n\n// ============================================================================\n// 5. Scene System & Animatable Object Draw Dispatch\n// Target Binary: scenesystem.dll\n// VTable RVA: scenesystem.dll + 0x5e5e50 (CSceneAnimatableObject, 3 methods)\n// VTable RVA: scenesystem.dll + 0x5e4748 (CSceneObject, 2 methods)\n// VTable RVA: scenesystem.dll + 0x5e5c90 (CAnimatableSceneObjectDesc)\n// ============================================================================\nclass CSceneObject {\npublic:\n    virtual ~CSceneObject() = default;\n\n    PAD(0x18, m_pad08);\n    void* m_pOwner; // +0x20\n};\n\nclass CSceneAnimatableObject : public CSceneObject {\npublic:\n    virtual ~CSceneAnimatableObject() override = default;\n\n    // Slot 1: scenesystem.dll + 0x36dc0 (Draws animatable mesh primitives)\n    virtual void Draw(void* pRenderContext, void* pDrawContext) = 0;\n};\n\n// Scene mesh drawing callback signature for material override / chams\n// scenesystem.dll + 0x055a90 (Slot 19 in CAnimatableSceneObjectDesc)\nusing FnDrawAnimatableSceneObjects = void (*)(\n    void*                   pDesc,              // CAnimatableSceneObjectDesc*\n    std::uint8_t            nDrawMode,          // 0=Depth, 1=Forward, 2=Shadow\n    void*                   pRenderContext,     // Command stream\n    void*                   pSceneView,         // Camera / View frustum state\n    void*                   pSceneLayer,        // Target render layer\n    void*                   pDrawCalls,         // Array of queued draw calls\n    std::uint32_t           nCount,             // Number of queued draw calls\n    CMaterial2*             pMaterialOverride   // Material override pointer\n);\n\n#undef PAD\n\n} // namespace cs2::sdk\n",
        "schema_system.hpp": "#pragma once\n\n#include <cstdint>\n#include <cstddef>\n#include <string_view>\n#include <type_traits>\n\n// ============================================================================\n// Source 2 Reverse Engineered SDK - Runtime SchemaSystem Reflection Subsystem\n// Target Binary: schemasystem.dll (Build: 2026-10-25_26144732)\n// Architecture: x86-64 (MSVC ABI)\n// Reconstructed & Authoritatively Verified via Static RTTI & VTable Analysis\n// Provenance:\n//   CSchemaSystem VTable:          schemasystem.dll + 0x58598 (40 bounded methods / 222 contiguous block)\n//   FindTypeScopeForModule (str):  schemasystem.dll + 0x11350 (Slot 13)\n//   FindTypeScopeForModule (hash): schemasystem.dll + 0x11510 (Slot 14)\n//   CSchemaSystemTypeScope VTable: schemasystem.dll + 0x586F0 (35 bounded methods / 179 contiguous block)\n//   FindDeclaredClass (binding):   schemasystem.dll + 0x162B0 (Slot 2)\n//   FindDeclaredClass (hash):      schemasystem.dll + 0x10460 (Slot 24)\n//   FindDeclaredClass (str):       schemasystem.dll + 0x10380 (Slot 25)\n//   FindDeclaredEnum (binding):    schemasystem.dll + 0x162F0 (Slot 3)\n//   FindDeclaredEnum (hash):       schemasystem.dll + 0x105A0 (Slot 26)\n//   FindDeclaredEnum (str):        schemasystem.dll + 0x104C0 (Slot 27)\n//   CSchemaType VTable:            schemasystem.dll + 0x58930 (17 methods)\n// ============================================================================\n\nnamespace cs2::sdk {\n\n#ifndef PAD\n#define PAD(bytes, name) private: [[maybe_unused]] std::uint8_t name[bytes]; public:\n#endif\n\n// Forward declarations\nclass CSchemaType;\nclass CSchemaClassInfo;\nclass CSchemaEnumInfo;\nclass CSchemaSystemTypeScope;\nclass ISchemaSystem;\n\n// ============================================================================\n// Schema Type Category Enums\n// Extracted from CSchemaType RTTI hierarchy in schemasystem.dll\n// ============================================================================\nenum class ESchemaTypeCategory : std::uint8_t {\n    Builtin          = 0,\n    Ptr              = 1,\n    FixedArray       = 2,\n    Atomic           = 3,\n    DeclaredClass    = 4,\n    DeclaredEnum     = 5,\n    Bitfield         = 6\n};\n\nenum class ESchemaAtomicCategory : std::uint8_t {\n    Basic            = 0,\n    T                = 1,\n    CollectionOfT    = 2,\n    TT               = 3,\n    I                = 4\n};\n\n// ============================================================================\n// CSchemaType\n// VTable RVA: schemasystem.dll + 0x58930 (17 methods)\n// RTTI: .?AVCSchemaType@@\n// Represents runtime type descriptor for class fields, return types, etc.\n// ============================================================================\nclass CSchemaType {\npublic:\n    virtual ~CSchemaType() = default;                                                            // Slot 0: 0xcdb0\n    virtual void GetTypeName(char* pOutBuf, std::size_t nBufSize) const = 0;                     // Slot 1: 0x2b8f0\n    virtual std::size_t GetSize() const = 0;                                                     // Slot 2: 0x2c5b0\n    virtual std::size_t GetAlignment() const = 0;                                                // Slot 3: 0x3a2ac\n\npublic:\n    const char*             m_pszName;          // +0x08: Null-terminated type name string (e.g., \"int32\", \"C_BaseEntity*\")\n    CSchemaSystemTypeScope* m_pTypeScope;       // +0x10: Owning type scope\n    ESchemaTypeCategory     m_nTypeCategory;    // +0x18: Schema type category enum\n    ESchemaAtomicCategory   m_nAtomicCategory;  // +0x19: Atomic subcategory enum\n    PAD(0x6, _pad1A);                           // +0x1A: Alignment padding to 0x20 bytes\n};\nstatic_assert(sizeof(CSchemaType) == 0x20, \"CSchemaType size mismatch\");\nstatic_assert(offsetof(CSchemaType, m_pszName) == 0x08, \"CSchemaType::m_pszName offset mismatch\");\nstatic_assert(offsetof(CSchemaType, m_pTypeScope) == 0x10, \"CSchemaType::m_pTypeScope offset mismatch\");\nstatic_assert(offsetof(CSchemaType, m_nTypeCategory) == 0x18, \"CSchemaType::m_nTypeCategory offset mismatch\");\nstatic_assert(offsetof(CSchemaType, m_nAtomicCategory) == 0x19, \"CSchemaType::m_nAtomicCategory offset mismatch\");\n\n// ============================================================================\n// CSchemaType_DeclaredClass\n// RTTI: .?AVCSchemaType_DeclaredClass@@\n// Type descriptor representing an engine class declaration reference.\n// Verified in schemasystem.dll @ 0x18002C4C0 (m_pClassInfo stored at +0x20).\n// ============================================================================\nclass CSchemaType_DeclaredClass : public CSchemaType {\npublic:\n    CSchemaClassInfo* m_pClassInfo; // +0x20: Pointer to resolved CSchemaClassInfo\n};\nstatic_assert(sizeof(CSchemaType_DeclaredClass) == 0x28, \"CSchemaType_DeclaredClass size mismatch\");\nstatic_assert(offsetof(CSchemaType_DeclaredClass, m_pClassInfo) == 0x20, \"CSchemaType_DeclaredClass::m_pClassInfo offset mismatch\");\n\n// ============================================================================\n// SchemaMetadataEntry_t (SchemaMetadataEntryData_t)\n// Layout verified in schemasystem.dll @ 0x180029C8E (stride 0x10 bytes)\n// and 0x18000C5E0-0x18000C5EC (iteration loop over metadata).\n//   +0x00: m_pszName (ASCII identifier, e.g., \"MNetworkEnable\", \"MNetworkChangeAccessorField\")\n//   +0x08: m_pValue   (Pointer to metadata network descriptor / value / type)\n// ============================================================================\nstruct SchemaMetadataEntry_t {\n    const char* m_pszName; // +0x00: Null-terminated metadata token\n    void*       m_pValue;  // +0x08: Value pointer or type descriptor\n};\nusing SchemaMetadataEntryData_t = SchemaMetadataEntry_t;\nstatic_assert(sizeof(SchemaMetadataEntry_t) == 0x10, \"SchemaMetadataEntry_t size must be 0x10 bytes\");\nstatic_assert(offsetof(SchemaMetadataEntry_t, m_pszName) == 0x00, \"SchemaMetadataEntry_t::m_pszName offset mismatch\");\nstatic_assert(offsetof(SchemaMetadataEntry_t, m_pValue)   == 0x08, \"SchemaMetadataEntry_t::m_pValue offset mismatch\");\n\n// ============================================================================\n// SchemaClassFieldData_t\n// Layout verified in schemasystem.dll:\n//   - Field iteration & stride (0x20 bytes): schemasystem.dll + 0x180029C96\n//   - Offset comparison & usage:             schemasystem.dll + 0x18000F1C6\n//   - Metadata array dereference:            schemasystem.dll + 0x180029C77\n//\n// Field Members:\n//   m_pszName                   : +0x00 (ASCII field name string, e.g., \"m_iHealth\")\n//   m_pType                     : +0x08 (Descriptor pointer to CSchemaType)\n//   m_nSingleInheritanceOffset  : +0x10 (Byte offset within class instance memory)\n//   m_nMetadataSize             : +0x14 (Count of metadata elements bound to field)\n//   m_pMetadata                 : +0x18 (Pointer to SchemaMetadataEntry_t array)\n// ============================================================================\nstruct SchemaClassFieldData_t {\n    const char*            m_pszName;                  // +0x00: Field identifier string\n    CSchemaType*           m_pType;                    // +0x08: Runtime field type descriptor\n    std::int32_t           m_nSingleInheritanceOffset; // +0x10: Relative byte offset within entity class\n    std::int32_t           m_nMetadataSize;            // +0x14: Metadata entry count\n    SchemaMetadataEntry_t* m_pMetadata;                // +0x18: Array of field metadata attributes\n};\nstatic_assert(sizeof(SchemaClassFieldData_t) == 0x20, \"SchemaClassFieldData_t size must be 0x20 bytes\");\nstatic_assert(offsetof(SchemaClassFieldData_t, m_pszName)                  == 0x00, \"SchemaClassFieldData_t::m_pszName offset mismatch\");\nstatic_assert(offsetof(SchemaClassFieldData_t, m_pType)                     == 0x08, \"SchemaClassFieldData_t::m_pType offset mismatch\");\nstatic_assert(offsetof(SchemaClassFieldData_t, m_nSingleInheritanceOffset)  == 0x10, \"SchemaClassFieldData_t::m_nSingleInheritanceOffset offset mismatch\");\nstatic_assert(offsetof(SchemaClassFieldData_t, m_nMetadataSize)             == 0x14, \"SchemaClassFieldData_t::m_nMetadataSize offset mismatch\");\nstatic_assert(offsetof(SchemaClassFieldData_t, m_pMetadata)                 == 0x18, \"SchemaClassFieldData_t::m_pMetadata offset mismatch\");\n\n// ============================================================================\n// SchemaBaseClassInfoData_t\n// Layout verified in schemasystem.dll @ 0x18000FFD0-0x18000FFDE (stride 0x10)\n//   +0x00: m_nOffset (Offset of the base class within the derived class)\n//   +0x08: m_pClass  (Resolved pointer to base CSchemaClassInfo)\n// ============================================================================\nstruct SchemaBaseClassInfoData_t {\n    std::uint32_t     m_nOffset; // +0x00: Base class sub-object byte offset\n    PAD(0x4, _pad04);            // +0x04: Alignment padding\n    CSchemaClassInfo* m_pClass;  // +0x08: Target base class descriptor\n};\nstatic_assert(sizeof(SchemaBaseClassInfoData_t) == 0x10, \"SchemaBaseClassInfoData_t size must be 0x10 bytes\");\nstatic_assert(offsetof(SchemaBaseClassInfoData_t, m_nOffset) == 0x00, \"SchemaBaseClassInfoData_t::m_nOffset offset mismatch\");\nstatic_assert(offsetof(SchemaBaseClassInfoData_t, m_pClass)  == 0x08, \"SchemaBaseClassInfoData_t::m_pClass offset mismatch\");\n\n// ============================================================================\n// SchemaStaticFieldData_t\n// Static field definition inside a schema class descriptor.\n// Verified in schemasystem.dll @ 0x180029C37 (m_pStaticFields array at +0x48).\n// ============================================================================\nstruct SchemaStaticFieldData_t {\n    const char*  m_pszName;  // +0x00: Static field identifier\n    CSchemaType* m_pType;    // +0x08: Type descriptor\n    void*        m_pInstance;// +0x10: Memory location of static member\n    PAD(0x8, _pad18);        // +0x18: Padding to 0x20 bytes\n};\nstatic_assert(sizeof(SchemaStaticFieldData_t) == 0x20, \"SchemaStaticFieldData_t size must be 0x20 bytes\");\n\n// ============================================================================\n// CSchemaClassInfo (SchemaClassInfoData_t)\n// Layout verified in schemasystem.dll (Build: 2026-10-25_26144732):\n//   - Logging inspection:    schemasystem.dll @ 0x18000B3D8-0x18000B3E3:\n//                            \"Class: %7d bytes, %4d fields, %4d nonderived fields\"\n//                            m_nSize read from [rbx+0x20], m_nFieldCount from [rbx+0x24]\n//   - Field count & array:   schemasystem.dll @ 0x180029C60 (field count at +0x24, fields array at +0x30)\n//   - Base class traversal:  schemasystem.dll @ 0x18000FFC2 (+0x29 count, +0x38 array)\n//   - MurmurHash2 token:     schemasystem.dll @ 0x180029FD4 (64-bit token stored at +0x18)\n//   - Static fields array:   schemasystem.dll @ 0x180029C37 (static fields at +0x48, count at +0x26)\n// ============================================================================\nclass CSchemaClassInfo {\npublic:\n    CSchemaClassInfo*          m_pSelf;            // +0x00: Registration node / self-pointer\n    const char*                m_pszName;          // +0x08: Null-terminated class identifier (e.g. \"C_CSPlayerPawn\")\n    const char*                m_pszModuleName;    // +0x10: Owning module token (e.g. \"client.dll\")\n    union {\n        std::uint64_t          m_nClassHash;       // +0x18: MurmurHash2 token calculated @ 0x180029FC5\n        void*                  m_pTypeScope;       // +0x18: Pointer to owning CSchemaSystemTypeScope\n    };\n    std::int32_t               m_nSize;            // +0x20: Instance byte size (Verified schemasystem.dll @ 0x18000B3E3)\n    std::int16_t               m_nFieldCount;      // +0x24: Declared field count (Verified schemasystem.dll @ 0x18000B3D8, 0x180029C60)\n    std::int16_t               m_nStaticCount;     // +0x26: Static field count (Verified schemasystem.dll @ 0x180029CB9)\n    std::uint8_t               m_nMetadataCount;   // +0x28: Metadata entry count (Verified schemasystem.dll @ 0x18000BC70, 0x18002A2AF)\n    std::uint8_t               m_nBaseClassCount;  // +0x29: Base classes count (Verified schemasystem.dll @ 0x18000FFC2, 0x180029CA3)\n    PAD(0x6, _pad2A);                              // +0x2A: Alignment padding to 0x30 boundary\n    SchemaClassFieldData_t*    m_pFields;          // +0x30: Array of declared fields (Verified schemasystem.dll @ 0x180029C73)\n    SchemaBaseClassInfoData_t* m_pBaseClasses;     // +0x38: Array of base class descriptors (Verified schemasystem.dll @ 0x18000FFDA)\n    PAD(0x8, _pad40);                              // +0x40: Internal reservation\n    SchemaStaticFieldData_t*   m_pStaticFields;    // +0x48: Array of static fields (Verified schemasystem.dll @ 0x180029C37)\n    PAD(0x10, _pad50);                             // +0x50: Internal reservation\n    std::uint32_t              m_nFlags;           // +0x60: Schema class flags (SCHEMA_CF1_*)\n    PAD(0x4, _pad64);                              // +0x64: Tail padding to 0x68 bytes\n\npublic:\n    [[nodiscard]] const char* GetName() const noexcept { return m_pszName; }\n    [[nodiscard]] const char* GetModuleName() const noexcept { return m_pszModuleName; }\n    [[nodiscard]] std::int32_t GetSize() const noexcept { return m_nSize; }\n    [[nodiscard]] std::int16_t GetFieldCount() const noexcept { return m_nFieldCount; }\n    [[nodiscard]] SchemaClassFieldData_t* GetFields() const noexcept { return m_pFields; }\n\n    [[nodiscard]] const SchemaClassFieldData_t* FindField(std::string_view fieldName) const noexcept {\n        if (!m_pFields || m_nFieldCount <= 0) return nullptr;\n        for (std::int16_t i = 0; i < m_nFieldCount; ++i) {\n            if (m_pFields[i].m_pszName && fieldName == m_pFields[i].m_pszName) {\n                return &m_pFields[i];\n            }\n        }\n        return nullptr;\n    }\n\n    [[nodiscard]] std::int32_t FindFieldOffset(std::string_view fieldName) const noexcept {\n        const auto* pField = FindField(fieldName);\n        return pField ? pField->m_nSingleInheritanceOffset : -1;\n    }\n};\nusing SchemaClassInfoData_t = CSchemaClassInfo;\n\nstatic_assert(sizeof(CSchemaClassInfo) == 0x68, \"CSchemaClassInfo size must be 0x68 bytes\");\nstatic_assert(offsetof(CSchemaClassInfo, m_pSelf)           == 0x00, \"CSchemaClassInfo::m_pSelf offset mismatch\");\nstatic_assert(offsetof(CSchemaClassInfo, m_pszName)         == 0x08, \"CSchemaClassInfo::m_pszName offset mismatch\");\nstatic_assert(offsetof(CSchemaClassInfo, m_pszModuleName)   == 0x10, \"CSchemaClassInfo::m_pszModuleName offset mismatch\");\nstatic_assert(offsetof(CSchemaClassInfo, m_nClassHash)      == 0x18, \"CSchemaClassInfo::m_nClassHash offset mismatch\");\nstatic_assert(offsetof(CSchemaClassInfo, m_nSize)           == 0x20, \"CSchemaClassInfo::m_nSize offset mismatch\");\nstatic_assert(offsetof(CSchemaClassInfo, m_nFieldCount)     == 0x24, \"CSchemaClassInfo::m_nFieldCount offset mismatch\");\nstatic_assert(offsetof(CSchemaClassInfo, m_nStaticCount)    == 0x26, \"CSchemaClassInfo::m_nStaticCount offset mismatch\");\nstatic_assert(offsetof(CSchemaClassInfo, m_nMetadataCount)  == 0x28, \"CSchemaClassInfo::m_nMetadataCount offset mismatch\");\nstatic_assert(offsetof(CSchemaClassInfo, m_nBaseClassCount) == 0x29, \"CSchemaClassInfo::m_nBaseClassCount offset mismatch\");\nstatic_assert(offsetof(CSchemaClassInfo, m_pFields)         == 0x30, \"CSchemaClassInfo::m_pFields offset mismatch\");\nstatic_assert(offsetof(CSchemaClassInfo, m_pBaseClasses)    == 0x38, \"CSchemaClassInfo::m_pBaseClasses offset mismatch\");\nstatic_assert(offsetof(CSchemaClassInfo, m_pStaticFields)   == 0x48, \"CSchemaClassInfo::m_pStaticFields offset mismatch\");\nstatic_assert(offsetof(CSchemaClassInfo, m_nFlags)          == 0x60, \"CSchemaClassInfo::m_nFlags offset mismatch\");\n\n// ============================================================================\n// CSchemaClassBinding\n// Wrapper structure returned by CSchemaSystemTypeScope::FindDeclaredClass (Slot 2)\n// Disassembly: schemasystem.dll @ 0x1800162B0\n// ============================================================================\nstruct CSchemaClassBinding {\n    CSchemaClassInfo* m_pClassInfo; // +0x00: Resolved schema class info pointer\n};\nstatic_assert(sizeof(CSchemaClassBinding) == 0x08, \"CSchemaClassBinding size must be 0x08 bytes\");\nstatic_assert(offsetof(CSchemaClassBinding, m_pClassInfo) == 0x00, \"CSchemaClassBinding::m_pClassInfo offset mismatch\");\n\n// ============================================================================\n// SchemaEnumFieldData_t\n// Enumerator field descriptor inside a schema enum info.\n// ============================================================================\nstruct SchemaEnumFieldData_t {\n    const char*   m_pszName;  // +0x00: Enum key identifier\n    std::uint64_t m_nValue;   // +0x08: Enum constant value\n    PAD(0x10, _pad10);        // +0x10: Metadata and padding to 0x20 bytes\n};\nstatic_assert(sizeof(SchemaEnumFieldData_t) == 0x20, \"SchemaEnumFieldData_t size mismatch\");\n\n// ============================================================================\n// CSchemaEnumInfo (SchemaEnumInfoData_t)\n// Verified in schemasystem.dll @ 0x1800104C0 (Slot 27 enum resolution)\n// ============================================================================\nclass CSchemaEnumInfo {\npublic:\n    CSchemaEnumInfo*       m_pSelf;          // +0x00\n    const char*            m_pszName;        // +0x08: Enum identifier\n    const char*            m_pszModuleName;  // +0x10: Owning module\n    std::uint8_t           m_nSize;          // +0x18: Storage byte size (1, 2, 4, 8)\n    std::uint8_t           m_nAlign;         // +0x19: Alignment\n    std::int16_t           m_nFieldCount;    // +0x1A: Enumerator count\n    std::int16_t           m_nMetadataCount; // +0x1C: Metadata count\n    PAD(0x2, _pad1E);                        // +0x1E: Alignment padding\n    SchemaEnumFieldData_t* m_pFields;        // +0x20: Enumerator elements array\n};\nusing SchemaEnumInfoData_t = CSchemaEnumInfo;\nstatic_assert(offsetof(CSchemaEnumInfo, m_pszName)     == 0x08, \"CSchemaEnumInfo::m_pszName offset mismatch\");\nstatic_assert(offsetof(CSchemaEnumInfo, m_nFieldCount) == 0x1A, \"CSchemaEnumInfo::m_nFieldCount offset mismatch\");\nstatic_assert(offsetof(CSchemaEnumInfo, m_pFields)     == 0x20, \"CSchemaEnumInfo::m_pFields offset mismatch\");\n\nstruct CSchemaEnumBinding {\n    CSchemaEnumInfo* m_pEnumInfo; // +0x00: Resolved schema enum pointer\n};\nstatic_assert(sizeof(CSchemaEnumBinding) == 0x08, \"CSchemaEnumBinding size mismatch\");\n\n// ============================================================================\n// CSchemaSystemTypeScope\n// VTable RVA: schemasystem.dll + 0x586F0 (35 bounded methods / 179 contiguous block)\n// RTTI: .?AVCSchemaSystemTypeScope@@\n// Instance Allocation: 0x3640 bytes (schemasystem.dll @ 0x180011420)\n//\n// Verified Virtual Slots:\n//   - Slot  0: ~CSchemaSystemTypeScope()            (RVA: 0x0FCD0)\n//   - Slot  1: Unk01                                (RVA: 0x10060)\n//   - Slot  2: FindDeclaredClass (via out binding)  (RVA: 0x162B0)\n//   - Slot  3: FindDeclaredEnum (via out binding)   (RVA: 0x162F0)\n//   - Slot 24: FindDeclaredClass (by MurmurHash2)   (RVA: 0x10460)\n//   - Slot 25: FindDeclaredClass (by class name str)(RVA: 0x10380)\n//   - Slot 26: FindDeclaredEnum (by MurmurHash2)    (RVA: 0x105A0)\n//   - Slot 27: FindDeclaredEnum (by enum name str)  (RVA: 0x104C0)\n// ============================================================================\nclass CSchemaSystemTypeScope {\npublic:\n    virtual ~CSchemaSystemTypeScope() = default;                                                 // Slot 0: 0x0fcd0\n    virtual void Unk01() = 0;                                                                    // Slot 1: 0x10060\n\n    // Slot 2: schemasystem.dll + 0x162B0 (Calls Slot 25 @ 0x180010380 and stores result into out pointer)\n    virtual CSchemaClassBinding* FindDeclaredClass(CSchemaClassBinding* pOutBinding, const char* pszClassName) = 0;\n\n    // Slot 3: schemasystem.dll + 0x162F0 (Calls Slot 27 @ 0x1800104C0 and stores result into out pointer)\n    virtual CSchemaEnumBinding* FindDeclaredEnum(CSchemaEnumBinding* pOutBinding, const char* pszEnumName) = 0;\n\n    // Virtual slots 4 to 23 (internal type reflection, serialization builders, callbacks)\n    virtual void Unk04() = 0; virtual void Unk05() = 0; virtual void Unk06() = 0; virtual void Unk07() = 0;\n    virtual void Unk08() = 0; virtual void Unk09() = 0; virtual void Unk10() = 0; virtual void Unk11() = 0;\n    virtual void Unk12() = 0; virtual void Unk13() = 0; virtual void Unk14() = 0; virtual void Unk15() = 0;\n    virtual void Unk16() = 0; virtual void Unk17() = 0; virtual void Unk18() = 0; virtual void Unk19() = 0;\n    virtual void Unk20() = 0; virtual void Unk21() = 0; virtual void Unk22() = 0; virtual void Unk23() = 0;\n\n    // Slot 24: schemasystem.dll + 0x10460 (Direct MurmurHash2 lookup in hash table at +0x560)\n    virtual CSchemaClassInfo* FindDeclaredClassByHash(std::uint32_t nClassNameHash) = 0;\n\n    // Slot 25: schemasystem.dll + 0x10380 (Hashes string with MurmurHash2 seed len^0xbaadfeed then calls Slot 24)\n    virtual CSchemaClassInfo* FindDeclaredClass(const char* pszClassName) = 0;\n\n    // Slot 26: schemasystem.dll + 0x105A0 (Direct MurmurHash2 lookup in enum hash table)\n    virtual CSchemaEnumInfo* FindDeclaredEnumByHash(std::uint32_t nEnumNameHash) = 0;\n\n    // Slot 27: schemasystem.dll + 0x104C0 (Hashes string and resolves enum descriptor)\n    virtual CSchemaEnumInfo* FindDeclaredEnum(const char* pszEnumName) = 0;\n\npublic:\n    char                    m_szScopeName[256]; // +0x08: Scope module identifier string (e.g., \"client.dll\")\n    CSchemaSystemTypeScope* m_pParentScope;     // +0x108: Pointer to global/parent type scope\n    bool                    m_bIsGlobalScope;   // +0x110: True if root global scope\n    PAD(0x7, _pad111);                          // +0x111: Alignment padding\n    PAD(0x448, _pad118);                        // +0x118 to +0x560: Type registry locks, allocation arenas\n    // +0x560: CUtlHashtable of MurmurHash2 -> CSchemaClassInfo*\n};\nstatic_assert(offsetof(CSchemaSystemTypeScope, m_szScopeName)    == 0x08, \"CSchemaSystemTypeScope::m_szScopeName offset mismatch\");\nstatic_assert(offsetof(CSchemaSystemTypeScope, m_pParentScope)   == 0x108, \"CSchemaSystemTypeScope::m_pParentScope offset mismatch\");\nstatic_assert(offsetof(CSchemaSystemTypeScope, m_bIsGlobalScope) == 0x110, \"CSchemaSystemTypeScope::m_bIsGlobalScope offset mismatch\");\n\n// ============================================================================\n// ISchemaSystem (CSchemaSystem)\n// Export Interface Token: \"SchemaSystem_001\" (schemasystem.dll)\n// Node RVA:    0x4C248, Factory RVA: 0x715F8\n// VTable RVA:  schemasystem.dll + 0x58598 (40 bounded methods / 222 contiguous block)\n// RTTI:        .?AVCSchemaSystem@@\n//\n// Verified Virtual Slots:\n//   - Slot  0: ~ISchemaSystem()                                 (RVA: 0x0E160)\n//   - Slot 11: GlobalTypeScope()                                (RVA: 0x11340)\n//   - Slot 12: FindOrCreateTypeScopeForModule (Allocates 0x3640)(RVA: 0x11420)\n//   - Slot 13: FindTypeScopeForModule (str, outRemainder)       (RVA: 0x11350)\n//   - Slot 14: FindTypeScopeForModule (typeFlag, str, outRem)   (RVA: 0x11510)\n//   - Slot 25: GlobalTypeScope()                                (RVA: 0x10C70)\n// ============================================================================\n#ifndef CS2_SDK_ISCHEMASYSTEM_DEFINED\n#define CS2_SDK_ISCHEMASYSTEM_DEFINED\nclass ISchemaSystem {\npublic:\n    virtual ~ISchemaSystem() = default;                                                          // Slot 0: 0x0e160\n\n    // Virtual slots 1 to 10 (Connect, Disconnect, QueryInterface, Init, Shutdown, etc.)\n    virtual void Unk01() = 0; virtual void Unk02() = 0; virtual void Unk03() = 0;\n    virtual void Unk04() = 0; virtual void Unk05() = 0; virtual void Unk06() = 0;\n    virtual void Unk07() = 0; virtual void Unk08() = 0; virtual void Unk09() = 0;\n    virtual void Unk10() = 0;\n\n    // Slot 11: schemasystem.dll + 0x11340 (Returns pointer to static global default type scope DAT_1800730d0)\n    virtual CSchemaSystemTypeScope* GetDefaultTypeScope() = 0;\n\n    // Slot 12: schemasystem.dll + 0x11420 (Looks up scope by module name; if absent, allocates 0x3640 bytes and constructs new scope)\n    virtual CSchemaSystemTypeScope* FindOrCreateTypeScopeForModule(const char* pszModuleName, void* pBindingContext = nullptr) = 0;\n\n    // Slot 13: schemasystem.dll + 0x11350 (Resolves existing module type scope by ASCII name string; parses '!' delimiter)\n    virtual CSchemaSystemTypeScope* FindTypeScopeForModule(const char* pszModuleName, void* pBindingContext = nullptr) = 0;\n\n    // Slot 14: schemasystem.dll + 0x11510 (Overloaded dispatch forwarding to Slot 12 or Slot 13 based on mode flag)\n    virtual CSchemaSystemTypeScope* FindTypeScopeForModule(int nType, const char* pszModuleName, void* pBindingContext = nullptr) = 0;\n\n    // Virtual slots 15 to 24 (type scope iteration, registration events, memory management)\n    virtual void Unk15() = 0; virtual void Unk16() = 0; virtual void Unk17() = 0; virtual void Unk18() = 0;\n    virtual void Unk19() = 0; virtual void Unk20() = 0; virtual void Unk21() = 0; virtual void Unk22() = 0;\n    virtual void Unk23() = 0; virtual void Unk24() = 0;\n\n    // Slot 25: schemasystem.dll + 0x10C70 (Resolves global type scope)\n    virtual CSchemaSystemTypeScope* GlobalTypeScope() = 0;\n};\n#endif\n\n// ============================================================================\n// MurmurHash2 Implementation matching schemasystem.dll @ 0x180010380\n// Used across all CSchemaSystemTypeScope runtime dictionary lookups.\n// Algorithm:\n//   seed = len ^ 0xbaadfeed\n//   multiplier m = 0x5bd1e995\n//   rotation r = 24\n// ============================================================================\nconstexpr std::uint32_t MurmurHash2(std::string_view str) noexcept {\n    const std::uint32_t len = static_cast<std::uint32_t>(str.length());\n    if (len == 0) return 0;\n\n    constexpr std::uint32_t m = 0x5bd1e995;\n    constexpr int r = 24;\n\n    std::uint32_t h = len ^ 0xbaadfeed;\n    const char* data = str.data();\n    std::uint32_t remaining = len;\n\n    while (remaining >= 4) {\n        std::uint32_t k = static_cast<std::uint8_t>(data[0]) |\n                         (static_cast<std::uint8_t>(data[1]) << 8) |\n                         (static_cast<std::uint8_t>(data[2]) << 16) |\n                         (static_cast<std::uint8_t>(data[3]) << 24);\n\n        k *= m;\n        k ^= k >> r;\n        k *= m;\n\n        h *= m;\n        h ^= k;\n\n        data += 4;\n        remaining -= 4;\n    }\n\n    if (remaining == 3) h ^= static_cast<std::uint8_t>(data[2]) << 16;\n    if (remaining >= 2) h ^= static_cast<std::uint8_t>(data[1]) << 8;\n    if (remaining >= 1) {\n        h ^= static_cast<std::uint8_t>(data[0]);\n        h *= m;\n    }\n\n    h ^= h >> 13;\n    h *= m;\n    h ^= h >> 15;\n\n    return h;\n}\n\n} // namespace cs2::sdk\n",
        "trace_events_aux.hpp": "#pragma once\n\n#include <cstdint>\n#include <cstddef>\n#include <type_traits>\n#include \"interfaces_registry.hpp\"\n#include \"entity_system.hpp\"\n#include \"client_classes.hpp\"\n\n// ============================================================================\n// Source 2 Reconstructed SDK - Phase 4: World Tracing, Events & Auxiliary Data\n// Target Build: 2026-10-25_26144732 (CS2 Update Archive)\n// Architecture: x86-64 (MSVC ABI)\n// Language Standard: C++20 (/std:c++20 /W4 /WX)\n//\n// Verified Components:\n//   1. Spatial Query Manager (CGameTraceManager, Ray_t, CTraceFilter, GameTrace_t)\n//   2. Volumetric Smoke Optical Occlusion (LineOfSightThroughSmoke @ 0x1807ce470)\n//   3. Game Events Subsystem (IGameEventManager2, IGameEvent, IGameEventListener2)\n//   4. Audio Subsystem (ISoundOpSystem, StartSoundEventInfo_t)\n//   5. Network Telemetry Interface (INetChannelInfo, FlowDirection)\n//   6. Weapon Configuration Metadata (CCSWeaponBaseVData, CSWeaponType)\n// ============================================================================\n\nnamespace cs2::sdk {\n\n#define PAD(bytes, name) private: [[maybe_unused]] std::uint8_t name[bytes]; public:\n\n// ============================================================================\n// SECTION 1: SPATIAL QUERY & RAY TRACING DATA STRUCTURES\n// Discovered in client.dll & vphysics2.dll:\n// - CGameTraceManager Global Pointer: client.dll + 0x02229020 (VA: 0x182229020)\n// - Static BSS Instance:              client.dll + 0x0254cf30 (VA: 0x18254cf30)\n// - TraceShape Function RVA:          client.dll + 0x00a1ae30 (VA: 0x180a1ae30)\n// - ClipRayToEntity Function RVA:     client.dll + 0x00a1b8a0 (VA: 0x180a1b8a0)\n// ============================================================================\n\n/**\n * @brief 64-byte Geometric Query Ray & Swept Extent Volume.\n * Provenance: client.dll @ 0x180a1ae30 / vphysics2.dll @ 0x1802544a0.\n */\nstruct alignas(16) Ray_t {\n    Vector3       m_vStart;         // +0x00: Ray segment trajectory origin\n    Vector3       m_vEnd;           // +0x0C: Ray segment trajectory terminus\n    Vector3       m_vOffset;        // +0x18: Swept centroid displacement vector\n    Vector3       m_vExtent;        // +0x24: Half-extent bounding box dimensions\n    bool          m_bIsRay;         // +0x30: True if line ray (extent == 0), false if swept volume\n    bool          m_bHasExtents;    // +0x31: True if swept volume possesses non-zero bounds\n    PAD(0x06, m_pad32);             // +0x32: Alignment padding\n    std::uint64_t m_nMask;          // +0x38: 64-bit spatial collision mask (e.g. MASK_SHOT = 0x46004003)\n\n    Ray_t() noexcept\n        : m_vStart{}, m_vEnd{}, m_vOffset{}, m_vExtent{}\n        , m_bIsRay{ true }, m_bHasExtents{ false }, m_pad32{}\n        , m_nMask{ 0x46004003ULL } {}\n\n    Ray_t(const Vector3& start, const Vector3& end, std::uint64_t mask = 0x46004003ULL) noexcept\n        : m_vStart{ start }, m_vEnd{ end }, m_vOffset{}, m_vExtent{}\n        , m_bIsRay{ true }, m_bHasExtents{ false }, m_pad32{}\n        , m_nMask{ mask } {}\n\n    Ray_t(const Vector3& start, const Vector3& end, const Vector3& mins, const Vector3& maxs, std::uint64_t mask = 0x46004003ULL) noexcept\n        : m_vStart{ start }, m_vEnd{ end }\n        , m_vOffset{ (mins.x + maxs.x) * 0.5f, (mins.y + maxs.y) * 0.5f, (mins.z + maxs.z) * 0.5f }\n        , m_vExtent{ (maxs.x - mins.x) * 0.5f, (maxs.y - mins.y) * 0.5f, (maxs.z - mins.z) * 0.5f }\n        , m_bIsRay{ false }, m_bHasExtents{ true }, m_pad32{}\n        , m_nMask{ mask } {}\n};\nstatic_assert(sizeof(Ray_t) == 0x40, \"Ray_t size must be exactly 0x40 (64 bytes)\");\nstatic_assert(offsetof(Ray_t, m_vStart)      == 0x00, \"Ray_t::m_vStart offset mismatch\");\nstatic_assert(offsetof(Ray_t, m_vEnd)        == 0x0C, \"Ray_t::m_vEnd offset mismatch\");\nstatic_assert(offsetof(Ray_t, m_vOffset)     == 0x18, \"Ray_t::m_vOffset offset mismatch\");\nstatic_assert(offsetof(Ray_t, m_vExtent)     == 0x24, \"Ray_t::m_vExtent offset mismatch\");\nstatic_assert(offsetof(Ray_t, m_bIsRay)      == 0x30, \"Ray_t::m_bIsRay offset mismatch\");\nstatic_assert(offsetof(Ray_t, m_bHasExtents) == 0x31, \"Ray_t::m_bHasExtents offset mismatch\");\nstatic_assert(offsetof(Ray_t, m_nMask)       == 0x38, \"Ray_t::m_nMask offset mismatch\");\n\n/**\n * @brief 72-byte Entity & Collision Layer Query Filter.\n * Provenance: client.dll @ 0x180205cb0 (alloc size 0x48) / VTable: 0x181ad4838.\n */\nclass CTraceFilter {\npublic:\n    virtual ~CTraceFilter() = default;                                                 // Slot 0 (0x180205cb0)\n    virtual bool ShouldHitEntity(void* pEntity, std::uint64_t nCollisionMask) = 0;   // Slot 1 (0x18022d900)\n\n    std::uint64_t m_nCollisionMask{ 0xFFFFFFFFFFFFFFFFULL }; // +0x08: 64-bit collision layer mask\n    std::uint64_t m_v1{ 0 };                                 // +0x10: Filter evaluation flags\n    std::uint64_t m_v2{ 0 };                                 // +0x18: Extended attribute mask\n    std::uint32_t m_hEntityToIgnore[2]{ 0xFFFFFFFF, 0 };     // +0x20: Primary entity handle to bypass\n    std::uint32_t m_hOwnerToIgnore[2]{ 0xFFFFFFFF, 0 };      // +0x28: Hierarchy owner handle to bypass\n    std::uint16_t m_nCollisionGroup[2]{ 0, 0 };              // +0x30: Collision group IDs\n    std::uint32_t m_nHitGroup{ 0 };                          // +0x34: Hitgroup filter\n    std::uint32_t m_nLayerMask{ 0 };                         // +0x38: Secondary collision layer mask\n    std::uint32_t m_nFilterLayer{ 0x100FFFF };               // +0x3C: Layer discriminator (0x100FFFF default)\n    std::uint8_t  m_nFilterMode{ 3 };                        // +0x40: Filter execution mode\n    std::uint8_t  m_nFlags{ 0x49 };                          // +0x41: Internal status bitfield\n    PAD(0x06, m_pad42);                                      // +0x42: Tail alignment padding\n};\nstatic_assert(sizeof(CTraceFilter) == 0x48, \"CTraceFilter size must be exactly 0x48 (72 bytes)\");\nstatic_assert(offsetof(CTraceFilter, m_nCollisionMask)  == 0x08, \"CTraceFilter::m_nCollisionMask offset mismatch\");\nstatic_assert(offsetof(CTraceFilter, m_v1)             == 0x10, \"CTraceFilter::m_v1 offset mismatch\");\nstatic_assert(offsetof(CTraceFilter, m_v2)             == 0x18, \"CTraceFilter::m_v2 offset mismatch\");\nstatic_assert(offsetof(CTraceFilter, m_hEntityToIgnore) == 0x20, \"CTraceFilter::m_hEntityToIgnore offset mismatch\");\nstatic_assert(offsetof(CTraceFilter, m_hOwnerToIgnore)  == 0x28, \"CTraceFilter::m_hOwnerToIgnore offset mismatch\");\nstatic_assert(offsetof(CTraceFilter, m_nCollisionGroup) == 0x30, \"CTraceFilter::m_nCollisionGroup offset mismatch\");\nstatic_assert(offsetof(CTraceFilter, m_nHitGroup)       == 0x34, \"CTraceFilter::m_nHitGroup offset mismatch\");\nstatic_assert(offsetof(CTraceFilter, m_nLayerMask)      == 0x38, \"CTraceFilter::m_nLayerMask offset mismatch\");\nstatic_assert(offsetof(CTraceFilter, m_nFilterLayer)    == 0x3C, \"CTraceFilter::m_nFilterLayer offset mismatch\");\nstatic_assert(offsetof(CTraceFilter, m_nFilterMode)     == 0x40, \"CTraceFilter::m_nFilterMode offset mismatch\");\nstatic_assert(offsetof(CTraceFilter, m_nFlags)          == 0x41, \"CTraceFilter::m_nFlags offset mismatch\");\n\n/**\n * @brief 192-byte Authoritative Ray Intersection Result Block.\n * Provenance: client.dll @ 0x18177b560 (Init function) / 0x180a1ae30.\n */\nstruct alignas(16) GameTrace_t {\n    void*         m_pSurface{ nullptr };       // +0x00: Pointer to physical SurfaceData_t descriptor\n    C_BaseEntity* m_pHitEntity{ nullptr };     // +0x08: Intersected C_BaseEntity pointer (nullptr if world / air)\n    void*         m_pHitboxData{ nullptr };    // +0x10: Target hitbox runtime descriptor pointer\n    std::uint64_t m_nContents{ 0 };            // +0x18: Point contents flags at hit position\n    std::uint64_t m_nHitBoxIndex{ 0 };         // +0x20: Hitbox bone index\n    PAD(0x08, m_pad28);                        // +0x28\n    Vector3       m_vStartPos{};               // +0x30: Trajectory origin position\n    PAD(0x04, m_pad3c);                        // +0x3C\n    Vector3       m_vEndPos{};                 // +0x40: Trajectory terminus position\n    PAD(0x04, m_pad4c);                        // +0x4C\n    std::uint8_t  m_rubikonBuffer[40]{};       // +0x50: Internal Rubikon sweep buffer (0x28 bytes)\n    Vector3       m_vRayStart{};               // +0x78: Exact evaluated ray entry vector\n    Vector3       m_vRayEnd{};                 // +0x84: Exact evaluated ray exit vector\n    PAD(0x08, m_pad90);                        // +0x90\n    PAD(0x04, m_pad98);                        // +0x98\n    Vector3       m_vHitNormal{};              // +0x9C: Surface unit normal vector at intersection\n    std::uint32_t m_nSpatialVolumeIndex{ 0 };  // +0xA8: Rubikon spatial subdivision cell / hitgroup ID\n    float         m_flFraction{ 1.0f };        // +0xAC: Intersection fraction [0.0..1.0] along ray (1.0 = miss)\n    std::uint64_t m_nHitFlags{ 0 };            // +0xB0: Intersection status flags\n    std::uint16_t m_nSurfaceFlags{ 0 };        // +0xB8: Physical material surface descriptor flags\n    std::uint8_t  m_bStartSolid{ 0 };          // +0xBA: True if ray started inside a solid geometry volume\n    PAD(0x05, m_padbb);                        // +0xBB\n\n    [[nodiscard]] constexpr bool DidHit() const noexcept {\n        return m_flFraction < 1.0f || m_bStartSolid;\n    }\n\n    [[nodiscard]] constexpr bool IsVisible() const noexcept {\n        return m_flFraction > 0.97f && !m_bStartSolid;\n    }\n};\nstatic_assert(sizeof(GameTrace_t) == 0xC0, \"GameTrace_t size must be exactly 0xC0 (192 bytes)\");\nstatic_assert(offsetof(GameTrace_t, m_pSurface)            == 0x00, \"GameTrace_t::m_pSurface offset mismatch\");\nstatic_assert(offsetof(GameTrace_t, m_pHitEntity)          == 0x08, \"GameTrace_t::m_pHitEntity offset mismatch\");\nstatic_assert(offsetof(GameTrace_t, m_pHitboxData)         == 0x10, \"GameTrace_t::m_pHitboxData offset mismatch\");\nstatic_assert(offsetof(GameTrace_t, m_nContents)           == 0x18, \"GameTrace_t::m_nContents offset mismatch\");\nstatic_assert(offsetof(GameTrace_t, m_nHitBoxIndex)        == 0x20, \"GameTrace_t::m_nHitBoxIndex offset mismatch\");\nstatic_assert(offsetof(GameTrace_t, m_vStartPos)           == 0x30, \"GameTrace_t::m_vStartPos offset mismatch\");\nstatic_assert(offsetof(GameTrace_t, m_vEndPos)             == 0x40, \"GameTrace_t::m_vEndPos offset mismatch\");\nstatic_assert(offsetof(GameTrace_t, m_vRayStart)           == 0x78, \"GameTrace_t::m_vRayStart offset mismatch\");\nstatic_assert(offsetof(GameTrace_t, m_vRayEnd)             == 0x84, \"GameTrace_t::m_vRayEnd offset mismatch\");\nstatic_assert(offsetof(GameTrace_t, m_vHitNormal)          == 0x9C, \"GameTrace_t::m_vHitNormal offset mismatch\");\nstatic_assert(offsetof(GameTrace_t, m_nSpatialVolumeIndex) == 0xA8, \"GameTrace_t::m_nSpatialVolumeIndex offset mismatch\");\nstatic_assert(offsetof(GameTrace_t, m_flFraction)          == 0xAC, \"GameTrace_t::m_flFraction offset mismatch\");\nstatic_assert(offsetof(GameTrace_t, m_nHitFlags)           == 0xB0, \"GameTrace_t::m_nHitFlags offset mismatch\");\nstatic_assert(offsetof(GameTrace_t, m_nSurfaceFlags)       == 0xB8, \"GameTrace_t::m_nSurfaceFlags offset mismatch\");\nstatic_assert(offsetof(GameTrace_t, m_bStartSolid)         == 0xBA, \"GameTrace_t::m_bStartSolid offset mismatch\");\n\n/**\n * @brief Spatial Query Master Interface (CGameTraceManager / IEngineTrace).\n * Global Instance in client.dll: +0x02229020 (VA: 0x182229020).\n */\nclass CGameTraceManager {\npublic:\n    virtual ~CGameTraceManager() = default;\n\n    // Slot 1: ClipRayToEntity narrowphase test (RVA client.dll + 0x00a1b8a0)\n    virtual bool ClipRayToEntity(\n        const Ray_t* pRay,\n        const Vector3* pStart,\n        const Vector3* pEnd,\n        C_BaseEntity* pEntity,\n        CTraceFilter* pFilter,\n        GameTrace_t* pTrace,\n        std::int32_t nTraceFlags = 0\n    ) = 0;\n\n    PAD(0x10, m_padVirtuals);\n\n    // Slot 5: TraceShape primary scene sweep (RVA client.dll + 0x00a1ae30)\n    virtual bool TraceShape(\n        const Ray_t* pRay,\n        const Vector3* pStart,\n        const Vector3* pEnd,\n        CTraceFilter* pFilter,\n        GameTrace_t* pTrace\n    ) = 0;\n};\n\n// ============================================================================\n// SECTION 2: VOLUMETRIC SMOKE OPTICAL OCCLUSION\n// Discovered in client.dll: RVA 0x007ce470 (VA: 0x1807ce470)\n// Prologue: 48 8B C4 55 53 56 41 55 41 57 48 8D 68 A8 48 81 EC 30 01 00 00\n// Evaluates 32x32x32 Morton Z-Order voxel density with 0.20f density gate threshold.\n// ============================================================================\nusing FnLineOfSightThroughSmoke = float (__fastcall*)(\n    const Vector3& vStart,            // RCX: Ray trajectory origin\n    const Vector3& vEnd,              // RDX: Ray trajectory terminus\n    Vector3* pOutIntersection         // R8:  Optional blocking point receiver\n);\n\n// ============================================================================\n// SECTION 3: GAME EVENT SUBSYSTEM (IGameEventManager2, IGameEvent)\n// Interface Token: \"GAMEEVENTSMANAGER002\"\n// - Global Instance Pointer: client.dll + 0x2228E40 (VA: 0x182228E40)\n// - Singleton Instance:      client.dll + 0x22292C0 (VA: 0x1822292C0)\n// - CGameEventManager VTable: client.dll + 0x1C337A8 (VA: 0x181C337A8)\n// - IGameEvent VTable:        client.dll + 0x1C334F0 (VA: 0x181C334F0)\n// ============================================================================\n\nclass CSVCMsg_GameEvent;\n\n/**\n * @brief Key-Value Game Event Deserialization Interface.\n * VTable: client.dll + 0x1C334F0 (18 virtual slots).\n */\nclass IGameEvent {\npublic:\n    virtual ~IGameEvent() = 0;                                                                           // Slot 0  (0x1809C8BD0)\n    [[nodiscard]] virtual const char* GetName() const = 0;                                               // Slot 1  (0x1809E8C80)\n    [[nodiscard]] virtual int GetID() const = 0;                                                         // Slot 2  (0x1809E7F40)\n    [[nodiscard]] virtual bool IsReliable() const = 0;                                                   // Slot 3  (0x1809F2730)\n    [[nodiscard]] virtual bool IsLocal() const = 0;                                                      // Slot 4  (0x1809F2640)\n    [[nodiscard]] virtual bool IsEmpty(const char* pszKeyName = nullptr) = 0;                            // Slot 5  (0x1809F25A0)\n    [[nodiscard]] virtual bool GetBool(const char* pszKeyName = nullptr, bool bDefaultValue = false) = 0;// Slot 6  (0x1809E4C90)\n    [[nodiscard]] virtual int GetInt(const char* pszKeyName = nullptr, int nDefaultValue = 0) = 0;      // Slot 7  (0x1809E7F50)\n    [[nodiscard]] virtual uint64_t GetUint64(const char* pszKeyName = nullptr, uint64_t nDefault = 0) = 0; // Slot 8  (0x1809EA5F0)\n    [[nodiscard]] virtual float GetFloat(const char* pszKeyName = nullptr, float flDefaultValue = 0.0f) = 0; // Slot 9  (0x1809E7B70)\n    [[nodiscard]] virtual const char* GetString(const char* pszKeyName = nullptr, const char* pszDefault = \"\") = 0; // Slot 10 (0x1809EA380)\n    [[nodiscard]] virtual const void* GetPtr(const char* pszKeyName = nullptr) = 0;                      // Slot 11 (0x1809E9DB0)\n    virtual void SetBool(const char* pszKeyName, bool bValue) = 0;                                       // Slot 12 (0x1809F1C70)\n    virtual void SetInt(const char* pszKeyName, int nValue) = 0;                                         // Slot 13 (0x1809E5500)\n    virtual void SetUint64(const char* pszKeyName, uint64_t nValue) = 0;                                 // Slot 14 (0x1809F2800)\n    virtual void SetFloat(const char* pszKeyName, float flValue) = 0;                                    // Slot 15 (0x1809F2000)\n    virtual void SetString(const char* pszKeyName, const char* pszValue) = 0;                            // Slot 16 (0x1809E9090)\n    virtual void SetPtr(const char* pszKeyName, const void* pValue) = 0;                                 // Slot 17 (0x1809F24F0)\n};\n\n/**\n * @brief Game Event Listener Callback Base Interface.\n */\nclass IGameEventListener2 {\npublic:\n    virtual ~IGameEventListener2() = default;\n    virtual void FireGameEvent(IGameEvent* pEvent) = 0;\n    [[nodiscard]] virtual int GetEventDebugID() { return 42; }\n};\n\n/**\n * @brief Game Events Master Manager Interface (\"GAMEEVENTSMANAGER002\").\n * VTable: client.dll + 0x1C337A8 (16 virtual slots).\n */\nclass IGameEventManager2 {\npublic:\n    virtual ~IGameEventManager2() = 0;                                                                   // Slot 0  (0x1809C8C20)\n    virtual int LoadEventsFromFile(const char* pszFilename, bool bSearchPaths = true) = 0;               // Slot 1  (0x1809F68B0)\n    virtual void Reset() = 0;                                                                            // Slot 2  (0x180A055E0)\n    virtual bool AddListener(IGameEventListener2* pListener, const char* pszName, bool bServer = false) = 0; // Slot 3  (0x1809CAB60)\n    virtual bool FindListener(IGameEventListener2* pListener, const char* pszName) = 0;                  // Slot 4  (0x1809E2A20)\n    virtual void RemoveListener(IGameEventListener2* pListener) = 0;                                     // Slot 5  (0x180A02370)\n    virtual IGameEvent* CreateEvent(const char* pszName, bool bForce = false, int* pCookie = nullptr) = 0;// Slot 6  (0x1809D5440)\n    virtual bool FireEvent(IGameEvent* pEvent, bool bDontBroadcast = false) = 0;                         // Slot 7  (0x1809E3500)\n    virtual bool FireEventClientSide(IGameEvent* pEvent) = 0;                                            // Slot 8  (0x1809E3790)\n    virtual IGameEvent* DuplicateEvent(IGameEvent* pEvent) = 0;                                          // Slot 9  (0x1809D9990)\n    virtual void FreeEvent(IGameEvent* pEvent) = 0;                                                      // Slot 10 (0x1809E3FE0)\n    virtual bool SerializeEvent(IGameEvent* pEvent, CSVCMsg_GameEvent* pMsg) = 0;                        // Slot 11 (0x180A0F840)\n    virtual IGameEvent* UnserializeEvent(const CSVCMsg_GameEvent* pMsg) = 0;                             // Slot 12 (0x180A1F290)\n    virtual int LookupEventId(const char* pszName) = 0;                                                  // Slot 13 (0x1809F79C0)\n    virtual bool SerializeKeyValues(IGameEvent* pEvent, void* pBuffer) = 0;                              // Slot 14 (0x1809FC580)\n    virtual bool HasEvent(const char* pszName) = 0;                                                      // Slot 15 (0x1809CF2E0)\n};\n\n// ============================================================================\n// SECTION 4: AUDIO SUBSYSTEM (SoundOpSystem001)\n// Interface Token: \"SoundOpSystem001\" (soundsystem.dll + 0x4AB140)\n// Dispatcher: CSoundServices::DispatchSoundEvent (client.dll + 0xB4FB20)\n// ============================================================================\n\nusing SoundEventGuid_t = std::uint64_t;\n\n/**\n * @brief Sound Emission Dispatcher Payload (80 bytes / 0x80).\n */\nstruct StartSoundEventInfo_t {\n    float         m_vecOrigin[3];       // +0x00: Spatial emission origin\n    float         m_angAngles[3];       // +0x0C: Directional orientation angles\n    float         m_flVolume;           // +0x18: Emission acoustic gain [0.0..1.0]\n    float         m_flPitch;            // +0x1C: Frequency pitch scalar\n    CEntityHandle m_hEntity;            // +0x20: Associated emitter entity handle\n    std::int32_t  m_nSoundSource;       // +0x24: Acoustic source channel\n    std::uint32_t m_nFlags;             // +0x28: Emission bitflags\n    PAD(0x04, m_pad2C);                 // +0x2C\n    float         m_matSpatial[12];     // +0x30: 3x4 affine spatial transformation matrix\n    PAD(0x20, m_pad60);                 // +0x60\n};\nstatic_assert(sizeof(StartSoundEventInfo_t) == 0x80, \"StartSoundEventInfo_t size must be 0x80 bytes\");\n\n// ============================================================================\n// SECTION 5: NETWORK TELEMETRY (INetChannelInfo)\n// Implementation: CNetChan (networksystem.dll VTable: 0x180235890)\n// ============================================================================\n\nenum FlowDirection : int {\n    FLOW_OUTGOING = 0,\n    FLOW_INCOMING = 1,\n    MAX_FLOWS     = 2\n};\n\n/**\n * @brief Source 2 Network Performance Telemetry Interface.\n * VTable: networksystem.dll + 0x235890 (32 slots).\n */\nclass INetChannelInfo {\npublic:\n    virtual ~INetChannelInfo() = default;\n\n    virtual const char*   GetName() const = 0;                                          // Slot 0  (0x0bd020)\n    virtual const char*   GetAddress() const = 0;                                       // Slot 1  (0x0bd040)\n    virtual const void*   GetRemoteAddress() const = 0;                                 // Slot 2  (0x0c3e10)\n    virtual float         GetTime() const = 0;                                          // Slot 3  (0x0c5ed0)\n    virtual float         GetConnectionTime() const = 0;                                // Slot 4  (0x0c3df0)\n    virtual int32_t       GetBufferSize() const = 0;                                    // Slot 5  (0x0c3d50)\n    virtual bool          IsLoopback() const = 0;                                       // Slot 6  (0x0bb550)\n    virtual bool          IsTimingOut() const = 0;                                      // Slot 7  (0x0bb540)\n    virtual bool          IsPlayback() const = 0;                                       // Slot 8  (0x0c3e60)\n    virtual bool          IsSplitScreenUser() const = 0;                                // Slot 9  (0x0c6ef0)\n    virtual float         GetLatency(int flow) const = 0;                               // Slot 10 (0x0c5c10)\n    virtual float         GetAvgLatency(int flow) const = 0;                            // Slot 11 (0x0c5cd0)\n    virtual float         GetAvgLoss(int flow) const = 0;                               // Slot 12 (0x0c5e70)\n    virtual float         GetAvgChoke(int flow) const = 0;                              // Slot 13 (0x0c5e90)\n    virtual float         GetAvgData(int flow) const = 0;                               // Slot 14 (0x0c5eb0)\n    virtual float         GetAvgPackets(int flow) const = 0;                            // Slot 15 (0x0c5a40)\n    virtual float         GetAvgPacketsDropped(int flow) const = 0;                     // Slot 16 (0x0c5ae0)\n    virtual uint64_t      GetTotalData(int flow) const = 0;                             // Slot 17 (0x0c5b80)\n    virtual int32_t       GetTotalPackets(int flow) const = 0;                          // Slot 18 (0x0c5ba0)\n    virtual int32_t       GetSequenceNr(int flow) const = 0;                            // Slot 19 (0x0c5bc0)\n    virtual float         GetTimeoutSeconds() const = 0;                                // Slot 20 (0x0c5a10)\n    virtual void          GetStreamProgress(int* r, int* s, int* t) const = 0;          // Slot 21 (0x0c5be0)\n    virtual float         GetRemoteFramerate() const = 0;                               // Slot 22 (0x0c5a00)\n    virtual float         GetRemoteFramerateStdDev() const = 0;                         // Slot 23 (0x0c3ea0)\n    virtual float         GetRemoteFramerateCompatibility() const = 0;                  // Slot 24 (0x0bd010)\n    virtual void*         GetNetStatsOut(int flow) = 0;                                 // Slot 25 (0x0c5d10)\n    virtual const void*   GetNetStatsIn(int flow) const = 0;                            // Slot 26 (0x0c5d40)\n    virtual void          CopyNetStats(void* dest) const = 0;                           // Slot 27 (0x0c5d60)\n    virtual void          SetInterpolationAmount(float fl1, float fl2) = 0;             // Slot 28 (0x0c65c0)\n    virtual void          SetCommandInterpolationAmount(int frame, int flow) = 0;       // Slot 29 (0x0c6240)\n    virtual void          SetTrace(bool bEnable) = 0;                                   // Slot 30 (0x0c3f20)\n    virtual int32_t       IsValidPacket(int flow, int frame, float* pflLatency = nullptr) const = 0; // Slot 31 (0x0c4180)\n};\n\n// ============================================================================\n// SECTION 6: WEAPON CONFIGURATION METADATA (CCSWeaponBaseVData)\n// Schema Class in client.dll: 2,208 bytes (0x8A0)\n// Base: CBasePlayerWeaponVData (1,312 bytes / 0x520)\n// ============================================================================\n\nenum class CSWeaponType : std::int32_t {\n    WEAPONTYPE_KNIFE         = 0,\n    WEAPONTYPE_PISTOL        = 1,\n    WEAPONTYPE_SUBMACHINEGUN = 2,\n    WEAPONTYPE_RIFLE         = 3,\n    WEAPONTYPE_SHOTGUN       = 4,\n    WEAPONTYPE_SNIPER_RIFLE  = 5,\n    WEAPONTYPE_MACHINEGUN    = 6,\n    WEAPONTYPE_C4            = 7,\n    WEAPONTYPE_TASER         = 8,\n    WEAPONTYPE_GRENADE       = 9,\n    WEAPONTYPE_EQUIPMENT     = 10,\n    WEAPONTYPE_STACKABLEITEM = 11,\n    WEAPONTYPE_UNKNOWN       = 12\n};\n\nstruct CBasePlayerWeaponVData {\n    PAD(0x520, m_padBaseWeaponVData);\n};\nstatic_assert(sizeof(CBasePlayerWeaponVData) == 0x520, \"CBasePlayerWeaponVData size mismatch\");\n\nstruct CCSWeaponBaseVData : public CBasePlayerWeaponVData {\n    CSWeaponType m_WeaponType;                           // +0x0520 (1312)\n    std::uint32_t m_WeaponCategory;                      // +0x0524 (1316)\n    char m_szAnimSkeleton[224];                          // +0x0528 (1320)\n    Vector3 m_vecMuzzlePos0;                             // +0x0608 (1544)\n    Vector3 m_vecMuzzlePos1;                             // +0x0614 (1556)\n    char m_szTracerParticle[224];                        // +0x0620 (1568)\n    std::uint32_t m_GearSlot;                            // +0x0700 (1792)\n    std::uint32_t m_GearSlotPosition;                    // +0x0704 (1796)\n    std::uint32_t m_DefaultLoadoutSlot;                  // +0x0708 (1800)\n    std::int32_t m_nPrice;                               // +0x070c (1804)\n    std::int32_t m_nKillAward;                           // +0x0710 (1808)\n    std::int32_t m_nPrimaryReserveAmmoMax;               // +0x0714 (1812)\n    std::int32_t m_nSecondaryReserveAmmoMax;             // +0x0718 (1816)\n    bool m_bMeleeWeapon;                                 // +0x071c (1820)\n    bool m_bHasBurstMode;                                // +0x071d (1821)\n    bool m_bIsRevolver;                                  // +0x071e (1822)\n    bool m_bCannotShootUnderwater;                       // +0x071f (1823)\n    const char* m_szName;                                // +0x0720 (1824)\n    std::uint32_t m_eSilencerType;                       // +0x0728 (1832)\n    bool m_bShowCrosshair;                               // +0x072c (1836)\n    bool m_bIsFullAuto;                                  // +0x072d (1837)\n    PAD(0x02, m_pad72e);                                 // +0x072e (1838)\n    std::int32_t m_nNumBullets;                          // +0x0730 (1840)\n    bool m_bReloadsSingleShells;                         // +0x0734 (1844)\n    PAD(0x03, m_pad735);                                 // +0x0735 (1845)\n    float m_flCycleTime;                                 // +0x0738 (1848)\n    PAD(0x04, m_pad73c);                                 // +0x073c (1852)\n    float m_flCycleTimeWhenInBurstMode;                  // +0x0740 (1856)\n    float m_flTimeBetweenBurstShots;                     // +0x0744 (1860)\n    float m_flMaxSpeed;                                  // +0x0748 (1864)\n    PAD(0x04, m_pad74c);                                 // +0x074c (1868)\n    float m_flSpread;                                    // +0x0750 (1872)\n    PAD(0x04, m_pad754);                                 // +0x0754 (1876)\n    float m_flInaccuracyCrouch;                          // +0x0758 (1880)\n    PAD(0x04, m_pad75c);                                 // +0x075c (1884)\n    float m_flInaccuracyStand;                           // +0x0760 (1888)\n    PAD(0x04, m_pad764);                                 // +0x0764 (1892)\n    float m_flInaccuracyJump;                            // +0x0768 (1896)\n    PAD(0x04, m_pad76c);                                 // +0x076c (1900)\n    float m_flInaccuracyLand;                            // +0x0770 (1904)\n    PAD(0x04, m_pad774);                                 // +0x0774 (1908)\n    float m_flInaccuracyLadder;                          // +0x0778 (1912)\n    PAD(0x04, m_pad77c);                                 // +0x077c (1916)\n    float m_flInaccuracyFire;                            // +0x0780 (1920)\n    PAD(0x04, m_pad784);                                 // +0x0784 (1924)\n    float m_flInaccuracyMove;                            // +0x0788 (1928)\n    PAD(0x04, m_pad78c);                                 // +0x078c (1932)\n    float m_flRecoilAngle;                               // +0x0790 (1936)\n    PAD(0x04, m_pad794);                                 // +0x0794 (1940)\n    float m_flRecoilAngleVariance;                       // +0x0798 (1944)\n    PAD(0x04, m_pad79c);                                 // +0x079c (1948)\n    float m_flRecoilMagnitude;                           // +0x07a0 (1952)\n    PAD(0x04, m_pad7a4);                                 // +0x07a4 (1956)\n    float m_flRecoilMagnitudeVariance;                   // +0x07a8 (1960)\n    PAD(0x04, m_pad7ac);                                 // +0x07ac (1964)\n    std::int64_t m_nTracerFrequency;                     // +0x07b0 (1968)\n    float m_flInaccuracyJumpInitial;                     // +0x07b8 (1976)\n    float m_flInaccuracyJumpApex;                        // +0x07bc (1980)\n    float m_flInaccuracyReload;                          // +0x07c0 (1984)\n    float m_flDeployDuration;                            // +0x07c4 (1988)\n    float m_flDisallowAttackAfterReloadStartDuration;    // +0x07c8 (1992)\n    std::int32_t m_nBurstShotCount;                      // +0x07cc (1996)\n    bool m_bAllowBurstHolster;                           // +0x07d0 (2000)\n    PAD(0x03, m_pad7d1);                                 // +0x07d1 (2001)\n    std::int32_t m_nRecoilSeed;                          // +0x07d4 (2004)\n    std::int32_t m_nSpreadSeed;                          // +0x07d8 (2008)\n    float m_flAttackMovespeedFactor;                     // +0x07dc (2012)\n    float m_flInaccuracyPitchShift;                      // +0x07e0 (2016)\n    float m_flInaccuracyAltSoundThreshold;               // +0x07e4 (2020)\n    const char* m_szUseRadioSubtitle;                    // +0x07e8 (2024)\n    bool m_bUnzoomsAfterShot;                            // +0x07f0 (2032)\n    bool m_bHideViewModelWhenZoomed;                     // +0x07f1 (2033)\n    PAD(0x02, m_pad7f2);                                 // +0x07f2 (2034)\n    std::int32_t m_nZoomLevels;                          // +0x07f4 (2036)\n    std::int32_t m_nZoomFOV1;                            // +0x07f8 (2040)\n    std::int32_t m_nZoomFOV2;                            // +0x07fc (2044)\n    float m_flZoomTime0;                                 // +0x0800 (2048)\n    float m_flZoomTime1;                                 // +0x0804 (2052)\n    float m_flZoomTime2;                                 // +0x0808 (2056)\n    float m_flIronSightPullUpSpeed;                      // +0x080c (2060)\n    float m_flIronSightPutDownSpeed;                     // +0x0810 (2064)\n    float m_flIronSightFOV;                              // +0x0814 (2068)\n    float m_flIronSightPivotForward;                     // +0x0818 (2072)\n    float m_flIronSightLooseness;                        // +0x081c (2076)\n    std::int32_t m_nDamage;                              // +0x0820 (2080) [Base ballistic power / m_iDamage]\n    float m_flHeadshotMultiplier;                        // +0x0824 (2084)\n    float m_flArmorRatio;                                // +0x0828 (2088) [Armor penetration efficiency]\n    float m_flPenetration;                               // +0x082c (2092) [Penetration depth]\n    float m_flRange;                                     // +0x0830 (2096) [Effective range]\n    float m_flRangeModifier;                             // +0x0834 (2100) [Distance attenuation]\n    float m_flFlinchVelocityModifierLarge;               // +0x0838 (2104)\n    float m_flFlinchVelocityModifierSmall;               // +0x083c (2108)\n    float m_flRecoveryTimeCrouch;                        // +0x0840 (2112)\n    float m_flRecoveryTimeStand;                         // +0x0844 (2116)\n    float m_flRecoveryTimeCrouchFinal;                   // +0x0848 (2120)\n    float m_flRecoveryTimeStandFinal;                    // +0x084c (2124)\n    std::int32_t m_nRecoveryTransitionStartBullet;       // +0x0850 (2128)\n    std::int32_t m_nRecoveryTransitionEndBullet;         // +0x0854 (2132)\n    float m_flThrowVelocity;                             // +0x0858 (2136)\n    Vector3 m_vSmokeColor;                               // +0x085c (2140)\n    char m_szAnimClass[56];                              // +0x0868 (2152)\n};\n\nstatic_assert(sizeof(CCSWeaponBaseVData) == 0x8A0, \"CCSWeaponBaseVData size must be 2208 bytes (0x8A0)\");\nstatic_assert(offsetof(CCSWeaponBaseVData, m_WeaponType) == 0x520, \"m_WeaponType offset mismatch\");\nstatic_assert(offsetof(CCSWeaponBaseVData, m_szName) == 0x720, \"m_szName offset mismatch\");\nstatic_assert(offsetof(CCSWeaponBaseVData, m_flCycleTime) == 0x738, \"m_flCycleTime offset mismatch\");\nstatic_assert(offsetof(CCSWeaponBaseVData, m_flSpread) == 0x750, \"m_flSpread offset mismatch\");\nstatic_assert(offsetof(CCSWeaponBaseVData, m_flInaccuracyCrouch) == 0x758, \"m_flInaccuracyCrouch offset mismatch\");\nstatic_assert(offsetof(CCSWeaponBaseVData, m_flInaccuracyStand) == 0x760, \"m_flInaccuracyStand offset mismatch\");\nstatic_assert(offsetof(CCSWeaponBaseVData, m_flInaccuracyJump) == 0x768, \"m_flInaccuracyJump offset mismatch\");\nstatic_assert(offsetof(CCSWeaponBaseVData, m_flInaccuracyMove) == 0x788, \"m_flInaccuracyMove offset mismatch\");\nstatic_assert(offsetof(CCSWeaponBaseVData, m_nDamage) == 0x820, \"m_nDamage offset mismatch\");\nstatic_assert(offsetof(CCSWeaponBaseVData, m_flArmorRatio) == 0x828, \"m_flArmorRatio offset mismatch\");\nstatic_assert(offsetof(CCSWeaponBaseVData, m_flPenetration) == 0x82c, \"m_flPenetration offset mismatch\");\nstatic_assert(offsetof(CCSWeaponBaseVData, m_flRange) == 0x830, \"m_flRange offset mismatch\");\nstatic_assert(offsetof(CCSWeaponBaseVData, m_flRangeModifier) == 0x834, \"m_flRangeModifier offset mismatch\");\n\n#undef PAD\n\n} // namespace cs2::sdk\n"
      }
    },
    {
      "module": "animationsystem.dll",
      "directory": "game/animationsystem",
      "standard": "C++20 (/std:c++20 /W4)",
      "files": {
        "animgraph_blender.cpp": "#include \"animgraph_blender.h\"\n#include <cmath>\n#include <algorithm>\n#include <cassert>\n\nnamespace cs2::animationsystem {\n\nQuaternion Quaternion::FromAngleAxis(const Vector3& axis, float angleRad) noexcept {\n    // Reconstructed from animationsystem.dll @ FUN_18038dcc0\n    float lenSqr = axis.LengthSqr();\n    if (lenSqr < 1e-6f || std::abs(angleRad) < 1e-6f) {\n        return {0.0f, 0.0f, 0.0f, 1.0f}; // Identity\n    }\n\n    float halfAngle = angleRad * 0.5f;\n    float sinHalf = std::sin(halfAngle);\n    float cosHalf = std::cos(halfAngle);\n\n    Vector3 normAxis = axis.Normalized();\n    return {\n        normAxis.x * sinHalf,\n        normAxis.y * sinHalf,\n        normAxis.z * sinHalf,\n        cosHalf\n    };\n}\n\nQuaternion Quaternion::Nlerp(\n    const Quaternion& q1,\n    const Quaternion& q2,\n    float t,\n    bool shortestArc) noexcept {\n\n    float dot = q1.Dot(q2);\n    Quaternion targetQ = q2;\n\n    // Shortest-arc check: if dot < 0, invert target to prevent 360-degree spins\n    if (shortestArc && dot < 0.0f) {\n        targetQ = -q2;\n    }\n\n    float invT = 1.0f - t;\n    Quaternion result{\n        q1.x * invT + targetQ.x * t,\n        q1.y * invT + targetQ.y * t,\n        q1.z * invT + targetQ.z * t,\n        q1.w * invT + targetQ.w * t\n    };\n\n    return result.Normalized();\n}\n\nQuaternion Quaternion::Slerp(\n    const Quaternion& q1,\n    const Quaternion& q2,\n    float t,\n    bool shortestArc) noexcept {\n\n    // Reconstructed from animationsystem.dll @ 0x1804721a0 / 0x180472ba1\n    float dot = q1.Dot(q2);\n    Quaternion targetQ = q2;\n\n    // Shortest-arc check\n    if (shortestArc && dot < 0.0f) {\n        targetQ = -q2;\n        dot = -dot;\n    }\n\n    // If quaternions are extremely close, fall back to Nlerp to prevent division by zero in sin(theta)\n    if (dot > 0.9995f) {\n        return Nlerp(q1, targetQ, t, false);\n    }\n\n    dot = std::clamp(dot, -1.0f, 1.0f);\n    float theta = std::acos(dot);\n    float sinTheta = std::sin(theta);\n\n    if (sinTheta < 1e-6f) {\n        return Nlerp(q1, targetQ, t, false);\n    }\n\n    float w1 = std::sin((1.0f - t) * theta) / sinTheta;\n    float w2 = std::sin(t * theta) / sinTheta;\n\n    return {\n        q1.x * w1 + targetQ.x * w2,\n        q1.y * w1 + targetQ.y * w2,\n        q1.z * w1 + targetQ.z * w2,\n        q1.w * w1 + targetQ.w * w2\n    };\n}\n\nBoneTransform BoneTransform::Lerp(\n    const BoneTransform& a,\n    const BoneTransform& b,\n    float t,\n    bool useSlerp) noexcept {\n\n    BoneTransform res;\n    float invT = 1.0f - t;\n\n    // Translation LERP\n    res.translation = a.translation * invT + b.translation * t;\n\n    // Rotation shortest-arc SLERP or NLERP\n    if (useSlerp) {\n        res.rotation = Quaternion::Slerp(a.rotation, b.rotation, t, true);\n    } else {\n        res.rotation = Quaternion::Nlerp(a.rotation, b.rotation, t, true);\n    }\n\n    // Scale LERP\n    res.scale = a.scale * invT + b.scale * t;\n    return res;\n}\n\nvoid CStateMachineUpdateNode::StartTransition(\n    int targetStateID,\n    float startTime,\n    float duration,\n    TransitionBlendType blendType) noexcept {\n\n    m_nTargetStateID = targetStateID;\n    m_flTransitionStartTime = startTime;\n    m_flTransitionDuration = std::max(duration, 1e-4f);\n    m_bIsTransitioning = true;\n    m_eBlendType = blendType;\n}\n\nfloat CStateMachineUpdateNode::EvaluateTransitionProgress(float currentTime) const noexcept {\n    // Reconstructed from animationsystem.dll @ FUN_180361670\n    if (!m_bIsTransitioning || m_flTransitionDuration <= 0.0f) {\n        return 1.0f;\n    }\n\n    float elapsed = currentTime - m_flTransitionStartTime;\n    if (elapsed <= 0.0f) {\n        return 0.0f;\n    }\n\n    float progress = elapsed / m_flTransitionDuration;\n    return std::clamp(progress, 0.0f, 1.0f);\n}\n\nfloat CStateMachineUpdateNode::EvaluateCrossfadeWeight(float currentTime) const noexcept {\n    float t = EvaluateTransitionProgress(currentTime);\n\n    switch (m_eBlendType) {\n        case TransitionBlendType::Linear:\n            return TransitionBlendMath::Linear(t);\n        case TransitionBlendType::HermiteSmoothStep:\n        default:\n            return TransitionBlendMath::HermiteSmoothStep(t);\n    }\n}\n\nvoid CStateMachineUpdateNode::Update(const CAnimUpdateContext& context) noexcept {\n    // Reconstructed from animationsystem.dll @ FUN_1802c82c0\n    if (!m_bIsTransitioning) {\n        return;\n    }\n\n    float progress = EvaluateTransitionProgress(context.m_flCurrentTime);\n    if (progress >= 1.0f) {\n        // Transition complete: commit target state\n        m_nCurrentStateID = m_nTargetStateID;\n        m_nTargetStateID = -1;\n        m_bIsTransitioning = false;\n        m_flTransitionStartTime = 0.0f;\n        m_flTransitionDuration = 0.0f;\n    }\n}\n\nstd::pair<CBlendUpdateNode::ChildWeight, CBlendUpdateNode::ChildWeight>\nCBlendUpdateNode::ComputeBlendWeights(float blendValue, int numChildren) noexcept {\n    // Reconstructed from animationsystem.dll @ FUN_1802d7a80\n    ChildWeight first{-1, 0.0f};\n    ChildWeight second{-1, 0.0f};\n\n    if (numChildren <= 0) {\n        return {first, second};\n    }\n    if (numChildren == 1) {\n        first = {0, 1.0f};\n        return {first, second};\n    }\n\n    float clampedVal = std::clamp(blendValue, 0.0f, static_cast<float>(numChildren - 1));\n    float baseIndexF = std::floor(clampedVal);\n    int baseIndex = static_cast<int>(baseIndexF);\n\n    if (baseIndex >= numChildren - 1) {\n        first = {numChildren - 1, 1.0f};\n        return {first, second};\n    }\n\n    float frac = clampedVal - baseIndexF; // In [0, 1]\n    float weightA = 1.0f - frac;\n    float weightB = frac;\n\n    first = {baseIndex, weightA};\n    second = {baseIndex + 1, weightB};\n\n    return {first, second};\n}\n\nvoid CBlendUpdateNode::BlendPose(\n    const std::vector<BoneTransform>& poseA,\n    const std::vector<BoneTransform>& poseB,\n    float weight,\n    std::vector<BoneTransform>& outPose,\n    bool useSlerp) noexcept {\n\n    size_t count = std::min(poseA.size(), poseB.size());\n    outPose.resize(count);\n\n    float clampedWeight = std::clamp(weight, 0.0f, 1.0f);\n\n    for (size_t i = 0; i < count; ++i) {\n        outPose[i] = BoneTransform::Lerp(poseA[i], poseB[i], clampedWeight, useSlerp);\n    }\n}\n\n} // namespace cs2::animationsystem\n",
        "animgraph_blender.h": "#ifndef CS2_ANIMGRAPH_BLENDER_H\n#define CS2_ANIMGRAPH_BLENDER_H\n\n#include \"two_bone_ik.h\"\n#include <vector>\n#include <algorithm>\n#include <cmath>\n\nnamespace cs2::animationsystem {\n\n/**\n * @brief 4D Unit Quaternion for Source 2 rotation transforms.\n * Matches packed 16-byte representation in animationsystem.dll.\n */\nstruct Quaternion {\n    float x{0.0f}, y{0.0f}, z{0.0f}, w{1.0f};\n\n    constexpr Quaternion() noexcept = default;\n    constexpr Quaternion(float _x, float _y, float _z, float _w) noexcept\n        : x(_x), y(_y), z(_z), w(_w) {}\n\n    [[nodiscard]] float Dot(const Quaternion& o) const noexcept {\n        return x * o.x + y * o.y + z * o.z + w * o.w;\n    }\n\n    [[nodiscard]] float LengthSqr() const noexcept {\n        return Dot(*this);\n    }\n\n    [[nodiscard]] float Length() const noexcept {\n        return std::sqrt(LengthSqr());\n    }\n\n    [[nodiscard]] Quaternion Normalized() const noexcept {\n        float len = Length();\n        if (len > 1e-6f) {\n            float inv = 1.0f / len;\n            return {x * inv, y * inv, z * inv, w * inv};\n        }\n        return {0.0f, 0.0f, 0.0f, 1.0f};\n    }\n\n    // Unary negation for shortest-arc quaternion alignment\n    [[nodiscard]] Quaternion operator-() const noexcept {\n        return {-x, -y, -z, -w};\n    }\n\n    [[nodiscard]] Quaternion operator+(const Quaternion& o) const noexcept {\n        return {x + o.x, y + o.y, z + o.z, w + o.w};\n    }\n\n    [[nodiscard]] Quaternion operator*(float s) const noexcept {\n        return {x * s, y * s, z * s, w * s};\n    }\n\n    // Hamilton quaternion product\n    [[nodiscard]] Quaternion operator*(const Quaternion& o) const noexcept {\n        return {\n            w * o.x + x * o.w + y * o.z - z * o.y,\n            w * o.y - x * o.z + y * o.w + z * o.x,\n            w * o.z + x * o.y - y * o.x + z * o.w,\n            w * o.w - x * o.x - y * o.y - z * o.z\n        };\n    }\n\n    /**\n     * @brief Rotate a 3D vector by this quaternion.\n     * Uses Rodrigues formula optimized for multiply-adds without trigonometric calls:\n     *   t = 2 * (q.xyz cross v)\n     *   v' = v + q.w * t + (q.xyz cross t)\n     */\n    [[nodiscard]] Vector3 RotateVector(const Vector3& v) const noexcept {\n        Vector3 qv{x, y, z};\n        Vector3 t = qv.Cross(v) * 2.0f;\n        return v + (t * w) + qv.Cross(t);\n    }\n\n    /**\n     * @brief Reconstructed from animationsystem.dll @ FUN_18038dcc0 (Quaternion_FromAngleAxis).\n     * Computes unit quaternion from axis and angle: q = (axis * sin(theta/2), cos(theta/2)).\n     */\n    [[nodiscard]] static Quaternion FromAngleAxis(const Vector3& axis, float angleRad) noexcept;\n\n    /**\n     * @brief Normalized Linear Interpolation (Nlerp) with shortest-arc check.\n     * If dot(q1, q2) < 0, q2 is negated to take the shortest geodesic arc.\n     */\n    [[nodiscard]] static Quaternion Nlerp(\n        const Quaternion& q1,\n        const Quaternion& q2,\n        float t,\n        bool shortestArc = true) noexcept;\n\n    /**\n     * @brief Spherical Linear Interpolation (Slerp) with shortest-arc check.\n     * Reconstructed from animationsystem.dll sequence blend engine (0x1804721a0).\n     */\n    [[nodiscard]] static Quaternion Slerp(\n        const Quaternion& q1,\n        const Quaternion& q2,\n        float t,\n        bool shortestArc = true) noexcept;\n};\n\n/**\n * @brief Packed bone transform in parent or world coordinate space.\n * Size: 32 bytes (16 bytes rotation + 12 bytes translation + 4 bytes scale).\n */\nstruct alignas(16) BoneTransform {\n    Quaternion rotation{0.0f, 0.0f, 0.0f, 1.0f}; // +0x00 (16 bytes)\n    Vector3 translation{0.0f, 0.0f, 0.0f};        // +0x10 (12 bytes)\n    float scale{1.0f};                            // +0x1C (4 bytes)\n\n    /**\n     * @brief Linearly interpolates bone translation & scale, and performs\n     * shortest-arc Slerp/Nlerp on rotation.\n     */\n    [[nodiscard]] static BoneTransform Lerp(\n        const BoneTransform& a,\n        const BoneTransform& b,\n        float t,\n        bool useSlerp = false) noexcept;\n};\n\n/**\n * @brief Execution context passed through AnimGraph update nodes.\n * Reconstructed from animationsystem.dll CAnimUpdateContext.\n */\nstruct CAnimUpdateContext {\n    float m_flCurrentTime{0.0f};\n    float m_flDeltaTime{0.0f};\n    float m_flPlaybackRate{1.0f};\n};\n\n/**\n * @brief Transition curve blending formulas for state transitions.\n */\nenum class TransitionBlendType : uint8_t {\n    Linear = 0,\n    HermiteSmoothStep = 1\n};\n\nclass TransitionBlendMath {\npublic:\n    /// Linear crossfade weight w(t) = clamp(t, 0, 1)\n    [[nodiscard]] static float Linear(float t) noexcept {\n        return std::clamp(t, 0.0f, 1.0f);\n    }\n\n    /// Hermite cubic smoothstep crossfade weight: w(t) = 3t^2 - 2t^3\n    [[nodiscard]] static float HermiteSmoothStep(float t) noexcept {\n        float c = std::clamp(t, 0.0f, 1.0f);\n        return c * c * (3.0f - 2.0f * c);\n    }\n};\n\n/**\n * @brief Reconstructed State Machine Update Node from animationsystem.dll.\n * Associated VTable: 0x180687838.\n * Evaluates active transitions, elapsed cross-fade weight w(t), and state switches.\n */\nclass CStateMachineUpdateNode {\npublic:\n    int m_nCurrentStateID{-1};\n    int m_nTargetStateID{-1};\n    float m_flTransitionStartTime{0.0f};\n    float m_flTransitionDuration{0.0f};\n    bool m_bIsTransitioning{false};\n    TransitionBlendType m_eBlendType{TransitionBlendType::HermiteSmoothStep};\n\n    CStateMachineUpdateNode() = default;\n\n    /**\n     * @brief Initiates a transition to a target state.\n     */\n    void StartTransition(\n        int targetStateID,\n        float startTime,\n        float duration,\n        TransitionBlendType blendType = TransitionBlendType::HermiteSmoothStep) noexcept;\n\n    /**\n     * @brief Reconstructed from animationsystem.dll @ FUN_180361670.\n     * Evaluates normalized transition progress t in [0, 1].\n     */\n    [[nodiscard]] float EvaluateTransitionProgress(float currentTime) const noexcept;\n\n    /**\n     * @brief Evaluates active transition cross-fade weight w(t) in [0, 1].\n     * Applies linear or Hermite smoothstep (3t^2 - 2t^3) interpolation.\n     */\n    [[nodiscard]] float EvaluateCrossfadeWeight(float currentTime) const noexcept;\n\n    /**\n     * @brief Updates state machine transitions using evaluation context.\n     * Reconstructed from animationsystem.dll @ FUN_1802c82c0.\n     */\n    void Update(const CAnimUpdateContext& context) noexcept;\n};\n\n/**\n * @brief Reconstructed 1D Blend Node from animationsystem.dll.\n * Associated VTable: 0x18065bb80.\n * Computes interpolation weights and blends skeletal poses.\n */\nclass CBlendUpdateNode {\npublic:\n    struct ChildWeight {\n        int childIndex{-1};\n        float weight{0.0f};\n    };\n\n    /**\n     * @brief Reconstructed from animationsystem.dll @ FUN_1802d7a80.\n     * Computes adjacent child indices and normalized linear blend weights from a continuous blend parameter.\n     */\n    [[nodiscard]] static std::pair<ChildWeight, ChildWeight> ComputeBlendWeights(\n        float blendValue,\n        int numChildren) noexcept;\n\n    /**\n     * @brief Blends two skeletal poses (bone arrays) using shortest-arc quaternion Slerp/Nlerp.\n     */\n    static void BlendPose(\n        const std::vector<BoneTransform>& poseA,\n        const std::vector<BoneTransform>& poseB,\n        float weight,\n        std::vector<BoneTransform>& outPose,\n        bool useSlerp = false) noexcept;\n};\n\n} // namespace cs2::animationsystem\n\n#endif // CS2_ANIMGRAPH_BLENDER_H\n",
        "two_bone_ik.cpp": "#include \"two_bone_ik.h\"\n#include <algorithm>\n\nnamespace cs2::animationsystem {\n\nIKSolveResult CTwoBoneIKSolver::Solve(\n    const Vector3& root,\n    const Vector3& target,\n    const Vector3& poleTarget,\n    float len1,\n    float len2) {\n\n    IKSolveResult res;\n    res.rootPos = root;\n\n    Vector3 toTarget = target - root;\n    float dist = toTarget.Length();\n    const float maxDist = len1 + len2;\n    const float minDist = std::abs(len1 - len2);\n\n    // Target clamp / reachability\n    if (dist >= maxDist) {\n        res.reachedTarget = false;\n        Vector3 dir = toTarget.Normalized();\n        res.midPos = root + (dir * len1);\n        res.effectorPos = root + (dir * maxDist);\n        return res;\n    }\n\n    if (dist <= minDist) {\n        dist = minDist + 1e-4f;\n    }\n\n    Vector3 targetDir = toTarget * (1.0f / dist);\n\n    // Law of Cosines for the angle at the root joint: cos(alpha) = (L1^2 + D^2 - L2^2) / (2 * L1 * D)\n    float cosAlpha = (len1 * len1 + dist * dist - len2 * len2) / (2.0f * len1 * dist);\n    cosAlpha = std::clamp(cosAlpha, -1.0f, 1.0f);\n    float sinAlpha = std::sqrt(std::max(0.0f, 1.0f - cosAlpha * cosAlpha));\n\n    // Plane normal defined by root-target line and pole target\n    Vector3 poleDir = (poleTarget - root).Normalized();\n    Vector3 planeNormal = targetDir.Cross(poleDir);\n    if (planeNormal.LengthSqr() < 1e-6f) {\n        // Fallback default up vector\n        planeNormal = targetDir.Cross(Vector3{0.0f, 0.0f, 1.0f});\n        if (planeNormal.LengthSqr() < 1e-6f) {\n            planeNormal = targetDir.Cross(Vector3{0.0f, 1.0f, 0.0f});\n        }\n    }\n    planeNormal = planeNormal.Normalized();\n\n    // Bend axis perpendicular to target line in the plane of the pole vector\n    Vector3 bendDir = planeNormal.Cross(targetDir).Normalized();\n\n    // Mid position = root + (targetDir * cosAlpha * len1) + (bendDir * sinAlpha * len1)\n    res.midPos = root + (targetDir * (cosAlpha * len1)) + (bendDir * (sinAlpha * len1));\n    res.effectorPos = target;\n    res.reachedTarget = true;\n\n    return res;\n}\n\n} // namespace cs2::animationsystem\n",
        "two_bone_ik.h": "#ifndef CS2_TWO_BONE_IK_H\n#define CS2_TWO_BONE_IK_H\n\n#include <cmath>\n#include <tuple>\n\nnamespace cs2::animationsystem {\n\nstruct Vector3 {\n    float x{0.0f}, y{0.0f}, z{0.0f};\n\n    Vector3 operator+(const Vector3& o) const noexcept { return {x + o.x, y + o.y, z + o.z}; }\n    Vector3 operator-(const Vector3& o) const noexcept { return {x - o.x, y - o.y, z - o.z}; }\n    Vector3 operator*(float s) const noexcept { return {x * s, y * s, z * s}; }\n    [[nodiscard]] float Dot(const Vector3& o) const noexcept { return x * o.x + y * o.y + z * o.z; }\n    [[nodiscard]] float LengthSqr() const noexcept { return Dot(*this); }\n    [[nodiscard]] float Length() const noexcept { return std::sqrt(LengthSqr()); }\n    [[nodiscard]] Vector3 Cross(const Vector3& o) const noexcept {\n        return {y * o.z - z * o.y, z * o.x - x * o.z, x * o.y - y * o.x};\n    }\n    [[nodiscard]] Vector3 Normalized() const noexcept {\n        float l = Length();\n        return l > 1e-6f ? (*this) * (1.0f / l) : Vector3{0, 0, 0};\n    }\n};\n\nstruct IKSolveResult {\n    Vector3 rootPos;\n    Vector3 midPos;\n    Vector3 effectorPos;\n    bool reachedTarget{true};\n};\n\n/**\n * @brief Reconstructed Two-Bone IK solver from animationsystem.dll @ FUN_1802f9750.\n * Applied for player leg IK foot-planting and weapon procedural hand placement.\n */\nclass CTwoBoneIKSolver {\npublic:\n    /**\n     * @brief Solves analytical two-bone IK using the Law of Cosines and pole vector plane projection.\n     * @param root Starting joint position (e.g. hip or shoulder)\n     * @param target Desired end effector target (e.g. foot ground contact or weapon grip)\n     * @param poleTarget Direction vector for the bending joint (knee or elbow forward)\n     * @param len1 Upper bone length\n     * @param len2 Lower bone length\n     */\n    static IKSolveResult Solve(\n        const Vector3& root,\n        const Vector3& target,\n        const Vector3& poleTarget,\n        float len1,\n        float len2);\n};\n\n} // namespace cs2::animationsystem\n\n#endif // CS2_TWO_BONE_IK_H\n"
      }
    },
    {
      "module": "client.dll",
      "directory": "game/client",
      "standard": "C++20 (/std:c++20 /W4)",
      "files": {
        "bone_setup.cpp": "#include \"bone_setup.h\"\n#include <cstring>\n#include <cmath>\n\nnamespace cs2::client {\n\n// ============================================================================\n// CBoneMergeCache Implementation\n// ============================================================================\nvoid CBoneMergeCache::Init(CSkeletonInstance* pOwner, CSkeletonInstance* pFollower, const int* pBoneMap, int count) noexcept {\n    m_pOwner = pOwner;\n    m_pFollower = pFollower;\n    m_mergedBoneIndices.clear();\n\n    if (!pOwner || !pFollower || !pBoneMap || count <= 0) {\n        return;\n    }\n\n    const int ownerMax = pOwner->GetBoneCount();\n    for (int i = 0; i < count; ++i) {\n        const int ownerIdx = pBoneMap[i];\n        if (ownerIdx >= 0 && ownerIdx < ownerMax) {\n            m_mergedBoneIndices.push_back({i, ownerIdx});\n        }\n    }\n}\n\nint CBoneMergeCache::MergeBones(matrix3x4_t* pOutFollowerBones, const matrix3x4_t* pOwnerBones) const noexcept {\n    if (!pOutFollowerBones || !pOwnerBones || m_mergedBoneIndices.empty()) {\n        return 0;\n    }\n\n    int merged = 0;\n    for (const auto& pair : m_mergedBoneIndices) {\n        pOutFollowerBones[pair.followerBoneIndex] = pOwnerBones[pair.ownerBoneIndex];\n        ++merged;\n    }\n    return merged;\n}\n\n// ============================================================================\n// C_BaseEntityAnimGraph Implementation\n// ============================================================================\nC_BaseEntityAnimGraph::C_BaseEntityAnimGraph() = default;\n\nvoid C_BaseEntityAnimGraph::AttachSkeleton(CSkeletonInstance* pSkeleton, const int* pBoneParents, int boneCount) noexcept {\n    m_pSkeletonInstance = pSkeleton;\n    m_boneParents.clear();\n    m_localBoneTransforms.clear();\n    m_worldBoneTransforms.clear();\n    m_cachedBoneMatrices.clear();\n\n    if (!pSkeleton || boneCount <= 0) return;\n\n    m_boneParents.resize(static_cast<std::size_t>(boneCount), -1);\n    m_localBoneTransforms.resize(static_cast<std::size_t>(boneCount));\n    m_worldBoneTransforms.resize(static_cast<std::size_t>(boneCount));\n    m_cachedBoneMatrices.resize(static_cast<std::size_t>(boneCount));\n\n    if (pBoneParents) {\n        for (int i = 0; i < boneCount; ++i) {\n            m_boneParents[static_cast<std::size_t>(i)] = pBoneParents[i];\n        }\n    }\n\n    // Set bone array pointer and count in CModelState\n    pSkeleton->m_modelState.m_nBoneCount = static_cast<std::uint16_t>(boneCount);\n    pSkeleton->m_modelState.m_pBoneArray = m_worldBoneTransforms.data();\n    pSkeleton->ClearCalculatedBoneFlags();\n}\n\nvoid C_BaseEntityAnimGraph::SetLocalBoneTransform(int boneIndex, const CTransform& localTransform) noexcept {\n    if (boneIndex >= 0 && static_cast<std::size_t>(boneIndex) < m_localBoneTransforms.size()) {\n        m_localBoneTransforms[static_cast<std::size_t>(boneIndex)] = localTransform;\n        if (m_pSkeletonInstance) {\n            m_pSkeletonInstance->ClearCalculatedBoneFlags();\n        }\n    }\n}\n\nvoid C_BaseEntityAnimGraph::CalculateWorldBones(std::uint32_t boneMask) noexcept {\n    if (!m_pSkeletonInstance || m_boneParents.empty()) return;\n\n    const std::size_t count = m_boneParents.size();\n    const CTransform& rootToWorld = m_pSkeletonInstance->m_nodeToWorld;\n\n    for (std::size_t i = 0; i < count; ++i) {\n        const int parentIdx = m_boneParents[i];\n        if (parentIdx < 0 || static_cast<std::size_t>(parentIdx) >= count) {\n            // Root bone: concatenate with model's root m_nodeToWorld\n            CTransform::ConcatenateTransforms(rootToWorld, m_localBoneTransforms[i], &m_worldBoneTransforms[i]);\n        } else {\n            // Child bone: concatenate with parent bone's evaluated world CTransform\n            CTransform::ConcatenateTransforms(m_worldBoneTransforms[static_cast<std::size_t>(parentIdx)],\n                                              m_localBoneTransforms[i],\n                                              &m_worldBoneTransforms[i]);\n        }\n\n        // Convert to matrix3x4_t format for skinning and ray-tracing\n        m_cachedBoneMatrices[i] = m_worldBoneTransforms[i].ToMatrix3x4();\n    }\n\n    m_pSkeletonInstance->SetCalculatedBoneFlags(boneMask | shared::BONE_FLAG_CALCULATED | shared::BONE_FLAG_WORLD_SPACE);\n}\n\nbool C_BaseEntityAnimGraph::SetupBones(matrix3x4_t* pOutBones, int maxBones, std::uint32_t boneMask, float currentTime) noexcept {\n    if (!m_pSkeletonInstance || !pOutBones || maxBones <= 0) return false;\n\n    const int boneCount = m_pSkeletonInstance->GetBoneCount();\n    if (boneCount <= 0 || boneCount > maxBones) return false;\n\n    // 1. Lazy evaluation check: if bones were already calculated for this mask and timestamp, copy cached matrices\n    if (m_flLastBoneSetupTime == currentTime && m_pSkeletonInstance->HasCalculatedBones(boneMask)) {\n        for (int i = 0; i < boneCount; ++i) {\n            pOutBones[i] = m_cachedBoneMatrices[static_cast<std::size_t>(i)];\n        }\n        return true;\n    }\n\n    // 2. Evaluate forward kinematics traversal\n    CalculateWorldBones(boneMask);\n    m_flLastBoneSetupTime = currentTime;\n\n    // 3. Export to caller buffer\n    for (int i = 0; i < boneCount; ++i) {\n        pOutBones[i] = m_cachedBoneMatrices[static_cast<std::size_t>(i)];\n    }\n\n    return true;\n}\n\nbool C_BaseEntityAnimGraph::GetBonePosition(int boneIndex, Vector3D& outPos) const noexcept {\n    if (!m_pSkeletonInstance || boneIndex < 0 ||\n        static_cast<std::size_t>(boneIndex) >= m_worldBoneTransforms.size()) {\n        return false;\n    }\n    outPos = m_worldBoneTransforms[static_cast<std::size_t>(boneIndex)].GetPosition();\n    return true;\n}\n\nbool C_BaseEntityAnimGraph::GetBoneMatrix(int boneIndex, matrix3x4_t& outMatrix) const noexcept {\n    if (!m_pSkeletonInstance || boneIndex < 0 ||\n        static_cast<std::size_t>(boneIndex) >= m_cachedBoneMatrices.size()) {\n        return false;\n    }\n    outMatrix = m_cachedBoneMatrices[static_cast<std::size_t>(boneIndex)];\n    return true;\n}\n\nbool C_BaseEntityAnimGraph::GetHitboxWorldBounds(const CHitBox& hitbox, Vector3D& outWorldCenter, Vector3D& outWorldMins, Vector3D& outWorldMaxs) const noexcept {\n    matrix3x4_t boneMatrix;\n    if (!GetBoneMatrix(static_cast<int>(hitbox.m_nBoneId), boneMatrix)) {\n        return false;\n    }\n\n    // Transform local minimum and maximum bounding coordinates\n    const Vector3D p1 = boneMatrix.TransformVector(hitbox.m_vMinBounds);\n    const Vector3D p2 = boneMatrix.TransformVector(hitbox.m_vMaxBounds);\n\n    outWorldCenter = (p1 + p2) * 0.5f;\n    outWorldMins = {\n        std::min(p1.x, p2.x) - hitbox.m_flShapeRadius,\n        std::min(p1.y, p2.y) - hitbox.m_flShapeRadius,\n        std::min(p1.z, p2.z) - hitbox.m_flShapeRadius\n    };\n    outWorldMaxs = {\n        std::max(p1.x, p2.x) + hitbox.m_flShapeRadius,\n        std::max(p1.y, p2.y) + hitbox.m_flShapeRadius,\n        std::max(p1.z, p2.z) + hitbox.m_flShapeRadius\n    };\n\n    return true;\n}\n\n} // namespace cs2::client\n",
        "bone_setup.h": "#ifndef CS2_CLIENT_BONE_SETUP_H\n#define CS2_CLIENT_BONE_SETUP_H\n\n#include <cstdint>\n#include <vector>\n#include <memory>\n#include \"../shared/skeleton.h\"\n#include \"../shared/hitbox.h\"\n\nnamespace cs2::client {\n\nusing shared::CTransform;\nusing shared::matrix3x4_t;\nusing shared::Vector3D;\nusing shared::CSkeletonInstance;\nusing shared::CHitBox;\nusing shared::BoneFlags_t;\n\n// ============================================================================\n// Source 2 Bone Merge Cache (CBoneMergeCache)\n// Reconstructed from client.dll @ 0x180b3d820\n// Handles hierarchical bone synchronization between parent models (e.g. player pawn)\n// and child attachments (e.g. viewmodel weapons, equipment, gloves).\n// ============================================================================\nclass CBoneMergeCache {\npublic:\n    CBoneMergeCache() = default;\n    ~CBoneMergeCache() = default;\n\n    /**\n     * @brief Initializes the merge lookup mapping from follower model bones to owner model bones.\n     * @param pOwner Parent skeleton instance (e.g. player body)\n     * @param pFollower Child skeleton instance (e.g. weapon / gloves)\n     * @param pBoneMap Mapping table where index = followerBone, value = ownerBone (-1 if unmapped)\n     * @param count Total number of follower bones\n     */\n    void Init(CSkeletonInstance* pOwner, CSkeletonInstance* pFollower, const int* pBoneMap, int count) noexcept;\n\n    /**\n     * @brief Copies and merges computed bone matrices from the owner skeleton to the follower.\n     * @param pOutFollowerBones Output array of follower bone matrices\n     * @param pOwnerBones Source array of computed owner bone matrices\n     * @return Number of bones successfully merged\n     */\n    int MergeBones(matrix3x4_t* pOutFollowerBones, const matrix3x4_t* pOwnerBones) const noexcept;\n\n    [[nodiscard]] bool IsValid() const noexcept {\n        return m_pOwner != nullptr && m_pFollower != nullptr && !m_mergedBoneIndices.empty();\n    }\n\n    [[nodiscard]] int GetMergedCount() const noexcept {\n        return static_cast<int>(m_mergedBoneIndices.size());\n    }\n\nprivate:\n    CSkeletonInstance* m_pOwner{nullptr};\n    CSkeletonInstance* m_pFollower{nullptr};\n    struct MergedBonePair {\n        int followerBoneIndex;\n        int ownerBoneIndex;\n    };\n    std::vector<MergedBonePair> m_mergedBoneIndices;\n};\n\n// ============================================================================\n// Animation Graph Controller (C_BaseAnimGraphController)\n// Manages playback cycles, sequence transitions, and AnimGraph blend tree states.\n// ============================================================================\nclass C_BaseAnimGraphController {\npublic:\n    C_BaseAnimGraphController() = default;\n\n    void Reset(int sequenceIndex = 0) noexcept {\n        m_nSequence = sequenceIndex;\n        m_flCycle = 0.0f;\n        m_flPlaybackRate = 1.0f;\n        m_bSequenceFinished = false;\n    }\n\n    void AdvanceTime(float dt) noexcept {\n        if (m_bSequenceFinished) return;\n        m_flCycle += dt * m_flPlaybackRate;\n        if (m_flCycle >= 1.0f) {\n            m_flCycle = 1.0f;\n            m_bSequenceFinished = true;\n        }\n    }\n\n    [[nodiscard]] float GetCycle() const noexcept { return m_flCycle; }\n    [[nodiscard]] int GetSequence() const noexcept { return m_nSequence; }\n    [[nodiscard]] float GetPlaybackRate() const noexcept { return m_flPlaybackRate; }\n    [[nodiscard]] bool IsSequenceFinished() const noexcept { return m_bSequenceFinished; }\n\n    void SetPlaybackRate(float rate) noexcept { m_flPlaybackRate = rate; }\n    void SetCycle(float cycle) noexcept { m_flCycle = std::clamp(cycle, 0.0f, 1.0f); }\n\nprivate:\n    int   m_nSequence{0};\n    float m_flCycle{0.0f};\n    float m_flPlaybackRate{1.0f};\n    bool  m_bSequenceFinished{false};\n};\n\n// ============================================================================\n// Client Animated Entity Graph (C_BaseEntityAnimGraph)\n// Reconstructed from client.dll (Size: 0x1268, Base Class of C_BaseCombatCharacter)\n// Reference: docs/09_skeleton_bone_hierarchy_and_animgraph.md\n// ============================================================================\nclass C_BaseEntityAnimGraph {\npublic:\n    C_BaseEntityAnimGraph();\n    virtual ~C_BaseEntityAnimGraph() = default;\n\n    /**\n     * @brief Primary client bone matrix setup pipeline.\n     * Reconstructed from client.dll @ FUN_180aa0f80 / 0x180b2a310.\n     * 1. Checks lazy evaluation dirty bitmask in CSkeletonInstance.\n     * 2. Evaluates inter-tick bone transform interpolation (t_curr between t_prev and t_sim).\n     * 3. Traverses skeletal hierarchy in topological order and concatenates local CTransforms.\n     * 4. Evaluates optional two-bone IK constraints for leg/foot or arm/weapon placement.\n     * 5. Converts CTransforms into 48-byte matrix3x4_t bones.\n     * 6. Commits boneMask to m_nCalculatedBoneFlags to cache evaluation for the render frame.\n     *\n     * @param pOutBones Destination buffer for transformed matrix3x4_t bones\n     * @param maxBones Size of destination buffer (must be >= boneCount)\n     * @param boneMask Bitmask of requested bone types (e.g. BONE_USED_BY_HITBOX)\n     * @param currentTime Current continuous render timestamp\n     * @return true if bones successfully evaluated or retrieved from cache\n     */\n    bool SetupBones(matrix3x4_t* pOutBones, int maxBones, std::uint32_t boneMask, float currentTime) noexcept;\n\n    /**\n     * @brief Executes hierarchical forward kinematics bone transform propagation.\n     * Matches client.dll @ CalculateWorldBones.\n     */\n    void CalculateWorldBones(std::uint32_t boneMask) noexcept;\n\n    /**\n     * @brief Computes world-space position of a bone by index.\n     */\n    [[nodiscard]] bool GetBonePosition(int boneIndex, Vector3D& outPos) const noexcept;\n\n    /**\n     * @brief Computes world-space matrix3x4_t of a bone by index.\n     */\n    [[nodiscard]] bool GetBoneMatrix(int boneIndex, matrix3x4_t& outMatrix) const noexcept;\n\n    /**\n     * @brief Projects a hitbox into world space using its attached bone matrix.\n     */\n    [[nodiscard]] bool GetHitboxWorldBounds(const CHitBox& hitbox, Vector3D& outWorldCenter, Vector3D& outWorldMins, Vector3D& outWorldMaxs) const noexcept;\n\n    // Hierarchy Configuration\n    void AttachSkeleton(CSkeletonInstance* pSkeleton, const int* pBoneParents, int boneCount) noexcept;\n    void SetLocalBoneTransform(int boneIndex, const CTransform& localTransform) noexcept;\n\n    // Simulation Timing\n    void SetSimulationTimes(float flPrevSimTime, float flSimTime) noexcept {\n        m_flPrevSimulationTime = flPrevSimTime;\n        m_flSimulationTime = flSimTime;\n    }\n\n    [[nodiscard]] CSkeletonInstance* GetSkeletonInstance() const noexcept { return m_pSkeletonInstance; }\n    [[nodiscard]] C_BaseAnimGraphController& GetAnimGraphController() noexcept { return m_animController; }\n    [[nodiscard]] CBoneMergeCache& GetBoneMergeCache() noexcept { return m_mergeCache; }\n\nprivate:\n    CSkeletonInstance*        m_pSkeletonInstance{nullptr};\n    C_BaseAnimGraphController m_animController;\n    CBoneMergeCache           m_mergeCache;\n\n    std::vector<int>          m_boneParents;          // Topological parent indices (-1 for root)\n    std::vector<CTransform>   m_localBoneTransforms;  // Local bone pose relative to parent\n    std::vector<CTransform>   m_worldBoneTransforms;  // Computed world-space CTransforms\n    std::vector<matrix3x4_t>  m_cachedBoneMatrices;   // Cached matrix3x4_t array\n\n    float m_flLastBoneSetupTime{-1.0f};\n    float m_flPrevSimulationTime{0.0f};\n    float m_flSimulationTime{0.0f};\n};\n\n} // namespace cs2::client\n\n#endif // CS2_CLIENT_BONE_SETUP_H\n",
        "entity_system.cpp": "#include \"entity_system.h\"\n\nnamespace cs2::client {\n\nCEntityIdentity* CGameEntitySystem::ResolveIdentity(shared::CEntityHandle handle) const noexcept {\n    if (!handle.IsValid()) return nullptr;\n\n    const std::uint32_t index = handle.GetEntryIndex();\n    if (index >= MAX_TOTAL_ENTITIES) return nullptr;\n\n    const std::uint32_t chunkIdx = index >> 9; // index / 512\n    const std::uint32_t slotIdx  = index & 0x1FF; // index % 512\n\n    if (chunkIdx >= MAX_CHUNKS) return nullptr;\n\n    CEntityIdentity* pChunk = m_EntityChunks[chunkIdx];\n    if (!pChunk) return nullptr;\n\n    return &pChunk[slotIdx];\n}\n\nvoid* CGameEntitySystem::ResolveEntity(shared::CEntityHandle handle) const noexcept {\n    CEntityIdentity* pIdentity = ResolveIdentity(handle);\n    if (!pIdentity) return nullptr;\n\n    // Serial verification: ensure entity slot hasn't been recycled\n    if (pIdentity->m_entityHandle.GetSerialNumber() != handle.GetSerialNumber()) {\n        return nullptr; // Stale handle\n    }\n\n    if (!pIdentity->IsActive()) {\n        return nullptr; // Dormant or queued for deletion\n    }\n\n    return pIdentity->m_pEntity;\n}\n\n} // namespace cs2::client\n",
        "entity_system.h": "#ifndef CS2_CLIENT_ENTITY_SYSTEM_H\n#define CS2_CLIENT_ENTITY_SYSTEM_H\n\n#include <cstdint>\n#include <cstddef>\n#include \"../shared/entity_handle.h\"\n\nnamespace cs2::client {\n\n#define CS2_PAD(bytes, name) private: [[maybe_unused]] std::uint8_t name[bytes]; public:\n\nconstexpr std::uint32_t MAX_TOTAL_ENTITIES   = 32768; // 64 chunks * 512 slots\nconstexpr std::uint32_t ENTITIES_PER_CHUNK   = 512;   // 0x200 slots per chunk\nconstexpr std::uint32_t MAX_CHUNKS           = 64;    // 0x40 chunks in table\n\n/**\n * @brief Authoritative Entity Identity Descriptor (CEntityIdentity)\n * Size: exactly 112 bytes (0x70), alignas(8).\n * Cacheline-aligned metadata container residing directly inside the 2D chunk array.\n */\nstruct alignas(8) CEntityIdentity {\n    void*                 m_pEntity{nullptr};        // +0x00: Active C_BaseEntity pointer (null if slot free)\n    void*                 m_pClassInfo{nullptr};     // +0x08: Runtime CSchemaClassInfo pointer\n    shared::CEntityHandle m_entityHandle{};          // +0x10: 32-bit handle (15-bit index, 17-bit serial)\n    std::uint32_t         m_flags{0};                // +0x14: Flags (0x02 = dormant, 0x04 = queued deletion)\n    CS2_PAD(0x40, m_pad18);                          // +0x18: Internal entity identity state\n    CEntityIdentity*      m_pPrev{nullptr};          // +0x58: Singly linked bucket pointer\n    CEntityIdentity*      m_pNext{nullptr};          // +0x60: Singly linked bucket pointer\n    CS2_PAD(0x08, m_pad68);                          // +0x68\n\n    [[nodiscard]] constexpr bool IsDormant() const noexcept { return (m_flags & 0x02) != 0; }\n    [[nodiscard]] constexpr bool IsQueuedForDeletion() const noexcept { return (m_flags & 0x04) != 0; }\n    [[nodiscard]] constexpr bool IsActive() const noexcept { return m_pEntity != nullptr && !IsDormant() && !IsQueuedForDeletion(); }\n};\nstatic_assert(sizeof(CEntityIdentity) == 0x70, \"CEntityIdentity must be exactly 0x70 (112 bytes)\");\n\n/**\n * @brief Source 2 Entity System Master Singleton (CGameEntitySystem)\n * Total Size: 8,576 bytes (0x2180).\n * Global Pointer in client.dll: client.dll + 0x271c8b8.\n */\nclass CGameEntitySystem {\npublic:\n    virtual ~CGameEntitySystem() = default;\n\n    // Slot 1: Release\n    virtual void Release() = 0;\n\n    // Slot 2: GetEntityIdentity (RVA: +0x007357c0, VA: 0x1807357c0)\n    virtual CEntityIdentity* GetEntityIdentity(int nIndex) = 0;\n\n    // Slot 3: GetEntityByIndex\n    virtual void* GetEntityByIndex(int nIndex) = 0;\n\n    CS2_PAD(0x08, m_pad0);\n    // +0x10: 2D Chunk Page-Table (64 pointers to 512-slot CEntityIdentity pages)\n    CEntityIdentity* m_EntityChunks[MAX_CHUNKS]{};\n    CS2_PAD(0x2170 - (MAX_CHUNKS * sizeof(void*)), m_padChunks);\n\n    /**\n     * @brief Resolves a 32-bit entity handle into a CEntityIdentity pointer.\n     * Matches client.dll @ 0x1807357c0 O(1) resolution algorithm.\n     */\n    [[nodiscard]] CEntityIdentity* ResolveIdentity(shared::CEntityHandle handle) const noexcept;\n\n    /**\n     * @brief Resolves an entity pointer by handle, verifying that serial numbers match.\n     */\n    [[nodiscard]] void* ResolveEntity(shared::CEntityHandle handle) const noexcept;\n};\n\n#undef CS2_PAD\n\n} // namespace cs2::client\n\n#endif // CS2_CLIENT_ENTITY_SYSTEM_H\n",
        "inventory_schema.cpp": "#include \"inventory_schema.h\"\n\n#include <numbers>\n#include <algorithm>\n#include <cstring>\n\nnamespace cs2::client {\n\n// ============================================================================\n// 1. Dynamic Attribute Key-Value Store Implementation\n// ============================================================================\n\nstd::uint32_t AttributeKeyValueStore::HashAttributeName(std::string_view name) noexcept {\n    // 32-bit FNV-1a Hash Algorithm\n    std::uint32_t hash = 2166136261u;\n    for (char c : name) {\n        hash ^= static_cast<std::uint8_t>(c);\n        hash *= 16777619u;\n    }\n    return hash;\n}\n\nvoid AttributeKeyValueStore::SetAttribute(std::uint16_t defIndex, AttributeValue value) {\n    m_indexedAttributes[defIndex] = std::move(value);\n}\n\nvoid AttributeKeyValueStore::SetAttributeByName(std::string_view name, AttributeValue value) {\n    const std::uint32_t hash = HashAttributeName(name);\n    m_namedAttributes[hash] = std::move(value);\n}\n\nconst AttributeValue* AttributeKeyValueStore::GetAttribute(std::uint16_t defIndex) const noexcept {\n    const auto it = m_indexedAttributes.find(defIndex);\n    if (it != m_indexedAttributes.end()) {\n        return &it->second;\n    }\n    return nullptr;\n}\n\nfloat AttributeKeyValueStore::GetAttributeFloat(std::uint16_t defIndex, float defaultValue) const noexcept {\n    const auto* attr = GetAttribute(defIndex);\n    if (!attr) return defaultValue;\n\n    if (std::holds_alternative<float>(*attr)) {\n        return std::get<float>(*attr);\n    }\n    if (std::holds_alternative<std::int32_t>(*attr)) {\n        return static_cast<float>(std::get<std::int32_t>(*attr));\n    }\n    if (std::holds_alternative<std::uint32_t>(*attr)) {\n        return static_cast<float>(std::get<std::uint32_t>(*attr));\n    }\n    return defaultValue;\n}\n\nstd::int32_t AttributeKeyValueStore::GetAttributeInt(std::uint16_t defIndex, std::int32_t defaultValue) const noexcept {\n    const auto* attr = GetAttribute(defIndex);\n    if (!attr) return defaultValue;\n\n    if (std::holds_alternative<std::int32_t>(*attr)) {\n        return std::get<std::int32_t>(*attr);\n    }\n    if (std::holds_alternative<std::uint32_t>(*attr)) {\n        return static_cast<std::int32_t>(std::get<std::uint32_t>(*attr));\n    }\n    if (std::holds_alternative<float>(*attr)) {\n        return static_cast<std::int32_t>(std::get<float>(*attr));\n    }\n    return defaultValue;\n}\n\nstd::uint32_t AttributeKeyValueStore::GetAttributeUInt(std::uint16_t defIndex, std::uint32_t defaultValue) const noexcept {\n    const auto* attr = GetAttribute(defIndex);\n    if (!attr) return defaultValue;\n\n    if (std::holds_alternative<std::uint32_t>(*attr)) {\n        return std::get<std::uint32_t>(*attr);\n    }\n    if (std::holds_alternative<std::int32_t>(*attr)) {\n        return static_cast<std::uint32_t>(std::get<std::int32_t>(*attr));\n    }\n    if (std::holds_alternative<float>(*attr)) {\n        return static_cast<std::uint32_t>(std::get<float>(*attr));\n    }\n    return defaultValue;\n}\n\nstd::string_view AttributeKeyValueStore::GetAttributeString(std::uint16_t defIndex, std::string_view defaultValue) const noexcept {\n    const auto* attr = GetAttribute(defIndex);\n    if (!attr) return defaultValue;\n\n    if (std::holds_alternative<std::string>(*attr)) {\n        return std::get<std::string>(*attr);\n    }\n    return defaultValue;\n}\n\nbool AttributeKeyValueStore::HasAttribute(std::uint16_t defIndex) const noexcept {\n    return m_indexedAttributes.find(defIndex) != m_indexedAttributes.end();\n}\n\nvoid AttributeKeyValueStore::RemoveAttribute(std::uint16_t defIndex) noexcept {\n    m_indexedAttributes.erase(defIndex);\n}\n\nvoid AttributeKeyValueStore::Clear() noexcept {\n    m_indexedAttributes.clear();\n    m_namedAttributes.clear();\n}\n\nstd::size_t AttributeKeyValueStore::Size() const noexcept {\n    return m_indexedAttributes.size() + m_namedAttributes.size();\n}\n\nbool AttributeKeyValueStore::Empty() const noexcept {\n    return m_indexedAttributes.empty() && m_namedAttributes.empty();\n}\n\n// ============================================================================\n// 2. Procedural Texture Coordinate Mapper Implementation\n// ============================================================================\n\nvoid ProceduralTextureMapper::ComputeSeedFactors(\n    std::int32_t seed,\n    const sdk::CPaintKitDefinition& kit,\n    float& out_offsetX,\n    float& out_offsetY,\n    float& out_rotationDeg) noexcept\n{\n    // CS2 32-bit MurmurHash/Wang integer mixing for deterministic procedural seed projection\n    std::uint32_t s = static_cast<std::uint32_t>(seed) * 0x9E3779B9u + 0x1234567u;\n    s ^= (s >> 16);\n    s *= 0x85EBCA6Bu;\n    s ^= (s >> 13);\n    s *= 0xC2B2AE35u;\n    s ^= (s >> 16);\n\n    const float r1 = static_cast<float>(s & 0xFFFFu) / 65535.0f;\n    const float r2 = static_cast<float>((s >> 16) & 0xFFFFu) / 65535.0f;\n\n    std::uint32_t s2 = s * 1103515245u + 12345u;\n    const float r3 = static_cast<float>((s2 >> 16) & 0xFFFFu) / 65535.0f;\n\n    out_offsetX = kit.m_flPatternOffsetXStart + r1 * (kit.m_flPatternOffsetXEnd - kit.m_flPatternOffsetXStart);\n    out_offsetY = kit.m_flPatternOffsetYStart + r2 * (kit.m_flPatternOffsetYEnd - kit.m_flPatternOffsetYStart);\n    out_rotationDeg = kit.m_flPatternRotateStart + r3 * (kit.m_flPatternRotateEnd - kit.m_flPatternRotateStart);\n}\n\nProceduralUVResult ProceduralTextureMapper::TransformUV(\n    std::int32_t seed,\n    const sdk::CPaintKitDefinition& kit,\n    float baseU,\n    float baseV) noexcept\n{\n    ProceduralUVResult result{};\n    result.scale = kit.m_flPatternScale > 0.0001f ? kit.m_flPatternScale : 1.0f;\n\n    ComputeSeedFactors(seed, kit, result.offset_x, result.offset_y, result.rotation_deg);\n\n    // Apply scale and translation offset\n    const float u_scaled = (baseU * result.scale) + result.offset_x;\n    const float v_scaled = (baseV * result.scale) + result.offset_y;\n\n    // Apply rotation matrix: R(theta) * [u, v]^T\n    const float rad = result.rotation_deg * (std::numbers::pi_v<float> / 180.0f);\n    const float cosTheta = std::cos(rad);\n    const float sinTheta = std::sin(rad);\n\n    const float u_rot = (cosTheta * u_scaled) - (sinTheta * v_scaled);\n    const float v_rot = (sinTheta * u_scaled) + (cosTheta * v_scaled);\n\n    // Modulo wrap to [0.0, 1.0] unit texture space\n    result.u_transformed = u_rot - std::floor(u_rot);\n    result.v_transformed = v_rot - std::floor(v_rot);\n\n    return result;\n}\n\nvoid ProceduralTextureMapper::ComputeUVMatrix(\n    std::int32_t seed,\n    const sdk::CPaintKitDefinition& kit,\n    std::array<float, 4>& out_rotationMatrix,\n    std::array<float, 2>& out_translation) noexcept\n{\n    float offX = 0.0f;\n    float offY = 0.0f;\n    float rotDeg = 0.0f;\n    ComputeSeedFactors(seed, kit, offX, offY, rotDeg);\n\n    const float scale = kit.m_flPatternScale > 0.0001f ? kit.m_flPatternScale : 1.0f;\n    const float rad = rotDeg * (std::numbers::pi_v<float> / 180.0f);\n    const float cosTheta = std::cos(rad);\n    const float sinTheta = std::sin(rad);\n\n    out_rotationMatrix[0] = cosTheta * scale; // [0,0]\n    out_rotationMatrix[1] = -sinTheta * scale;// [0,1]\n    out_rotationMatrix[2] = sinTheta * scale; // [1,0]\n    out_rotationMatrix[3] = cosTheta * scale;  // [1,1]\n\n    out_translation[0] = (cosTheta * offX) - (sinTheta * offY);\n    out_translation[1] = (sinTheta * offX) + (cosTheta * offY);\n}\n\n// ============================================================================\n// 3. Wear Degradation & Surface Abrasion Pipeline Implementation\n// ============================================================================\n\nfloat WearDegradationPipeline::SimulateWearDegradationODE(\n    float initialWear,\n    float abrasionRate,\n    float durationSeconds,\n    float timeStep) noexcept\n{\n    float w = std::clamp(initialWear, 0.0f, 1.0f);\n    if (durationSeconds <= 0.0f || abrasionRate <= 0.0f) {\n        return w;\n    }\n\n    // Runge-Kutta 4th Order (RK4) ODE integration of dw/dt = kappa * (1.0 - w)\n    const auto f = [abrasionRate](float current_w) noexcept -> float {\n        return abrasionRate * (1.0f - current_w);\n    };\n\n    float t = 0.0f;\n    const float dt = std::clamp(timeStep, 0.0001f, 0.1f);\n\n    while (t < durationSeconds) {\n        const float step = (t + dt > durationSeconds) ? (durationSeconds - t) : dt;\n\n        const float k1 = f(w);\n        const float k2 = f(w + 0.5f * step * k1);\n        const float k3 = f(w + 0.5f * step * k2);\n        const float k4 = f(w + step * k3);\n\n        w += (step / 6.0f) * (k1 + 2.0f * k2 + 2.0f * k3 + k4);\n        w = std::clamp(w, 0.0f, 1.0f);\n\n        t += step;\n        if (w >= 0.9999f) break;\n    }\n\n    return w;\n}\n\nfloat WearDegradationPipeline::EvaluateAbrasionAlpha(\n    float remappedWear,\n    float maskTextureSample,\n    float edgeSmoothness) noexcept\n{\n    // Smoothstep edge abrasion formula:\n    // When mask value < remappedWear, surface paint is scraped off exposing raw steel/patina.\n    const float edge = std::max(edgeSmoothness, 0.001f);\n    const float edge0 = remappedWear - edge;\n    const float edge1 = remappedWear + edge;\n\n    const float t = std::clamp((maskTextureSample - edge0) / (edge1 - edge0), 0.0f, 1.0f);\n    return t * t * (3.0f - 2.0f * t);\n}\n\n// ============================================================================\n// 4. Instantiated Client Inventory Item Implementation\n// ============================================================================\n\nInventoryItem::InventoryItem(\n    std::uint64_t itemID,\n    std::uint16_t defIndex,\n    sdk::EconQuality_t quality,\n    sdk::EconRarity_t rarity,\n    std::int32_t paintKitIndex,\n    std::int32_t seed,\n    float wear,\n    std::int32_t statTrakCount,\n    std::string_view customName)\n    : m_itemID(itemID),\n      m_defIndex(defIndex),\n      m_quality(quality),\n      m_rarity(rarity),\n      m_paintKitIndex(paintKitIndex),\n      m_seed(seed),\n      m_wear(std::clamp(wear, 0.0f, 1.0f)),\n      m_statTrakCount(statTrakCount),\n      m_customName(customName)\n{\n}\n\n// ============================================================================\n// 5. Economy Item Schema Catalog Implementation\n// ============================================================================\n\nEconItemCatalog& EconItemCatalog::GetInstance() noexcept {\n    static EconItemCatalog instance;\n    return instance;\n}\n\nbool EconItemCatalog::RegisterItemDefinition(const sdk::CEconItemDefinition& def) {\n    if (def.m_nDefIndex == 0) return false;\n\n    m_itemsByIndex[def.m_nDefIndex] = def;\n    if (def.m_pszItemBaseName && def.m_pszItemBaseName[0] != '\\0') {\n        m_itemsByName[def.m_pszItemBaseName] = def.m_nDefIndex;\n    }\n    return true;\n}\n\nbool EconItemCatalog::RegisterPaintKit(const sdk::CPaintKitDefinition& kit) {\n    if (kit.m_nID < 0) return false;\n\n    m_paintKitsById[kit.m_nID] = kit;\n    if (kit.m_pszName && kit.m_pszName[0] != '\\0') {\n        m_paintKitsByName[kit.m_pszName] = kit.m_nID;\n    }\n    return true;\n}\n\nconst sdk::CEconItemDefinition* EconItemCatalog::FindItemDefinition(std::uint16_t defIndex) const noexcept {\n    const auto it = m_itemsByIndex.find(defIndex);\n    if (it != m_itemsByIndex.end()) {\n        return &it->second;\n    }\n    return nullptr;\n}\n\nconst sdk::CEconItemDefinition* EconItemCatalog::FindItemDefinitionByName(std::string_view name) const noexcept {\n    const auto it = m_itemsByName.find(std::string(name));\n    if (it != m_itemsByName.end()) {\n        return FindItemDefinition(it->second);\n    }\n    return nullptr;\n}\n\nconst sdk::CPaintKitDefinition* EconItemCatalog::FindPaintKit(std::int32_t paintKitId) const noexcept {\n    const auto it = m_paintKitsById.find(paintKitId);\n    if (it != m_paintKitsById.end()) {\n        return &it->second;\n    }\n    return nullptr;\n}\n\nconst sdk::CPaintKitDefinition* EconItemCatalog::FindPaintKitByName(std::string_view name) const noexcept {\n    const auto it = m_paintKitsByName.find(std::string(name));\n    if (it != m_paintKitsByName.end()) {\n        return FindPaintKit(it->second);\n    }\n    return nullptr;\n}\n\nvoid EconItemCatalog::Clear() noexcept {\n    m_itemsByIndex.clear();\n    m_itemsByName.clear();\n    m_paintKitsById.clear();\n    m_paintKitsByName.clear();\n}\n\nvoid EconItemCatalog::InitializeDefaultCatalog() {\n    Clear();\n\n    // ------------------------------------------------------------------------\n    // Canonical Weapon Definitions (items_game.txt)\n    // ------------------------------------------------------------------------\n\n    // Desert Eagle\n    RegisterItemDefinition({\n        .m_nDefIndex = 1,\n        .m_nLoadoutSlot = sdk::LoadoutSlot_t::LOADOUT_SLOT_SECONDARY0,\n        .m_nEquipmentCategory = sdk::EquipmentCategory_t::CATEGORY_SECONDARY,\n        .m_nQuality = sdk::EconQuality_t::QUALITY_NORMAL,\n        .m_nRarity = sdk::EconRarity_t::RARITY_LEGENDARY,\n        .m_nDefaultDropQuantity = 1,\n        .m_nItemLevelMin = 1,\n        .m_nItemLevelMax = 1,\n        .m_pszItemBaseName = \"weapon_deagle\",\n        .m_pszItemTypeName = \"#CSGO_Type_Pistol\",\n        .m_pszItemDescription = \"#CSGO_Item_Desc_Deagle\",\n        .m_pszInventoryImage = \"econ/weapons/base_weapons/weapon_deagle\",\n        .m_pszModelPlayer = \"weapons/models/pistol/desert_eagle/weapon_desert_eagle.vmdl\",\n        .m_pszModelWorld = \"weapons/models/pistol/desert_eagle/weapon_desert_eagle_dropped.vmdl\"\n    });\n\n    // Glock-18\n    RegisterItemDefinition({\n        .m_nDefIndex = 4,\n        .m_nLoadoutSlot = sdk::LoadoutSlot_t::LOADOUT_SLOT_SECONDARY0,\n        .m_nEquipmentCategory = sdk::EquipmentCategory_t::CATEGORY_SECONDARY,\n        .m_nQuality = sdk::EconQuality_t::QUALITY_NORMAL,\n        .m_nRarity = sdk::EconRarity_t::RARITY_COMMON,\n        .m_nDefaultDropQuantity = 1,\n        .m_nItemLevelMin = 1,\n        .m_nItemLevelMax = 1,\n        .m_pszItemBaseName = \"weapon_glock\",\n        .m_pszItemTypeName = \"#CSGO_Type_Pistol\",\n        .m_pszItemDescription = \"#CSGO_Item_Desc_Glock\",\n        .m_pszInventoryImage = \"econ/weapons/base_weapons/weapon_glock\",\n        .m_pszModelPlayer = \"weapons/models/pistol/glock/weapon_glock.vmdl\",\n        .m_pszModelWorld = \"weapons/models/pistol/glock/weapon_glock_dropped.vmdl\"\n    });\n\n    // AK-47\n    RegisterItemDefinition({\n        .m_nDefIndex = 7,\n        .m_nLoadoutSlot = sdk::LoadoutSlot_t::LOADOUT_SLOT_RIFLE0,\n        .m_nEquipmentCategory = sdk::EquipmentCategory_t::CATEGORY_RIFLE,\n        .m_nQuality = sdk::EconQuality_t::QUALITY_NORMAL,\n        .m_nRarity = sdk::EconRarity_t::RARITY_ANCIENT,\n        .m_nDefaultDropQuantity = 1,\n        .m_nItemLevelMin = 1,\n        .m_nItemLevelMax = 1,\n        .m_pszItemBaseName = \"weapon_ak47\",\n        .m_pszItemTypeName = \"#CSGO_Type_Rifle\",\n        .m_pszItemDescription = \"#CSGO_Item_Desc_AK47\",\n        .m_pszInventoryImage = \"econ/weapons/base_weapons/weapon_ak47\",\n        .m_pszModelPlayer = \"weapons/models/rifles/ak47/weapon_ak47.vmdl\",\n        .m_pszModelWorld = \"weapons/models/rifles/ak47/weapon_ak47_dropped.vmdl\"\n    });\n\n    // AWP\n    RegisterItemDefinition({\n        .m_nDefIndex = 9,\n        .m_nLoadoutSlot = sdk::LoadoutSlot_t::LOADOUT_SLOT_RIFLE3,\n        .m_nEquipmentCategory = sdk::EquipmentCategory_t::CATEGORY_RIFLE,\n        .m_nQuality = sdk::EconQuality_t::QUALITY_NORMAL,\n        .m_nRarity = sdk::EconRarity_t::RARITY_ANCIENT,\n        .m_nDefaultDropQuantity = 1,\n        .m_nItemLevelMin = 1,\n        .m_nItemLevelMax = 1,\n        .m_pszItemBaseName = \"weapon_awp\",\n        .m_pszItemTypeName = \"#CSGO_Type_SniperRifle\",\n        .m_pszItemDescription = \"#CSGO_Item_Desc_AWP\",\n        .m_pszInventoryImage = \"econ/weapons/base_weapons/weapon_awp\",\n        .m_pszModelPlayer = \"weapons/models/rifles/awp/weapon_awp.vmdl\",\n        .m_pszModelWorld = \"weapons/models/rifles/awp/weapon_awp_dropped.vmdl\"\n    });\n\n    // M4A4\n    RegisterItemDefinition({\n        .m_nDefIndex = 16,\n        .m_nLoadoutSlot = sdk::LoadoutSlot_t::LOADOUT_SLOT_RIFLE0,\n        .m_nEquipmentCategory = sdk::EquipmentCategory_t::CATEGORY_RIFLE,\n        .m_nQuality = sdk::EconQuality_t::QUALITY_NORMAL,\n        .m_nRarity = sdk::EconRarity_t::RARITY_ANCIENT,\n        .m_nDefaultDropQuantity = 1,\n        .m_nItemLevelMin = 1,\n        .m_nItemLevelMax = 1,\n        .m_pszItemBaseName = \"weapon_m4a1\",\n        .m_pszItemTypeName = \"#CSGO_Type_Rifle\",\n        .m_pszItemDescription = \"#CSGO_Item_Desc_M4A4\",\n        .m_pszInventoryImage = \"econ/weapons/base_weapons/weapon_m4a1\",\n        .m_pszModelPlayer = \"weapons/models/rifles/m4a4/weapon_m4a4.vmdl\",\n        .m_pszModelWorld = \"weapons/models/rifles/m4a4/weapon_m4a4_dropped.vmdl\"\n    });\n\n    // SSG 08\n    RegisterItemDefinition({\n        .m_nDefIndex = 40,\n        .m_nLoadoutSlot = sdk::LoadoutSlot_t::LOADOUT_SLOT_RIFLE2,\n        .m_nEquipmentCategory = sdk::EquipmentCategory_t::CATEGORY_RIFLE,\n        .m_nQuality = sdk::EconQuality_t::QUALITY_NORMAL,\n        .m_nRarity = sdk::EconRarity_t::RARITY_RARE,\n        .m_nDefaultDropQuantity = 1,\n        .m_nItemLevelMin = 1,\n        .m_nItemLevelMax = 1,\n        .m_pszItemBaseName = \"weapon_ssg08\",\n        .m_pszItemTypeName = \"#CSGO_Type_SniperRifle\",\n        .m_pszItemDescription = \"#CSGO_Item_Desc_SSG08\",\n        .m_pszInventoryImage = \"econ/weapons/base_weapons/weapon_ssg08\",\n        .m_pszModelPlayer = \"weapons/models/rifles/ssg08/weapon_ssg08.vmdl\",\n        .m_pszModelWorld = \"weapons/models/rifles/ssg08/weapon_ssg08_dropped.vmdl\"\n    });\n\n    // M4A1-S\n    RegisterItemDefinition({\n        .m_nDefIndex = 60,\n        .m_nLoadoutSlot = sdk::LoadoutSlot_t::LOADOUT_SLOT_RIFLE0,\n        .m_nEquipmentCategory = sdk::EquipmentCategory_t::CATEGORY_RIFLE,\n        .m_nQuality = sdk::EconQuality_t::QUALITY_NORMAL,\n        .m_nRarity = sdk::EconRarity_t::RARITY_ANCIENT,\n        .m_nDefaultDropQuantity = 1,\n        .m_nItemLevelMin = 1,\n        .m_nItemLevelMax = 1,\n        .m_pszItemBaseName = \"weapon_m4a1_silencer\",\n        .m_pszItemTypeName = \"#CSGO_Type_Rifle\",\n        .m_pszItemDescription = \"#CSGO_Item_Desc_M4A1_Silencer\",\n        .m_pszInventoryImage = \"econ/weapons/base_weapons/weapon_m4a1_silencer\",\n        .m_pszModelPlayer = \"weapons/models/rifles/m4a1_silencer/weapon_m4a1_silencer.vmdl\",\n        .m_pszModelWorld = \"weapons/models/rifles/m4a1_silencer/weapon_m4a1_silencer_dropped.vmdl\"\n    });\n\n    // USP-S\n    RegisterItemDefinition({\n        .m_nDefIndex = 61,\n        .m_nLoadoutSlot = sdk::LoadoutSlot_t::LOADOUT_SLOT_SECONDARY0,\n        .m_nEquipmentCategory = sdk::EquipmentCategory_t::CATEGORY_SECONDARY,\n        .m_nQuality = sdk::EconQuality_t::QUALITY_NORMAL,\n        .m_nRarity = sdk::EconRarity_t::RARITY_RARE,\n        .m_nDefaultDropQuantity = 1,\n        .m_nItemLevelMin = 1,\n        .m_nItemLevelMax = 1,\n        .m_pszItemBaseName = \"weapon_usp_silencer\",\n        .m_pszItemTypeName = \"#CSGO_Type_Pistol\",\n        .m_pszItemDescription = \"#CSGO_Item_Desc_USP_Silencer\",\n        .m_pszInventoryImage = \"econ/weapons/base_weapons/weapon_usp_silencer\",\n        .m_pszModelPlayer = \"weapons/models/pistol/usp_silencer/weapon_usp_silencer.vmdl\",\n        .m_pszModelWorld = \"weapons/models/pistol/usp_silencer/weapon_usp_silencer_dropped.vmdl\"\n    });\n\n    // Karambit\n    RegisterItemDefinition({\n        .m_nDefIndex = 507,\n        .m_nLoadoutSlot = sdk::LoadoutSlot_t::LOADOUT_SLOT_MELEE,\n        .m_nEquipmentCategory = sdk::EquipmentCategory_t::CATEGORY_MELEE,\n        .m_nQuality = sdk::EconQuality_t::QUALITY_UNUSUAL,\n        .m_nRarity = sdk::EconRarity_t::RARITY_ANCIENT,\n        .m_nDefaultDropQuantity = 1,\n        .m_nItemLevelMin = 1,\n        .m_nItemLevelMax = 1,\n        .m_pszItemBaseName = \"weapon_knife_karambit\",\n        .m_pszItemTypeName = \"#CSGO_Type_Knife\",\n        .m_pszItemDescription = \"#CSGO_Item_Desc_Knife_Karambit\",\n        .m_pszInventoryImage = \"econ/weapons/base_weapons/weapon_knife_karambit\",\n        .m_pszModelPlayer = \"weapons/models/knife/karambit/weapon_knife_karambit.vmdl\",\n        .m_pszModelWorld = \"weapons/models/knife/karambit/weapon_knife_karambit_dropped.vmdl\"\n    });\n\n    // M9 Bayonet\n    RegisterItemDefinition({\n        .m_nDefIndex = 508,\n        .m_nLoadoutSlot = sdk::LoadoutSlot_t::LOADOUT_SLOT_MELEE,\n        .m_nEquipmentCategory = sdk::EquipmentCategory_t::CATEGORY_MELEE,\n        .m_nQuality = sdk::EconQuality_t::QUALITY_UNUSUAL,\n        .m_nRarity = sdk::EconRarity_t::RARITY_ANCIENT,\n        .m_nDefaultDropQuantity = 1,\n        .m_nItemLevelMin = 1,\n        .m_nItemLevelMax = 1,\n        .m_pszItemBaseName = \"weapon_knife_m9_bayonet\",\n        .m_pszItemTypeName = \"#CSGO_Type_Knife\",\n        .m_pszItemDescription = \"#CSGO_Item_Desc_Knife_M9_Bayonet\",\n        .m_pszInventoryImage = \"econ/weapons/base_weapons/weapon_knife_m9_bayonet\",\n        .m_pszModelPlayer = \"weapons/models/knife/m9_bayonet/weapon_knife_m9_bayonet.vmdl\",\n        .m_pszModelWorld = \"weapons/models/knife/m9_bayonet/weapon_knife_m9_bayonet_dropped.vmdl\"\n    });\n\n    // Butterfly Knife\n    RegisterItemDefinition({\n        .m_nDefIndex = 515,\n        .m_nLoadoutSlot = sdk::LoadoutSlot_t::LOADOUT_SLOT_MELEE,\n        .m_nEquipmentCategory = sdk::EquipmentCategory_t::CATEGORY_MELEE,\n        .m_nQuality = sdk::EconQuality_t::QUALITY_UNUSUAL,\n        .m_nRarity = sdk::EconRarity_t::RARITY_ANCIENT,\n        .m_nDefaultDropQuantity = 1,\n        .m_nItemLevelMin = 1,\n        .m_nItemLevelMax = 1,\n        .m_pszItemBaseName = \"weapon_knife_butterfly\",\n        .m_pszItemTypeName = \"#CSGO_Type_Knife\",\n        .m_pszItemDescription = \"#CSGO_Item_Desc_Knife_Butterfly\",\n        .m_pszInventoryImage = \"econ/weapons/base_weapons/weapon_knife_butterfly\",\n        .m_pszModelPlayer = \"weapons/models/knife/butterfly/weapon_knife_butterfly.vmdl\",\n        .m_pszModelWorld = \"weapons/models/knife/butterfly/weapon_knife_butterfly_dropped.vmdl\"\n    });\n\n    // Sport Gloves\n    RegisterItemDefinition({\n        .m_nDefIndex = 5030,\n        .m_nLoadoutSlot = sdk::LoadoutSlot_t::LOADOUT_SLOT_GLOVES,\n        .m_nEquipmentCategory = sdk::EquipmentCategory_t::CATEGORY_GLOVES,\n        .m_nQuality = sdk::EconQuality_t::QUALITY_UNUSUAL,\n        .m_nRarity = sdk::EconRarity_t::RARITY_ANCIENT,\n        .m_nDefaultDropQuantity = 1,\n        .m_nItemLevelMin = 1,\n        .m_nItemLevelMax = 1,\n        .m_pszItemBaseName = \"weapon_gloves_sport\",\n        .m_pszItemTypeName = \"#CSGO_Type_Gloves\",\n        .m_pszItemDescription = \"#CSGO_Item_Desc_Gloves_Sport\",\n        .m_pszInventoryImage = \"econ/weapons/base_weapons/weapon_gloves_sport\",\n        .m_pszModelPlayer = \"weapons/models/gloves/sport/glove_sport.vmdl\",\n        .m_pszModelWorld = \"weapons/models/gloves/sport/glove_sport_dropped.vmdl\"\n    });\n\n    // ------------------------------------------------------------------------\n    // Canonical Paint Kit Definitions (items_paintkits.txt)\n    // ------------------------------------------------------------------------\n\n    // Fade (ID: 38)\n    RegisterPaintKit({\n        .m_nID = 38,\n        .m_pszName = \"aa_fade\",\n        .m_pszDescription = \"#PaintKit_aa_fade\",\n        .m_pszTemplate = \"workshop/paintkits/templates/anodized_airbrushed.vcompmat\",\n        .m_nStyle = sdk::PaintKitStyle_t::PAINT_KIT_STYLE_ANODIZED_AIRBRUSHED,\n        .m_flWearRemapMin = 0.00f,\n        .m_flWearRemapMax = 0.08f,\n        .m_flPatternScale = 1.00f,\n        .m_flPatternOffsetXStart = 0.00f,\n        .m_flPatternOffsetXEnd = 1.00f,\n        .m_flPatternOffsetYStart = 0.00f,\n        .m_flPatternOffsetYEnd = 1.00f,\n        .m_flPatternRotateStart = 0.00f,\n        .m_flPatternRotateEnd = 360.00f,\n        .m_flPearlescent = 0.00f\n    });\n\n    // Case Hardened (ID: 44)\n    RegisterPaintKit({\n        .m_nID = 44,\n        .m_pszName = \"hy_case_hardened\",\n        .m_pszDescription = \"#PaintKit_hy_case_hardened\",\n        .m_pszTemplate = \"workshop/paintkits/templates/hydrographic.vcompmat\",\n        .m_nStyle = sdk::PaintKitStyle_t::PAINT_KIT_STYLE_HYDROGRAPHIC,\n        .m_flWearRemapMin = 0.00f,\n        .m_flWearRemapMax = 1.00f,\n        .m_flPatternScale = 4.00f,\n        .m_flPatternOffsetXStart = 0.00f,\n        .m_flPatternOffsetXEnd = 1.00f,\n        .m_flPatternOffsetYStart = 0.00f,\n        .m_flPatternOffsetYEnd = 1.00f,\n        .m_flPatternRotateStart = 0.00f,\n        .m_flPatternRotateEnd = 360.00f,\n        .m_flPearlescent = 0.00f\n    });\n\n    // Fire Serpent (ID: 180)\n    RegisterPaintKit({\n        .m_nID = 180,\n        .m_pszName = \"cu_fire_serpent\",\n        .m_pszDescription = \"#PaintKit_cu_fire_serpent\",\n        .m_pszTemplate = \"workshop/paintkits/templates/custom_paint_job.vcompmat\",\n        .m_nStyle = sdk::PaintKitStyle_t::PAINT_KIT_STYLE_CUSTOM_PAINT_JOB,\n        .m_flWearRemapMin = 0.06f,\n        .m_flWearRemapMax = 0.76f,\n        .m_flPatternScale = 1.00f,\n        .m_flPatternOffsetXStart = 0.00f,\n        .m_flPatternOffsetXEnd = 0.00f,\n        .m_flPatternOffsetYStart = 0.00f,\n        .m_flPatternOffsetYEnd = 0.00f,\n        .m_flPatternRotateStart = 0.00f,\n        .m_flPatternRotateEnd = 0.00f,\n        .m_flPearlescent = 0.00f\n    });\n\n    // Asiimov (ID: 255)\n    RegisterPaintKit({\n        .m_nID = 255,\n        .m_pszName = \"cu_asiimov\",\n        .m_pszDescription = \"#PaintKit_cu_asiimov\",\n        .m_pszTemplate = \"workshop/paintkits/templates/custom_paint_job.vcompmat\",\n        .m_nStyle = sdk::PaintKitStyle_t::PAINT_KIT_STYLE_CUSTOM_PAINT_JOB,\n        .m_flWearRemapMin = 0.18f,\n        .m_flWearRemapMax = 1.00f,\n        .m_flPatternScale = 1.00f,\n        .m_flPatternOffsetXStart = 0.00f,\n        .m_flPatternOffsetXEnd = 0.00f,\n        .m_flPatternOffsetYStart = 0.00f,\n        .m_flPatternOffsetYEnd = 0.00f,\n        .m_flPatternRotateStart = 0.00f,\n        .m_flPatternRotateEnd = 0.00f,\n        .m_flPearlescent = 0.00f\n    });\n\n    // Redline (ID: 282)\n    RegisterPaintKit({\n        .m_nID = 282,\n        .m_pszName = \"cu_redline\",\n        .m_pszDescription = \"#PaintKit_cu_redline\",\n        .m_pszTemplate = \"workshop/paintkits/templates/custom_paint_job.vcompmat\",\n        .m_nStyle = sdk::PaintKitStyle_t::PAINT_KIT_STYLE_CUSTOM_PAINT_JOB,\n        .m_flWearRemapMin = 0.10f,\n        .m_flWearRemapMax = 0.70f,\n        .m_flPatternScale = 1.00f,\n        .m_flPatternOffsetXStart = 0.00f,\n        .m_flPatternOffsetXEnd = 0.00f,\n        .m_flPatternOffsetYStart = 0.00f,\n        .m_flPatternOffsetYEnd = 0.00f,\n        .m_flPatternRotateStart = 0.00f,\n        .m_flPatternRotateEnd = 0.00f,\n        .m_flPearlescent = 0.00f\n    });\n\n    // Howl (ID: 309)\n    RegisterPaintKit({\n        .m_nID = 309,\n        .m_pszName = \"cu_howl\",\n        .m_pszDescription = \"#PaintKit_cu_howl\",\n        .m_pszTemplate = \"workshop/paintkits/templates/custom_paint_job.vcompmat\",\n        .m_nStyle = sdk::PaintKitStyle_t::PAINT_KIT_STYLE_CUSTOM_PAINT_JOB,\n        .m_flWearRemapMin = 0.00f,\n        .m_flWearRemapMax = 0.40f,\n        .m_flPatternScale = 1.00f,\n        .m_flPatternOffsetXStart = 0.00f,\n        .m_flPatternOffsetXEnd = 0.00f,\n        .m_flPatternOffsetYStart = 0.00f,\n        .m_flPatternOffsetYEnd = 0.00f,\n        .m_flPatternRotateStart = 0.00f,\n        .m_flPatternRotateEnd = 0.00f,\n        .m_flPearlescent = 0.00f\n    });\n\n    // Dragon Lore (ID: 344)\n    RegisterPaintKit({\n        .m_nID = 344,\n        .m_pszName = \"cu_dragon_lore\",\n        .m_pszDescription = \"#PaintKit_cu_dragon_lore\",\n        .m_pszTemplate = \"workshop/paintkits/templates/custom_paint_job.vcompmat\",\n        .m_nStyle = sdk::PaintKitStyle_t::PAINT_KIT_STYLE_CUSTOM_PAINT_JOB,\n        .m_flWearRemapMin = 0.00f,\n        .m_flWearRemapMax = 0.70f,\n        .m_flPatternScale = 1.00f,\n        .m_flPatternOffsetXStart = 0.00f,\n        .m_flPatternOffsetXEnd = 0.00f,\n        .m_flPatternOffsetYStart = 0.00f,\n        .m_flPatternOffsetYEnd = 0.00f,\n        .m_flPatternRotateStart = 0.00f,\n        .m_flPatternRotateEnd = 0.00f,\n        .m_flPearlescent = 0.00f\n    });\n\n    // Doppler (ID: 415)\n    RegisterPaintKit({\n        .m_nID = 415,\n        .m_pszName = \"am_doppler\",\n        .m_pszDescription = \"#PaintKit_am_doppler\",\n        .m_pszTemplate = \"workshop/paintkits/templates/anodized_airbrushed.vcompmat\",\n        .m_nStyle = sdk::PaintKitStyle_t::PAINT_KIT_STYLE_ANODIZED_AIRBRUSHED,\n        .m_flWearRemapMin = 0.00f,\n        .m_flWearRemapMax = 0.08f,\n        .m_flPatternScale = 4.00f,\n        .m_flPatternOffsetXStart = 0.00f,\n        .m_flPatternOffsetXEnd = 1.00f,\n        .m_flPatternOffsetYStart = 0.00f,\n        .m_flPatternOffsetYEnd = 1.00f,\n        .m_flPatternRotateStart = 0.00f,\n        .m_flPatternRotateEnd = 360.00f,\n        .m_flPearlescent = 0.00f\n    });\n\n    // Hyper Beast (ID: 430)\n    RegisterPaintKit({\n        .m_nID = 430,\n        .m_pszName = \"cu_hyper_beast\",\n        .m_pszDescription = \"#PaintKit_cu_hyper_beast\",\n        .m_pszTemplate = \"workshop/paintkits/templates/custom_paint_job.vcompmat\",\n        .m_nStyle = sdk::PaintKitStyle_t::PAINT_KIT_STYLE_CUSTOM_PAINT_JOB,\n        .m_flWearRemapMin = 0.00f,\n        .m_flWearRemapMax = 1.00f,\n        .m_flPatternScale = 1.00f,\n        .m_flPatternOffsetXStart = 0.00f,\n        .m_flPatternOffsetXEnd = 0.00f,\n        .m_flPatternOffsetYStart = 0.00f,\n        .m_flPatternOffsetYEnd = 0.00f,\n        .m_flPatternRotateStart = 0.00f,\n        .m_flPatternRotateEnd = 0.00f,\n        .m_flPearlescent = 0.00f\n    });\n\n    // Printstream (ID: 984)\n    RegisterPaintKit({\n        .m_nID = 984,\n        .m_pszName = \"gs_printstream\",\n        .m_pszDescription = \"#PaintKit_gs_printstream\",\n        .m_pszTemplate = \"workshop/paintkits/templates/gunsmith.vcompmat\",\n        .m_nStyle = sdk::PaintKitStyle_t::PAINT_KIT_STYLE_GUNSMITH,\n        .m_flWearRemapMin = 0.00f,\n        .m_flWearRemapMax = 0.80f,\n        .m_flPatternScale = 1.00f,\n        .m_flPatternOffsetXStart = 0.00f,\n        .m_flPatternOffsetXEnd = 0.00f,\n        .m_flPatternOffsetYStart = 0.00f,\n        .m_flPatternOffsetYEnd = 0.00f,\n        .m_flPatternRotateStart = 0.00f,\n        .m_flPatternRotateEnd = 0.00f,\n        .m_flPearlescent = 15.00f\n    });\n}\n\n} // namespace cs2::client\n",
        "inventory_schema.h": "#ifndef CS2_CLIENT_INVENTORY_SCHEMA_H\n#define CS2_CLIENT_INVENTORY_SCHEMA_H\n\n#include <cstdint>\n#include <string>\n#include <string_view>\n#include <vector>\n#include <unordered_map>\n#include <variant>\n#include <optional>\n#include <array>\n#include <cmath>\n#include <memory>\n\n#include \"sdk/item_schema.hpp\"\n\n// ============================================================================\n// Source 2 Client Inventory & Econ Item Schema Implementation\n// Architecture: x86-64 (MSVC ABI)\n// Binary: client.dll\n// Reconstructed & Clean-Room Implemented for Counter-Strike 2\n// ============================================================================\n\nnamespace cs2::client {\n\n// ============================================================================\n// 1. Dynamic Attribute Key-Value Store\n// ============================================================================\n\nusing AttributeValue = std::variant<float, std::int32_t, std::uint32_t, std::string>;\n\nclass AttributeKeyValueStore {\npublic:\n    AttributeKeyValueStore() = default;\n    ~AttributeKeyValueStore() = default;\n\n    void SetAttribute(std::uint16_t defIndex, AttributeValue value);\n    void SetAttributeByName(std::string_view name, AttributeValue value);\n\n    [[nodiscard]] const AttributeValue* GetAttribute(std::uint16_t defIndex) const noexcept;\n    [[nodiscard]] float GetAttributeFloat(std::uint16_t defIndex, float defaultValue = 0.0f) const noexcept;\n    [[nodiscard]] std::int32_t GetAttributeInt(std::uint16_t defIndex, std::int32_t defaultValue = 0) const noexcept;\n    [[nodiscard]] std::uint32_t GetAttributeUInt(std::uint16_t defIndex, std::uint32_t defaultValue = 0) const noexcept;\n    [[nodiscard]] std::string_view GetAttributeString(std::uint16_t defIndex, std::string_view defaultValue = \"\") const noexcept;\n\n    [[nodiscard]] bool HasAttribute(std::uint16_t defIndex) const noexcept;\n    void RemoveAttribute(std::uint16_t defIndex) noexcept;\n    void Clear() noexcept;\n\n    [[nodiscard]] std::size_t Size() const noexcept;\n    [[nodiscard]] bool Empty() const noexcept;\n\n    static std::uint32_t HashAttributeName(std::string_view name) noexcept;\n\nprivate:\n    std::unordered_map<std::uint16_t, AttributeValue> m_indexedAttributes;\n    std::unordered_map<std::uint32_t, AttributeValue> m_namedAttributes;\n};\n\n// ============================================================================\n// 2. Procedural Texture Coordinate Mapper\n// Transforms surface UVs based on seed (0..1000) and paint kit parameters.\n// ============================================================================\n\nstruct ProceduralUVResult {\n    float u_transformed = 0.0f;\n    float v_transformed = 0.0f;\n    float rotation_deg   = 0.0f;\n    float offset_x       = 0.0f;\n    float offset_y       = 0.0f;\n    float scale          = 1.0f;\n};\n\nclass ProceduralTextureMapper {\npublic:\n    ProceduralTextureMapper() = default;\n\n    /**\n     * @brief Computes pseudo-random offset and rotation factors from an integer seed.\n     */\n    static void ComputeSeedFactors(\n        std::int32_t seed,\n        const sdk::CPaintKitDefinition& kit,\n        float& out_offsetX,\n        float& out_offsetY,\n        float& out_rotationDeg) noexcept;\n\n    /**\n     * @brief Transforms base UV coordinates according to paint kit projection rules.\n     */\n    [[nodiscard]] static ProceduralUVResult TransformUV(\n        std::int32_t seed,\n        const sdk::CPaintKitDefinition& kit,\n        float baseU,\n        float baseV) noexcept;\n\n    /**\n     * @brief Computes a 2D affine transformation matrix [cos, -sin, sin, cos] and translation.\n     */\n    static void ComputeUVMatrix(\n        std::int32_t seed,\n        const sdk::CPaintKitDefinition& kit,\n        std::array<float, 4>& out_rotationMatrix,\n        std::array<float, 2>& out_translation) noexcept;\n};\n\n// ============================================================================\n// 3. Wear Degradation & Surface Abrasion Pipeline\n// ============================================================================\n\nclass WearDegradationPipeline {\npublic:\n    WearDegradationPipeline() = default;\n\n    /**\n     * @brief Evaluates wear classification rating enum from float wear.\n     */\n    [[nodiscard]] static constexpr sdk::WearRating_t EvaluateWearCondition(float wear) noexcept {\n        return sdk::EvaluateWearCondition(wear);\n    }\n\n    /**\n     * @brief Returns human-readable wear rating name.\n     */\n    [[nodiscard]] static constexpr const char* GetWearRatingName(sdk::WearRating_t rating) noexcept {\n        return sdk::GetWearRatingName(rating);\n    }\n\n    /**\n     * @brief Clamps and remaps raw wear to weapon-specific paint kit bounds.\n     */\n    [[nodiscard]] static constexpr float RemapWear(float rawWear, float minWear, float maxWear) noexcept {\n        return sdk::RemapWear(rawWear, minWear, maxWear);\n    }\n\n    /**\n     * @brief Simulates dynamic abrasion wear degradation ODE:\n     *        dw/dt = kappa * (1.0 - w)\n     *        w(t + dt) = 1.0 - (1.0 - w(t)) * exp(-kappa * dt)\n     */\n    [[nodiscard]] static float SimulateWearDegradationODE(\n        float initialWear,\n        float abrasionRate,\n        float durationSeconds,\n        float timeStep = 0.01f) noexcept;\n\n    /**\n     * @brief Evaluates the surface abrasion wear mask alpha using smoothstep transition.\n     *        Exposes the base patina or raw alloy beneath worn paint.\n     */\n    [[nodiscard]] static float EvaluateAbrasionAlpha(\n        float remappedWear,\n        float maskTextureSample,\n        float edgeSmoothness = 0.04f) noexcept;\n};\n\n// ============================================================================\n// 4. Instantiated Client Inventory Item\n// Composite runtime object mirroring C_EconItemView with client accessories.\n// ============================================================================\n\nclass InventoryItem {\npublic:\n    InventoryItem() = default;\n    InventoryItem(\n        std::uint64_t itemID,\n        std::uint16_t defIndex,\n        sdk::EconQuality_t quality,\n        sdk::EconRarity_t rarity,\n        std::int32_t paintKitIndex = 0,\n        std::int32_t seed = 0,\n        float wear = 0.0f,\n        std::int32_t statTrakCount = -1,\n        std::string_view customName = \"\");\n\n    [[nodiscard]] std::uint64_t GetItemID() const noexcept { return m_itemID; }\n    [[nodiscard]] std::uint16_t GetDefinitionIndex() const noexcept { return m_defIndex; }\n    [[nodiscard]] sdk::EconQuality_t GetQuality() const noexcept { return m_quality; }\n    [[nodiscard]] sdk::EconRarity_t GetRarity() const noexcept { return m_rarity; }\n    [[nodiscard]] std::int32_t GetPaintKitIndex() const noexcept { return m_paintKitIndex; }\n    [[nodiscard]] std::int32_t GetSeed() const noexcept { return m_seed; }\n    [[nodiscard]] float GetWear() const noexcept { return m_wear; }\n    [[nodiscard]] std::int32_t GetStatTrakCount() const noexcept { return m_statTrakCount; }\n    [[nodiscard]] std::string_view GetCustomName() const noexcept { return m_customName; }\n\n    [[nodiscard]] bool HasStatTrak() const noexcept { return m_statTrakCount >= 0; }\n    [[nodiscard]] bool HasCustomName() const noexcept { return !m_customName.empty(); }\n\n    [[nodiscard]] sdk::WearRating_t GetWearRating() const noexcept {\n        return WearDegradationPipeline::EvaluateWearCondition(m_wear);\n    }\n\n    [[nodiscard]] const char* GetWearRatingName() const noexcept {\n        return WearDegradationPipeline::GetWearRatingName(GetWearRating());\n    }\n\n    [[nodiscard]] float GetRemappedWear(const sdk::CPaintKitDefinition& kit) const noexcept {\n        return WearDegradationPipeline::RemapWear(m_wear, kit.m_flWearRemapMin, kit.m_flWearRemapMax);\n    }\n\n    void SetWear(float wear) noexcept { m_wear = (wear < 0.0f) ? 0.0f : ((wear > 1.0f) ? 1.0f : wear); }\n    void SetSeed(std::int32_t seed) noexcept { m_seed = seed; }\n    void SetPaintKit(std::int32_t paintKit) noexcept { m_paintKitIndex = paintKit; }\n    void SetStatTrakCount(std::int32_t count) noexcept { m_statTrakCount = count; }\n    void SetCustomName(std::string_view name) { m_customName = name; }\n\n    AttributeKeyValueStore& GetAttributes() noexcept { return m_attributes; }\n    [[nodiscard]] const AttributeKeyValueStore& GetAttributes() const noexcept { return m_attributes; }\n\nprivate:\n    std::uint64_t m_itemID = 0;\n    std::uint16_t m_defIndex = 0;\n    sdk::EconQuality_t m_quality = sdk::EconQuality_t::QUALITY_NORMAL;\n    sdk::EconRarity_t m_rarity = sdk::EconRarity_t::RARITY_DEFAULT;\n    std::int32_t m_paintKitIndex = 0;\n    std::int32_t m_seed = 0;\n    float m_wear = 0.0f;\n    std::int32_t m_statTrakCount = -1;\n    std::string m_customName;\n    AttributeKeyValueStore m_attributes;\n};\n\n// ============================================================================\n// 5. Economy Item Schema Catalog\n// Lookup catalog for Item Definitions and Paint Kits.\n// ============================================================================\n\nclass EconItemCatalog {\npublic:\n    EconItemCatalog() = default;\n    ~EconItemCatalog() = default;\n\n    static EconItemCatalog& GetInstance() noexcept;\n\n    bool RegisterItemDefinition(const sdk::CEconItemDefinition& def);\n    bool RegisterPaintKit(const sdk::CPaintKitDefinition& kit);\n\n    [[nodiscard]] const sdk::CEconItemDefinition* FindItemDefinition(std::uint16_t defIndex) const noexcept;\n    [[nodiscard]] const sdk::CEconItemDefinition* FindItemDefinitionByName(std::string_view name) const noexcept;\n\n    [[nodiscard]] const sdk::CPaintKitDefinition* FindPaintKit(std::int32_t paintKitId) const noexcept;\n    [[nodiscard]] const sdk::CPaintKitDefinition* FindPaintKitByName(std::string_view name) const noexcept;\n\n    [[nodiscard]] std::size_t GetItemCount() const noexcept { return m_itemsByIndex.size(); }\n    [[nodiscard]] std::size_t GetPaintKitCount() const noexcept { return m_paintKitsById.size(); }\n\n    void Clear() noexcept;\n    void InitializeDefaultCatalog();\n\nprivate:\n    std::unordered_map<std::uint16_t, sdk::CEconItemDefinition> m_itemsByIndex;\n    std::unordered_map<std::string, std::uint16_t> m_itemsByName;\n\n    std::unordered_map<std::int32_t, sdk::CPaintKitDefinition> m_paintKitsById;\n    std::unordered_map<std::string, std::int32_t> m_paintKitsByName;\n};\n\n} // namespace cs2::client\n\n#endif // CS2_CLIENT_INVENTORY_SCHEMA_H\n",
        "movement.cpp": "#include \"movement.h\"\n\nnamespace cs2::client {\n\nvoid CPlayerMovement::ClipVelocity(const Vector3& in, const Vector3& normal, Vector3& out, float overbounce) {\n    const float backoff = (in.x * normal.x + in.y * normal.y + in.z * normal.z) * overbounce;\n\n    out.x = in.x - (normal.x * backoff);\n    out.y = in.y - (normal.y * backoff);\n    out.z = in.z - (normal.z * backoff);\n\n    // Friction / rubbing deadzone\n    constexpr float STOP_EPSILON = 0.001f;\n    if (std::abs(out.x) < STOP_EPSILON) out.x = 0.0f;\n    if (std::abs(out.y) < STOP_EPSILON) out.y = 0.0f;\n    if (std::abs(out.z) < STOP_EPSILON) out.z = 0.0f;\n}\n\nMoveTrace_t CPlayerMovement::TracePlayerBBox(const Vector3& start, const Vector3& end,\n                                            const PlayerMovementServices& services) {\n    MoveTrace_t tr;\n    tr.startPos = start;\n    tr.endPos = end;\n    tr.planeNormal = Vector3{0.0f, 0.0f, 1.0f};\n\n    // Increments m_nTraceCount at offset +0x0648\n    const_cast<PlayerMovementServices&>(services).m_nTraceCount++;\n\n    // Ground plane analytical collision test (Z <= 0.0f is default solid floor)\n    if (end.z <= 0.0f) {\n        if (start.z <= 0.0f) {\n            tr.fraction = 0.0f;\n            tr.allSolid = true;\n            tr.startSolid = true;\n            tr.endPos = start;\n        } else {\n            const float deltaZ = start.z - end.z;\n            tr.fraction = (deltaZ > 0.0001f) ? (start.z / deltaZ) : 0.0f;\n            tr.fraction = std::clamp(tr.fraction, 0.0f, 1.0f);\n            tr.endPos.x = start.x + (end.x - start.x) * tr.fraction;\n            tr.endPos.y = start.y + (end.y - start.y) * tr.fraction;\n            tr.endPos.z = 0.0f;\n        }\n        tr.planeNormal = Vector3{0.0f, 0.0f, 1.0f};\n    } else {\n        tr.fraction = 1.0f;\n        tr.endPos = end;\n    }\n\n    return tr;\n}\n\nvoid CPlayerMovement::Friction(PlayerMovementServices& services, PlayerMoveData& mv, float dt) {\n    const float speed = std::sqrt(mv.velocity.x * mv.velocity.x + mv.velocity.y * mv.velocity.y);\n    if (speed < 0.1f) {\n        mv.velocity.x = 0.0f;\n        mv.velocity.y = 0.0f;\n        return;\n    }\n\n    // sv_stopspeed threshold clamping\n    const float control = (speed < SV_STOPSPEED) ? SV_STOPSPEED : speed;\n\n    // drop = control * sv_friction * m_flSurfaceFriction * dt\n    const float drop = control * SV_FRICTION * services.m_flSurfaceFriction * dt;\n    const float newspeed = std::max(0.0f, speed - drop);\n\n    if (newspeed != speed) {\n        const float fraction = newspeed / speed;\n        mv.velocity.x *= fraction;\n        mv.velocity.y *= fraction;\n    }\n}\n\nvoid CPlayerMovement::Accelerate(PlayerMovementServices& services, PlayerMoveData& mv,\n                                 const Vector3& wishdir, float wishspeed, float accel, float dt) {\n    // Current projected speed along wish direction\n    const float currentspeed = mv.velocity.x * wishdir.x + mv.velocity.y * wishdir.y;\n    const float addspeed = wishspeed - currentspeed;\n\n    if (addspeed <= 0.0f) {\n        return;\n    }\n\n    // Stance multipliers: crouch (0.34) and shift-walk (0.52)\n    float stanceMultiplier = 1.0f;\n    if (services.m_bDucked) {\n        stanceMultiplier = CS_DUCK_SPEED_MULTIPLIER;\n    } else if (mv.buttons & (IN_SPEED | IN_WALK)) {\n        stanceMultiplier = CS_WALK_SPEED_MULTIPLIER;\n    }\n\n    // Weapon max speed scalar (sv_accelerate_use_weapon_speed)\n    float weaponSpeedRatio = 1.0f;\n    if (mv.clientMaxSpeed > 0.0f && mv.clientMaxSpeed < 250.0f) {\n        weaponSpeedRatio = mv.clientMaxSpeed / 250.0f;\n    }\n\n    // accelspeed = accel * dt * wishspeed * m_flSurfaceFriction * stanceMultiplier * weaponSpeedRatio\n    float accelspeed = accel * dt * wishspeed * services.m_flSurfaceFriction * stanceMultiplier * weaponSpeedRatio;\n    if (accelspeed > addspeed) {\n        accelspeed = addspeed;\n    }\n\n    mv.velocity.x += accelspeed * wishdir.x;\n    mv.velocity.y += accelspeed * wishdir.y;\n}\n\nvoid CPlayerMovement::AirAccelerate(PlayerMovementServices& services, PlayerMoveData& mv,\n                                    const Vector3& wishdir, float wishspeed, float accel, float dt) {\n    // Air wishspeed is strictly clamped to sv_air_max_wishspeed (30.0f)\n    const float wishspd = std::min(wishspeed, SV_AIR_MAX_WISHSPEED);\n\n    const float currentspeed = mv.velocity.x * wishdir.x + mv.velocity.y * wishdir.y + mv.velocity.z * wishdir.z;\n    const float addspeed = wishspd - currentspeed;\n\n    if (addspeed <= 0.0f) {\n        return;\n    }\n\n    float accelspeed = accel * wishspeed * dt * services.m_flSurfaceFriction;\n    if (accelspeed > addspeed) {\n        accelspeed = addspeed;\n    }\n\n    mv.velocity.x += accelspeed * wishdir.x;\n    mv.velocity.y += accelspeed * wishdir.y;\n    mv.velocity.z += accelspeed * wishdir.z;\n}\n\nvoid CPlayerMovement::CategorizePosition(PlayerMovementServices& services, PlayerMoveData& mv, float /*dt*/) {\n    // Trace 2 units downward to detect floor contact\n    Vector3 point = mv.origin;\n    point.z -= 2.0f;\n\n    MoveTrace_t tr = TracePlayerBBox(mv.origin, point, services);\n\n    // Check if normal is steep or walkable (z >= 0.7071 for <= 45.57 deg)\n    if (tr.fraction < 1.0f && tr.planeNormal.z >= SV_STANDABLE_NORMAL_Z) {\n        mv.onGround = true;\n        services.m_groundNormal = tr.planeNormal;\n\n        // Snap vertical position to contact surface and kill downward velocity\n        if (mv.velocity.z <= 0.0f) {\n            mv.origin.z = tr.endPos.z;\n            mv.velocity.z = 0.0f;\n        }\n    } else {\n        mv.onGround = false;\n    }\n}\n\nvoid CPlayerMovement::StepMove(PlayerMovementServices& services, PlayerMoveData& mv, float dt) {\n    const Vector3 originalPos = mv.origin;\n    const Vector3 originalVel = mv.velocity;\n\n    // 1. First attempt direct horizontal move\n    Vector3 dest;\n    dest.x = originalPos.x + originalVel.x * dt;\n    dest.y = originalPos.y + originalVel.y * dt;\n    dest.z = originalPos.z;\n\n    MoveTrace_t tr = TracePlayerBBox(originalPos, dest, services);\n    if (tr.fraction == 1.0f) {\n        mv.origin = tr.endPos;\n        return;\n    }\n\n    // 2. Obstacle encountered: attempt obstacle step-up (up to sv_stepsize = 18.0f)\n    Vector3 stepUpPos = originalPos;\n    stepUpPos.z += SV_STEPSIZE;\n\n    Vector3 stepDest = stepUpPos;\n    stepDest.x += originalVel.x * dt;\n    stepDest.y += originalVel.y * dt;\n\n    MoveTrace_t trStep = TracePlayerBBox(stepUpPos, stepDest, services);\n\n    // 3. Step downward from elevated position to locate new ground surface\n    Vector3 stepDownEnd = trStep.endPos;\n    stepDownEnd.z -= SV_STEPSIZE;\n\n    MoveTrace_t trDown = TracePlayerBBox(trStep.endPos, stepDownEnd, services);\n\n    // 4. Verify if stepped move made valid horizontal progress\n    const float directDistSqr = (tr.endPos.x - originalPos.x) * (tr.endPos.x - originalPos.x) +\n                                (tr.endPos.y - originalPos.y) * (tr.endPos.y - originalPos.y);\n    const float stepDistSqr   = (trDown.endPos.x - originalPos.x) * (trDown.endPos.x - originalPos.x) +\n                                (trDown.endPos.y - originalPos.y) * (trDown.endPos.y - originalPos.y);\n\n    if (stepDistSqr > directDistSqr && trDown.planeNormal.z >= SV_STANDABLE_NORMAL_Z) {\n        mv.origin = trDown.endPos;\n    } else {\n        // Fall back to sliding along collision normal\n        ClipVelocity(originalVel, tr.planeNormal, mv.velocity);\n        mv.origin = tr.endPos;\n    }\n}\n\nfloat CPlayerMovement::CalculateSubtickJumpVelocity(const PlayerMovementServices& services,\n                                                   float subtickFraction, float horizontalSpeed) {\n    // Reverse engineered from client.dll FUN_1808c0460:\n    // fVar2 = clamp(1.0 + speed * 0.0005, 0.2, 1.0)\n    const float speedRatio = std::clamp(1.0f + horizontalSpeed * 0.0005f, 0.2f, 1.0f);\n\n    // Sub-tick continuous interpolation: earlier keypress within tick grants greater initial push\n    const float subtickLead = (1.0f - std::clamp(subtickFraction, 0.0f, 1.0f)) * 0.6f;\n    float subtickMultiplier = std::min(1.0f, speedRatio + subtickLead);\n\n    // Stamina penalty scaling: clamp(1.0 - stamina / 100.0, 0.0, 1.0)\n    if (services.m_flStamina > 0.0f) {\n        const float staminaRatio = std::clamp(1.0f - (services.m_flStamina / 100.0f), 0.0f, 1.0f);\n        subtickMultiplier *= staminaRatio;\n    }\n\n    // Half-gravity compensation during jump tick: sv_jump_impulse - (sv_gravity * 0.5 * 0.0078125)\n    // 301.993378 - (800.0 * 0.5 * 0.0078125) = 298.868378\n    constexpr float HALF_GRAVITY_JUMP_COMP = SV_GRAVITY * 0.5f * (TICK_INTERVAL * 0.5f);\n    const float baseJumpImpulse = SV_JUMP_IMPULSE - HALF_GRAVITY_JUMP_COMP;\n\n    return baseJumpImpulse * subtickMultiplier;\n}\n\nbool CPlayerMovement::CheckJumpButton(PlayerMovementServices& services, PlayerMoveData& mv, float /*dt*/) {\n    if (!(mv.buttons & IN_JUMP)) {\n        return false;\n    }\n\n    if (!mv.onGround) {\n        return false;\n    }\n\n    // Extract exact sub-tick fraction from subtick input events if available\n    float subtickFraction = 0.0f;\n    for (const auto& step : mv.subtickSteps) {\n        if (step.pressed && (step.button & IN_JUMP)) {\n            subtickFraction = step.when;\n            break;\n        }\n    }\n\n    const float horizontalSpeed = std::sqrt(mv.velocity.x * mv.velocity.x + mv.velocity.y * mv.velocity.y);\n    const float jumpVelZ = CalculateSubtickJumpVelocity(services, subtickFraction, horizontalSpeed);\n\n    mv.velocity.z = jumpVelZ;\n    mv.onGround = false;\n\n    // Update internal movement service tracking fields\n    services.m_bHasWalkMovedSinceLastJump = false;\n    services.m_flLastJumpFrac = subtickFraction;\n    services.m_flLastJumpVelocityZ = jumpVelZ;\n    services.m_flHeightAtJumpStart = mv.origin.z;\n    services.m_flStaminaAtJumpStart = services.m_flStamina;\n    services.m_flVelMulAtJumpStart = jumpVelZ / SV_JUMP_IMPULSE;\n    services.m_bJumpApexPending = true;\n\n    // Apply CS2 jump stamina cost (recovers exponentially over subsequent ticks)\n    services.m_flStamina = std::min(100.0f, services.m_flStamina + 40.0f);\n\n    return true;\n}\n\nvoid CPlayerMovement::WalkMove(PlayerMovementServices& services, PlayerMoveData& mv, float dt) {\n    // Sets m_bHasWalkMovedSinceLastJump = true (+0x0439)\n    services.m_bHasWalkMovedSinceLastJump = true;\n\n    // 1. Calculate view angles basis vectors (pitch zeroed for 2D ground movement)\n    QAngle moveAngles;\n    moveAngles.pitch = 0.0f;\n    moveAngles.yaw   = mv.viewAngles.y;\n    moveAngles.roll  = 0.0f;\n\n    Vector3 forward, right, up;\n    CViewRender::AngleVectors(moveAngles, &forward, &right, &up);\n\n    // 2. Compute wish velocity vector\n    Vector3 wishvel;\n    wishvel.x = forward.x * mv.forwardMove + right.x * mv.sideMove;\n    wishvel.y = forward.y * mv.forwardMove + right.y * mv.sideMove;\n    wishvel.z = 0.0f;\n\n    services.m_vecWalkWishVel = wishvel;\n\n    float wishspeed = std::sqrt(wishvel.x * wishvel.x + wishvel.y * wishvel.y);\n    Vector3 wishdir{0.0f, 0.0f, 0.0f};\n\n    if (wishspeed > 0.0001f) {\n        wishdir.x = wishvel.x / wishspeed;\n        wishdir.y = wishvel.y / wishspeed;\n    }\n\n    // Clamp wishspeed to player maximum speed\n    const float maxspeed = (mv.clientMaxSpeed > 0.0f) ? std::min(mv.maxSpeed, mv.clientMaxSpeed) : mv.maxSpeed;\n    if (wishspeed > maxspeed) {\n        wishspeed = maxspeed;\n    }\n\n    mv.wishSpeed = wishspeed;\n    mv.wishDirection = wishdir;\n\n    // 3. Apply ground friction\n    Friction(services, mv, dt);\n\n    // 4. Directional ground acceleration\n    Accelerate(services, mv, wishdir, wishspeed, SV_ACCELERATE, dt);\n\n    // Clamp vertical velocity to zero on ground\n    mv.velocity.z = 0.0f;\n\n    // 5. Add base velocity (conveyor belts, push triggers)\n    mv.velocity.x += mv.baseVelocity.x;\n    mv.velocity.y += mv.baseVelocity.y;\n\n    // 6. Execute step move and obstacle traversal\n    StepMove(services, mv, dt);\n\n    // 7. Remove base velocity\n    mv.velocity.x -= mv.baseVelocity.x;\n    mv.velocity.y -= mv.baseVelocity.y;\n\n    // 8. Re-categorize position and snap to floor\n    CategorizePosition(services, mv, dt);\n}\n\nvoid CPlayerMovement::AirMove(PlayerMovementServices& services, PlayerMoveData& mv, float dt) {\n    QAngle moveAngles;\n    moveAngles.pitch = 0.0f;\n    moveAngles.yaw   = mv.viewAngles.y;\n    moveAngles.roll  = 0.0f;\n\n    Vector3 forward, right, up;\n    CViewRender::AngleVectors(moveAngles, &forward, &right, &up);\n\n    Vector3 wishvel;\n    wishvel.x = forward.x * mv.forwardMove + right.x * mv.sideMove;\n    wishvel.y = forward.y * mv.forwardMove + right.y * mv.sideMove;\n    wishvel.z = 0.0f;\n\n    float wishspeed = std::sqrt(wishvel.x * wishvel.x + wishvel.y * wishvel.y);\n    Vector3 wishdir{0.0f, 0.0f, 0.0f};\n\n    if (wishspeed > 0.0001f) {\n        wishdir.x = wishvel.x / wishspeed;\n        wishdir.y = wishvel.y / wishspeed;\n    }\n\n    const float maxspeed = (mv.clientMaxSpeed > 0.0f) ? std::min(mv.maxSpeed, mv.clientMaxSpeed) : mv.maxSpeed;\n    if (wishspeed > maxspeed) {\n        wishspeed = maxspeed;\n    }\n\n    mv.wishSpeed = wishspeed;\n    mv.wishDirection = wishdir;\n\n    // 1. Airborne strafe acceleration\n    AirAccelerate(services, mv, wishdir, wishspeed, SV_AIRACCELERATE, dt);\n\n    // 2. Continuous sub-tick half-gravity integration (Verlet leapfrog)\n    mv.velocity.z -= SV_GRAVITY * 0.5f * dt;\n\n    // 3. Position integration\n    mv.origin.x += mv.velocity.x * dt;\n    mv.origin.y += mv.velocity.y * dt;\n    mv.origin.z += mv.velocity.z * dt;\n\n    // 4. Second half-gravity integration\n    mv.velocity.z -= SV_GRAVITY * 0.5f * dt;\n\n    // 5. Categorize position to test for landing\n    CategorizePosition(services, mv, dt);\n}\n\nvoid CPlayerMovement::ProcessMovement(PlayerMovementServices& services, PlayerMoveData& mv, float dt) {\n    // Stamina recovery\n    if (services.m_flStamina > 0.0f) {\n        services.m_flStamina = std::max(0.0f, services.m_flStamina - 20.0f * dt);\n    }\n\n    // Check if player is dead or immobilized\n    if (mv.moveType == MOVETYPE_NONE) {\n        mv.velocity = Vector3{0.0f, 0.0f, 0.0f};\n        return;\n    }\n\n    // Noclip movement\n    if (mv.moveType == MOVETYPE_NOCLIP) {\n        QAngle moveAngles{mv.viewAngles.x, mv.viewAngles.y, mv.viewAngles.z};\n        Vector3 forward, right, up;\n        CViewRender::AngleVectors(moveAngles, &forward, &right, &up);\n\n        mv.velocity.x = forward.x * mv.forwardMove + right.x * mv.sideMove;\n        mv.velocity.y = forward.y * mv.forwardMove + right.y * mv.sideMove;\n        mv.velocity.z = forward.z * mv.forwardMove + right.z * mv.sideMove + up.z * mv.upMove;\n\n        mv.origin.x += mv.velocity.x * dt;\n        mv.origin.y += mv.velocity.y * dt;\n        mv.origin.z += mv.velocity.z * dt;\n        return;\n    }\n\n    // Handle sub-tick slices if sub-tick input steps exist\n    if (!mv.subtickSteps.empty()) {\n        auto sortedSteps = mv.subtickSteps;\n        std::sort(sortedSteps.begin(), sortedSteps.end(), [](const SubtickInputStep& a, const SubtickInputStep& b) {\n            return a.when < b.when;\n        });\n\n        float currentFrac = 0.0f;\n        for (const auto& step : sortedSteps) {\n            const float sliceDt = (step.when - currentFrac) * dt;\n            if (sliceDt > 0.0f) {\n                if (mv.onGround) {\n                    WalkMove(services, mv, sliceDt);\n                } else {\n                    AirMove(services, mv, sliceDt);\n                }\n            }\n\n            // Apply instantaneous sub-tick button actions (e.g. analog jump)\n            if (step.pressed && (step.button & IN_JUMP)) {\n                mv.buttons |= IN_JUMP;\n                CheckJumpButton(services, mv, dt);\n            }\n\n            currentFrac = step.when;\n        }\n\n        const float remainderDt = (1.0f - currentFrac) * dt;\n        if (remainderDt > 0.0f) {\n            if (mv.onGround) {\n                WalkMove(services, mv, remainderDt);\n            } else {\n                AirMove(services, mv, remainderDt);\n            }\n        }\n        return;\n    }\n\n    // Standard discrete tick execution:\n    // 1. Initial jump check\n    CheckJumpButton(services, mv, dt);\n\n    // 2. Ground vs Airborne locomotion dispatch\n    if (mv.onGround) {\n        WalkMove(services, mv, dt);\n    } else {\n        AirMove(services, mv, dt);\n    }\n}\n\n} // namespace cs2::client\n",
        "movement.h": "#ifndef CS2_CLIENT_MOVEMENT_H\n#define CS2_CLIENT_MOVEMENT_H\n\n#include \"viewmatrix.h\"\n#include <cstdint>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n\nnamespace cs2::client {\n\n// Standard Source 2 button bitmasks\nenum MoveButtonBits : uint64_t {\n    IN_ATTACK       = (1ULL << 0),\n    IN_JUMP         = (1ULL << 1),\n    IN_DUCK         = (1ULL << 2),\n    IN_FORWARD      = (1ULL << 3),\n    IN_BACK         = (1ULL << 4),\n    IN_USE          = (1ULL << 5),\n    IN_CANCEL       = (1ULL << 6),\n    IN_LEFT         = (1ULL << 7),\n    IN_RIGHT        = (1ULL << 8),\n    IN_MOVELEFT     = (1ULL << 9),\n    IN_MOVERIGHT    = (1ULL << 10),\n    IN_ATTACK2      = (1ULL << 11),\n    IN_RUN          = (1ULL << 12),\n    IN_RELOAD       = (1ULL << 13),\n    IN_ALT1         = (1ULL << 14),\n    IN_ALT2         = (1ULL << 15),\n    IN_SPEED        = (1ULL << 16),\n    IN_WALK         = (1ULL << 17),\n    IN_ZOOM         = (1ULL << 19),\n    IN_BULLRUSH     = (1ULL << 22),\n    IN_GRENADE1     = (1ULL << 23),\n    IN_GRENADE2     = (1ULL << 24),\n    IN_ATTACK3      = (1ULL << 25),\n};\n\nenum MoveType_t : uint8_t {\n    MOVETYPE_NONE           = 0,\n    MOVETYPE_ISOMETRIC      = 1,\n    MOVETYPE_WALK           = 2,\n    MOVETYPE_STEP           = 3,\n    MOVETYPE_FLY            = 4,\n    MOVETYPE_FLYGRAVITY     = 5,\n    MOVETYPE_VPHYSICS       = 6,\n    MOVETYPE_PUSH           = 7,\n    MOVETYPE_NOCLIP         = 8,\n    MOVETYPE_LADDER         = 9,\n    MOVETYPE_OBSERVER       = 10,\n    MOVETYPE_CUSTOM         = 11,\n};\n\n// Sub-tick input action event from CSGOUserCmdPB / CSubtickMoveStep\nstruct SubtickInputStep {\n    float when = 0.0f;       // Sub-tick fractional offset [0.0, 1.0]\n    uint64_t button = 0;     // MoveButtonBits\n    bool pressed = false;    // True if key-down, false if key-up\n};\n\n// Movement simulation trace / collision result\nstruct MoveTrace_t {\n    Vector3 startPos;\n    Vector3 endPos;\n    Vector3 planeNormal;\n    float fraction = 1.0f;\n    bool allSolid = false;\n    bool startSolid = false;\n    uint32_t hitEntityHandle = 0xFFFFFFFF;\n};\n\n// Player movement parameters passed into ProcessMovement (matching CMoveData)\nstruct PlayerMoveData {\n    uint32_t playerHandle = 0xFFFFFFFF;\n    MoveType_t moveType = MOVETYPE_WALK;\n    Vector3 origin;\n    Vector3 velocity;\n    Vector3 baseVelocity;\n    Vector3 viewAngles;\n    Vector3 wishVelocity;\n    Vector3 wishDirection;\n    float wishSpeed = 0.0f;\n    float forwardMove = 0.0f;\n    float sideMove = 0.0f;\n    float upMove = 0.0f;\n    float maxSpeed = 320.0f;\n    float clientMaxSpeed = 250.0f;\n    uint64_t buttons = 0;\n    uint64_t oldButtons = 0;\n    bool onGround = false;\n    std::vector<SubtickInputStep> subtickSteps;\n};\n\n// Movement services state container matching CCSPlayer_MovementServices & CPlayer_MovementServices\nstruct PlayerMovementServices {\n    // Humanoid & surface physics\n    float m_flSurfaceFriction = 1.0f;         // +0x026c\n    float m_flStepSoundTime = 0.0f;           // +0x0258\n    float m_flFallVelocity = 0.0f;            // +0x025c\n    Vector3 m_groundNormal{0.0f, 0.0f, 1.0f}; // +0x0260\n\n    // Ducking state\n    bool m_bDucked = false;                   // +0x0408\n    float m_flDuckAmount = 0.0f;              // +0x040c\n    float m_flDuckSpeed = 0.0f;               // +0x0410\n    bool m_bDuckOverride = false;             // +0x0414\n    bool m_bDesiresDuck = false;              // +0x0415\n    bool m_bDucking = false;                  // +0x0416\n\n    // Locomotion & jumping\n    bool m_bHasWalkMovedSinceLastJump = false; // +0x0439\n    int32_t m_nTraceCount = 0;                // +0x0648\n    float m_flStamina = 0.0f;                 // +0x069c\n    float m_flHeightAtJumpStart = 0.0f;       // +0x06a0\n    float m_flMaxJumpHeightThisJump = 0.0f;   // +0x06a4\n    float m_flMaxJumpHeightLastJump = 0.0f;   // +0x06a8\n    float m_flStaminaAtJumpStart = 0.0f;      // +0x06ac\n    float m_flVelMulAtJumpStart = 1.0f;       // +0x06b0\n    float m_flAccumulatedJumpError = 0.0f;    // +0x06b4\n    int32_t m_nLastJumpTick = 0;              // +0x0708\n    float m_flLastJumpFrac = 0.0f;            // +0x070c\n    float m_flLastJumpVelocityZ = 0.0f;       // +0x0710\n    bool m_bJumpApexPending = false;          // +0x0714\n    Vector3 m_vecWalkWishVel;                 // +0x07a8\n};\n\n/**\n * @brief Source 2 Player Movement & Ground Physics Pipeline\n * Reconstructed clean-room implementation from client.dll (FUN_1808df090, FUN_1808ea1b0, FUN_1808bee90, FUN_1808bfa30)\n */\nclass CPlayerMovement {\npublic:\n    // Core Engine Physics Constants\n    static constexpr float TICK_INTERVAL             = 1.0f / 64.0f; // 0.015625s\n    static constexpr float SV_GRAVITY                = 800.0f;       // u/s^2 (sv_gravity)\n    static constexpr float SV_FRICTION               = 5.2f;         // sv_friction\n    static constexpr float SV_STOPSPEED              = 100.0f;       // sv_stopspeed\n    static constexpr float SV_ACCELERATE             = 5.5f;         // sv_accelerate\n    static constexpr float SV_AIRACCELERATE          = 12.0f;        // sv_airaccelerate\n    static constexpr float SV_AIR_MAX_WISHSPEED      = 30.0f;        // sv_air_max_wishspeed\n    static constexpr float SV_MAXSPEED               = 320.0f;       // sv_maxspeed\n    static constexpr float SV_STEPSIZE               = 18.0f;        // sv_stepsize\n    static constexpr float SV_STANDABLE_NORMAL_Z     = 0.7f;         // Cosine of 45.57 deg max walkable slope\n    static constexpr float SV_JUMP_IMPULSE           = 301.993378f;  // sqrt(2 * 800 * 57)\n    static constexpr float CS_DUCK_SPEED_MULTIPLIER  = 0.34f;        // Crouch speed scalar\n    static constexpr float CS_WALK_SPEED_MULTIPLIER  = 0.52f;        // Shift walking scalar\n\n    // Master execution dispatcher (FUN_1808df090)\n    static void ProcessMovement(PlayerMovementServices& services, PlayerMoveData& mv, float dt);\n\n    // Ground locomotion pipeline (FUN_1808ea1b0)\n    static void WalkMove(PlayerMovementServices& services, PlayerMoveData& mv, float dt);\n\n    // Airborne locomotion pipeline (FUN_1808e57b0)\n    static void AirMove(PlayerMovementServices& services, PlayerMoveData& mv, float dt);\n\n    // Ground surface friction (FUN_1808cbf50)\n    static void Friction(PlayerMovementServices& services, PlayerMoveData& mv, float dt);\n\n    // Directional ground acceleration with weapon and stance scaling (FUN_1808bee90 / FUN_1808bef60)\n    static void Accelerate(PlayerMovementServices& services, PlayerMoveData& mv,\n                           const Vector3& wishdir, float wishspeed, float accel, float dt);\n\n    // Airborne strafe acceleration clamped to sv_air_max_wishspeed (FUN_1808bfa30)\n    static void AirAccelerate(PlayerMovementServices& services, PlayerMoveData& mv,\n                              const Vector3& wishdir, float wishspeed, float accel, float dt);\n\n    // Surface detection and ground snapping (FUN_1808e6020)\n    static void CategorizePosition(PlayerMovementServices& services, PlayerMoveData& mv, float dt);\n\n    // Stair and curb obstacle stepping (FUN_1808e1940)\n    static void StepMove(PlayerMovementServices& services, PlayerMoveData& mv, float dt);\n\n    // Jump button handling and sub-tick impulse generation (FUN_1808c34f0 / FUN_1808e7e70)\n    static bool CheckJumpButton(PlayerMovementServices& services, PlayerMoveData& mv, float dt);\n\n    // Sub-tick continuous jump velocity modulation (FUN_1808c0460)\n    static float CalculateSubtickJumpVelocity(const PlayerMovementServices& services,\n                                              float subtickFraction, float horizontalSpeed);\n\n    // Helper: Environment trace simulation (swept AABB against world geometry)\n    static MoveTrace_t TracePlayerBBox(const Vector3& start, const Vector3& end,\n                                       const PlayerMovementServices& services);\n\n    // Helper: Clip velocity against collision plane normal\n    static void ClipVelocity(const Vector3& in, const Vector3& normal, Vector3& out, float overbounce = 1.0f);\n};\n\n} // namespace cs2::client\n\n#endif // CS2_CLIENT_MOVEMENT_H\n",
        "subtick_prediction.cpp": "#include \"subtick_prediction.h\"\n#include <cmath>\n#include <algorithm>\n\nnamespace cs2::client {\n\nvoid CSubtickPrediction::SimulateGroundFriction(PlayerMovementState& state, float dt) {\n    const float speed = std::sqrt(state.velocity.x * state.velocity.x + state.velocity.y * state.velocity.y);\n    if (speed < 0.1f) {\n        state.velocity.x = 0;\n        state.velocity.y = 0;\n        return;\n    }\n\n    const float drop = speed * FRICTION * dt;\n    const float newspeed = std::max(0.0f, speed - drop);\n    const float frac = newspeed / speed;\n\n    state.velocity.x *= frac;\n    state.velocity.y *= frac;\n}\n\nvoid CSubtickPrediction::SimulateAirborne(PlayerMovementState& state, float dt) {\n    state.velocity.z -= GRAVITY * dt;\n}\n\nvoid CSubtickPrediction::PredictUserCmd(PlayerMovementState& state, const UserCmd& cmd) {\n    float currentFraction = 0.0f;\n\n    auto events = cmd.subTickMoves;\n    std::sort(events.begin(), events.end(), [](const SubTickMoveStep& a, const SubTickMoveStep& b) {\n        return a.when < b.when;\n    });\n\n    for (const auto& ev : events) {\n        const float sliceDt = (ev.when - currentFraction) * TICK_INTERVAL;\n        if (sliceDt > 0.0f) {\n            if (state.onGround) {\n                SimulateGroundFriction(state, sliceDt);\n            } else {\n                SimulateAirborne(state, sliceDt);\n            }\n            state.origin.x += state.velocity.x * sliceDt;\n            state.origin.y += state.velocity.y * sliceDt;\n            state.origin.z += state.velocity.z * sliceDt;\n        }\n\n        // Sub-tick instantaneous action impulse\n        if (ev.pressed && (ev.button & IN_JUMP) && state.onGround) {\n            state.velocity.z = JUMP_IMPULSE;\n            state.onGround = false;\n        }\n\n        currentFraction = ev.when;\n    }\n\n    const float remainderDt = (1.0f - currentFraction) * TICK_INTERVAL;\n    if (remainderDt > 0.0f) {\n        if (state.onGround) {\n            SimulateGroundFriction(state, remainderDt);\n        } else {\n            SimulateAirborne(state, remainderDt);\n        }\n        state.origin.x += state.velocity.x * remainderDt;\n        state.origin.y += state.velocity.y * remainderDt;\n        state.origin.z += state.velocity.z * remainderDt;\n    }\n}\n\n} // namespace cs2::client\n",
        "subtick_prediction.h": "#ifndef CS2_CLIENT_SUBTICK_PREDICTION_H\n#define CS2_CLIENT_SUBTICK_PREDICTION_H\n\n#include \"viewmatrix.h\"\n#include \"movement.h\"\n#include <cstdint>\n#include <vector>\n\nnamespace cs2::client {\n\nusing InButtonBits = MoveButtonBits;\n\nstruct SubTickMoveStep {\n    float when;        // 0.0 to 1.0 (sub-tick fractional offset)\n    uint64_t button;   // InButtonBits\n    bool pressed;      // true if pressed, false if released\n};\n\nstruct UserCmd {\n    uint32_t commandNumber;\n    uint32_t clientTick;\n    float forwardMove;\n    float sideMove;\n    QAngle viewAngles;\n    uint64_t buttons;\n    std::vector<SubTickMoveStep> subTickMoves;\n};\n\nstruct PlayerMovementState {\n    Vector3 origin;\n    Vector3 velocity;\n    bool onGround;\n    float stamina;\n};\n\n/**\n * @brief Reconstructed Sub-Tick Movement Prediction from client.dll\n * Multi-slice continuous physics solver matching CS2 continuous analog jump timing.\n */\nclass CSubtickPrediction {\npublic:\n    static constexpr float TICK_INTERVAL = 1.0f / 64.0f; // 0.015625s\n    static constexpr float GRAVITY = 800.0f;             // u/s^2\n    static constexpr float JUMP_IMPULSE = 301.993378f;   // sqrt(2 * 800 * 57)\n    static constexpr float FRICTION = 5.2f;\n\n    static void PredictUserCmd(PlayerMovementState& state, const UserCmd& cmd);\n    static void SimulateGroundFriction(PlayerMovementState& state, float dt);\n    static void SimulateAirborne(PlayerMovementState& state, float dt);\n};\n\n} // namespace cs2::client\n\n#endif // CS2_CLIENT_SUBTICK_PREDICTION_H\n",
        "usercmd_wire.cpp": "#include \"usercmd_wire.h\"\n#include <cstring>\n#include <cmath>\n#include <stdexcept>\n\nnamespace cs2::client {\n\n// ============================================================================\n// CByteStreamReader Implementation\n// ============================================================================\n\nbool CByteStreamReader::ReadByte(uint8_t& outByte) {\n    if (m_nOffset >= m_nSize) return false;\n    outByte = m_pData[m_nOffset++];\n    return true;\n}\n\nbool CByteStreamReader::ReadVarInt32(uint32_t& outVal) {\n    uint64_t val64 = 0;\n    if (!ReadVarInt64(val64)) return false;\n    outVal = static_cast<uint32_t>(val64);\n    return true;\n}\n\nbool CByteStreamReader::ReadVarInt64(uint64_t& outVal) {\n    outVal = 0;\n    int shift = 0;\n    while (m_nOffset < m_nSize && shift < 64) {\n        uint8_t b = m_pData[m_nOffset++];\n        outVal |= static_cast<uint64_t>(b & 0x7F) << shift;\n        if ((b & 0x80) == 0) {\n            return true;\n        }\n        shift += 7;\n    }\n    return false;\n}\n\nbool CByteStreamReader::ReadFixed32(uint32_t& outVal) {\n    if (m_nOffset + sizeof(uint32_t) > m_nSize) return false;\n    std::memcpy(&outVal, m_pData + m_nOffset, sizeof(uint32_t));\n    m_nOffset += sizeof(uint32_t);\n    return true;\n}\n\nbool CByteStreamReader::ReadFloat(float& outVal) {\n    static_assert(sizeof(float) == sizeof(uint32_t), \"Float size mismatch\");\n    uint32_t bits = 0;\n    if (!ReadFixed32(bits)) return false;\n    std::memcpy(&outVal, &bits, sizeof(float));\n    return true;\n}\n\nbool CByteStreamReader::ReadFixed64(uint64_t& outVal) {\n    if (m_nOffset + sizeof(uint64_t) > m_nSize) return false;\n    std::memcpy(&outVal, m_pData + m_nOffset, sizeof(uint64_t));\n    m_nOffset += sizeof(uint64_t);\n    return true;\n}\n\nbool CByteStreamReader::ReadDouble(double& outVal) {\n    static_assert(sizeof(double) == sizeof(uint64_t), \"Double size mismatch\");\n    uint64_t bits = 0;\n    if (!ReadFixed64(bits)) return false;\n    std::memcpy(&outVal, &bits, sizeof(double));\n    return true;\n}\n\nbool CByteStreamReader::ReadBytes(uint8_t* outDest, size_t len) {\n    if (m_nOffset + len > m_nSize) return false;\n    std::memcpy(outDest, m_pData + m_nOffset, len);\n    m_nOffset += len;\n    return true;\n}\n\nbool CByteStreamReader::ReadString(std::string& outStr, size_t len) {\n    if (m_nOffset + len > m_nSize) return false;\n    outStr.assign(reinterpret_cast<const char*>(m_pData + m_nOffset), len);\n    m_nOffset += len;\n    return true;\n}\n\nbool CByteStreamReader::Skip(size_t len) {\n    if (m_nOffset + len > m_nSize) return false;\n    m_nOffset += len;\n    return true;\n}\n\nbool CByteStreamReader::SkipField(WireType wireType) {\n    switch (wireType) {\n        case WireType::VarInt: {\n            uint64_t dummy = 0;\n            return ReadVarInt64(dummy);\n        }\n        case WireType::Fixed64:\n            return Skip(8);\n        case WireType::LengthDelimited: {\n            uint32_t len = 0;\n            if (!ReadVarInt32(len)) return false;\n            return Skip(len);\n        }\n        case WireType::Fixed32:\n            return Skip(4);\n        default:\n            return false;\n    }\n}\n\n// ============================================================================\n// CByteStreamWriter Implementation\n// ============================================================================\n\nvoid CByteStreamWriter::WriteVarInt32(uint32_t val) {\n    while (val >= 0x80) {\n        m_Buffer.push_back(static_cast<uint8_t>((val & 0x7F) | 0x80));\n        val >>= 7;\n    }\n    m_Buffer.push_back(static_cast<uint8_t>(val & 0x7F));\n}\n\nvoid CByteStreamWriter::WriteVarInt64(uint64_t val) {\n    while (val >= 0x80) {\n        m_Buffer.push_back(static_cast<uint8_t>((val & 0x7F) | 0x80));\n        val >>= 7;\n    }\n    m_Buffer.push_back(static_cast<uint8_t>(val & 0x7F));\n}\n\nvoid CByteStreamWriter::WriteFixed32(uint32_t val) {\n    const uint8_t* p = reinterpret_cast<const uint8_t*>(&val);\n    m_Buffer.insert(m_Buffer.end(), p, p + 4);\n}\n\nvoid CByteStreamWriter::WriteFloat(float val) {\n    uint32_t bits = 0;\n    std::memcpy(&bits, &val, sizeof(float));\n    WriteFixed32(bits);\n}\n\nvoid CByteStreamWriter::WriteFixed64(uint64_t val) {\n    const uint8_t* p = reinterpret_cast<const uint8_t*>(&val);\n    m_Buffer.insert(m_Buffer.end(), p, p + 8);\n}\n\nvoid CByteStreamWriter::WriteDouble(double val) {\n    uint64_t bits = 0;\n    std::memcpy(&bits, &val, sizeof(double));\n    WriteFixed64(bits);\n}\n\nvoid CByteStreamWriter::WriteTag(uint32_t fieldNumber, WireType wireType) {\n    uint32_t key = (fieldNumber << 3) | static_cast<uint32_t>(wireType);\n    WriteVarInt32(key);\n}\n\nvoid CByteStreamWriter::WriteLengthDelimited(const uint8_t* data, size_t len) {\n    WriteVarInt32(static_cast<uint32_t>(len));\n    if (len > 0 && data != nullptr) {\n        m_Buffer.insert(m_Buffer.end(), data, data + len);\n    }\n}\n\nvoid CByteStreamWriter::WriteString(const std::string& str) {\n    WriteLengthDelimited(reinterpret_cast<const uint8_t*>(str.data()), str.size());\n}\n\nvoid CByteStreamWriter::WriteBytes(const uint8_t* data, size_t len) {\n    WriteLengthDelimited(data, len);\n}\n\n// ============================================================================\n// CSubtickMoveStep Serialization & Parsing\n// Reconstructed from FUN_1804f4c40 (_InternalSerialize) and FUN_1804f4950 (_InternalParse)\n// ============================================================================\n\nsize_t CSubtickMoveStep::ByteSizeLong() const {\n    size_t total = 0;\n\n    // Field 1: button (tag 1, wire 0, 1 byte tag)\n    if (m_nHasBits & HAS_BUTTON) {\n        total += 1;\n        uint64_t v = m_nButton;\n        do {\n            total++;\n            v >>= 7;\n        } while (v > 0);\n    }\n\n    // Field 2: pressed (tag 2, wire 0, tag 0x10 = 1 byte + 1 byte value)\n    if (m_nHasBits & HAS_PRESSED) {\n        total += 2;\n    }\n\n    // Field 3: when (tag 3, wire 5, tag 0x1D = 1 byte + 4 bytes float)\n    if (m_nHasBits & HAS_WHEN) {\n        total += 5;\n    }\n\n    // Field 4: analog_forward_delta (tag 4, wire 5, tag 0x25 = 1 byte + 4 bytes float)\n    if (m_nHasBits & HAS_ANALOG_FORWARD_DELTA) {\n        total += 5;\n    }\n\n    // Field 5: analog_left_delta (tag 5, wire 5, tag 0x2D = 1 byte + 4 bytes float)\n    if (m_nHasBits & HAS_ANALOG_LEFT_DELTA) {\n        total += 5;\n    }\n\n    // Field 8: analog_pitch_delta (tag 8, wire 5, tag 0x45 = 1 byte + 4 bytes float)\n    if (m_nHasBits & HAS_ANALOG_PITCH_DELTA) {\n        total += 5;\n    }\n\n    // Field 9: analog_yaw_delta (tag 9, wire 5, tag 0x4D = 1 byte + 4 bytes float)\n    if (m_nHasBits & HAS_ANALOG_YAW_DELTA) {\n        total += 5;\n    }\n\n    m_nCachedSize = static_cast<int32_t>(total);\n    return total;\n}\n\nvoid CSubtickMoveStep::_InternalSerialize(CByteStreamWriter& writer) const {\n    // 1. Field 1: uint64 button (Tag: (1 << 3) | 0 = 0x08)\n    if (m_nHasBits & HAS_BUTTON) {\n        writer.WriteTag(1, WireType::VarInt);\n        writer.WriteVarInt64(m_nButton);\n    }\n\n    // 2. Field 2: bool pressed (Tag: (2 << 3) | 0 = 0x10)\n    if (m_nHasBits & HAS_PRESSED) {\n        writer.WriteTag(2, WireType::VarInt);\n        writer.WriteByte(m_bPressed ? 1 : 0);\n    }\n\n    // 3. Field 3: float when (Tag: (3 << 3) | 5 = 0x1D)\n    if (m_nHasBits & HAS_WHEN) {\n        writer.WriteTag(3, WireType::Fixed32);\n        writer.WriteFloat(m_flWhen);\n    }\n\n    // 4. Field 4: float analog_forward_delta (Tag: (4 << 3) | 5 = 0x25)\n    if (m_nHasBits & HAS_ANALOG_FORWARD_DELTA) {\n        writer.WriteTag(4, WireType::Fixed32);\n        writer.WriteFloat(m_flAnalogForwardDelta);\n    }\n\n    // 5. Field 5: float analog_left_delta (Tag: (5 << 3) | 5 = 0x2D)\n    if (m_nHasBits & HAS_ANALOG_LEFT_DELTA) {\n        writer.WriteTag(5, WireType::Fixed32);\n        writer.WriteFloat(m_flAnalogLeftDelta);\n    }\n\n    // 6. Field 8: float analog_pitch_delta (Tag: (8 << 3) | 5 = 0x45)\n    if (m_nHasBits & HAS_ANALOG_PITCH_DELTA) {\n        writer.WriteTag(8, WireType::Fixed32);\n        writer.WriteFloat(m_flAnalogPitchDelta);\n    }\n\n    // 7. Field 9: float analog_yaw_delta (Tag: (9 << 3) | 5 = 0x4D)\n    if (m_nHasBits & HAS_ANALOG_YAW_DELTA) {\n        writer.WriteTag(9, WireType::Fixed32);\n        writer.WriteFloat(m_flAnalogYawDelta);\n    }\n}\n\nbool CSubtickMoveStep::_InternalParse(CByteStreamReader& reader) {\n    while (reader.HasMore()) {\n        uint32_t tag = 0;\n        if (!reader.ReadVarInt32(tag)) return false;\n\n        uint32_t fieldNumber = tag >> 3;\n        WireType wireType = static_cast<WireType>(tag & 7);\n\n        switch (fieldNumber) {\n            case 1: { // button (uint64)\n                if (wireType != WireType::VarInt) return false;\n                if (!reader.ReadVarInt64(m_nButton)) return false;\n                m_nHasBits |= HAS_BUTTON;\n                break;\n            }\n            case 2: { // pressed (bool)\n                if (wireType != WireType::VarInt) return false;\n                uint32_t val = 0;\n                if (!reader.ReadVarInt32(val)) return false;\n                m_bPressed = (val != 0);\n                m_nHasBits |= HAS_PRESSED;\n                break;\n            }\n            case 3: { // when (float)\n                if (wireType != WireType::Fixed32) return false;\n                if (!reader.ReadFloat(m_flWhen)) return false;\n                m_flWhen = std::clamp(m_flWhen, 0.0f, 1.0f);\n                m_nHasBits |= HAS_WHEN;\n                break;\n            }\n            case 4: { // analog_forward_delta (float)\n                if (wireType != WireType::Fixed32) return false;\n                if (!reader.ReadFloat(m_flAnalogForwardDelta)) return false;\n                m_nHasBits |= HAS_ANALOG_FORWARD_DELTA;\n                break;\n            }\n            case 5: { // analog_left_delta (float)\n                if (wireType != WireType::Fixed32) return false;\n                if (!reader.ReadFloat(m_flAnalogLeftDelta)) return false;\n                m_nHasBits |= HAS_ANALOG_LEFT_DELTA;\n                break;\n            }\n            case 8: { // analog_pitch_delta (float)\n                if (wireType != WireType::Fixed32) return false;\n                if (!reader.ReadFloat(m_flAnalogPitchDelta)) return false;\n                m_nHasBits |= HAS_ANALOG_PITCH_DELTA;\n                break;\n            }\n            case 9: { // analog_yaw_delta (float)\n                if (wireType != WireType::Fixed32) return false;\n                if (!reader.ReadFloat(m_flAnalogYawDelta)) return false;\n                m_nHasBits |= HAS_ANALOG_YAW_DELTA;\n                break;\n            }\n            default:\n                if (!reader.SkipField(wireType)) return false;\n                break;\n        }\n    }\n    return true;\n}\n\n// ============================================================================\n// CInButtonStatePB Implementation\n// ============================================================================\n\nsize_t CInButtonStatePB::ByteSizeLong() const {\n    size_t total = 0;\n    if (buttonstate1 != 0) {\n        total += 1;\n        uint64_t v = buttonstate1;\n        do { total++; v >>= 7; } while (v > 0);\n    }\n    if (buttonstate2 != 0) {\n        total += 1;\n        uint64_t v = buttonstate2;\n        do { total++; v >>= 7; } while (v > 0);\n    }\n    if (buttonstate3 != 0) {\n        total += 1;\n        uint64_t v = buttonstate3;\n        do { total++; v >>= 7; } while (v > 0);\n    }\n    return total;\n}\n\nvoid CInButtonStatePB::_InternalSerialize(CByteStreamWriter& writer) const {\n    if (buttonstate1 != 0) {\n        writer.WriteTag(1, WireType::VarInt);\n        writer.WriteVarInt64(buttonstate1);\n    }\n    if (buttonstate2 != 0) {\n        writer.WriteTag(2, WireType::VarInt);\n        writer.WriteVarInt64(buttonstate2);\n    }\n    if (buttonstate3 != 0) {\n        writer.WriteTag(3, WireType::VarInt);\n        writer.WriteVarInt64(buttonstate3);\n    }\n}\n\nbool CInButtonStatePB::_InternalParse(CByteStreamReader& reader) {\n    while (reader.HasMore()) {\n        uint32_t tag = 0;\n        if (!reader.ReadVarInt32(tag)) return false;\n        uint32_t fieldNumber = tag >> 3;\n        WireType wireType = static_cast<WireType>(tag & 7);\n\n        switch (fieldNumber) {\n            case 1:\n                if (wireType != WireType::VarInt || !reader.ReadVarInt64(buttonstate1)) return false;\n                break;\n            case 2:\n                if (wireType != WireType::VarInt || !reader.ReadVarInt64(buttonstate2)) return false;\n                break;\n            case 3:\n                if (wireType != WireType::VarInt || !reader.ReadVarInt64(buttonstate3)) return false;\n                break;\n            default:\n                if (!reader.SkipField(wireType)) return false;\n                break;\n        }\n    }\n    return true;\n}\n\n// ============================================================================\n// CSGOInputHistoryEntryPB Implementation\n// ============================================================================\n\nsize_t CSGOInputHistoryEntryPB::ByteSizeLong() const {\n    CByteStreamWriter temp;\n    _InternalSerialize(temp);\n    return temp.GetSize();\n}\n\nvoid CSGOInputHistoryEntryPB::_InternalSerialize(CByteStreamWriter& writer) const {\n    // Field 1: view_angles (embedded QAngle)\n    {\n        CByteStreamWriter angleWriter;\n        angleWriter.WriteTag(1, WireType::Fixed32);\n        angleWriter.WriteFloat(view_angles.pitch);\n        angleWriter.WriteTag(2, WireType::Fixed32);\n        angleWriter.WriteFloat(view_angles.yaw);\n        angleWriter.WriteTag(3, WireType::Fixed32);\n        angleWriter.WriteFloat(view_angles.roll);\n\n        writer.WriteTag(1, WireType::LengthDelimited);\n        writer.WriteLengthDelimited(angleWriter.GetData().data(), angleWriter.GetSize());\n    }\n\n    // Field 2: shoot_position (Vector3)\n    {\n        CByteStreamWriter posWriter;\n        posWriter.WriteTag(1, WireType::Fixed32);\n        posWriter.WriteFloat(shoot_position.x);\n        posWriter.WriteTag(2, WireType::Fixed32);\n        posWriter.WriteFloat(shoot_position.y);\n        posWriter.WriteTag(3, WireType::Fixed32);\n        posWriter.WriteFloat(shoot_position.z);\n\n        writer.WriteTag(2, WireType::LengthDelimited);\n        writer.WriteLengthDelimited(posWriter.GetData().data(), posWriter.GetSize());\n    }\n\n    // Field 3: target_ent_index\n    if (target_ent_index != -1) {\n        writer.WriteTag(3, WireType::VarInt);\n        writer.WriteVarInt32(static_cast<uint32_t>(target_ent_index));\n    }\n\n    // Field 4: player_tick_count\n    writer.WriteTag(4, WireType::VarInt);\n    writer.WriteVarInt32(static_cast<uint32_t>(player_tick_count));\n\n    // Field 5: player_tick_fraction\n    writer.WriteTag(5, WireType::Fixed32);\n    writer.WriteFloat(player_tick_fraction);\n}\n\nbool CSGOInputHistoryEntryPB::_InternalParse(CByteStreamReader& reader) {\n    while (reader.HasMore()) {\n        uint32_t tag = 0;\n        if (!reader.ReadVarInt32(tag)) return false;\n        uint32_t fieldNumber = tag >> 3;\n        WireType wireType = static_cast<WireType>(tag & 7);\n\n        switch (fieldNumber) {\n            case 1: { // view_angles\n                if (wireType != WireType::LengthDelimited) return false;\n                uint32_t len = 0;\n                if (!reader.ReadVarInt32(len)) return false;\n                CByteStreamReader subReader(reader.CurrentPtr(), len);\n                reader.Skip(len);\n                while (subReader.HasMore()) {\n                    uint32_t subTag = 0;\n                    if (!subReader.ReadVarInt32(subTag)) return false;\n                    uint32_t sf = subTag >> 3;\n                    if (sf == 1) subReader.ReadFloat(view_angles.pitch);\n                    else if (sf == 2) subReader.ReadFloat(view_angles.yaw);\n                    else if (sf == 3) subReader.ReadFloat(view_angles.roll);\n                    else subReader.SkipField(static_cast<WireType>(subTag & 7));\n                }\n                break;\n            }\n            case 2: { // shoot_position\n                if (wireType != WireType::LengthDelimited) return false;\n                uint32_t len = 0;\n                if (!reader.ReadVarInt32(len)) return false;\n                CByteStreamReader subReader(reader.CurrentPtr(), len);\n                reader.Skip(len);\n                while (subReader.HasMore()) {\n                    uint32_t subTag = 0;\n                    if (!subReader.ReadVarInt32(subTag)) return false;\n                    uint32_t sf = subTag >> 3;\n                    if (sf == 1) subReader.ReadFloat(shoot_position.x);\n                    else if (sf == 2) subReader.ReadFloat(shoot_position.y);\n                    else if (sf == 3) subReader.ReadFloat(shoot_position.z);\n                    else subReader.SkipField(static_cast<WireType>(subTag & 7));\n                }\n                break;\n            }\n            case 3: { // target_ent_index\n                uint32_t val = 0;\n                if (!reader.ReadVarInt32(val)) return false;\n                target_ent_index = static_cast<int32_t>(val);\n                break;\n            }\n            case 4: { // player_tick_count\n                uint32_t val = 0;\n                if (!reader.ReadVarInt32(val)) return false;\n                player_tick_count = static_cast<int32_t>(val);\n                break;\n            }\n            case 5: { // player_tick_fraction\n                if (!reader.ReadFloat(player_tick_fraction)) return false;\n                break;\n            }\n            default:\n                if (!reader.SkipField(wireType)) return false;\n                break;\n        }\n    }\n    return true;\n}\n\n// ============================================================================\n// CBaseUserCmdPB Serialization & Parsing\n// Reconstructed from FUN_1804f63f0 (_InternalSerialize) and FUN_1804f5c00 (_InternalParse)\n// ============================================================================\n\nsize_t CBaseUserCmdPB::ByteSizeLong() const {\n    CByteStreamWriter temp;\n    _InternalSerialize(temp);\n    return temp.GetSize();\n}\n\nvoid CBaseUserCmdPB::_InternalSerialize(CByteStreamWriter& writer) const {\n    // 1. Field 1: command_number (tag 0x08, wire 0)\n    if (m_nHasBits & HAS_COMMAND_NUMBER) {\n        writer.WriteTag(1, WireType::VarInt);\n        writer.WriteVarInt32(static_cast<uint32_t>(m_nCommandNumber));\n    }\n\n    // 2. Field 2: client_tick (tag 0x10, wire 0)\n    if (m_nHasBits & HAS_CLIENT_TICK) {\n        writer.WriteTag(2, WireType::VarInt);\n        writer.WriteVarInt32(static_cast<uint32_t>(m_nClientTick));\n    }\n\n    // 3. Field 3: buttons_pb (tag 0x1A, wire 2)\n    if (m_nHasBits & HAS_BUTTONS_PB) {\n        CByteStreamWriter btnWriter;\n        m_ButtonsPB._InternalSerialize(btnWriter);\n        writer.WriteTag(3, WireType::LengthDelimited);\n        writer.WriteLengthDelimited(btnWriter.GetData().data(), btnWriter.GetSize());\n    }\n\n    // 4. Field 5: forwardmove (tag 0x2D, wire 5)\n    if (m_nHasBits & HAS_FORWARDMOVE) {\n        writer.WriteTag(5, WireType::Fixed32);\n        writer.WriteFloat(m_flForwardMove);\n    }\n\n    // 5. Field 6: leftmove (tag 0x35, wire 5)\n    if (m_nHasBits & HAS_LEFTMOVE) {\n        writer.WriteTag(6, WireType::Fixed32);\n        writer.WriteFloat(m_flLeftMove);\n    }\n\n    // 6. Field 7: upmove (tag 0x3D, wire 5)\n    if (m_nHasBits & HAS_UPMOVE) {\n        writer.WriteTag(7, WireType::Fixed32);\n        writer.WriteFloat(m_flUpMove);\n    }\n\n    // 7. Field 18: repeated CSubtickMoveStep subtick_moves\n    // Exact binary tag: (18 << 3) | 2 = 146 = 0x92 0x01\n    for (const auto& step : m_SubtickMoves) {\n        CByteStreamWriter stepWriter;\n        step._InternalSerialize(stepWriter);\n        // Write tag 18 length-delimited (0x92 0x01)\n        writer.WriteTag(18, WireType::LengthDelimited);\n        writer.WriteLengthDelimited(stepWriter.GetData().data(), stepWriter.GetSize());\n    }\n\n    // 8. Field 19: move_crc (tag 0x9A 0x01, wire 2)\n    if ((m_nHasBits & HAS_MOVE_CRC) && !m_strMoveCRC.empty()) {\n        writer.WriteTag(19, WireType::LengthDelimited);\n        writer.WriteString(m_strMoveCRC);\n    }\n\n    // 9. Field 20: consumed_server_angle_changes (tag 0xA0 0x01, wire 0)\n    if (m_nHasBits & HAS_CONSUMED_SERVER_ANGLE_CHANGES) {\n        writer.WriteTag(20, WireType::VarInt);\n        writer.WriteVarInt32(static_cast<uint32_t>(m_nConsumedServerAngleChanges));\n    }\n\n    // 10. Field 21: cmd_flags (tag 0xA8 0x01, wire 0)\n    if (m_nHasBits & HAS_CMD_FLAGS) {\n        writer.WriteTag(21, WireType::VarInt);\n        writer.WriteVarInt32(static_cast<uint32_t>(m_nCmdFlags));\n    }\n}\n\nbool CBaseUserCmdPB::_InternalParse(CByteStreamReader& reader) {\n    while (reader.HasMore()) {\n        uint32_t tag = 0;\n        if (!reader.ReadVarInt32(tag)) return false;\n\n        uint32_t fieldNumber = tag >> 3;\n        WireType wireType = static_cast<WireType>(tag & 7);\n\n        switch (fieldNumber) {\n            case 1: { // command_number\n                uint32_t val = 0;\n                if (!reader.ReadVarInt32(val)) return false;\n                m_nCommandNumber = static_cast<int32_t>(val);\n                m_nHasBits |= HAS_COMMAND_NUMBER;\n                break;\n            }\n            case 2: { // client_tick\n                uint32_t val = 0;\n                if (!reader.ReadVarInt32(val)) return false;\n                m_nClientTick = static_cast<int32_t>(val);\n                m_nHasBits |= HAS_CLIENT_TICK;\n                break;\n            }\n            case 3: { // buttons_pb\n                uint32_t len = 0;\n                if (!reader.ReadVarInt32(len)) return false;\n                CByteStreamReader subReader(reader.CurrentPtr(), len);\n                reader.Skip(len);\n                if (!m_ButtonsPB._InternalParse(subReader)) return false;\n                m_nHasBits |= HAS_BUTTONS_PB;\n                break;\n            }\n            case 5: { // forwardmove\n                if (!reader.ReadFloat(m_flForwardMove)) return false;\n                m_nHasBits |= HAS_FORWARDMOVE;\n                break;\n            }\n            case 6: { // leftmove\n                if (!reader.ReadFloat(m_flLeftMove)) return false;\n                m_nHasBits |= HAS_LEFTMOVE;\n                break;\n            }\n            case 7: { // upmove\n                if (!reader.ReadFloat(m_flUpMove)) return false;\n                m_nHasBits |= HAS_UPMOVE;\n                break;\n            }\n            case 18: { // repeated subtick_moves (tag 0x92 0x01)\n                uint32_t len = 0;\n                if (!reader.ReadVarInt32(len)) return false;\n                CByteStreamReader subReader(reader.CurrentPtr(), len);\n                reader.Skip(len);\n\n                CSubtickMoveStep step;\n                if (!step._InternalParse(subReader)) return false;\n                m_SubtickMoves.push_back(step);\n                break;\n            }\n            case 19: { // move_crc\n                uint32_t len = 0;\n                if (!reader.ReadVarInt32(len)) return false;\n                if (!reader.ReadString(m_strMoveCRC, len)) return false;\n                m_nHasBits |= HAS_MOVE_CRC;\n                break;\n            }\n            case 20: { // consumed_server_angle_changes\n                uint32_t val = 0;\n                if (!reader.ReadVarInt32(val)) return false;\n                m_nConsumedServerAngleChanges = static_cast<int32_t>(val);\n                m_nHasBits |= HAS_CONSUMED_SERVER_ANGLE_CHANGES;\n                break;\n            }\n            case 21: { // cmd_flags\n                uint32_t val = 0;\n                if (!reader.ReadVarInt32(val)) return false;\n                m_nCmdFlags = static_cast<int32_t>(val);\n                m_nHasBits |= HAS_CMD_FLAGS;\n                break;\n            }\n            default:\n                if (!reader.SkipField(wireType)) return false;\n                break;\n        }\n    }\n    return true;\n}\n\n// ============================================================================\n// CSGOUserCmdPB Serialization & Parsing\n// Reconstructed from FUN_1807b0be0 (_InternalSerialize) and FUN_1807b0740 (_InternalParse)\n// ============================================================================\n\nsize_t CSGOUserCmdPB::ByteSizeLong() const {\n    CByteStreamWriter temp;\n    _InternalSerialize(temp);\n    return temp.GetSize();\n}\n\nvoid CSGOUserCmdPB::_InternalSerialize(CByteStreamWriter& writer) const {\n    // 1. Field 1: CBaseUserCmdPB base (tag 0x0A, wire 2)\n    {\n        CByteStreamWriter baseWriter;\n        m_Base._InternalSerialize(baseWriter);\n        writer.WriteTag(1, WireType::LengthDelimited);\n        writer.WriteLengthDelimited(baseWriter.GetData().data(), baseWriter.GetSize());\n    }\n\n    // 2. Field 2: repeated CSGOInputHistoryEntryPB input_history (tag 0x12, wire 2)\n    for (const auto& entry : m_InputHistory) {\n        CByteStreamWriter histWriter;\n        entry._InternalSerialize(histWriter);\n        writer.WriteTag(2, WireType::LengthDelimited);\n        writer.WriteLengthDelimited(histWriter.GetData().data(), histWriter.GetSize());\n    }\n\n    // 3. Field 6: attack1_start_history_index (tag 0x30, wire 0)\n    if (m_nAttack1StartHistoryIndex != -1) {\n        writer.WriteTag(6, WireType::VarInt);\n        writer.WriteVarInt32(static_cast<uint32_t>(m_nAttack1StartHistoryIndex));\n    }\n\n    // 4. Field 7: attack2_start_history_index (tag 0x38, wire 0)\n    if (m_nAttack2StartHistoryIndex != -1) {\n        writer.WriteTag(7, WireType::VarInt);\n        writer.WriteVarInt32(static_cast<uint32_t>(m_nAttack2StartHistoryIndex));\n    }\n\n    // 5. Field 9: has_been_predicted (tag 0x48, wire 0)\n    if (m_bHasBeenPredicted) {\n        writer.WriteTag(9, WireType::VarInt);\n        writer.WriteByte(1);\n    }\n\n    // 6. Field 11: attack3_start_history_index (tag 0x58, wire 0)\n    if (m_nAttack3StartHistoryIndex != -1) {\n        writer.WriteTag(11, WireType::VarInt);\n        writer.WriteVarInt32(static_cast<uint32_t>(m_nAttack3StartHistoryIndex));\n    }\n}\n\nbool CSGOUserCmdPB::_InternalParse(CByteStreamReader& reader) {\n    while (reader.HasMore()) {\n        uint32_t tag = 0;\n        if (!reader.ReadVarInt32(tag)) return false;\n\n        uint32_t fieldNumber = tag >> 3;\n        WireType wireType = static_cast<WireType>(tag & 7);\n\n        switch (fieldNumber) {\n            case 1: { // base\n                uint32_t len = 0;\n                if (!reader.ReadVarInt32(len)) return false;\n                CByteStreamReader subReader(reader.CurrentPtr(), len);\n                reader.Skip(len);\n                if (!m_Base._InternalParse(subReader)) return false;\n                m_nHasBits |= HAS_BASE;\n                break;\n            }\n            case 2: { // input_history\n                uint32_t len = 0;\n                if (!reader.ReadVarInt32(len)) return false;\n                CByteStreamReader subReader(reader.CurrentPtr(), len);\n                reader.Skip(len);\n                CSGOInputHistoryEntryPB entry;\n                if (!entry._InternalParse(subReader)) return false;\n                m_InputHistory.push_back(entry);\n                break;\n            }\n            case 6: { // attack1_start_history_index\n                uint32_t val = 0;\n                if (!reader.ReadVarInt32(val)) return false;\n                m_nAttack1StartHistoryIndex = static_cast<int32_t>(val);\n                m_nHasBits |= HAS_ATTACK1_START_HISTORY_INDEX;\n                break;\n            }\n            case 7: { // attack2_start_history_index\n                uint32_t val = 0;\n                if (!reader.ReadVarInt32(val)) return false;\n                m_nAttack2StartHistoryIndex = static_cast<int32_t>(val);\n                m_nHasBits |= HAS_ATTACK2_START_HISTORY_INDEX;\n                break;\n            }\n            case 9: { // has_been_predicted\n                uint32_t val = 0;\n                if (!reader.ReadVarInt32(val)) return false;\n                m_bHasBeenPredicted = (val != 0);\n                m_nHasBits |= HAS_HAS_BEEN_PREDICTED;\n                break;\n            }\n            case 11: { // attack3_start_history_index\n                uint32_t val = 0;\n                if (!reader.ReadVarInt32(val)) return false;\n                m_nAttack3StartHistoryIndex = static_cast<int32_t>(val);\n                m_nHasBits |= HAS_ATTACK3_START_HISTORY_INDEX;\n                break;\n            }\n            default:\n                if (!reader.SkipField(wireType)) return false;\n                break;\n        }\n    }\n    return true;\n}\n\n// ============================================================================\n// CCLCMsg_Move Serialization & Parsing\n// ============================================================================\n\nsize_t CCLCMsg_Move::ByteSizeLong() const {\n    CByteStreamWriter temp;\n    _InternalSerialize(temp);\n    return temp.GetSize();\n}\n\nvoid CCLCMsg_Move::_InternalSerialize(CByteStreamWriter& writer) const {\n    // Field 1: num_backup_commands (tag 0x08, wire 0)\n    if (m_nNumBackupCommands > 0) {\n        writer.WriteTag(1, WireType::VarInt);\n        writer.WriteVarInt32(m_nNumBackupCommands);\n    }\n\n    // Field 2: num_new_commands (tag 0x10, wire 0)\n    writer.WriteTag(2, WireType::VarInt);\n    writer.WriteVarInt32(m_nNumNewCommands);\n\n    // Field 3: data (bytes, tag 0x1A, wire 2)\n    if (!m_vecData.empty()) {\n        writer.WriteTag(3, WireType::LengthDelimited);\n        writer.WriteBytes(m_vecData.data(), m_vecData.size());\n    }\n}\n\nbool CCLCMsg_Move::_InternalParse(CByteStreamReader& reader) {\n    while (reader.HasMore()) {\n        uint32_t tag = 0;\n        if (!reader.ReadVarInt32(tag)) return false;\n\n        uint32_t fieldNumber = tag >> 3;\n        WireType wireType = static_cast<WireType>(tag & 7);\n\n        switch (fieldNumber) {\n            case 1:\n                if (!reader.ReadVarInt32(m_nNumBackupCommands)) return false;\n                break;\n            case 2:\n                if (!reader.ReadVarInt32(m_nNumNewCommands)) return false;\n                break;\n            case 3: {\n                uint32_t len = 0;\n                if (!reader.ReadVarInt32(len)) return false;\n                m_vecData.resize(len);\n                if (!reader.ReadBytes(m_vecData.data(), len)) return false;\n                break;\n            }\n            default:\n                if (!reader.SkipField(wireType)) return false;\n                break;\n        }\n    }\n    return true;\n}\n\n// ============================================================================\n// CSGOInputWireCodec Implementation\n// ============================================================================\n\nCSubtickMoveStep CSGOInputWireCodec::CreateSubtickMoveStep(\n    uint64_t button,\n    bool pressed,\n    double eventTimestampSec,\n    double tickStartTimestampSec,\n    float tickInterval,\n    float analogForwardDelta,\n    float analogLeftDelta\n) {\n    CSubtickMoveStep step;\n    step.SetButton(button);\n    step.SetPressed(pressed);\n\n    // Continuous temporal slicing: when = (T_event - T_tick_start) / dt\n    double elapsed = eventTimestampSec - tickStartTimestampSec;\n    float whenFraction = static_cast<float>(elapsed / static_cast<double>(tickInterval));\n    step.SetWhen(whenFraction);\n\n    if (std::abs(analogForwardDelta) > 1e-5f) {\n        step.SetAnalogForwardDelta(analogForwardDelta);\n    }\n    if (std::abs(analogLeftDelta) > 1e-5f) {\n        step.SetAnalogLeftDelta(analogLeftDelta);\n    }\n\n    return step;\n}\n\nvoid CSGOInputWireCodec::WriteVariableBitMessageId(\n    std::vector<uint8_t>& bitstream,\n    size_t& bitOffset,\n    uint32_t messageId\n) {\n    // Source 2 Variable-Bit Encoding:\n    // Prefix 0b00 (6 bits):   0..15\n    // Prefix 0b01 (10 bits):  16..255\n    // Prefix 0b10 (14 bits):  256..4095\n    // Prefix 0b11 (34 bits):  4096..2^32-1\n    auto writeBits = [&](uint32_t val, size_t numBits) {\n        for (size_t i = 0; i < numBits; ++i) {\n            size_t byteIdx = bitOffset / 8;\n            size_t bitInByte = bitOffset % 8;\n            if (byteIdx >= bitstream.size()) {\n                bitstream.resize(byteIdx + 1, 0);\n            }\n            if ((val >> i) & 1) {\n                bitstream[byteIdx] |= static_cast<uint8_t>(1 << bitInByte);\n            }\n            bitOffset++;\n        }\n    };\n\n    if (messageId < 16) {\n        uint32_t header = (0 << 4) | (messageId & 0x0F);\n        writeBits(header, 6);\n    } else if (messageId < 256) {\n        uint32_t header = (1 << 4) | (messageId & 0x0F);\n        writeBits(header, 6);\n        writeBits(messageId >> 4, 4);\n    } else if (messageId < 4096) {\n        uint32_t header = (2 << 4) | (messageId & 0x0F);\n        writeBits(header, 6);\n        writeBits(messageId >> 4, 8);\n    } else {\n        uint32_t header = (3 << 4) | (messageId & 0x0F);\n        writeBits(header, 6);\n        writeBits(messageId >> 4, 28);\n    }\n}\n\nuint32_t CSGOInputWireCodec::ReadVariableBitMessageId(\n    const uint8_t* bitstream,\n    size_t& bitOffset,\n    size_t maxBits\n) {\n    auto readBits = [&](size_t numBits) -> uint32_t {\n        uint32_t res = 0;\n        for (size_t i = 0; i < numBits; ++i) {\n            if (bitOffset >= maxBits) return 0;\n            size_t byteIdx = bitOffset / 8;\n            size_t bitInByte = bitOffset % 8;\n            if ((bitstream[byteIdx] >> bitInByte) & 1) {\n                res |= (1 << i);\n            }\n            bitOffset++;\n        }\n        return res;\n    };\n\n    uint32_t initial6 = readBits(6);\n    uint32_t prefix = (initial6 >> 4) & 3;\n    uint32_t extraBits = ((static_cast<int32_t>(2 - prefix) >> 31 & 0x10) + prefix * 4);\n    if (extraBits == 0) {\n        return initial6 & 0x0F;\n    }\n    uint32_t upper = readBits(extraBits);\n    return (upper << 4) | (initial6 & 0x0F);\n}\n\nstd::vector<uint8_t> CSGOInputWireCodec::SerializeUserCmdToBitbuf(\n    const CSGOUserCmdPB& userCmd,\n    uint32_t numBackupCommands,\n    uint32_t numNewCommands\n) {\n    // 1. Serialize CSGOUserCmdPB to protobuf bytes\n    CByteStreamWriter cmdWriter;\n    userCmd._InternalSerialize(cmdWriter);\n\n    // 2. Wrap into CCLCMsg_Move\n    CCLCMsg_Move moveMsg;\n    moveMsg.m_nNumBackupCommands = numBackupCommands;\n    moveMsg.m_nNumNewCommands = numNewCommands;\n    moveMsg.m_vecData = cmdWriter.GetData();\n\n    // 3. Serialize CCLCMsg_Move to protobuf payload\n    CByteStreamWriter moveWriter;\n    moveMsg._InternalSerialize(moveWriter);\n\n    // 4. Frame into bitstream with Variable-Bit NetMessage ID header (0x15 = 21 -> 10 bits)\n    std::vector<uint8_t> outputBitstream;\n    size_t bitOffset = 0;\n    WriteVariableBitMessageId(outputBitstream, bitOffset, CCLCMsg_Move::NET_MESSAGE_ID);\n\n    // Byte-align for payload fast-path blit (per networksystem.dll)\n    size_t alignedBytes = (bitOffset + 7) / 8;\n    outputBitstream.resize(alignedBytes);\n\n    // Append VarInt32 length prefix\n    CByteStreamWriter lenWriter;\n    lenWriter.WriteVarInt32(static_cast<uint32_t>(moveWriter.GetSize()));\n    outputBitstream.insert(outputBitstream.end(), lenWriter.GetData().begin(), lenWriter.GetData().end());\n\n    // Append raw protobuf payload\n    outputBitstream.insert(outputBitstream.end(), moveWriter.GetData().begin(), moveWriter.GetData().end());\n\n    return outputBitstream;\n}\n\nbool CSGOInputWireCodec::UnpackUserCmdFromBitbuf(\n    const uint8_t* payloadData,\n    size_t payloadSize,\n    std::vector<CSGOUserCmdPB>& outCmds,\n    uint32_t& outNumBackup,\n    uint32_t& outNumNew\n) {\n    if (payloadData == nullptr || payloadSize == 0) return false;\n\n    size_t bitOffset = 0;\n    size_t maxBits = payloadSize * 8;\n    uint32_t msgId = ReadVariableBitMessageId(payloadData, bitOffset, maxBits);\n    if (msgId != CCLCMsg_Move::NET_MESSAGE_ID) {\n        return false;\n    }\n\n    // Align to byte boundary\n    size_t byteOffset = (bitOffset + 7) / 8;\n    if (byteOffset >= payloadSize) return false;\n\n    CByteStreamReader lenReader(payloadData + byteOffset, payloadSize - byteOffset);\n    uint32_t movePayloadLen = 0;\n    if (!lenReader.ReadVarInt32(movePayloadLen)) return false;\n\n    size_t dataStart = byteOffset + lenReader.GetOffset();\n    if (dataStart + movePayloadLen > payloadSize) return false;\n\n    // Parse CCLCMsg_Move\n    CByteStreamReader moveReader(payloadData + dataStart, movePayloadLen);\n    CCLCMsg_Move moveMsg;\n    if (!moveMsg._InternalParse(moveReader)) return false;\n\n    outNumBackup = moveMsg.m_nNumBackupCommands;\n    outNumNew = moveMsg.m_nNumNewCommands;\n\n    // Parse concatenated CSGOUserCmdPB stream from moveMsg.m_vecData\n    CByteStreamReader cmdStreamReader(moveMsg.m_vecData.data(), moveMsg.m_vecData.size());\n    while (cmdStreamReader.HasMore()) {\n        CSGOUserCmdPB cmd;\n        if (!cmd._InternalParse(cmdStreamReader)) break;\n        outCmds.push_back(cmd);\n    }\n\n    return !outCmds.empty();\n}\n\n} // namespace cs2::client\n",
        "usercmd_wire.h": "#ifndef CS2_CLIENT_USERCMD_WIRE_H\n#define CS2_CLIENT_USERCMD_WIRE_H\n\n#include <cstdint>\n#include <cstddef>\n#include <vector>\n#include <string>\n#include <optional>\n#include <algorithm>\n#include \"viewmatrix.h\"\n\nnamespace cs2::client {\n\n// ============================================================================\n// Source 2 UserCmd Wire & Protobuf Definitions\n// Reconstructed via Ghidra static decompilation of client.dll and networksystem.dll\n// ============================================================================\n\n/**\n * @brief Standard Source 2 button bitmasks (64-bit uint64).\n */\nenum InButtonBits : uint64_t {\n    IN_ATTACK       = (1ULL << 0),\n    IN_JUMP         = (1ULL << 1),\n    IN_DUCK         = (1ULL << 2),\n    IN_FORWARD      = (1ULL << 3),\n    IN_BACK         = (1ULL << 4),\n    IN_USE          = (1ULL << 5),\n    IN_CANCEL       = (1ULL << 6),\n    IN_LEFT         = (1ULL << 7),\n    IN_RIGHT        = (1ULL << 8),\n    IN_MOVELEFT     = (1ULL << 9),\n    IN_MOVERIGHT    = (1ULL << 10),\n    IN_ATTACK2      = (1ULL << 11),\n    IN_RUN          = (1ULL << 12),\n    IN_RELOAD       = (1ULL << 13),\n    IN_ALT1         = (1ULL << 14),\n    IN_ALT2         = (1ULL << 15),\n    IN_SPEED        = (1ULL << 16),\n    IN_WALK         = (1ULL << 17),\n    IN_ZOOM         = (1ULL << 19),\n    IN_FIRST_MOD    = (1ULL << 20),\n    IN_SECOND_MOD   = (1ULL << 21),\n    IN_BULLRUSH     = (1ULL << 22),\n    IN_GRENADE1     = (1ULL << 23),\n    IN_GRENADE2     = (1ULL << 24),\n    IN_ATTACK3      = (1ULL << 25),\n};\n\n/**\n * @brief Protobuf Wire Types (Google Protobuf specification).\n */\nenum class WireType : uint32_t {\n    VarInt          = 0,\n    Fixed64         = 1,\n    LengthDelimited = 2,\n    StartGroup      = 3, // deprecated\n    EndGroup        = 4, // deprecated\n    Fixed32         = 5,\n};\n\n/**\n * @brief Lightweight low-level binary buffer reader for protobuf parsing.\n */\nclass CByteStreamReader {\npublic:\n    CByteStreamReader(const uint8_t* data, size_t size)\n        : m_pData(data), m_nSize(size), m_nOffset(0) {}\n\n    [[nodiscard]] bool HasMore() const noexcept { return m_nOffset < m_nSize; }\n    [[nodiscard]] size_t GetOffset() const noexcept { return m_nOffset; }\n    [[nodiscard]] size_t GetRemaining() const noexcept { return m_nOffset < m_nSize ? m_nSize - m_nOffset : 0; }\n    [[nodiscard]] const uint8_t* CurrentPtr() const noexcept { return m_pData + m_nOffset; }\n\n    bool ReadByte(uint8_t& outByte);\n    bool ReadVarInt32(uint32_t& outVal);\n    bool ReadVarInt64(uint64_t& outVal);\n    bool ReadFixed32(uint32_t& outVal);\n    bool ReadFloat(float& outVal);\n    bool ReadFixed64(uint64_t& outVal);\n    bool ReadDouble(double& outVal);\n    bool ReadBytes(uint8_t* outDest, size_t len);\n    bool ReadString(std::string& outStr, size_t len);\n    bool Skip(size_t len);\n    bool SkipField(WireType wireType);\n\nprivate:\n    const uint8_t* m_pData;\n    size_t m_nSize;\n    size_t m_nOffset;\n};\n\n/**\n * @brief Lightweight low-level binary buffer writer for protobuf serialization.\n */\nclass CByteStreamWriter {\npublic:\n    CByteStreamWriter() = default;\n\n    void WriteByte(uint8_t b) { m_Buffer.push_back(b); }\n    void WriteVarInt32(uint32_t val);\n    void WriteVarInt64(uint64_t val);\n    void WriteFixed32(uint32_t val);\n    void WriteFloat(float val);\n    void WriteFixed64(uint64_t val);\n    void WriteDouble(double val);\n    void WriteTag(uint32_t fieldNumber, WireType wireType);\n    void WriteLengthDelimited(const uint8_t* data, size_t len);\n    void WriteString(const std::string& str);\n    void WriteBytes(const uint8_t* data, size_t len);\n\n    [[nodiscard]] const std::vector<uint8_t>& GetData() const noexcept { return m_Buffer; }\n    [[nodiscard]] size_t GetSize() const noexcept { return m_Buffer.size(); }\n    void Clear() noexcept { m_Buffer.clear(); }\n\nprivate:\n    std::vector<uint8_t> m_Buffer;\n};\n\n/**\n * @brief CSubtickMoveStep exact memory layout and wire codec.\n * Reconstructed from client.dll:\n *   - VTable: 0x181b2d4d8 (baseline) / 0x181b2f488 (current)\n *   - Size: 0x38 (56 bytes)\n *   - Parse: FUN_1804f4950 (baseline) / FUN_1804f5640 (current)\n *   - Serialize: FUN_1804f4c40 (baseline) / FUN_1804f5930 (current)\n */\nclass CSubtickMoveStep {\npublic:\n    void* m_pVTable{nullptr};            // +0x00: vtable pointer\n    void* m_pInternalArena{nullptr};     // +0x08: Google protobuf Arena pointer\n    uint32_t m_nHasBits{0};              // +0x10: _has_bits_ mask\n    mutable int32_t m_nCachedSize{0};    // +0x14: _cached_size_\n    uint64_t m_nButton{0};               // +0x18: field 1: button mask\n    bool m_bPressed{false};              // +0x20: field 2: keydown edge\n    uint8_t m_nPad[3]{0, 0, 0};          // +0x21..0x23: alignment padding\n    float m_flWhen{0.0f};                // +0x24: field 3: normalized fraction [0.0, 1.0]\n    float m_flAnalogForwardDelta{0.0f};  // +0x28: field 4: analog forward delta\n    float m_flAnalogLeftDelta{0.0f};     // +0x2c: field 5: analog left delta\n    float m_flAnalogPitchDelta{0.0f};    // +0x30: field 8: analog pitch delta\n    float m_flAnalogYawDelta{0.0f};      // +0x34: field 9: analog yaw delta\n\n    // Has-bits bitmasks (from FUN_1804f4c40)\n    enum HasBits : uint32_t {\n        HAS_BUTTON               = (1 << 0), // 0x01\n        HAS_PRESSED              = (1 << 1), // 0x02\n        HAS_WHEN                 = (1 << 2), // 0x04\n        HAS_ANALOG_FORWARD_DELTA = (1 << 3), // 0x08\n        HAS_ANALOG_LEFT_DELTA    = (1 << 4), // 0x10\n        HAS_ANALOG_PITCH_DELTA   = (1 << 5), // 0x20\n        HAS_ANALOG_YAW_DELTA     = (1 << 6), // 0x40\n    };\n\n    CSubtickMoveStep() = default;\n\n    // Field setters with automatic has-bits tracking\n    void SetButton(uint64_t btn) noexcept { m_nButton = btn; m_nHasBits |= HAS_BUTTON; }\n    void SetPressed(bool pressed) noexcept { m_bPressed = pressed; m_nHasBits |= HAS_PRESSED; }\n    void SetWhen(float when) noexcept { m_flWhen = std::clamp(when, 0.0f, 1.0f); m_nHasBits |= HAS_WHEN; }\n    void SetAnalogForwardDelta(float delta) noexcept { m_flAnalogForwardDelta = delta; m_nHasBits |= HAS_ANALOG_FORWARD_DELTA; }\n    void SetAnalogLeftDelta(float delta) noexcept { m_flAnalogLeftDelta = delta; m_nHasBits |= HAS_ANALOG_LEFT_DELTA; }\n    void SetAnalogPitchDelta(float delta) noexcept { m_flAnalogPitchDelta = delta; m_nHasBits |= HAS_ANALOG_PITCH_DELTA; }\n    void SetAnalogYawDelta(float delta) noexcept { m_flAnalogYawDelta = delta; m_nHasBits |= HAS_ANALOG_YAW_DELTA; }\n\n    [[nodiscard]] size_t ByteSizeLong() const;\n    void _InternalSerialize(CByteStreamWriter& writer) const;\n    bool _InternalParse(CByteStreamReader& reader);\n};\nstatic_assert(sizeof(CSubtickMoveStep) == 0x38, \"CSubtickMoveStep memory layout mismatch (must be 56 bytes)\");\n\n/**\n * @brief CSGOInputHistoryEntryPB analog shot recording message.\n * Reconstructed from client.dll:\n *   - VTable: 0x181bccd20 (baseline) / 0x181bcecb0 (current)\n */\nstruct CSGOInputHistoryEntryPB {\n    QAngle view_angles{0.0f, 0.0f, 0.0f};\n    Vector3 shoot_position{0.0f, 0.0f, 0.0f};\n    int32_t target_ent_index{-1};\n    int32_t player_tick_count{0};\n    float player_tick_fraction{0.0f};\n    Vector3 target_head_pos_check{0.0f, 0.0f, 0.0f};\n    Vector3 target_abs_pos_check{0.0f, 0.0f, 0.0f};\n\n    [[nodiscard]] size_t ByteSizeLong() const;\n    void _InternalSerialize(CByteStreamWriter& writer) const;\n    bool _InternalParse(CByteStreamReader& reader);\n};\n\n/**\n * @brief Button state protobuf representation (CInButtonStatePB).\n */\nstruct CInButtonStatePB {\n    uint64_t buttonstate1{0};\n    uint64_t buttonstate2{0};\n    uint64_t buttonstate3{0};\n\n    [[nodiscard]] size_t ByteSizeLong() const;\n    void _InternalSerialize(CByteStreamWriter& writer) const;\n    bool _InternalParse(CByteStreamReader& reader);\n};\n\n/**\n * @brief CBaseUserCmdPB exact memory layout and wire codec.\n * Reconstructed from client.dll:\n *   - VTable: 0x181b2d618 (baseline) / 0x181b2f5c8 (current)\n *   - Parse: FUN_1804f5c00 (baseline) / FUN_1804f68f0 (current)\n *   - Serialize: FUN_1804f63f0 (baseline) / FUN_1804f70e0 (current)\n *\n * Wire Tags:\n *   - field 1: command_number (tag 0x08, wire 0)\n *   - field 2: client_tick (tag 0x10, wire 0)\n *   - field 3: buttons_pb (tag 0x1A, wire 2)\n *   - field 5: forwardmove (tag 0x2D, wire 5)\n *   - field 6: leftmove (tag 0x35, wire 5)\n *   - field 7: upmove (tag 0x3D, wire 5)\n *   - field 18: repeated subtick_moves (tag 0x92 0x01, wire 2)\n *   - field 19: move_crc (tag 0x9A 0x01, wire 2)\n *   - field 20: consumed_server_angle_changes (tag 0xA0 0x01, wire 0)\n *   - field 21: cmd_flags (tag 0xA8 0x01, wire 0)\n */\nclass CBaseUserCmdPB {\npublic:\n    uint32_t m_nHasBits{0};\n    int32_t m_nCommandNumber{0};\n    int32_t m_nClientTick{0};\n    CInButtonStatePB m_ButtonsPB;\n    float m_flForwardMove{0.0f};\n    float m_flLeftMove{0.0f};\n    float m_flUpMove{0.0f};\n    QAngle m_ViewAngles{0.0f, 0.0f, 0.0f};\n    std::vector<CSubtickMoveStep> m_SubtickMoves; // Field 18 (tag 0x92 0x01)\n    std::string m_strMoveCRC;\n    int32_t m_nConsumedServerAngleChanges{0};\n    int32_t m_nCmdFlags{0};\n\n    enum HasBits : uint32_t {\n        HAS_COMMAND_NUMBER                 = (1 << 4),  // 0x10\n        HAS_CLIENT_TICK                    = (1 << 5),  // 0x20\n        HAS_BUTTONS_PB                     = (1 << 1),  // 0x02\n        HAS_FORWARDMOVE                    = (1 << 6),  // 0x40\n        HAS_LEFTMOVE                       = (1 << 7),  // 0x80\n        HAS_UPMOVE                         = (1 << 8),  // 0x100\n        HAS_VIEWANGLES                     = (1 << 9),  // 0x200\n        HAS_MOVE_CRC                       = (1 << 0),  // 0x01\n        HAS_CONSUMED_SERVER_ANGLE_CHANGES  = (1 << 15), // 0x8000\n        HAS_CMD_FLAGS                      = (1 << 16), // 0x10000\n    };\n\n    CBaseUserCmdPB() = default;\n\n    [[nodiscard]] size_t ByteSizeLong() const;\n    void _InternalSerialize(CByteStreamWriter& writer) const;\n    bool _InternalParse(CByteStreamReader& reader);\n};\n\n/**\n * @brief CSGOUserCmdPB wrapper framing Base UserCmd and Input History shots.\n * Reconstructed from client.dll:\n *   - VTable: 0x181bccdc0 (baseline) / 0x181bced50 (current)\n *   - Parse: FUN_1807b0740 (baseline) / FUN_1807b1830 (current)\n *   - Serialize: FUN_1807b0be0 (baseline) / FUN_1807b1cd0 (current)\n */\nclass CSGOUserCmdPB {\npublic:\n    uint32_t m_nHasBits{0};\n    CBaseUserCmdPB m_Base;\n    std::vector<CSGOInputHistoryEntryPB> m_InputHistory;\n    int32_t m_nAttack1StartHistoryIndex{-1};\n    int32_t m_nAttack2StartHistoryIndex{-1};\n    int32_t m_nAttack3StartHistoryIndex{-1};\n    bool m_bHasBeenPredicted{false};\n\n    enum HasBits : uint32_t {\n        HAS_BASE                           = (1 << 0), // 0x01\n        HAS_ATTACK1_START_HISTORY_INDEX    = (1 << 5), // 0x20\n        HAS_ATTACK2_START_HISTORY_INDEX    = (1 << 6), // 0x40\n        HAS_HAS_BEEN_PREDICTED             = (1 << 1), // 0x02\n        HAS_ATTACK3_START_HISTORY_INDEX    = (1 << 2), // 0x04\n    };\n\n    CSGOUserCmdPB() = default;\n\n    [[nodiscard]] size_t ByteSizeLong() const;\n    void _InternalSerialize(CByteStreamWriter& writer) const;\n    bool _InternalParse(CByteStreamReader& reader);\n};\n\n/**\n * @brief CCLCMsg_Move network packet encapsulation (clc_Move, NetMessage 0x15).\n * Reconstructed from networksystem.dll and client.dll:\n *   - NetMessage ID: 0x15 (21)\n *   - Wire format:\n *       field 1: num_backup_commands (uint32, tag 0x08)\n *       field 2: num_new_commands (uint32, tag 0x10)\n *       field 3: data (bytes, tag 0x1A) - length-delimited stream of CSGOUserCmdPB\n */\nclass CCLCMsg_Move {\npublic:\n    static constexpr uint32_t NET_MESSAGE_ID = 0x15; // 21\n\n    uint32_t m_nNumBackupCommands{0};\n    uint32_t m_nNumNewCommands{1};\n    std::vector<uint8_t> m_vecData;\n\n    [[nodiscard]] size_t ByteSizeLong() const;\n    void _InternalSerialize(CByteStreamWriter& writer) const;\n    bool _InternalParse(CByteStreamReader& reader);\n};\n\n/**\n * @brief Reconstructed CSGOInput client-side user command coordinator.\n * Reconstructed from client.dll (FUN_180cfa6b0 / CSGOInput::CreateMove).\n */\nclass CSGOInputWireCodec {\npublic:\n    static constexpr float DEFAULT_TICK_INTERVAL = 1.0f / 64.0f; // 0.015625s\n\n    /**\n     * @brief Computes normalized sub-tick fraction w in [0.0, 1.0] and instantiates CSubtickMoveStep.\n     */\n    static CSubtickMoveStep CreateSubtickMoveStep(\n        uint64_t button,\n        bool pressed,\n        double eventTimestampSec,\n        double tickStartTimestampSec,\n        float tickInterval = DEFAULT_TICK_INTERVAL,\n        float analogForwardDelta = 0.0f,\n        float analogLeftDelta = 0.0f\n    );\n\n    /**\n     * @brief Encodes variable-bit NetMessage ID (6, 10, 14, or 34 bits) as used by networksystem.dll.\n     */\n    static void WriteVariableBitMessageId(std::vector<uint8_t>& bitstream, size_t& bitOffset, uint32_t messageId);\n\n    /**\n     * @brief Decodes variable-bit NetMessage ID header from bitstream.\n     */\n    static uint32_t ReadVariableBitMessageId(const uint8_t* bitstream, size_t& bitOffset, size_t maxBits);\n\n    /**\n     * @brief Serializes a CSGOUserCmdPB into a clc_Move wire payload.\n     */\n    static std::vector<uint8_t> SerializeUserCmdToBitbuf(\n        const CSGOUserCmdPB& userCmd,\n        uint32_t numBackupCommands = 0,\n        uint32_t numNewCommands = 1\n    );\n\n    /**\n     * @brief Unpacks a clc_Move netmessage payload back into CSGOUserCmdPB commands.\n     */\n    static bool UnpackUserCmdFromBitbuf(\n        const uint8_t* payloadData,\n        size_t payloadSize,\n        std::vector<CSGOUserCmdPB>& outCmds,\n        uint32_t& outNumBackup,\n        uint32_t& outNumNew\n    );\n};\n\n} // namespace cs2::client\n\n#endif // CS2_CLIENT_USERCMD_WIRE_H\n",
        "viewmatrix.cpp": "#include \"viewmatrix.h\"\n#include <cmath>\n\nnamespace cs2::client {\n\nconstexpr float DEG2RAD = 3.14159265358979323846f / 180.0f;\n\nvoid CViewRender::AngleVectors(const QAngle& angles, Vector3* forward, Vector3* right, Vector3* up) {\n    const float sp = std::sin(angles.pitch * DEG2RAD);\n    const float cp = std::cos(angles.pitch * DEG2RAD);\n    const float sy = std::sin(angles.yaw * DEG2RAD);\n    const float cy = std::cos(angles.yaw * DEG2RAD);\n    const float sr = std::sin(angles.roll * DEG2RAD);\n    const float cr = std::cos(angles.roll * DEG2RAD);\n\n    if (forward) {\n        forward->x = cp * cy;\n        forward->y = cp * sy;\n        forward->z = -sp;\n    }\n\n    if (right) {\n        right->x = -1.0f * sr * sp * cy + -1.0f * cr * -sy;\n        right->y = -1.0f * sr * sp * sy + -1.0f * cr * cy;\n        right->z = -1.0f * sr * cp;\n    }\n\n    if (up) {\n        up->x = cr * sp * cy + -sr * -sy;\n        up->y = cr * sp * sy + -sr * cy;\n        up->z = cr * cp;\n    }\n}\n\nQAngle CViewRender::ApplyRecoilPunch(const QAngle& viewAngles, const QAngle& aimPunch) {\n    QAngle eff;\n    eff.pitch = viewAngles.pitch + aimPunch.pitch * AIM_PUNCH_MULTIPLIER;\n    eff.yaw = viewAngles.yaw + aimPunch.yaw * AIM_PUNCH_MULTIPLIER;\n    eff.roll = viewAngles.roll + aimPunch.roll * AIM_PUNCH_MULTIPLIER;\n    return eff;\n}\n\nbool CViewRender::WorldToScreen(const Vector3& world, float& screenX, float& screenY,\n                               const ViewMatrix& matrix, int screenWidth, int screenHeight) {\n    const float w = matrix.m[3][0] * world.x + matrix.m[3][1] * world.y + matrix.m[3][2] * world.z + matrix.m[3][3];\n\n    // Homogeneous frustum rejection\n    if (w < 0.001f) {\n        return false;\n    }\n\n    const float invw = 1.0f / w;\n    const float x = (matrix.m[0][0] * world.x + matrix.m[0][1] * world.y + matrix.m[0][2] * world.z + matrix.m[0][3]) * invw;\n    const float y = (matrix.m[1][0] * world.x + matrix.m[1][1] * world.y + matrix.m[1][2] * world.z + matrix.m[1][3]) * invw;\n\n    screenX = (screenWidth * 0.5f) + (0.5f * x * screenWidth + 0.5f);\n    screenY = (screenHeight * 0.5f) - (0.5f * y * screenHeight + 0.5f);\n    return true;\n}\n\n} // namespace cs2::client\n",
        "viewmatrix.h": "#ifndef CS2_CLIENT_VIEWMATRIX_H\n#define CS2_CLIENT_VIEWMATRIX_H\n\n#include <cmath>\n\nnamespace cs2::client {\n\nstruct Vector3 {\n    float x = 0.0f;\n    float y = 0.0f;\n    float z = 0.0f;\n\n    constexpr Vector3() noexcept = default;\n    constexpr Vector3(float fx, float fy, float fz) noexcept : x(fx), y(fy), z(fz) {}\n\n    Vector3 operator+(const Vector3& o) const noexcept { return {x + o.x, y + o.y, z + o.z}; }\n    Vector3 operator-(const Vector3& o) const noexcept { return {x - o.x, y - o.y, z - o.z}; }\n    Vector3 operator*(float s) const noexcept { return {x * s, y * s, z * s}; }\n    Vector3 operator/(float s) const noexcept { return {x / s, y / s, z / s}; }\n\n    [[nodiscard]] float Dot(const Vector3& o) const noexcept { return x * o.x + y * o.y + z * o.z; }\n    [[nodiscard]] float LengthSqr() const noexcept { return Dot(*this); }\n    [[nodiscard]] float Length() const noexcept { return std::sqrt(LengthSqr()); }\n    [[nodiscard]] Vector3 Normalized() const noexcept {\n        float l = Length();\n        return l > 1e-6f ? (*this) * (1.0f / l) : Vector3{0, 0, 0};\n    }\n};\n\nstruct QAngle {\n    float pitch = 0.0f;\n    float yaw = 0.0f;\n    float roll = 0.0f;\n};\n\nstruct ViewMatrix {\n    float m[4][4];\n};\n\n/**\n * @brief Reconstructed Camera & View Matrix Pipeline from client.dll\n * Reverse engineered from AngleVectors @ FUN_1817402a0 and WorldToScreen projection.\n */\nclass CViewRender {\npublic:\n    static constexpr float AIM_PUNCH_MULTIPLIER = 2.0f; // CS2 recoil scalar\n\n    // FUN_1817402a0\n    static void AngleVectors(const QAngle& angles, Vector3* forward, Vector3* right = nullptr, Vector3* up = nullptr);\n\n    static QAngle ApplyRecoilPunch(const QAngle& viewAngles, const QAngle& aimPunch);\n\n    static bool WorldToScreen(const Vector3& world, float& screenX, float& screenY,\n                             const ViewMatrix& matrix, int screenWidth, int screenHeight);\n};\n\n} // namespace cs2::client\n\n#endif // CS2_CLIENT_VIEWMATRIX_H\n",
        "weapon_accuracy.cpp": "#include \"weapon_accuracy.h\"\n#include <algorithm>\n#include <cmath>\n\nnamespace cs2::client {\n\nconstexpr float PI = 3.14159265358979323846f;\nconstexpr float DEG2RAD = PI / 180.0f;\nconstexpr float RAD2DEG = 180.0f / PI;\n\nstatic float ClampFloat(float val, float minVal, float maxVal) {\n    if (val < minVal) return minVal;\n    if (val > maxVal) return maxVal;\n    return val;\n}\n\nstatic float DotProduct(const Vector3& a, const Vector3& b) {\n    return a.x * b.x + a.y * b.y + a.z * b.z;\n}\n\nstatic Vector3 NormalizeVector(const Vector3& v) {\n    float mag = std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z);\n    if (mag < 1e-9f) return {0.0f, 0.0f, 0.0f};\n    float inv = 1.0f / mag;\n    return {v.x * inv, v.y * inv, v.z * inv};\n}\n\n// =======================================================================================\n// CUniformRandomStream: Valve Park-Miller LCG with Bays-Durham Shuffle Table (tier0.dll)\n// Reconstructed from ?SetSeed_Locked@?$CUniformRandomStreamImpl@VCThreadNullMutex@@@@AEAAXH@Z\n// and ?GenerateRandomNumber_Locked@?$CUniformRandomStreamImpl@VCThreadNullMutex@@@@AEAAHXZ\n// =======================================================================================\n\nconstexpr int32_t IA_PM   = 16807;\nconstexpr int32_t IM_PM   = 2147483647; // 2^31 - 1\nconstexpr int32_t IQ_PM   = 127773;\nconstexpr int32_t IR_PM   = 2836;\nconstexpr int32_t NTAB_PM = 32;\n\nvoid CUniformRandomStream::SetSeed(int32_t seed) {\n    m_idum = (seed < 0) ? seed : -seed;\n    if (m_idum == 0) m_idum = -1;\n    m_iy = 0;\n    for (int i = 0; i < NTAB_PM; ++i) {\n        m_iv[i] = 0;\n    }\n\n    // Warm-up shuffle table matching tier0.dll\n    for (int j = NTAB_PM + 7; j >= 0; --j) {\n        int32_t k = m_idum / IQ_PM;\n        m_idum = IA_PM * (m_idum - k * IQ_PM) - IR_PM * k;\n        if (m_idum < 0) {\n            m_idum += IM_PM;\n        }\n        if (j < NTAB_PM) {\n            m_iv[j] = m_idum;\n        }\n    }\n    m_iy = m_iv[0];\n}\n\nfloat CUniformRandomStream::RandomFloat(float minVal, float maxVal) {\n    if (m_idum == 0) {\n        SetSeed(1);\n    }\n    int32_t k = m_idum / IQ_PM;\n    m_idum = IA_PM * (m_idum - k * IQ_PM) - IR_PM * k;\n    if (m_idum < 0) {\n        m_idum += IM_PM;\n    }\n\n    int32_t j = m_iy / (1 + (IM_PM - 1) / NTAB_PM);\n    if (j < 0) j = 0;\n    if (j >= NTAB_PM) j = NTAB_PM - 1;\n    m_iy = m_iv[j];\n    m_iv[j] = m_idum;\n\n    float fl = static_cast<float>(m_iy) * (1.0f / static_cast<float>(IM_PM));\n    if (fl > (1.0f - 1.2e-7f)) {\n        fl = 1.0f - 1.2e-7f;\n    }\n    return minVal + fl * (maxVal - minVal);\n}\n\nint32_t CUniformRandomStream::RandomInt(int32_t minVal, int32_t maxVal) {\n    return static_cast<int32_t>(RandomFloat(static_cast<float>(minVal), static_cast<float>(maxVal) + 0.999f));\n}\n\n// =======================================================================================\n// CWeaponAccuracyPipeline Reconstructed Functions\n// =======================================================================================\n\n// FUN_18080cef0 @ RVA 0x0080cef0\nfloat CWeaponAccuracyPipeline::GetRecoveryTime(\n    const CCSWeaponBaseVData_Accuracy& vdata,\n    const PlayerPawnAccuracyContext& ctx,\n    int32_t recoilIndex\n) {\n    // Air recovery penalty: 4x slower recovery while airborne\n    if (!ctx.onGround) {\n        return vdata.m_flRecoveryTimeCrouch * 4.0f;\n    }\n\n    if (ctx.onLadder) {\n        return vdata.m_flRecoveryTimeStand;\n    }\n\n    float baseRecovery = ctx.ducking ? vdata.m_flRecoveryTimeCrouch : vdata.m_flRecoveryTimeStand;\n    float finalRecovery = ctx.ducking ? vdata.m_flRecoveryTimeCrouchFinal : vdata.m_flRecoveryTimeStandFinal;\n\n    if (finalRecovery != -1.0f && vdata.m_nRecoveryTransitionEndBullet > vdata.m_nRecoveryTransitionStartBullet) {\n        float frac = static_cast<float>(recoilIndex - vdata.m_nRecoveryTransitionStartBullet) /\n                     static_cast<float>(vdata.m_nRecoveryTransitionEndBullet - vdata.m_nRecoveryTransitionStartBullet);\n        frac = ClampFloat(frac, 0.0f, 1.0f);\n        return baseRecovery + frac * (finalRecovery - baseRecovery);\n    }\n\n    return baseRecovery;\n}\n\n// FUN_18080d4c0 @ RVA 0x0080d4c0\nfloat CWeaponAccuracyPipeline::CalculateStrafingInaccuracy(\n    const PlayerPawnAccuracyContext& ctx,\n    const AccuracyConVars& cvars\n) {\n    if (!cvars.sv_strafing_inaccuracy_enabled) {\n        return 0.0f;\n    }\n\n    float speedSqr = ctx.velocity.x * ctx.velocity.x +\n                     ctx.velocity.y * ctx.velocity.y +\n                     ctx.velocity.z * ctx.velocity.z;\n\n    if (speedSqr < 0.001f) {\n        return 0.0f;\n    }\n\n    float speed = std::sqrt(speedSqr);\n    Vector3 velDir = {ctx.velocity.x / speed, ctx.velocity.y / speed, ctx.velocity.z / speed};\n\n    Vector3 eyeForward;\n    CViewRender::AngleVectors(ctx.eyeAngles, &eyeForward, nullptr, nullptr);\n\n    float dot = DotProduct(eyeForward, velDir);\n    float perpFrac = 1.0f - std::abs(dot);\n\n    // Bias transformation function matching FUN_18173d3d0\n    float biasedPerp = std::pow(ClampFloat(perpFrac, 0.0f, 1.0f), cvars.sv_strafing_inaccuracy_bias);\n\n    return (speed / 250.0f) * biasedPerp * cvars.sv_strafing_inaccuracy_scale;\n}\n\n// FUN_180828d90 @ RVA 0x00828d90\nvoid CWeaponAccuracyPipeline::UpdateTurningInaccuracy(\n    WeaponAccuracyState& state,\n    const QAngle& eyeAngles,\n    [[maybe_unused]] float dt,\n    const AccuracyConVars& cvars\n) {\n    if (!cvars.sv_turning_inaccuracy_enabled) {\n        state.m_flTurningInaccuracyDelta = 0.0f;\n        state.m_flTurningInaccuracy = 0.0f;\n        return;\n    }\n\n    Vector3 currentDir;\n    CViewRender::AngleVectors(eyeAngles, &currentDir, nullptr, nullptr);\n\n    if (state.m_vecTurningInaccuracyEyeDirLast.x == 0.0f &&\n        state.m_vecTurningInaccuracyEyeDirLast.y == 0.0f &&\n        state.m_vecTurningInaccuracyEyeDirLast.z == 0.0f) {\n        state.m_vecTurningInaccuracyEyeDirLast = currentDir;\n        return;\n    }\n\n    float deltaDeg = 0.0f;\n    float dot = DotProduct(currentDir, state.m_vecTurningInaccuracyEyeDirLast);\n    dot = ClampFloat(dot, -1.0f, 1.0f);\n\n    float angleRad = std::acos(dot);\n    deltaDeg = std::abs(angleRad) * RAD2DEG;\n    if (deltaDeg > 180.0f) deltaDeg = 180.0f;\n\n    // Decay prior turning delta\n    state.m_flTurningInaccuracyDelta *= cvars.sv_turning_inaccuracy_decay;\n    if (state.m_flTurningInaccuracyDelta < 1e-5f) {\n        state.m_flTurningInaccuracyDelta = 0.0f;\n    }\n\n    // Accumulate normalized delta beyond sv_turning_inaccuracy_angle_min\n    float minAngle = cvars.sv_turning_inaccuracy_angle_min;\n    if (minAngle < 180.0f && deltaDeg > minAngle) {\n        float angleFrac = (deltaDeg - minAngle) / (180.0f - minAngle);\n        angleFrac = ClampFloat(angleFrac, 0.0f, 1.0f);\n        state.m_flTurningInaccuracyDelta += angleFrac;\n    }\n\n    state.m_flTurningInaccuracyDelta = ClampFloat(state.m_flTurningInaccuracyDelta, 0.0f, 1.0f);\n    state.m_flTurningInaccuracy = state.m_flTurningInaccuracyDelta;\n    state.m_vecTurningInaccuracyEyeDirLast = currentDir;\n}\n\n// FUN_180827be0 @ RVA 0x00827be0 / 0x00828a10\nvoid CWeaponAccuracyPipeline::UpdateAccuracyPenalty(\n    WeaponAccuracyState& state,\n    const CCSWeaponBaseVData_Accuracy& vdata,\n    const PlayerPawnAccuracyContext& ctx,\n    float curTime,\n    float dt,\n    const AccuracyConVars& cvars\n) {\n    // 1. Determine target baseline inaccuracy for current posture\n    float targetInaccuracy = 0.0f;\n\n    if (ctx.onLadder) {\n        targetInaccuracy = vdata.m_flInaccuracyLadder;\n    } else if (!ctx.onGround) {\n        targetInaccuracy = vdata.m_flInaccuracyStand + vdata.m_flInaccuracyJump;\n    } else if (ctx.boostStackCount >= cvars.weapon_accuracy_stack_boost_limit && cvars.weapon_accuracy_stack_boost_limit > 0) {\n        // Player stacking / pyramid boost penalty\n        targetInaccuracy = vdata.m_flInaccuracyLadder * 2.0f;\n    } else if (ctx.ducking) {\n        targetInaccuracy = vdata.m_flInaccuracyCrouch;\n    } else {\n        targetInaccuracy = vdata.m_flInaccuracyStand;\n    }\n\n    if (state.m_bInReload) {\n        targetInaccuracy += vdata.m_flInaccuracyReload;\n    }\n\n    // 2. Exponential recovery decay towards target\n    if (state.m_fAccuracyPenalty >= targetInaccuracy) {\n        float recoveryTime = GetRecoveryTime(vdata, ctx, state.m_iRecoilIndex);\n        if (recoveryTime > 0.0001f) {\n            // Valve formula: exp(-(ln(10.0f) / recoveryTime) * dt)\n            float decayFactor = std::exp(-(std::log(10.0f) / recoveryTime) * dt);\n            state.m_fAccuracyPenalty = targetInaccuracy + (state.m_fAccuracyPenalty - targetInaccuracy) * decayFactor;\n        } else {\n            state.m_fAccuracyPenalty = targetInaccuracy;\n        }\n    } else {\n        state.m_fAccuracyPenalty = targetInaccuracy;\n    }\n\n    // 3. Update view turning inaccuracy\n    UpdateTurningInaccuracy(state, ctx.eyeAngles, dt, cvars);\n\n    // 4. Continuous rapid-fire recoil index decay (FUN_180827be0 lines 88-120)\n    if (state.m_flRecoilIndex > 0.0f) {\n        float timeSinceShot = curTime - state.m_fLastShotTime;\n        if (timeSinceShot > (vdata.m_flCycleTime + dt)) {\n            // Valve formula: exp(-2.0f * ln(10.0f) * dt)\n            float recoilDecay = std::exp(-2.0f * std::log(10.0f) * dt);\n            state.m_flRecoilIndex *= recoilDecay;\n            if (state.m_flRecoilIndex <= 0.1f) {\n                state.m_flRecoilIndex = 0.0f;\n                state.m_iRecoilIndex = 0;\n            }\n        }\n    }\n\n    state.m_flLastAccuracyUpdateTime = curTime;\n}\n\n// FUN_18080c1a0 @ RVA 0x0080c1a0 / 0x0080cfd0\nfloat CWeaponAccuracyPipeline::GetInaccuracy(\n    const WeaponAccuracyState& state,\n    const CCSWeaponBaseVData_Accuracy& vdata,\n    const PlayerPawnAccuracyContext& ctx,\n    float* outSpread,\n    float* outJumpInacc,\n    const AccuracyConVars& cvars\n) {\n    if (cvars.weapon_accuracy_forcespread > 0.0f) {\n        if (outSpread) *outSpread = cvars.weapon_accuracy_forcespread;\n        if (outJumpInacc) *outJumpInacc = 0.0f;\n        return cvars.weapon_accuracy_forcespread;\n    }\n\n    if (cvars.weapon_accuracy_nospread) {\n        if (outSpread) *outSpread = 0.0f;\n        if (outJumpInacc) *outJumpInacc = 0.0f;\n        return 0.0f;\n    }\n\n    float totalInaccuracy = state.m_fAccuracyPenalty;\n\n    // Movement speed modulation: RemapValClamped(speed, maxSpeed * 0.34, maxSpeed * 0.95, 0.0, 1.0)\n    float speed2D = std::sqrt(ctx.velocity.x * ctx.velocity.x + ctx.velocity.y * ctx.velocity.y);\n    float lowSpeed = vdata.m_flMaxSpeed * 0.34f;\n    float highSpeed = vdata.m_flMaxSpeed * 0.95f;\n\n    float moveFactor = 0.0f;\n    if (speed2D > lowSpeed) {\n        moveFactor = (speed2D - lowSpeed) / (highSpeed - lowSpeed);\n        moveFactor = ClampFloat(moveFactor, 0.0f, 1.0f);\n        if (ctx.ducking) {\n            // Valve pow(f, 0.25f) when crouched\n            moveFactor = std::pow(moveFactor, 0.25f);\n        }\n    }\n\n    float moveInaccuracy = moveFactor * vdata.m_flInaccuracyMove;\n    if (outSpread) *outSpread = moveInaccuracy;\n    totalInaccuracy += moveInaccuracy;\n\n    // Jumping / Airborne Inaccuracy\n    float jumpInacc = 0.0f;\n    if (!ctx.onGround) {\n        float vz = std::abs(ctx.velocity.z);\n        float apexThreshold = 200.0f; // Approx apex vertical speed band\n        float jumpApex = vdata.m_flInaccuracyJumpApex;\n        float jumpInitial = vdata.m_flInaccuracyJumpInitial;\n\n        if (vz <= apexThreshold) {\n            jumpInacc = jumpApex;\n        } else {\n            float frac = (vz - apexThreshold) / (800.0f - apexThreshold);\n            frac = ClampFloat(frac, 0.0f, 1.0f);\n            jumpInacc = jumpApex + frac * (jumpInitial - jumpApex);\n        }\n        totalInaccuracy += jumpInacc;\n    }\n    if (outJumpInacc) *outJumpInacc = jumpInacc;\n\n    // Strafing component\n    totalInaccuracy += CalculateStrafingInaccuracy(ctx, cvars);\n\n    // Turning component\n    totalInaccuracy += state.m_flTurningInaccuracy;\n\n    return ClampFloat(totalInaccuracy, 0.0f, 1.0f);\n}\n\nfloat CWeaponAccuracyPipeline::GetSpread(\n    const CCSWeaponBaseVData_Accuracy& vdata,\n    int32_t /*weaponMode*/\n) {\n    return vdata.m_flSpread;\n}\n\n// FUN_180d23fe0 @ RVA 0x00d23fe0 / 0x00d25630 (FX_CalculateSpread)\nSpreadVector2D CWeaponAccuracyPipeline::CalculateSpreadVector(\n    uint16_t itemDefIndex,\n    int32_t /*bulletIndex*/,\n    int32_t /*numBullets*/,\n    int32_t weaponMode,\n    int32_t randomSeed,\n    float inaccuracy,\n    float spread,\n    float recoilIndex,\n    const AccuracyConVars& cvars\n) {\n    if (cvars.weapon_accuracy_nospread) {\n        return {0.0f, 0.0f};\n    }\n\n    CUniformRandomStream rng;\n    // Valve PRNG seed initialization matching RandomSeed(param_4)\n    rng.SetSeed(randomSeed);\n\n    // Dual uniform disk sampling\n    // -----------------------------------------------------------------------------------\n    // Disk 1: Inaccuracy Disk (r1 in [0, 1], theta1 in [0, 2*PI])\n    // -----------------------------------------------------------------------------------\n    float r1 = rng.RandomFloat(0.0f, 1.0f);\n    float theta1 = rng.RandomFloat(0.0f, 2.0f * PI);\n\n    // Revolver secondary fire (fan-the-hammer: item def 64, weaponMode 1)\n    constexpr uint16_t WEAPON_REVOLVER = 64;\n    constexpr uint16_t WEAPON_NEGEV    = 28;\n\n    if (itemDefIndex == WEAPON_REVOLVER && weaponMode == 1) {\n        // Power distribution pushes shots outwards towards cone perimeter\n        r1 = 1.0f - r1 * r1;\n    } else if (itemDefIndex == WEAPON_NEGEV && recoilIndex < 3.0f) {\n        // Negev initial spin-up inaccuracy power curve: collapses towards laser precision\n        for (int32_t i = 3; i > static_cast<int32_t>(recoilIndex); --i) {\n            r1 = r1 * r1;\n        }\n        r1 = 1.0f - r1;\n    }\n\n    if (cvars.weapon_accuracy_forcespread > 0.0f) {\n        r1 = 1.0f;\n    }\n\n    float R_inacc = r1 * inaccuracy;\n\n    // -----------------------------------------------------------------------------------\n    // Disk 2: Intrinsic Spread Disk (r2 in [0, 1], theta2 in [0, 2*PI])\n    // -----------------------------------------------------------------------------------\n    float r2 = rng.RandomFloat(0.0f, 1.0f);\n    float theta2 = rng.RandomFloat(0.0f, 2.0f * PI);\n\n    if (itemDefIndex == WEAPON_REVOLVER && weaponMode == 1) {\n        r2 = 1.0f - r2 * r2;\n    } else if (itemDefIndex == WEAPON_NEGEV && recoilIndex < 3.0f) {\n        for (int32_t i = 3; i > static_cast<int32_t>(recoilIndex); --i) {\n            r2 = r2 * r2;\n        }\n        r2 = 1.0f - r2;\n    }\n\n    if (cvars.weapon_accuracy_forcespread > 0.0f) {\n        r2 = 1.0f;\n    }\n\n    float R_spread = r2 * spread;\n\n    // -----------------------------------------------------------------------------------\n    // Vectorial combination matching FUN_180d23fe0 lines 128-137:\n    // dx = cos(theta1) * R_inacc + cos(theta2) * R_spread\n    // dy = sin(theta1) * R_inacc + sin(theta2) * R_spread\n    // -----------------------------------------------------------------------------------\n    SpreadVector2D result{};\n    result.x = std::cos(theta1) * R_inacc + std::cos(theta2) * R_spread;\n    result.y = std::sin(theta1) * R_inacc + std::sin(theta2) * R_spread;\n\n    return result;\n}\n\nvoid CWeaponAccuracyPipeline::OnWeaponFired(\n    WeaponAccuracyState& state,\n    const CCSWeaponBaseVData_Accuracy& vdata,\n    AimPunchState& punchState,\n    float curTime\n) {\n    // 1. Fire Inaccuracy impulse\n    state.m_fAccuracyPenalty += vdata.m_flInaccuracyFire;\n    state.m_flRecoilIndex += 1.0f;\n    state.m_iRecoilIndex += 1;\n    state.m_fLastShotTime = curTime;\n\n    // 2. Recoil punch kick impulse (pitch kicks upward, yaw has directional spread)\n    float punchPitch = vdata.m_flRecoilMagnitude * 0.055f;\n    punchState.m_aimPunchAngle.pitch -= punchPitch;\n    punchState.m_aimPunchAngleVel.pitch -= punchPitch * 20.0f;\n}\n\n// FUN_18085dc60 @ RVA 0x0085dc60 & FUN_18084d8b0 @ RVA 0x0084d8b0\nvoid CWeaponAccuracyPipeline::SimulateAimPunchDecay(\n    AimPunchState& punchState,\n    float dt,\n    float dampingRate\n) {\n    // Second-order spring integration with exponential velocity damping (-4.5f rate)\n    float velDamping = std::exp(-dampingRate * dt);\n\n    punchState.m_aimPunchAngleVel.pitch *= velDamping;\n    punchState.m_aimPunchAngleVel.yaw   *= velDamping;\n    punchState.m_aimPunchAngleVel.roll  *= velDamping;\n\n    // Integrate angle from velocity\n    punchState.m_aimPunchAngle.pitch += punchState.m_aimPunchAngleVel.pitch * dt;\n    punchState.m_aimPunchAngle.yaw   += punchState.m_aimPunchAngleVel.yaw * dt;\n    punchState.m_aimPunchAngle.roll  += punchState.m_aimPunchAngleVel.roll * dt;\n\n    // Deadzone filter: 0.140625 threshold (0.375^2)\n    float magSqr = punchState.m_aimPunchAngle.pitch * punchState.m_aimPunchAngle.pitch +\n                   punchState.m_aimPunchAngle.yaw   * punchState.m_aimPunchAngle.yaw +\n                   punchState.m_aimPunchAngle.roll  * punchState.m_aimPunchAngle.roll;\n\n    if (magSqr <= 0.140625f) {\n        punchState.m_aimPunchAngle = {0.0f, 0.0f, 0.0f};\n        punchState.m_aimPunchAngleVel = {0.0f, 0.0f, 0.0f};\n    } else {\n        float scale = 1.0f - (0.140625f / magSqr);\n        punchState.m_aimPunchAngle.pitch *= scale;\n        punchState.m_aimPunchAngle.yaw   *= scale;\n        punchState.m_aimPunchAngle.roll  *= scale;\n    }\n\n    // Clamp pitch to [-89.0f, +89.0f]\n    punchState.m_aimPunchAngle.pitch = ClampFloat(punchState.m_aimPunchAngle.pitch, -89.0f, 89.0f);\n}\n\nVector3 CWeaponAccuracyPipeline::CalculateSpreadConeRay(\n    const SpreadVector2D& spreadVec,\n    const Vector3& forward,\n    const Vector3& right,\n    const Vector3& up\n) {\n    Vector3 ray = {\n        forward.x + right.x * spreadVec.x + up.x * spreadVec.y,\n        forward.y + right.y * spreadVec.x + up.y * spreadVec.y,\n        forward.z + right.z * spreadVec.x + up.z * spreadVec.y\n    };\n\n    return NormalizeVector(ray);\n}\n\nVector3 CWeaponAccuracyPipeline::CalculateSpreadConeRay(\n    float inaccuracy,\n    float spread,\n    float randU1,\n    float randU2,\n    const Vector3& forward,\n    const Vector3& right,\n    const Vector3& up\n) {\n    float r = (inaccuracy + spread) * std::sqrt(randU1);\n    float theta = randU2 * 2.0f * PI;\n\n    float spreadX = std::cos(theta) * r;\n    float spreadY = std::sin(theta) * r;\n\n    Vector3 ray = {\n        forward.x + right.x * spreadX + up.x * spreadY,\n        forward.y + right.y * spreadX + up.y * spreadY,\n        forward.z + right.z * spreadX + up.z * spreadY\n    };\n\n    return NormalizeVector(ray);\n}\n\n} // namespace cs2::client\n",
        "weapon_accuracy.h": "#ifndef CS2_CLIENT_WEAPON_ACCURACY_H\n#define CS2_CLIENT_WEAPON_ACCURACY_H\n\n#include \"viewmatrix.h\"\n#include <cstdint>\n#include <cmath>\n\nnamespace cs2::client {\n\n/**\n * @brief Weapon configuration parameters parsed from CCSWeaponBaseVData (client.dll & server.dll).\n */\nstruct CCSWeaponBaseVData_Accuracy {\n    float m_flSpread = 0.002f;\n    float m_flInaccuracyCrouch = 0.004f;\n    float m_flInaccuracyStand = 0.006f;\n    float m_flInaccuracyJump = 0.350f;\n    float m_flInaccuracyLand = 0.080f;\n    float m_flInaccuracyLadder = 0.110f;\n    float m_flInaccuracyFire = 0.055f;\n    float m_flInaccuracyMove = 0.130f;\n    float m_flInaccuracyReload = 0.020f;\n    float m_flInaccuracyJumpInitial = 0.450f;\n    float m_flInaccuracyJumpApex = 0.280f;\n\n    // Recovery Times (exponential penalty decay)\n    float m_flRecoveryTimeCrouch = 0.340f;\n    float m_flRecoveryTimeStand = 0.450f;\n    float m_flRecoveryTimeCrouchFinal = 0.420f;\n    float m_flRecoveryTimeStandFinal = 0.580f;\n    int32_t m_nRecoveryTransitionStartBullet = 2;\n    int32_t m_nRecoveryTransitionEndBullet = 5;\n\n    // Recoil Punch Properties\n    float m_flRecoilAngle = 0.0f;\n    float m_flRecoilAngleVariance = 0.0f;\n    float m_flRecoilMagnitude = 21.0f;\n    float m_flRecoilMagnitudeVariance = 1.0f;\n\n    float m_flCycleTime = 0.09f;\n    float m_flMaxSpeed = 250.0f;\n    int32_t m_nNumBullets = 1;\n};\n\n/**\n * @brief Dynamic runtime weapon accuracy and recoil state (C_CSWeaponBase).\n */\nstruct WeaponAccuracyState {\n    float m_fAccuracyPenalty = 0.0f;              // +0x1a18\n    float m_flLastAccuracyUpdateTime = 0.0f;      // +0x1a1c\n    float m_fAccuracySmoothedForZoom = 0.0f;      // +0x1a20\n    int32_t m_iRecoilIndex = 0;                   // +0x1a24\n    float m_flRecoilIndex = 0.0f;                 // +0x1a28\n    float m_flTurningInaccuracyDelta = 0.0f;      // +0x1a04\n    Vector3 m_vecTurningInaccuracyEyeDirLast{};   // +0x1a08\n    float m_flTurningInaccuracy = 0.0f;           // +0x1a14\n    float m_fLastShotTime = 0.0f;                 // +0x1b68\n    int32_t m_weaponMode = 0;                     // +0x1a00\n    bool m_bInReload = false;                     // +0x1a3c\n};\n\n/**\n * @brief Player Pawn physical state context required for accuracy evaluation.\n */\nstruct PlayerPawnAccuracyContext {\n    Vector3 velocity{};\n    QAngle eyeAngles{};\n    bool onGround = true;\n    bool ducking = false;\n    bool onLadder = false;\n    int32_t boostStackCount = 0; // Stacked atop other players\n};\n\n/**\n * @brief Recoil aim punch spring-damper state (CPlayer_AimPunchServices).\n */\nstruct AimPunchState {\n    int32_t m_predictableBaseTick = 0;            // +0x0048\n    float m_predictableBaseTickInterpAmount = 0.0f; // +0x004c\n    QAngle m_aimPunchAngle{};                     // +0x0050 (m_predictableBaseAngle)\n    QAngle m_aimPunchAngleVel{};                  // +0x005c (m_predictableBaseAngleVel)\n};\n\n/**\n * @brief 2D spread deflection vector on the view plane.\n */\nstruct SpreadVector2D {\n    float x = 0.0f;\n    float y = 0.0f;\n};\n\n/**\n * @brief Global engine ConVars controlling accuracy and recoil physics.\n */\nstruct AccuracyConVars {\n    bool sv_turning_inaccuracy_enabled = true;\n    float sv_turning_inaccuracy_angle_min = 1.0f;     // deg\n    float sv_turning_inaccuracy_decay = 0.90f;        // rate per evaluation\n    bool sv_strafing_inaccuracy_enabled = true;\n    float sv_strafing_inaccuracy_bias = 0.45f;\n    float sv_strafing_inaccuracy_scale = 0.65f;\n    float weapon_accuracy_forcespread = 0.0f;\n    bool weapon_accuracy_nospread = false;\n    int32_t weapon_accuracy_stack_boost_limit = 1;\n    float weapon_recoil_decay = 4.5f;                 // Second-order spring damping\n};\n\n/**\n * @brief Clean-room implementation of Valve's CUniformRandomStream (tier0.dll).\n * Based on Park-Miller minimal standard LCG with Bays-Durham shuffle table (ran1).\n */\nclass CUniformRandomStream {\nprivate:\n    int32_t m_idum = 0;\n    int32_t m_iy = 0;\n    int32_t m_iv[32]{};\n\npublic:\n    CUniformRandomStream() = default;\n    explicit CUniformRandomStream(int32_t seed) { SetSeed(seed); }\n\n    void SetSeed(int32_t seed);\n    float RandomFloat(float minVal = 0.0f, float maxVal = 1.0f);\n    int32_t RandomInt(int32_t minVal, int32_t maxVal);\n};\n\n/**\n * @brief Clean-room reconstructed CS2 Weapon Accuracy, Spread Cone, and Recoil Decay Pipeline.\n * Reverse engineered from client.dll:\n *   - FUN_18080c1a0 (C_CSWeaponBase::GetInaccuracy @ RVA 0x0080c1a0 / 0x0080cfd0)\n *   - FUN_180d23fe0 (FX_CalculateSpread @ RVA 0x00d23fe0 / 0x00d25630)\n *   - FUN_180827be0 (C_CSWeaponBase::UpdateAccuracyPenalty @ RVA 0x00827be0 / 0x00828a10)\n *   - FUN_18080cef0 (GetRecoveryTime @ RVA 0x0080cef0)\n *   - FUN_18085dc60 (CPlayer_AimPunchServices::SimulateAimPunchDecay @ RVA 0x0085dc60 / 0x0085ea90)\n */\nclass CWeaponAccuracyPipeline {\npublic:\n    static constexpr float TICK_INTERVAL = 1.0f / 64.0f; // 0.015625s\n\n    /**\n     * @brief Evaluates recovery time based on stance, air status, and recoil index.\n     * Reconstructed from FUN_18080cef0 @ RVA 0x0080cef0.\n     */\n    static float GetRecoveryTime(\n        const CCSWeaponBaseVData_Accuracy& vdata,\n        const PlayerPawnAccuracyContext& ctx,\n        int32_t recoilIndex\n    );\n\n    /**\n     * @brief Computes strafing-induced inaccuracy from movement velocity and eye angle.\n     * Reconstructed from FUN_18080d4c0 @ RVA 0x0080d4c0.\n     */\n    static float CalculateStrafingInaccuracy(\n        const PlayerPawnAccuracyContext& ctx,\n        const AccuracyConVars& cvars\n    );\n\n    /**\n     * @brief Updates turning delta and angular inaccuracy.\n     * Reconstructed from FUN_180828d90 @ RVA 0x00828d90.\n     */\n    static void UpdateTurningInaccuracy(\n        WeaponAccuracyState& state,\n        const QAngle& eyeAngles,\n        float dt,\n        const AccuracyConVars& cvars\n    );\n\n    /**\n     * @brief Main tick update for weapon accuracy penalty and recoil index decay.\n     * Reconstructed from FUN_180827be0 @ RVA 0x00827be0 / 0x00828a10.\n     */\n    static void UpdateAccuracyPenalty(\n        WeaponAccuracyState& state,\n        const CCSWeaponBaseVData_Accuracy& vdata,\n        const PlayerPawnAccuracyContext& ctx,\n        float curTime,\n        float dt,\n        const AccuracyConVars& cvars\n    );\n\n    /**\n     * @brief Evaluates total composite weapon inaccuracy and base spread.\n     * Reconstructed from FUN_18080c1a0 @ RVA 0x0080c1a0 / 0x0080cfd0.\n     */\n    static float GetInaccuracy(\n        const WeaponAccuracyState& state,\n        const CCSWeaponBaseVData_Accuracy& vdata,\n        const PlayerPawnAccuracyContext& ctx,\n        float* outSpread,\n        float* outJumpInacc,\n        const AccuracyConVars& cvars\n    );\n\n    /**\n     * @brief Retrieves intrinsic weapon spread from weapon vdata.\n     */\n    static float GetSpread(\n        const CCSWeaponBaseVData_Accuracy& vdata,\n        int32_t weaponMode = 0\n    );\n\n    /**\n     * @brief Generates dual uniform disk spread deflection vector for bullet/pellet.\n     * Reconstructed from FX_CalculateSpread @ RVA 0x00d23fe0 / 0x00d25630 (FUN_180d23fe0).\n     *\n     * Evaluates independent uniform random variates for inaccuracy disk (r1, theta1)\n     * and intrinsic spread disk (r2, theta2), applying weapon-specific distributions\n     * (Revolver fan-the-hammer power inversion, Negev continuous spin-up convergence)\n     * and summing them vectorially.\n     *\n     * @param itemDefIndex Weapon item definition index (64 = revolver, 28 = negev, etc.)\n     * @param bulletIndex Index of pellet/bullet in current burst\n     * @param numBullets Total pellets/bullets fired in this shot\n     * @param weaponMode Primary (0) or Secondary (1)\n     * @param randomSeed Deterministic random seed\n     * @param inaccuracy Current composite inaccuracy from GetInaccuracy\n     * @param spread Intrinsic weapon spread from GetSpread\n     * @param recoilIndex Current continuous recoil index\n     * @param cvars Accuracy ConVars\n     * @return 2D spread deflection vector (dx, dy)\n     */\n    static SpreadVector2D CalculateSpreadVector(\n        uint16_t itemDefIndex,\n        int32_t bulletIndex,\n        int32_t numBullets,\n        int32_t weaponMode,\n        int32_t randomSeed,\n        float inaccuracy,\n        float spread,\n        float recoilIndex,\n        const AccuracyConVars& cvars\n    );\n\n    /**\n     * @brief Handles weapon firing impulse: applies fire inaccuracy and recoil punch.\n     */\n    static void OnWeaponFired(\n        WeaponAccuracyState& state,\n        const CCSWeaponBaseVData_Accuracy& vdata,\n        AimPunchState& punchState,\n        float curTime\n    );\n\n    /**\n     * @brief Simulates second-order recoil aim punch ODE spring damping per tick.\n     * Reconstructed from FUN_18085dc60 @ RVA 0x0085dc60 and FUN_18084d8b0 @ RVA 0x0084d8b0.\n     */\n    static void SimulateAimPunchDecay(\n        AimPunchState& punchState,\n        float dt,\n        float dampingRate = 4.5f\n    );\n\n    /**\n     * @brief Generates 3D perturbed firing ray direction vector from spread deflection.\n     */\n    static Vector3 CalculateSpreadConeRay(\n        const SpreadVector2D& spreadVec,\n        const Vector3& forward,\n        const Vector3& right,\n        const Vector3& up\n    );\n\n    /**\n     * @brief Generates 3D perturbed firing ray direction vector from spread cone (polar overload).\n     */\n    static Vector3 CalculateSpreadConeRay(\n        float inaccuracy,\n        float spread,\n        float randU1,\n        float randU2,\n        const Vector3& forward,\n        const Vector3& right,\n        const Vector3& up\n    );\n};\n\n} // namespace cs2::client\n\n#endif // CS2_CLIENT_WEAPON_ACCURACY_H\n"
      }
    },
    {
      "module": "engine2.dll",
      "directory": "game/engine2",
      "standard": "C++20 (/std:c++20 /W4)",
      "files": {
        "cvar_engine.cpp": "#include \"cvar_engine.h\"\n#include <cctype>\n\nnamespace cs2::engine2 {\n\nCCvarEngine::CCvarEngine() {\n    RegisterConVar(\"sv_cheats\", \"0\", FCVAR_REPLICATED | FCVAR_NOTIFY, \"Allows cheats on server.\");\n    RegisterConVar(\"sv_friction\", \"5.2\", FCVAR_REPLICATED, \"World ground friction scalar.\");\n    RegisterConVar(\"cl_interp\", \"0.015625\", FCVAR_CLIENTDLL, \"Client interpolation duration.\");\n}\n\nCCvarEngine& CCvarEngine::Get() {\n    static CCvarEngine s_Instance;\n    return s_Instance;\n}\n\nuint32_t CCvarEngine::HashConVarName(const std::string& name) noexcept {\n    // Caseless 32-bit FNV-1a hash matching engine2.dll seed 0x31415926\n    uint32_t hash = 0x31415926;\n    for (char c : name) {\n        hash ^= static_cast<uint8_t>(std::tolower(static_cast<unsigned char>(c)));\n        hash *= 0x01000193;\n    }\n    return hash;\n}\n\nvoid CCvarEngine::RegisterConVar(const std::string& name, const std::string& defaultValue, uint32_t flags, const std::string& help) {\n    m_ConVars[name] = { name, defaultValue, flags, help };\n}\n\nconst ConVarRecord* CCvarEngine::FindConVar(const std::string& name) const {\n    auto it = m_ConVars.find(name);\n    return it != m_ConVars.end() ? &it->second : nullptr;\n}\n\nbool CCvarEngine::IsCheatProtected(const std::string& name) const {\n    const auto* cvar = FindConVar(name);\n    return cvar && (cvar->flags & FCVAR_CHEAT) != 0;\n}\n\nbool CCvarEngine::IsReplicated(const std::string& name) const {\n    const auto* cvar = FindConVar(name);\n    return cvar && (cvar->flags & FCVAR_REPLICATED) != 0;\n}\n\nbool CCvarEngine::SetClientConVar(const std::string& name, const std::string& newValue, bool isServerCall) {\n    auto it = m_ConVars.find(name);\n    if (it == m_ConVars.end()) {\n        return false;\n    }\n\n    // Gatekeeper 1: FCVAR_REPLICATED (Bit 13) cannot be modified by client unless pushed by server\n    if ((it->second.flags & FCVAR_REPLICATED) && !isServerCall) {\n        return false; // Unauthorized client overwrite rejected\n    }\n\n    // Gatekeeper 2: FCVAR_CHEAT (Bit 14) requires sv_cheats == \"1\"\n    if ((it->second.flags & FCVAR_CHEAT)) {\n        const auto* svCheats = FindConVar(\"sv_cheats\");\n        if (!svCheats || svCheats->value != \"1\") {\n            return false; // Cheats are not enabled\n        }\n    }\n\n    it->second.value = newValue;\n    return true;\n}\n\n} // namespace cs2::engine2\n",
        "cvar_engine.h": "#ifndef CS2_ENGINE2_CVAR_ENGINE_H\n#define CS2_ENGINE2_CVAR_ENGINE_H\n\n#include <cstdint>\n#include <string>\n#include <unordered_map>\n\nnamespace cs2::engine2 {\n\n// ConVar Bit Flags verified from engine2.dll @ 0x1800825e0\nconstexpr uint32_t FCVAR_NONE               = 0;\nconstexpr uint32_t FCVAR_UNREGISTERED       = (1 << 0);\nconstexpr uint32_t FCVAR_DEVELOPMENTONLY    = (1 << 1);\nconstexpr uint32_t FCVAR_GAMEDLL            = (1 << 2);\nconstexpr uint32_t FCVAR_CLIENTDLL          = (1 << 3);\nconstexpr uint32_t FCVAR_HIDDEN             = (1 << 4);\nconstexpr uint32_t FCVAR_PROTECTED          = (1 << 5);\nconstexpr uint32_t FCVAR_NOTIFY             = (1 << 8);\nconstexpr uint32_t FCVAR_REPLICATED         = (1 << 13); // Bit 13 / 0x2000: Server authoritative\nconstexpr uint32_t FCVAR_CHEAT              = (1 << 14); // Bit 14 / 0x4000: Protected by sv_cheats\n\nstruct ConVarRecord {\n    std::string name;\n    std::string value;\n    uint32_t flags = 0;\n    std::string helpString;\n};\n\n/**\n * @brief Reconstructed CCvar Engine Subsystem from engine2.dll\n * Implements FCVAR security gates, caseless string hashing, and authoritative synchronization.\n */\nclass CCvarEngine {\npublic:\n    static CCvarEngine& Get();\n\n    void RegisterConVar(const std::string& name, const std::string& defaultValue, uint32_t flags, const std::string& help);\n    [[nodiscard]] const ConVarRecord* FindConVar(const std::string& name) const;\n\n    bool SetClientConVar(const std::string& name, const std::string& newValue, bool isServerCall);\n    [[nodiscard]] bool IsCheatProtected(const std::string& name) const;\n    [[nodiscard]] bool IsReplicated(const std::string& name) const;\n\n    static uint32_t HashConVarName(const std::string& name) noexcept;\n\nprivate:\n    CCvarEngine();\n    std::unordered_map<std::string, ConVarRecord> m_ConVars;\n};\n\n} // namespace cs2::engine2\n\n#endif // CS2_ENGINE2_CVAR_ENGINE_H\n",
        "game_events.cpp": "#include \"game_events.h\"\n#include <algorithm>\n\nnamespace cs2::engine2 {\n\nCGameEventDispatcher& CGameEventDispatcher::Get() {\n    static CGameEventDispatcher s_Instance;\n    return s_Instance;\n}\n\nvoid CGameEventDispatcher::RegisterEventDescriptor(uint32_t id, const std::string& name, const std::vector<EventKeyDescriptor>& keys) {\n    m_DescriptorsById[id] = { id, name, keys };\n    m_IdByName[name] = id;\n}\n\nvoid CGameEventDispatcher::AddListener(const std::string& eventName, IGameEventListener* listener) {\n    auto it = m_IdByName.find(eventName);\n    if (it != m_IdByName.end() && listener) {\n        m_Listeners[it->second].push_back(listener);\n    }\n}\n\nvoid CGameEventDispatcher::RemoveListener(IGameEventListener* listener) {\n    if (!listener) return;\n    for (auto& pair : m_Listeners) {\n        auto& vec = pair.second;\n        vec.erase(std::remove(vec.begin(), vec.end(), listener), vec.end());\n    }\n}\n\nvoid CGameEventDispatcher::DispatchEvent(const EventInstance& ev) {\n    auto it = m_Listeners.find(ev.eventId);\n    if (it != m_Listeners.end()) {\n        for (auto* listener : it->second) {\n            if (listener) {\n                listener->OnEventFired(ev);\n            }\n        }\n    }\n}\n\n} // namespace cs2::engine2\n",
        "game_events.h": "#ifndef CS2_ENGINE2_GAME_EVENTS_H\n#define CS2_ENGINE2_GAME_EVENTS_H\n\n#include <cstdint>\n#include <string>\n#include <vector>\n#include <unordered_map>\n\nnamespace cs2::engine2 {\n\nstruct EventKeyDescriptor {\n    std::string keyName;\n    int dataType; // 1: bool, 2: int32, 3: float, 4: string\n};\n\nstruct EventDescriptor {\n    uint32_t eventId;\n    std::string eventName;\n    std::vector<EventKeyDescriptor> keys;\n};\n\nstruct EventInstance {\n    uint32_t eventId;\n    std::unordered_map<std::string, std::string> values;\n};\n\nclass IGameEventListener {\npublic:\n    virtual ~IGameEventListener() = default;\n    virtual void OnEventFired(const EventInstance& ev) = 0;\n};\n\n/**\n * @brief Reconstructed 2-Phase GameEvent Dispatcher from engine2.dll\n * Phase 1: CSVCMsg_GameEventList signon dictionary synchronization\n * Phase 2: CSVCMsgList_GameEvents batched wire delivery\n */\nclass CGameEventDispatcher {\npublic:\n    static CGameEventDispatcher& Get();\n\n    void RegisterEventDescriptor(uint32_t id, const std::string& name, const std::vector<EventKeyDescriptor>& keys);\n    void AddListener(const std::string& eventName, IGameEventListener* listener);\n    void RemoveListener(IGameEventListener* listener);\n\n    void DispatchEvent(const EventInstance& ev);\n\nprivate:\n    CGameEventDispatcher() = default;\n    std::unordered_map<uint32_t, EventDescriptor> m_DescriptorsById;\n    std::unordered_map<std::string, uint32_t> m_IdByName;\n    std::unordered_map<uint32_t, std::vector<IGameEventListener*>> m_Listeners;\n};\n\n} // namespace cs2::engine2\n\n#endif // CS2_ENGINE2_GAME_EVENTS_H\n"
      }
    },
    {
      "module": "interfaces",
      "directory": "game/interfaces",
      "standard": "C++20 (/std:c++20 /W4)",
      "files": {
        "cvar.h": "#ifndef CS2_INTERFACES_CVAR_H\n#define CS2_INTERFACES_CVAR_H\n\n#include <cstdint>\n#include <string_view>\n#include \"../tier0/utl_string_token.h\"\n\nnamespace cs2::interfaces {\n\n// Source 2 ConVar Security & Replication Flags\nnamespace FCVAR {\n    constexpr std::uint32_t UNREGISTERED              = (1 << 0);\n    constexpr std::uint32_t DEVELOPMENTONLY           = (1 << 1);\n    constexpr std::uint32_t GAMEDLL                   = (1 << 2);\n    constexpr std::uint32_t CLIENTDLL                 = (1 << 3);\n    constexpr std::uint32_t HIDDEN                    = (1 << 4);\n    constexpr std::uint32_t PROTECTED                 = (1 << 5);\n    constexpr std::uint32_t SPONLY                    = (1 << 6);\n    constexpr std::uint32_t ARCHIVE                   = (1 << 7);\n    constexpr std::uint32_t NOTIFY                    = (1 << 8);\n    constexpr std::uint32_t USERINFO                  = (1 << 9);\n    constexpr std::uint32_t CHEAT                     = (1 << 14);\n    constexpr std::uint32_t REPLICATED                = (1 << 29);\n    constexpr std::uint32_t DEMO                      = (1 << 16);\n    constexpr std::uint32_t DONTRECORD                = (1 << 17);\n    constexpr std::uint32_t RELEASE                   = (1 << 19);\n}\n\n/**\n * @brief ConVar Raw Descriptor (Source 2)\n */\nclass ConVar {\npublic:\n    const char*   m_pszName{nullptr};        // +0x00: Primary convar identifier\n    ConVar*       m_pNext{nullptr};          // +0x08: Next convar node in tier0 hash table\n    const char*   m_pszDescription{nullptr}; // +0x10: Descriptive documentation\n    std::uint32_t m_nFlags{0};               // +0x18: FCVAR flags bitmask\n\n    // Accessors\n    [[nodiscard]] const char* GetName() const noexcept { return m_pszName; }\n    [[nodiscard]] const char* GetHelpText() const noexcept { return m_pszDescription; }\n    [[nodiscard]] bool HasFlag(std::uint32_t flag) const noexcept { return (m_nFlags & flag) != 0; }\n};\n\n/**\n * @brief Engine ConVar Master Interface (CCvar / ICvar)\n * Token: \"VEngineCvar007\" in tier0.dll\n * VTable RVA: +0x313208 (48 slots)\n */\nclass CCvar {\npublic:\n    virtual ~CCvar() = default;\n\n    // Slot 12: FindVarByName\n    virtual ConVar* FindVarByName(const char* pszVarName) = 0;\n\n    // Slot 13: FindVarByToken\n    virtual ConVar* FindVarByToken(tier0::CUtlStringToken token) = 0;\n\n    // Slot 14: FindCommandByName\n    virtual void* FindCommandByName(const char* pszCommandName) = 0;\n\n    // Slot 27: GetFirstConVar\n    virtual ConVar* GetFirstConVar() = 0;\n\n    // Slot 28: GetNextConVar\n    virtual ConVar* GetNextConVar(ConVar* pPrev) = 0;\n};\n\n} // namespace cs2::interfaces\n\n#endif // CS2_INTERFACES_CVAR_H\n",
        "engine_client.h": "#ifndef CS2_INTERFACES_ENGINE_CLIENT_H\n#define CS2_INTERFACES_ENGINE_CLIENT_H\n\n#include <cstdint>\n#include <cstddef>\n#include \"../shared/math_types.h\"\n\nnamespace cs2::interfaces {\n\n/**\n * @brief Source 2 Engine to Client Interface (ISource2EngineToClient)\n * Token: \"Source2EngineToClient001\" in engine2.dll\n * VTable RVA: +0x5d5c38 (185 slots)\n */\nclass ISource2EngineToClient {\npublic:\n    virtual ~ISource2EngineToClient() = default;\n\n    // Slot 1..26: Standard IAppSystem methods\n    virtual bool Connect(void* /*pFactory*/) = 0;\n    virtual void Disconnect() = 0;\n    virtual void* QueryInterface(const char* /*pInterfaceName*/) = 0;\n    virtual int  Init() = 0;\n    virtual void Shutdown() = 0;\n\n    // Slot 27: IsInGame (RVA: +0x1bf4b0)\n    virtual bool IsInGame() = 0;\n\n    // Slot 28: IsConnected\n    virtual bool IsConnected() = 0;\n\n    // Slot 29: IsPaused\n    virtual bool IsPaused() = 0;\n\n    // Slot 30: GetMaxClients\n    virtual int  GetMaxClients() = 0;\n\n    // Slot 31: GetLevelName\n    virtual const char* GetLevelName() = 0;\n\n    // Slot 32: GetLevelNameShort\n    virtual const char* GetLevelNameShort() = 0;\n\n    // Slot 33: GetScreenSize\n    virtual void GetScreenSize(int& width, int& height) = 0;\n\n    // Slot 35: GetLocalPlayerSlot (0-based client index)\n    virtual int  GetLocalPlayerSlot() = 0;\n};\n\n/**\n * @brief Network Game Client Service (CNetworkGameClient)\n * Token: \"NetworkClientService_001\" in engine2.dll\n * VTable RVA: +0x613ac8 (64 slots)\n */\nclass CNetworkGameClient {\npublic:\n    virtual ~CNetworkGameClient() = default;\n\n    // Slot 23: IsConnected\n    virtual bool IsConnected() = 0;\n\n    // Slot 24: GetDeltaFrame\n    virtual int  GetDeltaFrame() = 0;\n\n    // Slot 25: GetServerTick\n    virtual int  GetServerTick() = 0;\n\n    // Slot 26: GetClientTick\n    virtual int  GetClientTick() = 0;\n\n    // Slot 27: GetLatency (round-trip time in seconds)\n    virtual float GetLatency() = 0;\n};\n\n/**\n * @brief Game Resource Service Client (CGameResourceService)\n * Token: \"GameResourceServiceClientV001\" in engine2.dll\n * VTable RVA: +0x60e7c8 (182 slots)\n */\nclass CGameResourceService {\npublic:\n    virtual ~CGameResourceService() = default;\n\n    // Slot 58: GetGameEntitySystem (client.dll + 0x271c8b8)\n    virtual void* GetGameEntitySystem() = 0;\n};\n\n} // namespace cs2::interfaces\n\n#endif // CS2_INTERFACES_ENGINE_CLIENT_H\n",
        "game_event_manager.h": "#ifndef CS2_INTERFACES_GAME_EVENT_MANAGER_H\n#define CS2_INTERFACES_GAME_EVENT_MANAGER_H\n\n#include <cstdint>\n\nnamespace cs2::interfaces {\n\nclass IGameEvent {\npublic:\n    virtual ~IGameEvent() = default;\n\n    // Slot 1: GetName (RVA: +0x009d9990)\n    virtual const char* GetName() const = 0;\n\n    // Slot 2: GetID\n    virtual int GetID() const = 0;\n\n    // Slot 3: IsReliable\n    virtual bool IsReliable() const = 0;\n\n    // Slot 4: IsLocal\n    virtual bool IsLocal() const = 0;\n\n    // Slot 5: IsEmpty\n    virtual bool IsEmpty(const char* keyName = nullptr) = 0;\n\n    // Slot 6: GetBool\n    virtual bool GetBool(const char* keyName = nullptr, bool defaultValue = false) = 0;\n\n    // Slot 7: GetInt\n    virtual int GetInt(const char* keyName = nullptr, int defaultValue = 0) = 0;\n\n    // Slot 8: GetUint64\n    virtual std::uint64_t GetUint64(const char* keyName = nullptr, std::uint64_t defaultValue = 0) = 0;\n\n    // Slot 9: GetFloat\n    virtual float GetFloat(const char* keyName = nullptr, float defaultValue = 0.0f) = 0;\n\n    // Slot 10: GetString\n    virtual const char* GetString(const char* keyName = nullptr, const char* defaultValue = \"\") = 0;\n};\n\nclass IGameEventListener2 {\npublic:\n    virtual ~IGameEventListener2() = default;\n    virtual void FireGameEvent(IGameEvent* pEvent) = 0;\n    virtual int  GetEventDebugID() { return 42; }\n};\n\n/**\n * @brief Source 2 Game Events Subsystem (IGameEventManager2)\n * Token: \"GAMEEVENTSMANAGER002\" in client.dll\n * Global Instance: client.dll + 0x2228E40 -> 0x22292C0\n * VTable: client.dll + 0x1C337A8 (16 slots)\n */\nclass IGameEventManager2 {\npublic:\n    virtual ~IGameEventManager2() = default;\n\n    // Slot 1: LoadEventsFromFile\n    virtual int LoadEventsFromFile(const char* filename) = 0;\n\n    // Slot 2: Reset\n    virtual void Reset() = 0;\n\n    // Slot 3: AddListener (RVA: +0x009cab60)\n    virtual bool AddListener(IGameEventListener2* listener, const char* name, bool bServerSide = false) = 0;\n\n    // Slot 4: FindListener (RVA: +0x009e2a20)\n    virtual bool FindListener(IGameEventListener2* listener, const char* name) = 0;\n\n    // Slot 5: RemoveListener (RVA: +0x00a02370)\n    virtual void RemoveListener(IGameEventListener2* listener) = 0;\n\n    // Slot 6: CreateEvent (RVA: +0x009d5440)\n    virtual IGameEvent* CreateEvent(const char* name, bool bForce = false, int* pCookie = nullptr) = 0;\n\n    // Slot 7: FireEvent (RVA: +0x009e3500)\n    virtual bool FireEvent(IGameEvent* event, bool bDontBroadcast = false) = 0;\n\n    // Slot 8: FireEventClientSide (RVA: +0x009e3790)\n    virtual bool FireEventClientSide(IGameEvent* event) = 0;\n\n    // Slot 9: DuplicateEvent (RVA: +0x009d9990)\n    virtual IGameEvent* DuplicateEvent(IGameEvent* event) = 0;\n\n    // Slot 10: FreeEvent (RVA: +0x009e3fe0)\n    virtual void FreeEvent(IGameEvent* event) = 0;\n};\n\n} // namespace cs2::interfaces\n\n#endif // CS2_INTERFACES_GAME_EVENT_MANAGER_H\n",
        "interfaces.h": "#ifndef CS2_INTERFACES_INTERFACES_H\n#define CS2_INTERFACES_INTERFACES_H\n\n#include <cstdint>\n#include <cstring>\n\nnamespace cs2::interfaces {\n\nusing InstantiateInterfaceFn = void* (*)();\n\n/**\n * @brief Source 2 Internal Interface Registry Node (InterfaceReg)\n * Singly-linked list node populated by DLL exports.\n * Size: 24 bytes (0x18) on x64.\n */\nstruct InterfaceReg {\n    InstantiateInterfaceFn m_CreateFn; // +0x00: Factory function returning interface instance\n    const char*            m_pName;    // +0x08: Null-terminated versioned token string\n    InterfaceReg*          m_pNext;    // +0x10: Next node in linked list\n};\nstatic_assert(sizeof(InterfaceReg) == 0x18, \"InterfaceReg must be 24 bytes (0x18)\");\n\nusing CreateInterfaceFn = void* (*)(const char* pName, int* pReturnCode);\n\n/**\n * @brief Traverses an InterfaceReg linked list to locate an interface by version token.\n */\ninline void* CaptureInterface(InterfaceReg* pHead, const char* pInterfaceName) noexcept {\n    if (!pHead || !pInterfaceName) return nullptr;\n    for (InterfaceReg* pCur = pHead; pCur; pCur = pCur->m_pNext) {\n        if (pCur->m_pName && std::strcmp(pCur->m_pName, pInterfaceName) == 0) {\n            return pCur->m_CreateFn ? pCur->m_CreateFn() : nullptr;\n        }\n    }\n    return nullptr;\n}\n\n} // namespace cs2::interfaces\n\n#endif // CS2_INTERFACES_INTERFACES_H\n",
        "schema_interface.h": "#ifndef CS2_INTERFACES_SCHEMA_INTERFACE_H\n#define CS2_INTERFACES_SCHEMA_INTERFACE_H\n\n#include <cstdint>\n#include <cstddef>\n#include \"../tier0/utl_string_token.h\"\n\nnamespace cs2::interfaces {\n\n#define CS2_PAD(bytes, name) private: [[maybe_unused]] std::uint8_t name[bytes]; public:\n\nstruct SchemaClassFieldData_t {\n    const char*   m_pszName{nullptr};        // +0x00: Field identifier string\n    void*         m_pType{nullptr};          // +0x08: Schema type descriptor\n    std::int32_t  m_nSingleInheritanceOffset{0}; // +0x10: Exact byte offset within class\n    std::int32_t  m_nMetadataSize{0};        // +0x14: Metadata attribute count\n    void*         m_pMetadata{nullptr};      // +0x18: Schema metadata array pointer\n};\nstatic_assert(sizeof(SchemaClassFieldData_t) == 0x20, \"SchemaClassFieldData_t must be 32 bytes (0x20)\");\n\nstruct CSchemaClassInfo {\n    void*                   m_pSelf{nullptr};         // +0x00\n    const char*             m_pszName{nullptr};       // +0x08: Class technical name\n    const char*             m_pszModuleName{nullptr}; // +0x10: Owning binary module name\n    std::int32_t            m_nSize{0};               // +0x18: Total instance byte size\n    std::int16_t            m_nFieldsCount{0};        // +0x1C: Field member count\n    CS2_PAD(0x0A, m_pad1e);\n    SchemaClassFieldData_t* m_pFields{nullptr};       // +0x28: Field descriptors array\n    CS2_PAD(0x38, m_pad30);\n};\nstatic_assert(sizeof(CSchemaClassInfo) == 0x68, \"CSchemaClassInfo must be 104 bytes (0x68)\");\n\nclass CSchemaSystemTypeScope {\npublic:\n    virtual ~CSchemaSystemTypeScope() = default;\n\n    // Slot 2: FindDeclaredClass (RVA: +0x00010380)\n    virtual CSchemaClassInfo* FindDeclaredClass(const char* pszClassName) = 0;\n};\n\n/**\n * @brief SchemaSystem Master Interface (CSchemaSystem)\n * Token: \"SchemaSystem_001\" in schemasystem.dll\n * VTable: 0x180058598 (222 slots)\n */\nclass CSchemaSystem {\npublic:\n    virtual ~CSchemaSystem() = default;\n\n    // Slot 13: FindTypeScopeForModule (RVA: +0x00013b80)\n    virtual CSchemaSystemTypeScope* FindTypeScopeForModule(const char* pszModuleName) = 0;\n};\n\n#undef CS2_PAD\n\n} // namespace cs2::interfaces\n\n#endif // CS2_INTERFACES_SCHEMA_INTERFACE_H\n",
        "sound_system.h": "#ifndef CS2_INTERFACES_SOUND_SYSTEM_H\n#define CS2_INTERFACES_SOUND_SYSTEM_H\n\n#include <cstdint>\n#include <cstddef>\n#include \"../shared/math_types.h\"\n#include \"../shared/entity_handle.h\"\n\nnamespace cs2::interfaces {\n\n#define CS2_PAD(bytes, name) private: [[maybe_unused]] std::uint8_t name[bytes]; public:\n\n/**\n * @brief Dispatch Sound Event Parameter Payload (StartSoundEventInfo_t)\n * Total Size: exactly 128 bytes (0x80).\n */\nstruct StartSoundEventInfo_t {\n    shared::Vector3D     m_vecOrigin{};          // +0x00: 3D spatial emitter coordinates\n    shared::QAngle       m_angAngles{};          // +0x0C: Spatial directional orientation\n    float                m_flVolume{ 1.0f };     // +0x18: Linear gain amplitude [0.0..1.0]\n    float                m_flPitch{ 1.0f };      // +0x1C: Frequency pitch shift factor\n    shared::CEntityHandle m_hEntity{};           // +0x20: Associated emitter entity handle\n    CS2_PAD(0x0C, m_pad24);                      // +0x24: Padding to 16-byte alignment\n    float                m_matSpatial[3][4]{};   // +0x30: 3x4 spatial coordinate transform\n    CS2_PAD(0x20, m_pad60);                      // +0x60: DSP runtime context payload\n};\nstatic_assert(sizeof(StartSoundEventInfo_t) == 0x80, \"StartSoundEventInfo_t must be 128 bytes (0x80)\");\n\n/**\n * @brief Source 2 Sound Operator Subsystem (ISoundOpSystem)\n * Token: \"SoundOpSystem001\" in soundsystem.dll\n * VTable: 0x1804AB140 (16 slots)\n */\nclass ISoundOpSystem {\npublic:\n    virtual ~ISoundOpSystem() = default;\n\n    // Slot 1..10: IAppSystem methods\n    virtual bool Connect(void* /*pFactory*/) = 0;\n    virtual void Disconnect() = 0;\n    virtual void* QueryInterface(const char* /*pInterfaceName*/) = 0;\n    virtual int  Init() = 0;\n    virtual void Shutdown() = 0;\n\n    // Slot 11: StartSoundEvent\n    virtual std::uint64_t StartSoundEvent(const char* pEventName, const StartSoundEventInfo_t* pInfo) = 0;\n\n    // Slot 12: StartSoundEventByHash\n    virtual std::uint64_t StartSoundEventByHash(std::uint32_t nEventHash, const StartSoundEventInfo_t* pInfo) = 0;\n\n    // Slot 13: StartSoundEventReliable\n    virtual std::uint64_t StartSoundEventReliable(std::uint32_t nEventHash, const StartSoundEventInfo_t* pInfo) = 0;\n\n    // Slot 14: StopSoundEvent\n    virtual void StopSoundEvent(std::uint64_t nGuid, float flFadeTime) = 0;\n\n    // Slot 15: SetSoundEventParam\n    virtual void SetSoundEventParam(std::uint64_t nGuid, const char* pParamName, float flValue) = 0;\n};\n\n#undef CS2_PAD\n\n} // namespace cs2::interfaces\n\n#endif // CS2_INTERFACES_SOUND_SYSTEM_H\n",
        "trace_manager.h": "#ifndef CS2_INTERFACES_TRACE_MANAGER_H\n#define CS2_INTERFACES_TRACE_MANAGER_H\n\n#include <cstdint>\n#include \"../shared/ray_trace.h\"\n\nnamespace cs2::interfaces {\n\n/**\n * @brief Spatial Query Master Interface (CGameTraceManager / IEngineTrace)\n * Global Instance in client.dll: +0x02229020 (VA: 0x182229020)\n * Static BSS Instance in client.dll: +0x0254cf30 (VA: 0x18254cf30)\n */\nclass CGameTraceManager {\npublic:\n    virtual ~CGameTraceManager() = default;\n\n    // Slot 1: ClipRayToEntity (RVA: +0x00a1b8a0, VA: 0x180a1b8a0)\n    virtual bool ClipRayToEntity(const shared::Ray_t* pRay, const shared::CTraceFilter* pFilter, void* pEntity, shared::GameTrace_t* pTrace) = 0;\n\n    // Slot 2: ClipRayToCollideable\n    virtual bool ClipRayToCollideable(const shared::Ray_t* pRay, const shared::CTraceFilter* pFilter, void* pCollide, shared::GameTrace_t* pTrace) = 0;\n\n    // Slot 3: TraceRay\n    virtual void TraceRay(const shared::Ray_t* pRay, const shared::CTraceFilter* pFilter, shared::GameTrace_t* pTrace) = 0;\n\n    // Slot 4: SetupTraceShape\n    virtual void SetupTraceShape(void* pShape, const shared::Ray_t* pRay) = 0;\n\n    // Slot 5: TraceShape (RVA: +0x00a1ae30, VA: 0x180a1ae30)\n    virtual bool TraceShape(const shared::Ray_t* pRay, const shared::CTraceFilter* pFilter, shared::GameTrace_t* pTrace) = 0;\n};\n\n} // namespace cs2::interfaces\n\n#endif // CS2_INTERFACES_TRACE_MANAGER_H\n"
      }
    },
    {
      "module": "materialsystem2.dll",
      "directory": "game/materialsystem2",
      "standard": "C++20 (/std:c++20 /W4)",
      "files": {
        "material_system2.cpp": "#include \"material_system2.h\"\n\nnamespace cs2::materialsystem2 {\n\n// Emulated material descriptor for tooling & standalone tests\nclass CMaterial2Standalone : public CMaterial2 {\npublic:\n    const char* m_pName{\"materials/models/player/ctm_sas.vmat\"};\n    const char* m_pShader{\"csgo_character.vfx\"};\n\n    const char* GetName() const override { return m_pName; }\n    void GetPath(void* /*pBufferString*/) const override {}\n    const char* GetShaderName() const override { return m_pShader; }\n    std::uint8_t GetFlags() const override { return 0; }\n    void* GetMaterialData() const override { return nullptr; }\n    std::int32_t GetMaterialId() const override { return 1; }\n    void* GetShaderBinding() override { return nullptr; }\n    void IncrementRefCount() override {}\n};\n\nstatic CMaterial2Standalone s_DefaultMaterial;\n\n} // namespace cs2::materialsystem2\n",
        "material_system2.h": "#ifndef CS2_MATERIALSYSTEM2_H\n#define CS2_MATERIALSYSTEM2_H\n\n#include <cstdint>\n#include <cstddef>\n\nnamespace cs2::materialsystem2 {\n\n/**\n * @brief Material Instance Runtime Interface (CMaterial2)\n * VTable: materialsystem2.dll + 0x129ae0 (25 methods)\n */\nclass CMaterial2 {\npublic:\n    virtual ~CMaterial2() = default;\n\n    // Slot 1: GetName (RVA: +0x0000b350)\n    virtual const char* GetName() const = 0;\n\n    // Slot 2: GetPath (RVA: +0x0000b370)\n    virtual void GetPath(void* pBufferString) const = 0;\n\n    // Slot 3: GetShaderName (RVA: +0x0000b5e0)\n    virtual const char* GetShaderName() const = 0;\n\n    // Slot 4: GetFlags (RVA: +0x0000a100)\n    virtual std::uint8_t GetFlags() const = 0;\n\n    // Slot 7: GetMaterialData (RVA: +0x0000ba60)\n    virtual void* GetMaterialData() const = 0;\n\n    // Slot 25: GetMaterialId (RVA: +0x0000b880)\n    virtual std::int32_t GetMaterialId() const = 0;\n\n    // Slot 26: GetShaderBinding (RVA: +0x0001b2d0)\n    virtual void* GetShaderBinding() = 0;\n\n    // Slot 29: IncrementRefCount (RVA: +0x0000b890)\n    virtual void IncrementRefCount() = 0;\n};\nstatic_assert(sizeof(CMaterial2) == 8, \"CMaterial2 interface must be 8 bytes (vptr)\");\n\n/**\n * @brief Source 2 Material System Interface (IMaterialSystem2)\n * Token: \"VMaterialSystem2_001\" in materialsystem2.dll\n * VTable: +0x12d920 (57 slots)\n */\nclass IMaterialSystem2 {\npublic:\n    virtual ~IMaterialSystem2() = default;\n\n    // Slot 14: FindOrCreateMaterialFromResource\n    virtual CMaterial2* FindOrCreateMaterialFromResource(const char* pMaterialResourceName) = 0;\n\n    // Slot 24: CreateMaterial\n    virtual CMaterial2* CreateMaterial(const char* pMaterialName, void* pKeyValues) = 0;\n};\n\n} // namespace cs2::materialsystem2\n\n#endif // CS2_MATERIALSYSTEM2_H\n"
      }
    },
    {
      "module": "navsystem.dll",
      "directory": "game/navsystem",
      "standard": "C++20 (/std:c++20 /W4)",
      "files": {
        "navmesh.cpp": "#include \"navmesh.h\"\n#include <cstring>\n#include <algorithm>\n\nnamespace cs2::navsystem {\n\n// -----------------------------------------------------------------------------\n// Buffer Reader Helper for Binary Deserialization\n// -----------------------------------------------------------------------------\nclass BufferReader {\npublic:\n    BufferReader(const uint8_t* data, size_t size) : m_data(data), m_size(size), m_pos(0) {}\n\n    [[nodiscard]] bool HasBytes(size_t n) const noexcept {\n        return m_pos + n <= m_size;\n    }\n\n    template <typename T>\n    bool Read(T& outVal) noexcept {\n        if (!HasBytes(sizeof(T))) return false;\n        std::memcpy(&outVal, m_data + m_pos, sizeof(T));\n        m_pos += sizeof(T);\n        return true;\n    }\n\n    bool ReadBytes(void* outBuf, size_t n) noexcept {\n        if (!HasBytes(n)) return false;\n        std::memcpy(outBuf, m_data + m_pos, n);\n        m_pos += n;\n        return true;\n    }\n\n    bool ReadVector3(Vector3& outVec) noexcept {\n        return Read(outVec.x) && Read(outVec.y) && Read(outVec.z);\n    }\n\n    bool ReadString(std::string& outStr, size_t length) {\n        if (!HasBytes(length)) return false;\n        outStr.assign(reinterpret_cast<const char*>(m_data + m_pos), length);\n        m_pos += length;\n        return true;\n    }\n\n    [[nodiscard]] size_t GetPos() const noexcept { return m_pos; }\n    void Seek(size_t pos) noexcept { m_pos = std::min(pos, m_size); }\n\nprivate:\n    const uint8_t* m_data{nullptr};\n    size_t m_size{0};\n    size_t m_pos{0};\n};\n\n// -----------------------------------------------------------------------------\n// CNavArea Methods\n// -----------------------------------------------------------------------------\nbool CNavArea::Contains(const Vector3& pos) const noexcept {\n    // 1. Check AABB bounding extents\n    if (pos.x < m_nwCorner.x || pos.x > m_seCorner.x ||\n        pos.y < m_nwCorner.y || pos.y > m_seCorner.y) {\n        return false;\n    }\n\n    // 2. If arbitrary polygon vertices exist, perform point-in-polygon test\n    if (m_polyPoints.size() >= 3) {\n        bool inside = false;\n        size_t n = m_polyPoints.size();\n        for (size_t i = 0, j = n - 1; i < n; j = i++) {\n            const auto& vi = m_polyPoints[i];\n            const auto& vj = m_polyPoints[j];\n            if (((vi.y > pos.y) != (vj.y > pos.y)) &&\n                (pos.x < (vj.x - vi.x) * (pos.y - vi.y) / (vj.y - vi.y) + vi.x)) {\n                inside = !inside;\n            }\n        }\n        return inside;\n    }\n\n    return true;\n}\n\nfloat CNavArea::ComputeZ(float x, float y) const noexcept {\n    float width = m_seCorner.x - m_nwCorner.x;\n    float height = m_seCorner.y - m_nwCorner.y;\n\n    if (width <= 0.001f || height <= 0.001f) {\n        return m_nwCorner.z;\n    }\n\n    float u = std::clamp((x - m_nwCorner.x) / width, 0.0f, 1.0f);\n    float v = std::clamp((y - m_nwCorner.y) / height, 0.0f, 1.0f);\n\n    // Bilinear interpolation across the 4 corners:\n    // NW = m_nwCorner.z, NE = m_neZ, SW = m_swZ, SE = m_seCorner.z\n    float zNorth = m_nwCorner.z + u * (m_neZ - m_nwCorner.z);\n    float zSouth = m_swZ + u * (m_seCorner.z - m_swZ);\n    return zNorth + v * (zSouth - zNorth);\n}\n\n// -----------------------------------------------------------------------------\n// CNavPathCost Methods\n// -----------------------------------------------------------------------------\nfloat CNavPathCost::GroundCost(const CNavArea* from, const CNavArea* to, float dist) const {\n    if (!from || !to) return -1.0f;\n    if (IsAreaBlocked(to)) return -1.0f;\n\n    float cost = dist;\n\n    // Apply area attribute modifiers\n    if (to->HasFlag(NAV_MESH_CROUCH)) {\n        cost *= 1.35f; // Slower movement in crouch areas\n    }\n    if (to->HasFlag(NAV_MESH_JUMP)) {\n        cost += 50.0f; // Jump traversal penalty\n    }\n    if (to->HasFlag(NAV_MESH_AVOID)) {\n        cost *= 3.0f;  // Heavy avoid penalty\n    }\n\n    return cost;\n}\n\nfloat CNavPathCost::LadderCost(const CNavLadder* ladder) const {\n    if (!ladder || !m_bAllowLadders) return -1.0f;\n    return ladder->m_length * 1.5f; // Climbing is slower than running\n}\n\nbool CNavPathCost::IsAreaBlocked(const CNavArea* area) const {\n    if (!area) return true;\n\n    // Exclude blocked or transient locked areas\n    if (m_navHull >= 0) {\n        // Hull-specific compatibility checks\n    }\n\n    return false;\n}\n\n// -----------------------------------------------------------------------------\n// CNavMesh Parsing & Search Methods\n// -----------------------------------------------------------------------------\nbool CNavMesh::LoadFromBuffer(const uint8_t* data, size_t dataSize) {\n    if (!data || dataSize < 16) return false;\n\n    BufferReader reader(data, dataSize);\n\n    // 1. Header & Magic Verification\n    if (!reader.Read(m_magic) || m_magic != NAV_MAGIC) {\n        return false;\n    }\n\n    if (!reader.Read(m_version) || m_version > NAV_VERSION) {\n        return false;\n    }\n\n    if (m_version > 9) {\n        if (!reader.Read(m_subVersion)) return false;\n    }\n\n    if (m_version >= 4) {\n        if (!reader.Read(m_bspSize)) return false;\n    }\n\n    if (m_version >= 14) {\n        uint8_t analyzedByte = 0;\n        if (!reader.Read(analyzedByte)) return false;\n        m_isAnalyzed = (analyzedByte != 0);\n    }\n\n    // 2. Directory of Place Names\n    if (m_version >= 5) {\n        uint16_t placeCount = 0;\n        if (!reader.Read(placeCount)) return false;\n\n        m_places.clear();\n        m_places.reserve(placeCount);\n\n        for (uint16_t i = 0; i < placeCount; ++i) {\n            uint16_t strLen = 0;\n            if (!reader.Read(strLen)) return false;\n            std::string placeStr;\n            if (!reader.ReadString(placeStr, strLen)) return false;\n            m_places.push_back(std::move(placeStr));\n        }\n    }\n\n    // 3. Navigation Areas (CNavArea array)\n    uint32_t areaCount = 0;\n    if (!reader.Read(areaCount)) return false;\n\n    m_areas.clear();\n    m_areas.reserve(areaCount);\n    m_areaIndexMap.clear();\n\n    for (uint32_t i = 0; i < areaCount; ++i) {\n        CNavArea area;\n        if (!reader.Read(area.m_id)) return false;\n\n        // Flags\n        if (m_version < 9) {\n            uint8_t f = 0;\n            if (!reader.Read(f)) return false;\n            area.m_flags = f;\n        } else if (m_version < 13) {\n            uint16_t f = 0;\n            if (!reader.Read(f)) return false;\n            area.m_flags = f;\n        } else {\n            if (!reader.Read(area.m_flags)) return false;\n        }\n\n        // Bounding extents\n        if (m_version < 20) {\n            if (!reader.ReadVector3(area.m_nwCorner)) return false;\n            if (!reader.ReadVector3(area.m_seCorner)) return false;\n            if (!reader.Read(area.m_neZ)) return false;\n            if (!reader.Read(area.m_swZ)) return false;\n        } else {\n            uint32_t polyVertCount = 0;\n            if (!reader.Read(polyVertCount)) return false;\n\n            if (m_version < 31 && polyVertCount > 0 && polyVertCount < 100) {\n                area.m_polyPoints.resize(polyVertCount);\n                for (uint32_t v = 0; v < polyVertCount; ++v) {\n                    if (!reader.ReadVector3(area.m_polyPoints[v])) return false;\n                }\n                // Derive AABB from poly vertices\n                if (!area.m_polyPoints.empty()) {\n                    area.m_nwCorner = area.m_polyPoints[0];\n                    area.m_seCorner = area.m_polyPoints[0];\n                    for (const auto& pt : area.m_polyPoints) {\n                        area.m_nwCorner.x = std::min(area.m_nwCorner.x, pt.x);\n                        area.m_nwCorner.y = std::min(area.m_nwCorner.y, pt.y);\n                        area.m_nwCorner.z = std::min(area.m_nwCorner.z, pt.z);\n                        area.m_seCorner.x = std::max(area.m_seCorner.x, pt.x);\n                        area.m_seCorner.y = std::max(area.m_seCorner.y, pt.y);\n                        area.m_seCorner.z = std::max(area.m_seCorner.z, pt.z);\n                    }\n                    area.m_neZ = area.m_nwCorner.z;\n                    area.m_swZ = area.m_seCorner.z;\n                }\n            } else {\n                if (!reader.ReadVector3(area.m_nwCorner)) return false;\n                if (!reader.ReadVector3(area.m_seCorner)) return false;\n                if (!reader.Read(area.m_neZ)) return false;\n                if (!reader.Read(area.m_swZ)) return false;\n            }\n        }\n\n        // Connections in 4 cardinal directions (North, East, South, West)\n        for (uint32_t dir = 0; dir < NUM_DIRECTIONS; ++dir) {\n            uint32_t connCount = 0;\n            if (!reader.Read(connCount)) return false;\n\n            area.m_adjacentAreas[dir].reserve(connCount);\n            for (uint32_t c = 0; c < connCount; ++c) {\n                NavConnect_t conn;\n                if (!reader.Read(conn.m_areaId)) return false;\n                if (m_version >= 21) {\n                    if (!reader.Read(conn.m_edgeId)) return false;\n                }\n                area.m_adjacentAreas[dir].push_back(conn);\n            }\n        }\n\n        // Hiding spots\n        if (m_version >= 2) {\n            uint8_t hidingSpotCount = 0;\n            if (!reader.Read(hidingSpotCount)) return false;\n\n            area.m_hidingSpots.reserve(hidingSpotCount);\n            for (uint8_t h = 0; h < hidingSpotCount; ++h) {\n                HidingSpot spot;\n                if (!reader.Read(spot.m_id)) return false;\n                if (!reader.ReadVector3(spot.m_pos)) return false;\n                if (!reader.Read(spot.m_flags)) return false;\n                area.m_hidingSpots.push_back(spot);\n            }\n        }\n\n        // Ladder connections\n        if (m_version >= 6) {\n            for (uint32_t ladderDir = 0; ladderDir < NUM_LADDER_DIRECTIONS; ++ladderDir) {\n                uint32_t ladderCount = 0;\n                if (!reader.Read(ladderCount)) return false;\n\n                area.m_ladderConnections[ladderDir].reserve(ladderCount);\n                for (uint32_t l = 0; l < ladderCount; ++l) {\n                    uint32_t ladderId = 0;\n                    if (!reader.Read(ladderId)) return false;\n                    area.m_ladderConnections[ladderDir].push_back(ladderId);\n                }\n            }\n        }\n\n        // Place ID\n        if (m_version >= 5 && m_version < 23) {\n            uint16_t pId = 0;\n            if (!reader.Read(pId)) return false;\n            area.m_placeId = pId;\n        }\n\n        m_areaIndexMap[area.m_id] = m_areas.size();\n        m_areas.push_back(std::move(area));\n    }\n\n    // 4. Navigation Ladders (CNavLadder array)\n    if (m_version >= 6) {\n        uint32_t ladderCount = 0;\n        if (!reader.Read(ladderCount)) return false;\n\n        m_ladders.clear();\n        m_ladders.reserve(ladderCount);\n        m_ladderIndexMap.clear();\n\n        for (uint32_t i = 0; i < ladderCount; ++i) {\n            CNavLadder ladder;\n            if (!reader.Read(ladder.m_id)) return false;\n            if (!reader.Read(ladder.m_width)) return false;\n            if (!reader.ReadVector3(ladder.m_top)) return false;\n            if (!reader.ReadVector3(ladder.m_bottom)) return false;\n            if (!reader.Read(ladder.m_length)) return false;\n\n            uint32_t dirVal = 0;\n            if (!reader.Read(dirVal)) return false;\n            ladder.m_dir = static_cast<NavDirType>(dirVal % NUM_DIRECTIONS);\n\n            // Compute ladder directional unit normal\n            switch (ladder.m_dir) {\n                case NORTH: ladder.m_normal = Vector3{ 0.0f, -1.0f, 0.0f}; break;\n                case EAST:  ladder.m_normal = Vector3{ 1.0f,  0.0f, 0.0f}; break;\n                case SOUTH: ladder.m_normal = Vector3{ 0.0f,  1.0f, 0.0f}; break;\n                case WEST:  ladder.m_normal = Vector3{-1.0f,  0.0f, 0.0f}; break;\n                default:    ladder.m_normal = Vector3{ 0.0f,  0.0f, 1.0f}; break;\n            }\n\n            // Area connections\n            if (!reader.Read(ladder.m_topForwardAreaId)) return false;\n            if (!reader.Read(ladder.m_topLeftAreaId)) return false;\n            if (!reader.Read(ladder.m_topRightAreaId)) return false;\n            if (!reader.Read(ladder.m_topBehindAreaId)) return false;\n            if (!reader.Read(ladder.m_bottomAreaId)) return false;\n\n            if (m_version >= 33) {\n                if (!reader.Read(ladder.m_bottomLeftAreaId)) return false;\n                if (!reader.Read(ladder.m_bottomRightAreaId)) return false;\n            }\n\n            m_ladderIndexMap[ladder.m_id] = m_ladders.size();\n            m_ladders.push_back(std::move(ladder));\n        }\n    }\n\n    return true;\n}\n\nCNavArea* CNavMesh::GetAreaByID(uint32_t id) noexcept {\n    auto it = m_areaIndexMap.find(id);\n    return (it != m_areaIndexMap.end()) ? &m_areas[it->second] : nullptr;\n}\n\nconst CNavArea* CNavMesh::GetAreaByID(uint32_t id) const noexcept {\n    auto it = m_areaIndexMap.find(id);\n    return (it != m_areaIndexMap.end()) ? &m_areas[it->second] : nullptr;\n}\n\nCNavLadder* CNavMesh::GetLadderByID(uint32_t id) noexcept {\n    auto it = m_ladderIndexMap.find(id);\n    return (it != m_ladderIndexMap.end()) ? &m_ladders[it->second] : nullptr;\n}\n\nconst CNavLadder* CNavMesh::GetLadderByID(uint32_t id) const noexcept {\n    auto it = m_ladderIndexMap.find(id);\n    return (it != m_ladderIndexMap.end()) ? &m_ladders[it->second] : nullptr;\n}\n\nCNavArea* CNavMesh::GetNearestNavArea(\n    const Vector3& pos,\n    float maxDistance,\n    uint32_t excludedFlags) noexcept {\n\n    CNavArea* bestArea = nullptr;\n    float bestDistSq = maxDistance * maxDistance;\n\n    for (auto& area : m_areas) {\n        if (excludedFlags != 0 && (area.m_flags & excludedFlags) != 0) {\n            continue;\n        }\n\n        if (area.Contains(pos)) {\n            float areaZ = area.ComputeZ(pos.x, pos.y);\n            float dz = std::abs(pos.z - areaZ);\n            if (dz <= 71.0f) { // Source 2 player eye/origin tolerance\n                return &area;\n            }\n        }\n\n        Vector3 center = area.GetCenter();\n        float distSq = (pos - center).LengthSqr();\n        if (distSq < bestDistSq) {\n            bestDistSq = distSq;\n            bestArea = &area;\n        }\n    }\n\n    return bestArea;\n}\n\nfloat CNavMesh::ComputeHeuristicDistance(\n    const Vector3& from,\n    const Vector3& goal,\n    float stepHeight) noexcept {\n\n    float dx = goal.x - from.x;\n    float dy = goal.y - from.y;\n    float rawDz = std::abs(goal.z - from.z);\n\n    // Source 2 elevation penalty:\n    // Vertical delta beyond standard step height (18 units * 2 = 36 units)\n    // is penalized with a 3.0x scaling factor in navsystem.dll.\n    float maxStepClimb = stepHeight * 2.0f;\n    float dzClamped = std::min(rawDz, maxStepClimb);\n    float dzPenalized = (rawDz - dzClamped) * 3.0f + dzClamped;\n\n    return std::sqrt(dx * dx + dy * dy + dzPenalized * dzPenalized);\n}\n\nbool CNavMesh::FindPath(\n    const Vector3& startPos,\n    const Vector3& goalPos,\n    CNavArea* startArea,\n    CNavArea* goalArea,\n    const INavPathCost& costFunc,\n    std::vector<Vector3>& outPathWaypoints,\n    float maxPathLength,\n    float inadmissibleHeuristicFactor) {\n\n    outPathWaypoints.clear();\n    if (!startArea) startArea = GetNearestNavArea(startPos);\n    if (!goalArea) goalArea = GetNearestNavArea(goalPos);\n\n    if (!startArea || !goalArea) {\n        return false;\n    }\n\n    // Trivial case: already in goal area\n    if (startArea == goalArea) {\n        outPathWaypoints.push_back(startPos);\n        outPathWaypoints.push_back(goalPos);\n        return true;\n    }\n\n    // Node allocator map\n    std::unordered_map<uint32_t, std::unique_ptr<AStarNode>> nodePool;\n    auto getNode = [&](CNavArea* area) -> AStarNode* {\n        auto it = nodePool.find(area->m_id);\n        if (it != nodePool.end()) return it->second.get();\n        auto node = std::make_unique<AStarNode>();\n        node->m_area = area;\n        AStarNode* ptr = node.get();\n        nodePool[area->m_id] = std::move(node);\n        return ptr;\n    };\n\n    std::priority_queue<AStarNode*, std::vector<AStarNode*>, AStarNode::Compare> openList;\n\n    AStarNode* startNode = getNode(startArea);\n    startNode->m_gCost = 0.0f;\n    startNode->m_hCost = ComputeHeuristicDistance(startPos, goalPos) * inadmissibleHeuristicFactor;\n    startNode->m_totalCost = startNode->m_gCost + startNode->m_hCost;\n    startNode->m_open = true;\n\n    openList.push(startNode);\n    AStarNode* goalNode = nullptr;\n\n    while (!openList.empty()) {\n        AStarNode* current = openList.top();\n        openList.pop();\n\n        if (current->m_closed) continue;\n        current->m_open = false;\n        current->m_closed = true;\n\n        if (current->m_area == goalArea) {\n            goalNode = current;\n            break;\n        }\n\n        if (current->m_gCost > maxPathLength) {\n            continue;\n        }\n\n        Vector3 currentPos = (current->m_parent == nullptr) ? startPos : current->m_area->GetCenter();\n\n        // 1. Expand cardinal adjacent area connections\n        for (uint32_t dir = 0; dir < NUM_DIRECTIONS; ++dir) {\n            for (const auto& conn : current->m_area->m_adjacentAreas[dir]) {\n                CNavArea* neighborArea = GetAreaByID(conn.m_areaId);\n                if (!neighborArea) continue;\n\n                AStarNode* neighborNode = getNode(neighborArea);\n                if (neighborNode->m_closed) continue;\n\n                Vector3 neighborPos = (neighborArea == goalArea) ? goalPos : neighborArea->GetCenter();\n                float dist = currentPos.DistTo(neighborPos);\n\n                float traversalCost = costFunc.GroundCost(current->m_area, neighborArea, dist);\n                if (traversalCost < 0.0f) continue; // Obstacle / blocked\n\n                float tentativeG = current->m_gCost + traversalCost;\n\n                if (!neighborNode->m_open || tentativeG < neighborNode->m_gCost) {\n                    neighborNode->m_parent = current;\n                    neighborNode->m_ladder = nullptr;\n                    neighborNode->m_gCost = tentativeG;\n                    neighborNode->m_hCost = ComputeHeuristicDistance(neighborPos, goalPos) * inadmissibleHeuristicFactor;\n                    neighborNode->m_totalCost = neighborNode->m_gCost + neighborNode->m_hCost;\n\n                    if (!neighborNode->m_open) {\n                        neighborNode->m_open = true;\n                        openList.push(neighborNode);\n                    }\n                }\n            }\n        }\n\n        // 2. Expand ladder connections\n        if (costFunc.AllowLadders()) {\n            for (uint32_t ladderDir = 0; ladderDir < NUM_LADDER_DIRECTIONS; ++ladderDir) {\n                for (uint32_t ladderId : current->m_area->m_ladderConnections[ladderDir]) {\n                    const CNavLadder* ladder = GetLadderByID(ladderId);\n                    if (!ladder) continue;\n\n                    // Ladder leads to target area (top or bottom)\n                    uint32_t targetAreaIds[2] = {ladder->m_topForwardAreaId, ladder->m_bottomAreaId};\n                    for (uint32_t targetId : targetAreaIds) {\n                        if (targetId == 0 || targetId == current->m_area->m_id) continue;\n\n                        CNavArea* ladderTargetArea = GetAreaByID(targetId);\n                        if (!ladderTargetArea) continue;\n\n                        AStarNode* targetNode = getNode(ladderTargetArea);\n                        if (targetNode->m_closed) continue;\n\n                        float ladderCost = costFunc.LadderCost(ladder);\n                        if (ladderCost < 0.0f) continue;\n\n                        float tentativeG = current->m_gCost + ladderCost;\n\n                        if (!targetNode->m_open || tentativeG < targetNode->m_gCost) {\n                            targetNode->m_parent = current;\n                            targetNode->m_ladder = ladder;\n                            targetNode->m_gCost = tentativeG;\n                            Vector3 targetPos = (ladderTargetArea == goalArea) ? goalPos : ladderTargetArea->GetCenter();\n                            targetNode->m_hCost = ComputeHeuristicDistance(targetPos, goalPos) * inadmissibleHeuristicFactor;\n                            targetNode->m_totalCost = targetNode->m_gCost + targetNode->m_hCost;\n\n                            if (!targetNode->m_open) {\n                                targetNode->m_open = true;\n                                openList.push(targetNode);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    if (!goalNode) {\n        return false;\n    }\n\n    // Trace path back from goalNode to start\n    std::vector<Vector3> reversePath;\n    reversePath.push_back(goalPos);\n\n    for (AStarNode* curr = goalNode; curr != nullptr; curr = curr->m_parent) {\n        if (curr->m_ladder != nullptr) {\n            // Include ladder top and bottom waypoints for vertical climbing\n            reversePath.push_back(curr->m_ladder->m_top);\n            reversePath.push_back(curr->m_ladder->m_bottom);\n        } else if (curr != goalNode && curr != startNode) {\n            reversePath.push_back(curr->m_area->GetCenter());\n        }\n    }\n    reversePath.push_back(startPos);\n\n    std::reverse(reversePath.begin(), reversePath.end());\n    outPathWaypoints = std::move(reversePath);\n\n    return true;\n}\n\n} // namespace cs2::navsystem\n",
        "navmesh.h": "#ifndef CS2_NAVSYSTEM_NAVMESH_H\n#define CS2_NAVSYSTEM_NAVMESH_H\n\n#include <cstdint>\n#include <cmath>\n#include <vector>\n#include <array>\n#include <string>\n#include <memory>\n#include <queue>\n#include <unordered_map>\n#include <limits>\n#include <algorithm>\n\nnamespace cs2::navsystem {\n\n// Source 2 Navigation Mesh Magic Identifier (0xFEEDFACE)\nconstexpr uint32_t NAV_MAGIC = 0xFEEDFACE;\nconstexpr uint32_t NAV_VERSION = 36; // Maximum supported in CS2 (0x24)\nconstexpr uint32_t NAV_SUBVERSION = 2;\n\n// Cardinal traversal directions\nenum NavDirType : uint32_t {\n    NORTH = 0,\n    EAST = 1,\n    SOUTH = 2,\n    WEST = 3,\n    NUM_DIRECTIONS = 4\n};\n\n// Ladder traversal directions\nenum NavLadderDirType : uint32_t {\n    LADDER_UP = 0,\n    LADDER_DOWN = 1,\n    NUM_LADDER_DIRECTIONS = 2\n};\n\n// Area navigational attribute flags\nenum NavAreaFlags : uint32_t {\n    NAV_MESH_INVALID        = 0,\n    NAV_MESH_JUMP           = (1 << 1),   // 0x00000002: Area requires jump\n    NAV_MESH_PRECISE        = (1 << 2),   // 0x00000004: Precise positioning (no shortcutting)\n    NAV_MESH_NO_JUMP        = (1 << 3),   // 0x00000008: Inhibits bot jumping\n    NAV_MESH_STOP           = (1 << 4),   // 0x00000010: Bot must stop briefly\n    NAV_MESH_RUN            = (1 << 5),   // 0x00000020: Bot must run through\n    NAV_MESH_WALK           = (1 << 6),   // 0x00000040: Bot must walk through\n    NAV_MESH_AVOID          = (1 << 7),   // 0x00000080: Avoid area unless necessary\n    NAV_MESH_TRANSIENT      = (1 << 8),   // 0x00000100: Dynamic/changing state (doors, breakables)\n    NAV_MESH_DONT_HIDE      = (1 << 9),   // 0x00000200: Bots cannot hide here\n    NAV_MESH_STAND          = (1 << 10),  // 0x00000400: Bots must stand (cannot crouch)\n    NAV_MESH_NO_HOSTAGES    = (1 << 11),  // 0x00000800: Hostages excluded from entry\n    NAV_MESH_STAIRS         = (1 << 12),  // 0x00001000: Staircase navigation\n    NAV_MESH_OBSTACLE_TOP   = (1 << 13),  // 0x00002000: Mantle/obstacle top\n    NAV_MESH_CLIFF          = (1 << 14),  // 0x00004000: Edge cliff drop-off\n    NAV_MESH_CROUCH         = (1 << 16),  // 0x00010000: Must crouch\n    NAV_MESH_CRAWL          = (1 << 18),  // 0x00040000: Must crawl (Source 2 addition)\n    NAV_MESH_FIRST_CUSTOM   = (1 << 19)   // 0x00080000: Game-specific markup boundary\n};\n\n// Tactical hiding spot attributes\nenum HidingSpotFlags : uint8_t {\n    HIDING_SPOT_IN_COVER      = (1 << 0), // 0x01: High cover\n    HIDING_SPOT_GOOD_SNIPER   = (1 << 1), // 0x02: Sniper vantage point\n    HIDING_SPOT_IDEAL_SNIPER  = (1 << 2), // 0x04: Optimum sniper line of sight\n    HIDING_SPOT_EXPOSED       = (1 << 3)  // 0x08: Exposed hiding spot\n};\n\n// 3D Cartesian Coordinate Vector\nstruct Vector3 {\n    float x{0.0f}, y{0.0f}, z{0.0f};\n\n    constexpr Vector3() noexcept = default;\n    constexpr Vector3(float x_, float y_, float z_) noexcept : x(x_), y(y_), z(z_) {}\n\n    Vector3 operator+(const Vector3& o) const noexcept { return {x + o.x, y + o.y, z + o.z}; }\n    Vector3 operator-(const Vector3& o) const noexcept { return {x - o.x, y - o.y, z - o.z}; }\n    Vector3 operator*(float s) const noexcept { return {x * s, y * s, z * s}; }\n    Vector3 operator/(float s) const noexcept { return {x / s, y / s, z / s}; }\n\n    [[nodiscard]] float Dot(const Vector3& o) const noexcept { return x * o.x + y * o.y + z * o.z; }\n    [[nodiscard]] float LengthSqr() const noexcept { return Dot(*this); }\n    [[nodiscard]] float Length() const noexcept { return std::sqrt(LengthSqr()); }\n    [[nodiscard]] float DistTo(const Vector3& o) const noexcept { return (*this - o).Length(); }\n\n    [[nodiscard]] Vector3 Normalized() const noexcept {\n        float l = Length();\n        return l > 1e-6f ? (*this) * (1.0f / l) : Vector3{0.0f, 0.0f, 0.0f};\n    }\n};\n\n// Tactical cover marker within a CNavArea\nstruct HidingSpot {\n    uint32_t m_id{0};\n    Vector3  m_pos{0.0f, 0.0f, 0.0f};\n    uint8_t  m_flags{0};\n};\n\n// Directional connection from one area to another\nstruct NavConnect_t {\n    uint32_t m_areaId{0};\n    uint32_t m_edgeId{0};\n};\n\n// Ladder structure in navigation mesh\nstruct CNavLadder {\n    uint32_t m_id{0};\n    float    m_width{0.0f};\n    Vector3  m_top{0.0f, 0.0f, 0.0f};\n    Vector3  m_bottom{0.0f, 0.0f, 0.0f};\n    float    m_length{0.0f};\n    NavDirType m_dir{NORTH};\n    Vector3  m_normal{0.0f, 0.0f, 0.0f};\n\n    // Connected area IDs\n    uint32_t m_topForwardAreaId{0};\n    uint32_t m_topLeftAreaId{0};\n    uint32_t m_topRightAreaId{0};\n    uint32_t m_topBehindAreaId{0};\n    uint32_t m_bottomAreaId{0};\n    uint32_t m_bottomLeftAreaId{0};\n    uint32_t m_bottomRightAreaId{0};\n};\n\n// Single convex polygon region in the navigation mesh\nclass CNavArea {\npublic:\n    uint32_t m_id{0};\n    uint32_t m_flags{0};\n    uint8_t  m_lightIntensity{0};\n    Vector3  m_nwCorner{0.0f, 0.0f, 0.0f};\n    Vector3  m_seCorner{0.0f, 0.0f, 0.0f};\n    float    m_neZ{0.0f};\n    float    m_swZ{0.0f};\n    uint32_t m_placeId{0};\n\n    // Source 2 arbitrary polygon vertices (when present)\n    std::vector<Vector3> m_polyPoints;\n\n    // Outgoing directional connections (North, East, South, West)\n    std::array<std::vector<NavConnect_t>, NUM_DIRECTIONS> m_adjacentAreas;\n\n    // Tactical hiding spots located in this area\n    std::vector<HidingSpot> m_hidingSpots;\n\n    // Ladder references (LADDER_UP, LADDER_DOWN)\n    std::array<std::vector<uint32_t>, NUM_LADDER_DIRECTIONS> m_ladderConnections;\n\n    [[nodiscard]] Vector3 GetCenter() const noexcept {\n        return (m_nwCorner + m_seCorner) * 0.5f;\n    }\n\n    [[nodiscard]] bool Contains(const Vector3& pos) const noexcept;\n    [[nodiscard]] float ComputeZ(float x, float y) const noexcept;\n    [[nodiscard]] bool HasFlag(uint32_t flag) const noexcept { return (m_flags & flag) != 0; }\n};\n\n// Abstract path traversal cost functor interface (INavPathCost)\nclass INavPathCost {\npublic:\n    virtual ~INavPathCost() = default;\n    virtual float GroundCost(const CNavArea* from, const CNavArea* to, float dist) const = 0;\n    virtual float LadderCost(const CNavLadder* ladder) const = 0;\n    virtual bool  IsAreaBlocked(const CNavArea* area) const = 0;\n    virtual bool  AllowLadders() const = 0;\n\n    int32_t m_navHull{-1}; // Compatible agent hull index (-1 = any)\n};\n\n// Reconstructed clean-room CNavPathCost implementation\nclass CNavPathCost : public INavPathCost {\npublic:\n    bool  m_bAllowLadders{true};\n    bool  m_bCanFly{false};\n    bool  m_bCanSwim{false};\n    float m_flTransitionPenalty{0.0f};\n\n    float GroundCost(const CNavArea* from, const CNavArea* to, float dist) const override;\n    float LadderCost(const CNavLadder* ladder) const override;\n    bool  IsAreaBlocked(const CNavArea* area) const override;\n    bool  AllowLadders() const override { return m_bAllowLadders; }\n};\n\n// Internal A* Search OpenList Priority Queue Node\nstruct AStarNode {\n    CNavArea*         m_area{nullptr};\n    AStarNode*        m_parent{nullptr};\n    const CNavLadder* m_ladder{nullptr};\n    float             m_gCost{0.0f};      // Cost from start to current node\n    float             m_hCost{0.0f};      // Heuristic estimate to goal\n    float             m_totalCost{0.0f};  // f = g + h\n    bool              m_open{false};\n    bool              m_closed{false};\n\n    struct Compare {\n        bool operator()(const AStarNode* a, const AStarNode* b) const noexcept {\n            return a->m_totalCost > b->m_totalCost; // Min-heap\n        }\n    };\n};\n\n// Core Navigation Mesh Architecture and A* Pathfinding Engine\nclass CNavMesh {\npublic:\n    uint32_t m_magic{0};\n    uint32_t m_version{0};\n    uint32_t m_subVersion{0};\n    uint32_t m_bspSize{0};\n    bool     m_isAnalyzed{false};\n\n    std::vector<std::string> m_places;\n    std::vector<CNavArea>    m_areas;\n    std::vector<CNavLadder>  m_ladders;\n\n    std::unordered_map<uint32_t, size_t> m_areaIndexMap;\n    std::unordered_map<uint32_t, size_t> m_ladderIndexMap;\n\n    CNavMesh() = default;\n\n    /**\n     * @brief Parses a binary .nav file buffer matching Source 2 specifications.\n     */\n    bool LoadFromBuffer(const uint8_t* data, size_t dataSize);\n\n    /**\n     * @brief Retrieves a CNavArea pointer by unique ID.\n     */\n    [[nodiscard]] CNavArea* GetAreaByID(uint32_t id) noexcept;\n    [[nodiscard]] const CNavArea* GetAreaByID(uint32_t id) const noexcept;\n\n    /**\n     * @brief Retrieves a CNavLadder pointer by unique ID.\n     */\n    [[nodiscard]] CNavLadder* GetLadderByID(uint32_t id) noexcept;\n    [[nodiscard]] const CNavLadder* GetLadderByID(uint32_t id) const noexcept;\n\n    /**\n     * @brief Locates the nearest navigable area to world coordinates (GetNearestNav).\n     */\n    [[nodiscard]] CNavArea* GetNearestNavArea(\n        const Vector3& pos,\n        float maxDistance = 500.0f,\n        uint32_t excludedFlags = NAV_MESH_CROUCH | NAV_MESH_CRAWL) noexcept;\n\n    /**\n     * @brief Executes A* pathfinding search heuristic (NavAreaBuildPath) from start to goal.\n     * \n     * Incorporates Source 2 elevation penalties (3.0x multiplier on vertical climb)\n     * and admissible/inadmissible heuristic factors.\n     */\n    bool FindPath(\n        const Vector3& startPos,\n        const Vector3& goalPos,\n        CNavArea* startArea,\n        CNavArea* goalArea,\n        const INavPathCost& costFunc,\n        std::vector<Vector3>& outPathWaypoints,\n        float maxPathLength = 10000.0f,\n        float inadmissibleHeuristicFactor = 1.0f);\n\n    /**\n     * @brief Computes 3D A* heuristic distance incorporating vertical elevation penalty.\n     */\n    static float ComputeHeuristicDistance(\n        const Vector3& from,\n        const Vector3& goal,\n        float stepHeight = 18.0f) noexcept;\n};\n\n} // namespace cs2::navsystem\n\n#endif // CS2_NAVSYSTEM_NAVMESH_H\n",
        "pathfinder.cpp": "#include \"pathfinder.h\"\n#include <cmath>\n#include <algorithm>\n#include <memory>\n\nnamespace cs2::sdk {\n\n// ============================================================================\n// INavPathCost / CNavPathCost Method Implementations\n// ============================================================================\nfloat CNavPathCost::GroundCost(const CNavArea* from, const CNavArea* to, float dist) const {\n    if (!to || IsAreaBlocked(to)) {\n        return -1.0f;\n    }\n\n    float cost = dist;\n\n    // Movement stance modifiers\n    if (to->HasFlag(NAV_MESH_CROUCH)) {\n        cost *= 1.35f;\n    }\n    if (to->HasFlag(NAV_MESH_CRAWL)) {\n        cost *= 2.0f;\n    }\n    if (to->HasFlag(NAV_MESH_JUMP)) {\n        cost += 50.0f + m_flTransitionPenalty;\n    }\n    if (to->HasFlag(NAV_MESH_AVOID)) {\n        cost *= 3.0f;\n    }\n\n    // Elevation climb penalty\n    if (from) {\n        float dz = to->GetCenter().z - from->GetCenter().z;\n        if (dz > 18.0f) {\n            cost += dz * 2.0f; // Extra effort for climbing\n        }\n    }\n\n    return cost;\n}\n\nfloat CNavPathCost::LadderCost(const CNavLadder* ladder) const {\n    if (!m_bAllowLadders || !ladder) {\n        return -1.0f;\n    }\n    return ladder->m_length * 1.5f;\n}\n\nbool CNavPathCost::IsAreaBlocked(const CNavArea* area) const {\n    if (!area) return true;\n    return area->HasFlag(NAV_MESH_INVALID);\n}\n\n// ============================================================================\n// CNavMesh Helper Query Implementations\n// ============================================================================\nCNavArea* CNavMesh::GetNearestNavArea(\n    const Vector3& pos,\n    float maxDistance,\n    std::uint32_t excludedFlags) noexcept {\n    CNavArea* bestArea = nullptr;\n    float bestDistSqr = maxDistance * maxDistance;\n\n    for (auto& area : m_areas) {\n        if (excludedFlags != 0 && area.HasFlag(excludedFlags)) {\n            continue;\n        }\n\n        Vector3 center = area.GetCenter();\n        float distSqr = (center - pos).LengthSqr();\n\n        // Check if inside polygon/bounding box\n        if (area.Contains(pos)) {\n            float z = area.ComputeZ(pos.x, pos.y);\n            float dz = std::abs(pos.z - z);\n            if (dz < 64.0f) {\n                return &area; // Direct vertical match within step/jump tolerance\n            }\n        }\n\n        if (distSqr < bestDistSqr) {\n            bestDistSqr = distSqr;\n            bestArea = &area;\n        }\n    }\n\n    return bestArea;\n}\n\n} // namespace cs2::sdk\n\nnamespace cs2::navsystem {\n\nusing namespace cs2::sdk;\n\n// ============================================================================\n// CPathfinder Static Geometric Primitives\n// ============================================================================\nVector3 CPathfinder::ClosestPointOnSegment(\n    const Vector3& p,\n    const Vector3& a,\n    const Vector3& b) noexcept {\n    Vector3 ab = b - a;\n    float lenSqr = ab.LengthSqr();\n    if (lenSqr < 1e-6f) {\n        return a;\n    }\n\n    float t = (p - a).Dot(ab) / lenSqr;\n    t = std::clamp(t, 0.0f, 1.0f);\n    return a + ab * t;\n}\n\nfloat CPathfinder::ComputeHeuristic(\n    const Vector3& from,\n    const Vector3& goal,\n    float stepHeight) noexcept {\n    float dx = goal.x - from.x;\n    float dy = goal.y - from.y;\n    float dzRaw = std::abs(goal.z - from.z);\n    float dzClamped = std::min(dzRaw, 2.0f * stepHeight);\n    float dzPenalized = (dzRaw - dzClamped) * 3.0f + dzClamped;\n    return std::sqrt(dx * dx + dy * dy + dzPenalized * dzPenalized);\n}\n\n// ============================================================================\n// CPathfinder Main Pipeline Execution\n// ============================================================================\nPathResult CPathfinder::FindPath(\n    const Vector3& startPos,\n    const Vector3& goalPos,\n    const PathOptions& options,\n    const INavPathCost* customCost) const {\n    PathResult result;\n    if (!m_pNavMesh) {\n        result.m_status = PathResult::EStatus::Failed_NoPath;\n        return result;\n    }\n\n    // Default cost functor if none specified\n    CNavPathCost defaultCost;\n    defaultCost.m_bAllowLadders = options.m_bAllowLadders;\n    const INavPathCost& costFunc = customCost ? *customCost : defaultCost;\n\n    // 1. Locate start and goal areas\n    CNavArea* startArea = const_cast<CNavMesh*>(m_pNavMesh)->GetNearestNavArea(\n        startPos, 600.0f, options.m_nExcludedFlags);\n    if (!startArea) {\n        result.m_status = PathResult::EStatus::Failed_NoStartArea;\n        return result;\n    }\n\n    CNavArea* goalArea = const_cast<CNavMesh*>(m_pNavMesh)->GetNearestNavArea(\n        goalPos, 600.0f, options.m_nExcludedFlags);\n    if (!goalArea) {\n        result.m_status = PathResult::EStatus::Failed_NoGoalArea;\n        return result;\n    }\n\n    // Same area trivial path\n    if (startArea == goalArea) {\n        result.m_status = PathResult::EStatus::Success;\n        result.m_areaCorridor.push_back(startArea);\n        result.m_rawWaypoints.push_back(startPos);\n        result.m_rawWaypoints.push_back(goalPos);\n        result.m_smoothedWaypoints.push_back(startPos);\n        result.m_smoothedWaypoints.push_back(goalPos);\n        result.m_annotatedWaypoints.emplace_back(startPos, startArea->m_id, startArea->m_flags, NavWaypointType::Ground);\n        result.m_annotatedWaypoints.emplace_back(goalPos, goalArea->m_id, goalArea->m_flags, NavWaypointType::Ground);\n        result.m_totalCost = (goalPos - startPos).Length();\n        result.m_totalLength = result.m_totalCost;\n        result.m_nodesExplored = 1;\n        return result;\n    }\n\n    // 2. Perform A* graph search over area adjacency graph\n    bool found = SearchAStar(\n        startArea, goalArea,\n        startPos, goalPos,\n        options, costFunc,\n        result.m_areaCorridor,\n        result.m_totalCost,\n        result.m_nodesExplored);\n\n    if (!found || result.m_areaCorridor.empty()) {\n        result.m_status = PathResult::EStatus::Failed_NoPath;\n        return result;\n    }\n\n    // 3. Extract portal gates between consecutive areas\n    ExtractPortals(result.m_areaCorridor, startPos, goalPos, result.m_portals);\n\n    // 4. Build raw waypoint trajectory (area centers & portal midpoints)\n    result.m_rawWaypoints.push_back(startPos);\n    for (const auto& portal : result.m_portals) {\n        result.m_rawWaypoints.push_back((portal.m_left + portal.m_right) * 0.5f);\n    }\n    result.m_rawWaypoints.push_back(goalPos);\n\n    // 5. Apply Simple Stupid Funnel Algorithm (SSFA) / String-Pulling\n    if (options.m_bStringPullCorridor && !result.m_portals.empty()) {\n        StringPullCorridor(\n            startPos, goalPos,\n            result.m_portals,\n            result.m_areaCorridor,\n            options.m_flAgentRadius,\n            result.m_smoothedWaypoints);\n    } else {\n        result.m_smoothedWaypoints = result.m_rawWaypoints;\n    }\n\n    // 6. Annotate movement types and integrate Euclidean length\n    result.m_totalLength = 0.0f;\n    for (std::size_t i = 0; i < result.m_smoothedWaypoints.size(); ++i) {\n        const auto& pt = result.m_smoothedWaypoints[i];\n        if (i > 0) {\n            result.m_totalLength += (pt - result.m_smoothedWaypoints[i - 1]).Length();\n        }\n\n        // Determine current area for waypoint\n        CNavArea* currentArea = nullptr;\n        for (auto* area : result.m_areaCorridor) {\n            if (area && area->Contains(pt)) {\n                currentArea = area;\n                break;\n            }\n        }\n        if (!currentArea) {\n            currentArea = (i < result.m_areaCorridor.size()) ? result.m_areaCorridor[i] : result.m_areaCorridor.back();\n        }\n\n        NavWaypointType type = NavWaypointType::Ground;\n        if (currentArea->HasFlag(NAV_MESH_JUMP)) {\n            type = NavWaypointType::Jump;\n        } else if (currentArea->HasFlag(NAV_MESH_CROUCH)) {\n            type = NavWaypointType::Crouch;\n        } else if (currentArea->HasFlag(NAV_MESH_CLIFF)) {\n            type = NavWaypointType::DropCliff;\n        }\n\n        result.m_annotatedWaypoints.emplace_back(pt, currentArea->m_id, currentArea->m_flags, type);\n    }\n\n    result.m_status = PathResult::EStatus::Success;\n    return result;\n}\n\n// ============================================================================\n// A* Search Implementation (NavAreaBuildPath @ 0x18003BDF0)\n// ============================================================================\nbool CPathfinder::SearchAStar(\n    CNavArea* startArea,\n    CNavArea* goalArea,\n    const Vector3& startPos,\n    const Vector3& goalPos,\n    const PathOptions& options,\n    const INavPathCost& costFunc,\n    std::vector<CNavArea*>& outCorridor,\n    float& outTotalCost,\n    std::size_t& outNodesExplored) const {\n    outCorridor.clear();\n    outTotalCost = 0.0f;\n    outNodesExplored = 0;\n\n    std::priority_queue<PathfinderAStarNode*, std::vector<PathfinderAStarNode*>, PathfinderAStarNode::MinHeapCompare> openList;\n    std::unordered_map<std::uint32_t, std::unique_ptr<PathfinderAStarNode>> nodeMap;\n\n    auto getNode = [&](CNavArea* area) -> PathfinderAStarNode* {\n        if (!area) return nullptr;\n        auto it = nodeMap.find(area->m_id);\n        if (it != nodeMap.end()) {\n            return it->second.get();\n        }\n        auto node = std::make_unique<PathfinderAStarNode>();\n        node->m_area = area;\n        PathfinderAStarNode* ptr = node.get();\n        nodeMap[area->m_id] = std::move(node);\n        return ptr;\n    };\n\n    PathfinderAStarNode* startNode = getNode(startArea);\n    startNode->m_gCost = 0.0f;\n    startNode->m_hCost = ComputeHeuristic(startPos, goalPos, options.m_flStepHeight);\n    startNode->m_totalCost = startNode->m_gCost + options.m_flInadmissibleHeuristicFactor * startNode->m_hCost;\n    startNode->m_open = true;\n    openList.push(startNode);\n\n    PathfinderAStarNode* goalNode = nullptr;\n\n    while (!openList.empty()) {\n        PathfinderAStarNode* current = openList.top();\n        openList.pop();\n\n        if (current->m_closed) {\n            continue;\n        }\n\n        current->m_open = false;\n        current->m_closed = true;\n        ++outNodesExplored;\n\n        // Check if goal reached\n        if (current->m_area == goalArea) {\n            goalNode = current;\n            break;\n        }\n\n        // Check path length cutoff\n        if (current->m_gCost > options.m_flMaxPathLength) {\n            continue;\n        }\n\n        Vector3 curCenter = current->m_area->GetCenter();\n\n        // ---------------------------------------------------------------------\n        // 1. Traverse Direct Portal Edges\n        // ---------------------------------------------------------------------\n        for (const auto& edge : current->m_area->m_portalEdges) {\n            CNavArea* neighbor = edge.m_pTargetArea;\n            if (!neighbor || (options.m_nExcludedFlags && neighbor->HasFlag(options.m_nExcludedFlags))) {\n                continue;\n            }\n            if (!options.m_bAllowCrouch && neighbor->HasFlag(NAV_MESH_CROUCH)) {\n                continue;\n            }\n            if (!options.m_bAllowJump && neighbor->HasFlag(NAV_MESH_JUMP)) {\n                continue;\n            }\n\n            float dist = edge.m_flLength > 0.0f ? (neighbor->GetCenter() - curCenter).Length() : 50.0f;\n            float stepCost = costFunc.GroundCost(current->m_area, neighbor, dist);\n            if (stepCost < 0.0f) continue; // Blocked\n\n            float newGCost = current->m_gCost + stepCost;\n            PathfinderAStarNode* neighborNode = getNode(neighbor);\n            if (neighborNode->m_closed && newGCost >= neighborNode->m_gCost) {\n                continue;\n            }\n\n            if (!neighborNode->m_open || newGCost < neighborNode->m_gCost) {\n                neighborNode->m_parent = current;\n                neighborNode->m_gCost = newGCost;\n                neighborNode->m_hCost = ComputeHeuristic(neighbor->GetCenter(), goalPos, options.m_flStepHeight);\n                neighborNode->m_totalCost = newGCost + options.m_flInadmissibleHeuristicFactor * neighborNode->m_hCost;\n                neighborNode->m_open = true;\n                neighborNode->m_closed = false;\n                openList.push(neighborNode);\n            }\n        }\n\n        // ---------------------------------------------------------------------\n        // 2. Traverse Cardinal Directional Adjacencies\n        // ---------------------------------------------------------------------\n        for (std::uint32_t dir = 0; dir < NUM_DIRECTIONS; ++dir) {\n            for (const auto& conn : current->m_area->m_adjacentAreas[dir]) {\n                CNavArea* neighbor = const_cast<CNavMesh*>(m_pNavMesh)->GetAreaByID(conn.m_areaId);\n                if (!neighbor || (options.m_nExcludedFlags && neighbor->HasFlag(options.m_nExcludedFlags))) {\n                    continue;\n                }\n                if (!options.m_bAllowCrouch && neighbor->HasFlag(NAV_MESH_CROUCH)) {\n                    continue;\n                }\n                if (!options.m_bAllowJump && neighbor->HasFlag(NAV_MESH_JUMP)) {\n                    continue;\n                }\n\n                float dist = (neighbor->GetCenter() - curCenter).Length();\n                float stepCost = costFunc.GroundCost(current->m_area, neighbor, dist);\n                if (stepCost < 0.0f) continue;\n\n                float newGCost = current->m_gCost + stepCost;\n                PathfinderAStarNode* neighborNode = getNode(neighbor);\n                if (neighborNode->m_closed && newGCost >= neighborNode->m_gCost) {\n                    continue;\n                }\n\n                if (!neighborNode->m_open || newGCost < neighborNode->m_gCost) {\n                    neighborNode->m_parent = current;\n                    neighborNode->m_gCost = newGCost;\n                    neighborNode->m_hCost = ComputeHeuristic(neighbor->GetCenter(), goalPos, options.m_flStepHeight);\n                    neighborNode->m_totalCost = newGCost + options.m_flInadmissibleHeuristicFactor * neighborNode->m_hCost;\n                    neighborNode->m_open = true;\n                    neighborNode->m_closed = false;\n                    openList.push(neighborNode);\n                }\n            }\n        }\n\n        // ---------------------------------------------------------------------\n        // 3. Traverse Vertical Ladder Links\n        // ---------------------------------------------------------------------\n        if (options.m_bAllowLadders) {\n            for (std::uint32_t lDir = 0; lDir < NUM_LADDER_DIRECTIONS; ++lDir) {\n                for (std::uint32_t ladderId : current->m_area->m_ladderConnections[lDir]) {\n                    const CNavLadder* ladder = m_pNavMesh->GetLadderByID(ladderId);\n                    if (!ladder) continue;\n\n                    float lCost = costFunc.LadderCost(ladder);\n                    if (lCost < 0.0f) continue;\n\n                    // Collect target connected areas\n                    std::uint32_t targetIds[] = {\n                        ladder->m_topForwardAreaId, ladder->m_topLeftAreaId,\n                        ladder->m_topRightAreaId, ladder->m_topBehindAreaId,\n                        ladder->m_bottomAreaId, ladder->m_bottomLeftAreaId,\n                        ladder->m_bottomRightAreaId\n                    };\n\n                    for (std::uint32_t tid : targetIds) {\n                        if (tid == 0 || tid == current->m_area->m_id) continue;\n                        CNavArea* neighbor = const_cast<CNavMesh*>(m_pNavMesh)->GetAreaByID(tid);\n                        if (!neighbor) continue;\n\n                        float newGCost = current->m_gCost + lCost;\n                        PathfinderAStarNode* neighborNode = getNode(neighbor);\n                        if (neighborNode->m_closed && newGCost >= neighborNode->m_gCost) {\n                            continue;\n                        }\n\n                        if (!neighborNode->m_open || newGCost < neighborNode->m_gCost) {\n                            neighborNode->m_parent = current;\n                            neighborNode->m_ladder = ladder;\n                            neighborNode->m_gCost = newGCost;\n                            neighborNode->m_hCost = ComputeHeuristic(neighbor->GetCenter(), goalPos, options.m_flStepHeight);\n                            neighborNode->m_totalCost = newGCost + options.m_flInadmissibleHeuristicFactor * neighborNode->m_hCost;\n                            neighborNode->m_open = true;\n                            neighborNode->m_closed = false;\n                            openList.push(neighborNode);\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    if (!goalNode) {\n        return false;\n    }\n\n    // Backtrack from goalNode to startNode\n    outTotalCost = goalNode->m_gCost;\n    PathfinderAStarNode* trace = goalNode;\n    while (trace) {\n        outCorridor.push_back(trace->m_area);\n        trace = trace->m_parent;\n    }\n    std::reverse(outCorridor.begin(), outCorridor.end());\n    return true;\n}\n\n// ============================================================================\n// Extract Portals Connecting Consecutive Corridor Areas\n// ============================================================================\nbool CPathfinder::ExtractPortals(\n    const std::vector<CNavArea*>& corridor,\n    const Vector3& /*startPos*/,\n    const Vector3& /*goalPos*/,\n    std::vector<NavPortal>& outPortals) const {\n    outPortals.clear();\n    if (corridor.size() < 2) {\n        return false;\n    }\n\n    for (std::size_t i = 0; i < corridor.size() - 1; ++i) {\n        const CNavArea* from = corridor[i];\n        const CNavArea* to = corridor[i + 1];\n        if (!from || !to) continue;\n\n        Vector3 leftPoint{0.0f, 0.0f, 0.0f};\n        Vector3 rightPoint{0.0f, 0.0f, 0.0f};\n        NavPortalEdge_t edgeData{};\n\n        // Check if explicit portal edge exists in from area\n        const NavPortalEdge_t* pEdge = from->FindPortalEdgeTo(to);\n        if (pEdge) {\n            leftPoint = pEdge->m_portalLeft;\n            rightPoint = pEdge->m_portalRight;\n            edgeData = *pEdge;\n        } else {\n            // Synthesize portal from overlapping AABB bounds\n            float minX = std::max(from->m_nwCorner.x, to->m_nwCorner.x);\n            float maxX = std::min(from->m_seCorner.x, to->m_seCorner.x);\n            float minY = std::max(from->m_nwCorner.y, to->m_nwCorner.y);\n            float maxY = std::min(from->m_seCorner.y, to->m_seCorner.y);\n\n            if (maxX >= minX && (maxY - minY) < 2.0f) {\n                // Horizontal edge boundary (North/South)\n                float edgeY = (from->m_seCorner.y + to->m_nwCorner.y) * 0.5f;\n                leftPoint = Vector3{minX, edgeY, from->ComputeZ(minX, edgeY)};\n                rightPoint = Vector3{maxX, edgeY, from->ComputeZ(maxX, edgeY)};\n            } else if (maxY >= minY && (maxX - minX) < 2.0f) {\n                // Vertical edge boundary (East/West)\n                float edgeX = (from->m_seCorner.x + to->m_nwCorner.x) * 0.5f;\n                leftPoint = Vector3{edgeX, minY, from->ComputeZ(edgeX, minY)};\n                rightPoint = Vector3{edgeX, maxY, from->ComputeZ(edgeX, maxY)};\n            } else {\n                // Fallback: connect centers\n                Vector3 mid = (from->GetCenter() + to->GetCenter()) * 0.5f;\n                leftPoint = mid;\n                rightPoint = mid;\n            }\n        }\n\n        // Consistent orientation: left must be to the left, right to the right\n        // from perspective of moving fromCenter -> toCenter\n        Vector3 fromCenter = from->GetCenter();\n        if (TriArea2D(fromCenter, leftPoint, rightPoint) > 0.0f) {\n            std::swap(leftPoint, rightPoint);\n        }\n\n        outPortals.emplace_back(leftPoint, rightPoint, from->m_id, to->m_id, edgeData);\n    }\n\n    return !outPortals.empty();\n}\n\n// ============================================================================\n// Simple Stupid Funnel Algorithm (SSFA) / String-Pulling Optimization\n// Decompiled from server.dll @ 0x1810EE570 (SpacePathfind_StringPull_Core)\n// ============================================================================\nbool CPathfinder::StringPullCorridor(\n    const Vector3& startPos,\n    const Vector3& goalPos,\n    const std::vector<NavPortal>& portals,\n    const std::vector<CNavArea*>& corridor,\n    float agentRadius,\n    std::vector<Vector3>& outSmoothedWaypoints) {\n    outSmoothedWaypoints.clear();\n    if (portals.empty()) {\n        outSmoothedWaypoints.push_back(startPos);\n        outSmoothedWaypoints.push_back(goalPos);\n        return true;\n    }\n\n    // 1. Prepare portal boundary arrays with agent radius inset\n    std::vector<Vector3> leftVerts;\n    std::vector<Vector3> rightVerts;\n    leftVerts.reserve(portals.size() + 2);\n    rightVerts.reserve(portals.size() + 2);\n\n    // Initial position (apex 0)\n    leftVerts.push_back(startPos);\n    rightVerts.push_back(startPos);\n\n    for (const auto& portal : portals) {\n        Vector3 l = portal.m_left;\n        Vector3 r = portal.m_right;\n\n        // Apply collision hull inset along portal segment\n        Vector3 dir = r - l;\n        float len = dir.Length2D();\n        if (len > 2.0f * agentRadius && agentRadius > 0.0f) {\n            Vector3 unitDir = dir / len;\n            l = l + unitDir * agentRadius;\n            r = r - unitDir * agentRadius;\n        } else {\n            // Narrow portal: clamp to midpoint\n            Vector3 mid = (l + r) * 0.5f;\n            l = mid;\n            r = mid;\n        }\n\n        leftVerts.push_back(l);\n        rightVerts.push_back(r);\n    }\n\n    // Goal position (end apex)\n    leftVerts.push_back(goalPos);\n    rightVerts.push_back(goalPos);\n\n    // 2. Execute Funnel String-Pulling\n    std::size_t numPortals = leftVerts.size();\n    Vector3 apex = startPos;\n    Vector3 leftRay = leftVerts[1];\n    Vector3 rightRay = rightVerts[1];\n\n    std::size_t apexIdx = 0;\n    std::size_t leftIdx = 1;\n    std::size_t rightIdx = 1;\n\n    outSmoothedWaypoints.push_back(startPos);\n\n    for (std::size_t i = 2; i < numPortals; ++i) {\n        const Vector3& nextLeft = leftVerts[i];\n        const Vector3& nextRight = rightVerts[i];\n\n        // -----------------------------------------------------------------\n        // Update Right Leg\n        // -----------------------------------------------------------------\n        if (TriArea2D(apex, rightRay, nextRight) <= 0.0f) {\n            // Tighten right leg if within current left boundary\n            if (apex.Dist2DTo(leftRay) < 1e-3f || TriArea2D(apex, leftRay, nextRight) > 0.0f) {\n                rightRay = nextRight;\n                rightIdx = i;\n            } else {\n                // Right leg crosses over left leg: corner found!\n                apex = leftRay;\n                apexIdx = leftIdx;\n\n                // Adjust elevation to walkable area surface\n                std::size_t areaIdx = std::min(apexIdx, corridor.size() - 1);\n                if (areaIdx < corridor.size() && corridor[areaIdx]) {\n                    apex.z = corridor[areaIdx]->ComputeZ(apex.x, apex.y);\n                }\n\n                outSmoothedWaypoints.push_back(apex);\n\n                // Restart funnel from new apex\n                leftRay = apex;\n                rightRay = apex;\n                leftIdx = apexIdx;\n                rightIdx = apexIdx;\n                i = apexIdx + 1;\n                if (i < numPortals) {\n                    leftRay = leftVerts[i];\n                    rightRay = rightVerts[i];\n                    leftIdx = i;\n                    rightIdx = i;\n                }\n                continue;\n            }\n        }\n\n        // -----------------------------------------------------------------\n        // Update Left Leg\n        // -----------------------------------------------------------------\n        if (TriArea2D(apex, leftRay, nextLeft) >= 0.0f) {\n            // Tighten left leg if within current right boundary\n            if (apex.Dist2DTo(rightRay) < 1e-3f || TriArea2D(apex, rightRay, nextLeft) < 0.0f) {\n                leftRay = nextLeft;\n                leftIdx = i;\n            } else {\n                // Left leg crosses over right leg: corner found!\n                apex = rightRay;\n                apexIdx = rightIdx;\n\n                // Adjust elevation to walkable area surface\n                std::size_t areaIdx = std::min(apexIdx, corridor.size() - 1);\n                if (areaIdx < corridor.size() && corridor[areaIdx]) {\n                    apex.z = corridor[areaIdx]->ComputeZ(apex.x, apex.y);\n                }\n\n                outSmoothedWaypoints.push_back(apex);\n\n                // Restart funnel from new apex\n                leftRay = apex;\n                rightRay = apex;\n                leftIdx = apexIdx;\n                rightIdx = apexIdx;\n                i = apexIdx + 1;\n                if (i < numPortals) {\n                    leftRay = leftVerts[i];\n                    rightRay = rightVerts[i];\n                    leftIdx = i;\n                    rightIdx = i;\n                }\n                continue;\n            }\n        }\n    }\n\n    // Final waypoint to goalPos\n    if (outSmoothedWaypoints.empty() || outSmoothedWaypoints.back().DistTo(goalPos) > 1.0f) {\n        outSmoothedWaypoints.push_back(goalPos);\n    }\n\n    return true;\n}\n\n} // namespace cs2::navsystem\n",
        "pathfinder.h": "#pragma once\n\n#include \"sdk/navmesh.hpp\"\n#include <vector>\n#include <queue>\n#include <unordered_map>\n#include <unordered_set>\n#include <limits>\n#include <cmath>\n#include <algorithm>\n#include <cstdint>\n\n// ============================================================================\n// Source 2 Clean-Room A* Pathfinding Engine & Corridor Funnel String-Pulling\n// Target Binaries: navsystem.dll & server.dll\n// Architecture: x86-64 (MSVC ABI, /std:c++20 /W4 /WX)\n// Provenance:\n//   NavAreaBuildPath:               navsystem.dll @ 0x18003BDF0\n//   Vertical Elevation Heuristic:   navsystem.dll @ 0x18003C400 (3.0x climb penalty)\n//   CNavPathCost Traversal:         navsystem.dll @ 0x18003B420 & server.dll schemas\n//   SpacePathfind_StringPull_Core:  server.dll    @ 0x1810EE570\n//   Portal Traversal Intersect:     server.dll    @ 0x1814F2100 (0x38-byte NavPortalEdge_t)\n// ============================================================================\n\nnamespace cs2::navsystem {\n\n// Traversal movement taxonomy for path waypoints\nenum class NavWaypointType : std::uint32_t {\n    Ground      = 0,\n    Jump        = 1,\n    LadderUp    = 2,\n    LadderDown  = 3,\n    Crouch      = 4,\n    DropCliff   = 5,\n    Obstacle    = 6\n};\n\n// Annotated path waypoint along optimized trajectory\nstruct NavWaypoint {\n    sdk::Vector3    m_position{0.0f, 0.0f, 0.0f};\n    std::uint32_t   m_areaId{0};\n    std::uint32_t   m_flags{0};\n    NavWaypointType m_type{NavWaypointType::Ground};\n    float           m_flCurvature{0.0f};\n\n    constexpr NavWaypoint() noexcept = default;\n    constexpr NavWaypoint(const sdk::Vector3& pos, std::uint32_t areaId, std::uint32_t flags, NavWaypointType type) noexcept\n        : m_position(pos), m_areaId(areaId), m_flags(flags), m_type(type) {}\n};\n\n// Portal gate spanning the shared boundary between adjacent convex areas\nstruct NavPortal {\n    sdk::Vector3         m_left{0.0f, 0.0f, 0.0f};   // Portal left endpoint (from traversal perspective)\n    sdk::Vector3         m_right{0.0f, 0.0f, 0.0f};  // Portal right endpoint (from traversal perspective)\n    std::uint32_t        m_fromAreaId{0};\n    std::uint32_t        m_toAreaId{0};\n    sdk::NavPortalEdge_t m_edge{};\n\n    constexpr NavPortal() noexcept = default;\n    constexpr NavPortal(const sdk::Vector3& l, const sdk::Vector3& r, std::uint32_t fromId, std::uint32_t toId, const sdk::NavPortalEdge_t& e) noexcept\n        : m_left(l), m_right(r), m_fromAreaId(fromId), m_toAreaId(toId), m_edge(e) {}\n};\n\n// Algorithmic query tuning options\nstruct PathOptions {\n    float         m_flMaxPathLength{15000.0f};                  // Max traversal distance cutoff\n    float         m_flInadmissibleHeuristicFactor{1.0f};         // nav_pathfind_inadmissable_heuristic_factor\n    float         m_flAgentRadius{16.0f};                       // Collision hull radius clearance (portal margin)\n    float         m_flStepHeight{18.0f};                        // Standard step height threshold\n    bool          m_bAllowLadders{true};                        // Enable vertical ladders\n    bool          m_bAllowJump{true};                           // Enable jump links\n    bool          m_bAllowCrouch{true};                         // Enable crouch/crawl areas\n    bool          m_bStringPullCorridor{true};                  // Run Simple Stupid Funnel Algorithm\n    std::uint32_t m_nExcludedFlags{sdk::NAV_MESH_INVALID};      // Excluded area bitmask\n};\n\n// Pathfinding query outcome container\nstruct PathResult {\n    enum class EStatus : std::uint32_t {\n        Success               = 0,\n        Failed_NoStartArea    = 1,\n        Failed_NoGoalArea     = 2,\n        Failed_NoPath         = 3,\n        Failed_LengthExceeded = 4\n    };\n\n    EStatus                       m_status{EStatus::Failed_NoPath};\n    std::vector<sdk::CNavArea*>   m_areaCorridor;       // Chronological area channel sequence\n    std::vector<NavPortal>        m_portals;            // Geometric portals connecting adjacent areas\n    std::vector<sdk::Vector3>     m_rawWaypoints;       // Polygon center / portal edge midpoints\n    std::vector<sdk::Vector3>     m_smoothedWaypoints;  // Funnel string-pulled piecewise-linear trajectory\n    std::vector<NavWaypoint>      m_annotatedWaypoints; // Movement metadata annotations\n    float                         m_totalCost{0.0f};    // Accumulated A* traversal cost\n    float                         m_totalLength{0.0f};  // Integrated 3D Euclidean trajectory length\n    std::size_t                   m_nodesExplored{0};   // Open/closed node expansion count\n\n    [[nodiscard]] constexpr bool IsValid() const noexcept {\n        return m_status == EStatus::Success && !m_smoothedWaypoints.empty();\n    }\n};\n\n// Internal A* Search OpenList Priority Queue Entry\nstruct PathfinderAStarNode {\n    sdk::CNavArea*              m_area{nullptr};\n    PathfinderAStarNode*        m_parent{nullptr};\n    const sdk::CNavLadder*      m_ladder{nullptr};\n    float                       m_gCost{0.0f};\n    float                       m_hCost{0.0f};\n    float                       m_totalCost{0.0f}; // f(n) = g(n) + alpha * h(n)\n    bool                        m_open{false};\n    bool                        m_closed{false};\n\n    struct MinHeapCompare {\n        bool operator()(const PathfinderAStarNode* a, const PathfinderAStarNode* b) const noexcept {\n            return a->m_totalCost > b->m_totalCost;\n        }\n    };\n};\n\n// ============================================================================\n// CPathfinder - Core Graph Pathfinding and Trajectory Optimization Engine\n// ============================================================================\nclass CPathfinder {\npublic:\n    explicit CPathfinder(const sdk::CNavMesh* pNavMesh) noexcept : m_pNavMesh(pNavMesh) {}\n\n    /**\n     * @brief Computes the shortest and smoothest navigable trajectory from start to goal.\n     */\n    [[nodiscard]] PathResult FindPath(\n        const sdk::Vector3& startPos,\n        const sdk::Vector3& goalPos,\n        const PathOptions& options = {},\n        const sdk::INavPathCost* customCost = nullptr) const;\n\n    /**\n     * @brief Executes A* graph search over convex navigation area graph.\n     * Decompiled from navsystem.dll @ 0x18003BDF0 (NavAreaBuildPath)\n     */\n    bool SearchAStar(\n        sdk::CNavArea* startArea,\n        sdk::CNavArea* goalArea,\n        const sdk::Vector3& startPos,\n        const sdk::Vector3& goalPos,\n        const PathOptions& options,\n        const sdk::INavPathCost& costFunc,\n        std::vector<sdk::CNavArea*>& outCorridor,\n        float& outTotalCost,\n        std::size_t& outNodesExplored) const;\n\n    /**\n     * @brief Extracts ordered portal segments between consecutive corridor areas.\n     * Decompiled from server.dll @ 0x1814F2100\n     */\n    bool ExtractPortals(\n        const std::vector<sdk::CNavArea*>& corridor,\n        const sdk::Vector3& startPos,\n        const sdk::Vector3& goalPos,\n        std::vector<NavPortal>& outPortals) const;\n\n    /**\n     * @brief Applies Simple Stupid Funnel Algorithm (SSFA) / String-Pulling to straighten path.\n     * Decompiled from server.dll @ 0x1810EE570 (SpacePathfind_StringPull_Core)\n     */\n    static bool StringPullCorridor(\n        const sdk::Vector3& startPos,\n        const sdk::Vector3& goalPos,\n        const std::vector<NavPortal>& portals,\n        const std::vector<sdk::CNavArea*>& corridor,\n        float agentRadius,\n        std::vector<sdk::Vector3>& outSmoothedWaypoints);\n\n    /**\n     * @brief Signed 2D cross product determining triangle orientation (CCW > 0, CW < 0).\n     */\n    [[nodiscard]] static constexpr float TriArea2D(\n        const sdk::Vector3& a,\n        const sdk::Vector3& b,\n        const sdk::Vector3& c) noexcept {\n        return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);\n    }\n\n    /**\n     * @brief Finds closest point on 3D segment AB to point P.\n     */\n    [[nodiscard]] static sdk::Vector3 ClosestPointOnSegment(\n        const sdk::Vector3& p,\n        const sdk::Vector3& a,\n        const sdk::Vector3& b) noexcept;\n\n    /**\n     * @brief Computes 3D A* heuristic with 3.0x vertical climb penalty above step clearance.\n     * Decompiled from navsystem.dll @ 0x18003C400\n     */\n    [[nodiscard]] static float ComputeHeuristic(\n        const sdk::Vector3& from,\n        const sdk::Vector3& goal,\n        float stepHeight = 18.0f) noexcept;\n\nprivate:\n    const sdk::CNavMesh* m_pNavMesh{nullptr};\n};\n\n} // namespace cs2::navsystem\n"
      }
    },
    {
      "module": "networksystem.dll",
      "directory": "game/networksystem",
      "standard": "C++20 (/std:c++20 /W4)",
      "files": {
        "entity_delta_codec.cpp": "#include \"entity_delta_codec.h\"\n#include <sstream>\n#include <iomanip>\n#include <cmath>\n#include <cstring>\n#include <algorithm>\n\nnamespace cs2::networksystem {\n\n// ============================================================================\n// 1. PropertyValue Implementation\n// ============================================================================\n\nbool PropertyValue::operator==(const PropertyValue& o) const noexcept {\n    if (type != o.type) return false;\n    switch (type) {\n    case Type::None: return true;\n    case Type::Bool: return bVal == o.bVal;\n    case Type::Int32: return i32Val == o.i32Val;\n    case Type::UInt32: return u32Val == o.u32Val;\n    case Type::Int64: return i64Val == o.i64Val;\n    case Type::UInt64: return u64Val == o.u64Val;\n    case Type::Float: return std::abs(fVal - o.fVal) < 1e-5f;\n    case Type::Vector: return vecVal == o.vecVal;\n    case Type::QAngle: return angVal == o.angVal;\n    case Type::String: return strVal == o.strVal;\n    case Type::Handle: return handleVal == o.handleVal;\n    default: return false;\n    }\n}\n\nstd::string PropertyValue::ToString() const {\n    std::ostringstream ss;\n    switch (type) {\n    case Type::None: return \"None\";\n    case Type::Bool: return bVal ? \"true\" : \"false\";\n    case Type::Int32: ss << i32Val; return ss.str();\n    case Type::UInt32: ss << u32Val; return ss.str();\n    case Type::Int64: ss << i64Val; return ss.str();\n    case Type::UInt64: ss << u64Val; return ss.str();\n    case Type::Float:\n        ss << std::fixed << std::setprecision(3) << fVal;\n        return ss.str();\n    case Type::Vector:\n        ss << std::fixed << std::setprecision(2)\n           << \"(\" << vecVal.x << \", \" << vecVal.y << \", \" << vecVal.z << \")\";\n        return ss.str();\n    case Type::QAngle:\n        ss << std::fixed << std::setprecision(2)\n           << \"{\" << angVal.pitch << \", \" << angVal.yaw << \", \" << angVal.roll << \"}\";\n        return ss.str();\n    case Type::String: return \"\\\"\" + strVal + \"\\\"\";\n    case Type::Handle:\n        ss << \"0x\" << std::hex << handleVal;\n        return ss.str();\n    default: return \"Unknown\";\n    }\n}\n\n// ============================================================================\n// 2. CEntityBaselineStorage Implementation\n// ============================================================================\n\nvoid CEntityBaselineStorage::SetBaseline(uint32_t baselineIndex, uint32_t entityIndex,\n                                         std::unordered_map<std::string, PropertyValue> properties) {\n    m_Baselines[baselineIndex][entityIndex] = std::move(properties);\n}\n\nconst std::unordered_map<std::string, PropertyValue>* CEntityBaselineStorage::GetBaseline(\n    uint32_t baselineIndex, uint32_t entityIndex) const {\n    auto bIt = m_Baselines.find(baselineIndex);\n    if (bIt == m_Baselines.end()) return nullptr;\n\n    auto eIt = bIt->second.find(entityIndex);\n    if (eIt == bIt->second.end()) return nullptr;\n\n    return &eIt->second;\n}\n\nvoid CEntityBaselineStorage::CopyBaseline(uint32_t srcBaseline, uint32_t dstBaseline) {\n    auto it = m_Baselines.find(srcBaseline);\n    if (it != m_Baselines.end()) {\n        m_Baselines[dstBaseline] = it->second;\n    } else {\n        m_Baselines.erase(dstBaseline);\n    }\n}\n\nvoid CEntityBaselineStorage::ClearBaseline(uint32_t baselineIndex) {\n    m_Baselines.erase(baselineIndex);\n}\n\nvoid CEntityBaselineStorage::ClearAll() {\n    m_Baselines.clear();\n}\n\nsize_t CEntityBaselineStorage::GetEntityCount(uint32_t baselineIndex) const {\n    auto it = m_Baselines.find(baselineIndex);\n    return (it != m_Baselines.end()) ? it->second.size() : 0;\n}\n\n// ============================================================================\n// 3. CFieldChangeDispatcher Implementation\n// ============================================================================\n\nuint32_t CFieldChangeDispatcher::RegisterCallback(const std::string& fieldName, FieldChangeCallbackFn callback) {\n    const uint32_t id = m_NextId++;\n    m_Callbacks.push_back(CallbackEntry{id, fieldName, std::move(callback)});\n    return id;\n}\n\nvoid CFieldChangeDispatcher::UnregisterCallback(uint32_t callbackId) {\n    std::erase_if(m_Callbacks, [callbackId](const CallbackEntry& entry) {\n        return entry.id == callbackId;\n    });\n}\n\nvoid CFieldChangeDispatcher::Dispatch(uint32_t entityIndex,\n                                      const std::string& fieldName,\n                                      const FieldPath& path,\n                                      const PropertyValue& oldValue,\n                                      const PropertyValue& newValue) const {\n    for (const auto& entry : m_Callbacks) {\n        if (entry.fieldName.empty() || entry.fieldName == \"*\" || entry.fieldName == fieldName) {\n            entry.callback(entityIndex, fieldName, path, oldValue, newValue);\n        }\n    }\n}\n\n// ============================================================================\n// 4. CEntitySnapshot Implementation\n// ============================================================================\n\nconst PropertyValue* CEntitySnapshot::GetProperty(const std::string& name) const {\n    auto it = m_Properties.find(name);\n    return (it != m_Properties.end()) ? &it->second : nullptr;\n}\n\nvoid CEntitySnapshot::SetProperty(const std::string& name, PropertyValue value) {\n    m_Properties[name] = std::move(value);\n}\n\nbool CEntitySnapshot::HasProperty(const std::string& name) const {\n    return m_Properties.contains(name);\n}\n\n// ============================================================================\n// 5. CEntityDeltaCodec Implementation\n// ============================================================================\n\nvoid CEntityDeltaCodec::RegisterSerializer(uint32_t classId, CFlattenedSerializer serializer) {\n    m_Serializers.insert_or_assign(classId, std::move(serializer));\n}\n\nconst CFlattenedSerializer* CEntityDeltaCodec::GetSerializer(uint32_t classId) const {\n    auto it = m_Serializers.find(classId);\n    return (it != m_Serializers.end()) ? &it->second : nullptr;\n}\n\nconst CEntitySnapshot* CEntityDeltaCodec::GetEntity(uint32_t entityIndex) const {\n    auto it = m_ActiveEntities.find(entityIndex);\n    return (it != m_ActiveEntities.end()) ? &it->second : nullptr;\n}\n\nCEntitySnapshot* CEntityDeltaCodec::GetEntityMutable(uint32_t entityIndex) {\n    auto it = m_ActiveEntities.find(entityIndex);\n    return (it != m_ActiveEntities.end()) ? &it->second : nullptr;\n}\n\n// Entity index delta reading:\n// Bit 0 == 0: Consecutive (+1)\n// Bit 0 == 1: Tiered jump\nuint32_t CEntityDeltaCodec::ReadEntityIndexDelta(CBitReadStream& stream, uint32_t prevIndex) {\n    if (stream.ReadUBits(1) == 0) {\n        return prevIndex + 1;\n    }\n    const uint32_t tier = stream.ReadUBits(2);\n    switch (tier) {\n    case 0: return prevIndex + 2 + stream.ReadUBits(3);\n    case 1: return prevIndex + 10 + stream.ReadUBits(6);\n    case 2: return prevIndex + 74 + stream.ReadUBits(9);\n    case 3: return stream.ReadUBits(14); // Absolute index\n    default: return prevIndex + 1;\n    }\n}\n\nvoid CEntityDeltaCodec::WriteEntityIndexDelta(CBitWriteStream& stream, uint32_t currentIndex, uint32_t prevIndex) {\n    if (currentIndex == prevIndex + 1) {\n        stream.WriteUBits(0, 1);\n        return;\n    }\n\n    stream.WriteUBits(1, 1);\n    const uint32_t delta = currentIndex - prevIndex;\n    if (delta >= 2 && delta < 10) {\n        stream.WriteUBits(0, 2);\n        stream.WriteUBits(delta - 2, 3);\n    } else if (delta >= 10 && delta < 74) {\n        stream.WriteUBits(1, 2);\n        stream.WriteUBits(delta - 10, 6);\n    } else if (delta >= 74 && delta < 586) {\n        stream.WriteUBits(2, 2);\n        stream.WriteUBits(delta - 74, 9);\n    } else {\n        stream.WriteUBits(3, 2);\n        stream.WriteUBits(currentIndex & 0x3FFF, 14);\n    }\n}\n\nEntityDeltaHeader CEntityDeltaCodec::ReadEntityHeader(CBitReadStream& stream, uint32_t prevIndex, bool isDelta) {\n    EntityDeltaHeader header;\n    header.entityIndex = ReadEntityIndexDelta(stream, prevIndex);\n\n    if (!isDelta) {\n        // Full update / EnterPVS\n        header.updateType = EntityUpdateType::EnterPVS;\n        header.classId = stream.ReadVarInt32();\n        header.serialNumber = stream.ReadUBits(17);\n        return header;\n    }\n\n    // Delta update mode: 2-bit PVS status flag\n    const uint32_t pvsFlag = stream.ReadUBits(2);\n    switch (pvsFlag) {\n    case 0:\n        header.updateType = EntityUpdateType::Preserve;\n        break;\n    case 1:\n        // Entity leaves PVS\n        header.updateType = EntityUpdateType::LeavePVS;\n        if (stream.ReadUBits(1) != 0) {\n            header.updateType = EntityUpdateType::Delete;\n        }\n        break;\n    case 2:\n        // Entity enters PVS\n        header.updateType = EntityUpdateType::EnterPVS;\n        header.classId = stream.ReadVarInt32();\n        header.serialNumber = stream.ReadUBits(17);\n        break;\n    case 3:\n    default:\n        // Existing entity delta property update\n        header.updateType = EntityUpdateType::DeltaUpdate;\n        break;\n    }\n\n    return header;\n}\n\nvoid CEntityDeltaCodec::WriteEntityHeader(CBitWriteStream& stream, const EntityDeltaHeader& header,\n                                         uint32_t prevIndex, bool isDelta) {\n    WriteEntityIndexDelta(stream, header.entityIndex, prevIndex);\n\n    if (!isDelta) {\n        stream.WriteVarInt32(header.classId);\n        stream.WriteUBits(header.serialNumber & 0x1FFFF, 17);\n        return;\n    }\n\n    switch (header.updateType) {\n    case EntityUpdateType::Preserve:\n        stream.WriteUBits(0, 2);\n        break;\n    case EntityUpdateType::LeavePVS:\n        stream.WriteUBits(1, 2);\n        stream.WriteUBits(0, 1);\n        break;\n    case EntityUpdateType::Delete:\n        stream.WriteUBits(1, 2);\n        stream.WriteUBits(1, 1);\n        break;\n    case EntityUpdateType::EnterPVS:\n        stream.WriteUBits(2, 2);\n        stream.WriteVarInt32(header.classId);\n        stream.WriteUBits(header.serialNumber & 0x1FFFF, 17);\n        break;\n    case EntityUpdateType::DeltaUpdate:\n        stream.WriteUBits(3, 2);\n        break;\n    }\n}\n\nPropertyValue CEntityDeltaCodec::DecodeFieldValue(CBitReadStream& stream, const SerializedFieldInfo& fieldInfo) {\n    const std::string& type = fieldInfo.varType;\n\n    if (type == \"bool\") {\n        return PropertyValue(stream.ReadUBits(1) != 0);\n    }\n    if (type == \"uint8\" || type == \"int8\") {\n        return PropertyValue(stream.ReadUBits(8));\n    }\n    if (type == \"uint16\" || type == \"int16\") {\n        return PropertyValue(stream.ReadUBits(16));\n    }\n    if (type == \"uint32\" || type == \"int32\") {\n        return PropertyValue(stream.ReadUBits(32));\n    }\n    if (type == \"uint64\" || type == \"int64\") {\n        const uint64_t low = stream.ReadUBits(32);\n        const uint64_t high = stream.ReadUBits(32);\n        return PropertyValue(static_cast<uint64_t>(low | (high << 32)));\n    }\n    if (type == \"float32\" || type == \"float\") {\n        if (fieldInfo.bitCount > 0 && fieldInfo.bitCount <= 32) {\n            // Source 2 Quantized Float\n            const uint32_t rawBits = stream.ReadUBits(static_cast<size_t>(fieldInfo.bitCount));\n            const auto maxVal = static_cast<float>((1ULL << fieldInfo.bitCount) - 1);\n            const float norm = (maxVal > 0.0f) ? static_cast<float>(rawBits) / maxVal : 0.0f;\n            const float val = fieldInfo.lowValue + norm * (fieldInfo.highValue - fieldInfo.lowValue);\n            return PropertyValue(val);\n        }\n        // Standard IEEE 754 32-bit float\n        const uint32_t raw = stream.ReadUBits(32);\n        float fVal = 0.0f;\n        std::memcpy(&fVal, &raw, sizeof(fVal));\n        return PropertyValue(fVal);\n    }\n    if (type == \"Vector\" || type == \"Vector3\") {\n        Vector3_t v{};\n        if (fieldInfo.bitCount > 0) {\n            const auto maxVal = static_cast<float>((1ULL << fieldInfo.bitCount) - 1);\n            const float range = fieldInfo.highValue - fieldInfo.lowValue;\n            v.x = fieldInfo.lowValue + (static_cast<float>(stream.ReadUBits(static_cast<size_t>(fieldInfo.bitCount))) / maxVal) * range;\n            v.y = fieldInfo.lowValue + (static_cast<float>(stream.ReadUBits(static_cast<size_t>(fieldInfo.bitCount))) / maxVal) * range;\n            v.z = fieldInfo.lowValue + (static_cast<float>(stream.ReadUBits(static_cast<size_t>(fieldInfo.bitCount))) / maxVal) * range;\n        } else {\n            uint32_t rx = stream.ReadUBits(32);\n            uint32_t ry = stream.ReadUBits(32);\n            uint32_t rz = stream.ReadUBits(32);\n            std::memcpy(&v.x, &rx, sizeof(float));\n            std::memcpy(&v.y, &ry, sizeof(float));\n            std::memcpy(&v.z, &rz, sizeof(float));\n        }\n        return PropertyValue(v);\n    }\n    if (type == \"QAngle\") {\n        QAngle_t a{};\n        if (fieldInfo.bitCount > 0) {\n            const auto maxVal = static_cast<float>((1ULL << fieldInfo.bitCount) - 1);\n            const float range = fieldInfo.highValue - fieldInfo.lowValue;\n            a.pitch = fieldInfo.lowValue + (static_cast<float>(stream.ReadUBits(static_cast<size_t>(fieldInfo.bitCount))) / maxVal) * range;\n            a.yaw   = fieldInfo.lowValue + (static_cast<float>(stream.ReadUBits(static_cast<size_t>(fieldInfo.bitCount))) / maxVal) * range;\n            a.roll  = fieldInfo.lowValue + (static_cast<float>(stream.ReadUBits(static_cast<size_t>(fieldInfo.bitCount))) / maxVal) * range;\n        } else {\n            uint32_t rp = stream.ReadUBits(32);\n            uint32_t ry = stream.ReadUBits(32);\n            uint32_t rr = stream.ReadUBits(32);\n            std::memcpy(&a.pitch, &rp, sizeof(float));\n            std::memcpy(&a.yaw,   &ry, sizeof(float));\n            std::memcpy(&a.roll,  &rr, sizeof(float));\n        }\n        return PropertyValue(a);\n    }\n    if (type == \"CEntityHandle\" || type == \"CHandle\") {\n        return PropertyValue::FromHandle(stream.ReadUBits(32));\n    }\n    if (type == \"CUtlString\" || type == \"string\") {\n        const uint32_t len = stream.ReadVarInt32();\n        std::vector<uint8_t> strBytes(len);\n        if (stream.ReadBytes(strBytes.data(), len)) {\n            return PropertyValue(std::string(reinterpret_cast<char*>(strBytes.data()), len));\n        }\n        return PropertyValue(std::string{});\n    }\n\n    // Default fallback: 32-bit unsigned integer\n    return PropertyValue(stream.ReadUBits(32));\n}\n\nvoid CEntityDeltaCodec::EncodeFieldValue(CBitWriteStream& stream, const SerializedFieldInfo& fieldInfo, const PropertyValue& val) {\n    const std::string& type = fieldInfo.varType;\n\n    if (type == \"bool\") {\n        stream.WriteUBits(val.bVal ? 1 : 0, 1);\n        return;\n    }\n    if (type == \"uint8\" || type == \"int8\") {\n        stream.WriteUBits(val.u32Val & 0xFF, 8);\n        return;\n    }\n    if (type == \"uint16\" || type == \"int16\") {\n        stream.WriteUBits(val.u32Val & 0xFFFF, 16);\n        return;\n    }\n    if (type == \"uint32\" || type == \"int32\") {\n        stream.WriteUBits(val.u32Val, 32);\n        return;\n    }\n    if (type == \"uint64\" || type == \"int64\") {\n        stream.WriteUBits(static_cast<uint32_t>(val.u64Val & 0xFFFFFFFF), 32);\n        stream.WriteUBits(static_cast<uint32_t>(val.u64Val >> 32), 32);\n        return;\n    }\n    if (type == \"float32\" || type == \"float\") {\n        if (fieldInfo.bitCount > 0 && fieldInfo.bitCount <= 32) {\n            const float clamped = std::clamp(val.fVal, fieldInfo.lowValue, fieldInfo.highValue);\n            const float range = fieldInfo.highValue - fieldInfo.lowValue;\n            const float norm = (range > 0.0f) ? (clamped - fieldInfo.lowValue) / range : 0.0f;\n            const auto maxVal = static_cast<float>((1ULL << fieldInfo.bitCount) - 1);\n            const auto raw = static_cast<uint32_t>(norm * maxVal + 0.5f);\n            stream.WriteUBits(raw, static_cast<size_t>(fieldInfo.bitCount));\n            return;\n        }\n        uint32_t raw = 0;\n        std::memcpy(&raw, &val.fVal, sizeof(raw));\n        stream.WriteUBits(raw, 32);\n        return;\n    }\n    if (type == \"Vector\" || type == \"Vector3\") {\n        if (fieldInfo.bitCount > 0) {\n            const auto maxVal = static_cast<float>((1ULL << fieldInfo.bitCount) - 1);\n            const float range = fieldInfo.highValue - fieldInfo.lowValue;\n            auto encodeComp = [&](float comp) {\n                const float c = std::clamp(comp, fieldInfo.lowValue, fieldInfo.highValue);\n                const float n = (range > 0.0f) ? (c - fieldInfo.lowValue) / range : 0.0f;\n                return static_cast<uint32_t>(n * maxVal + 0.5f);\n            };\n            stream.WriteUBits(encodeComp(val.vecVal.x), static_cast<size_t>(fieldInfo.bitCount));\n            stream.WriteUBits(encodeComp(val.vecVal.y), static_cast<size_t>(fieldInfo.bitCount));\n            stream.WriteUBits(encodeComp(val.vecVal.z), static_cast<size_t>(fieldInfo.bitCount));\n        } else {\n            uint32_t rx = 0, ry = 0, rz = 0;\n            std::memcpy(&rx, &val.vecVal.x, sizeof(float));\n            std::memcpy(&ry, &val.vecVal.y, sizeof(float));\n            std::memcpy(&rz, &val.vecVal.z, sizeof(float));\n            stream.WriteUBits(rx, 32);\n            stream.WriteUBits(ry, 32);\n            stream.WriteUBits(rz, 32);\n        }\n        return;\n    }\n    if (type == \"QAngle\") {\n        if (fieldInfo.bitCount > 0) {\n            const auto maxVal = static_cast<float>((1ULL << fieldInfo.bitCount) - 1);\n            const float range = fieldInfo.highValue - fieldInfo.lowValue;\n            auto encodeComp = [&](float comp) {\n                const float c = std::clamp(comp, fieldInfo.lowValue, fieldInfo.highValue);\n                const float n = (range > 0.0f) ? (c - fieldInfo.lowValue) / range : 0.0f;\n                return static_cast<uint32_t>(n * maxVal + 0.5f);\n            };\n            stream.WriteUBits(encodeComp(val.angVal.pitch), static_cast<size_t>(fieldInfo.bitCount));\n            stream.WriteUBits(encodeComp(val.angVal.yaw),   static_cast<size_t>(fieldInfo.bitCount));\n            stream.WriteUBits(encodeComp(val.angVal.roll),  static_cast<size_t>(fieldInfo.bitCount));\n        } else {\n            uint32_t rp = 0, ry = 0, rr = 0;\n            std::memcpy(&rp, &val.angVal.pitch, sizeof(float));\n            std::memcpy(&ry, &val.angVal.yaw,   sizeof(float));\n            std::memcpy(&rr, &val.angVal.roll,  sizeof(float));\n            stream.WriteUBits(rp, 32);\n            stream.WriteUBits(ry, 32);\n            stream.WriteUBits(rr, 32);\n        }\n        return;\n    }\n    if (type == \"CEntityHandle\" || type == \"CHandle\") {\n        stream.WriteUBits(val.handleVal, 32);\n        return;\n    }\n    if (type == \"CUtlString\" || type == \"string\") {\n        stream.WriteVarInt32(static_cast<uint32_t>(val.strVal.size()));\n        stream.WriteBytes(reinterpret_cast<const uint8_t*>(val.strVal.data()), val.strVal.size());\n        return;\n    }\n\n    stream.WriteUBits(val.u32Val, 32);\n}\n\nbool CEntityDeltaCodec::DecodeSingleEntity(CBitReadStream& stream, const EntityDeltaHeader& header, int32_t baselineIndex) {\n    if (header.updateType == EntityUpdateType::Preserve) {\n        return true;\n    }\n\n    if (header.updateType == EntityUpdateType::LeavePVS) {\n        auto it = m_ActiveEntities.find(header.entityIndex);\n        if (it != m_ActiveEntities.end()) {\n            it->second.m_bDormant = true;\n        }\n        return true;\n    }\n\n    if (header.updateType == EntityUpdateType::Delete) {\n        m_ActiveEntities.erase(header.entityIndex);\n        return true;\n    }\n\n    // For EnterPVS or DeltaUpdate, resolve serializer\n    CEntitySnapshot* pEntity = nullptr;\n\n    if (header.updateType == EntityUpdateType::EnterPVS) {\n        auto& ent = m_ActiveEntities[header.entityIndex];\n        ent.m_nEntityIndex = header.entityIndex;\n        ent.m_nClassId = header.classId;\n        ent.m_nSerialNumber = header.serialNumber;\n        ent.m_bActive = true;\n        ent.m_bDormant = false;\n\n        // Copy baseline properties if available\n        if (baselineIndex >= 0) {\n            const auto* pBaseline = m_BaselineStorage.GetBaseline(static_cast<uint32_t>(baselineIndex), header.entityIndex);\n            if (pBaseline) {\n                ent.m_Properties = *pBaseline;\n            }\n        }\n        pEntity = &ent;\n    } else {\n        auto it = m_ActiveEntities.find(header.entityIndex);\n        if (it == m_ActiveEntities.end()) {\n            return false; // Received delta for non-existent entity\n        }\n        pEntity = &it->second;\n        pEntity->m_bDormant = false;\n    }\n\n    const auto* pSerializer = GetSerializer(pEntity->m_nClassId);\n    if (!pSerializer) {\n        return false; // Missing serializer for class\n    }\n\n    // Decode changed field paths from bitstream using 40-op Huffman tree\n    const std::vector<FieldPath> fieldPaths = CFlattenedSerializer::DecodeFieldPaths(stream);\n    const auto& serializerFields = pSerializer->GetFields();\n\n    for (const auto& fp : fieldPaths) {\n        if (fp.path.empty()) continue;\n\n        // In flattened serializers, root path index addresses the flattened field array\n        const auto fieldIdx = static_cast<size_t>(fp.path[0]);\n        if (fieldIdx >= serializerFields.size()) {\n            continue;\n        }\n\n        const auto& fieldInfo = serializerFields[fieldIdx];\n        const PropertyValue newVal = DecodeFieldValue(stream, fieldInfo);\n\n        // Track change & dispatch callbacks\n        PropertyValue oldVal;\n        auto propIt = pEntity->m_Properties.find(fieldInfo.varName);\n        if (propIt != pEntity->m_Properties.end()) {\n            oldVal = propIt->second;\n        }\n\n        pEntity->m_Properties[fieldInfo.varName] = newVal;\n        pEntity->m_DirtyBitmask.Set(fieldIdx);\n\n        if (oldVal != newVal) {\n            m_Dispatcher.Dispatch(header.entityIndex, fieldInfo.varName, fp, oldVal, newVal);\n        }\n    }\n\n    return true;\n}\n\nbool CEntityDeltaCodec::DecodePacketEntities(const sdk::CSVCMsg_PacketEntities& msg,\n                                            const uint8_t* pPayloadData,\n                                            size_t nPayloadBytes) {\n    if (!pPayloadData || nPayloadBytes == 0) {\n        return false;\n    }\n\n    m_nServerTick = msg.server_tick;\n    CBitReadStream stream(pPayloadData, nPayloadBytes, true);\n\n    const int32_t totalUpdated = msg.updated_entries;\n    const bool isDelta = !msg.pending_full_frame && msg.legacy_is_delta;\n    const int32_t baselineIdx = msg.baseline;\n\n    uint32_t currentEntityIndex = 0;\n    int32_t entriesRead = 0;\n\n    while (entriesRead < totalUpdated && !stream.HasOverflowed() && stream.GetBitsRead() < stream.GetTotalBits()) {\n        const EntityDeltaHeader header = ReadEntityHeader(stream, currentEntityIndex, isDelta);\n        currentEntityIndex = header.entityIndex;\n\n        if (!DecodeSingleEntity(stream, header, baselineIdx)) {\n            return false;\n        }\n        entriesRead++;\n    }\n\n    // If update_baseline flag is set, synchronize active entities into baseline snapshot\n    if (msg.update_baseline && baselineIdx >= 0) {\n        for (const auto& [idx, ent] : m_ActiveEntities) {\n            m_BaselineStorage.SetBaseline(static_cast<uint32_t>(baselineIdx), idx, ent.m_Properties);\n        }\n    }\n\n    return true;\n}\n\nbool CEntityDeltaCodec::EncodePacketEntities(const std::vector<uint32_t>& updatedEntityIndices,\n                                            bool isDelta,\n                                            int32_t deltaFrom,\n                                            int32_t baselineIndex,\n                                            sdk::CSVCMsg_PacketEntities& outMsg,\n                                            CBitWriteStream& outStream) {\n    outMsg.delta_from = deltaFrom;\n    outMsg.baseline = baselineIndex;\n    outMsg.legacy_is_delta = isDelta;\n    outMsg.pending_full_frame = !isDelta;\n    outMsg.updated_entries = static_cast<int32_t>(updatedEntityIndices.size());\n    outMsg.server_tick = m_nServerTick;\n\n    uint32_t prevEntityIndex = 0;\n\n    for (uint32_t entIdx : updatedEntityIndices) {\n        auto it = m_ActiveEntities.find(entIdx);\n        if (it == m_ActiveEntities.end()) continue;\n\n        const auto& ent = it->second;\n        EntityDeltaHeader header;\n        header.entityIndex = entIdx;\n        header.classId = ent.m_nClassId;\n        header.serialNumber = ent.m_nSerialNumber;\n        header.updateType = isDelta ? EntityUpdateType::DeltaUpdate : EntityUpdateType::EnterPVS;\n\n        WriteEntityHeader(outStream, header, prevEntityIndex, isDelta);\n        prevEntityIndex = entIdx;\n\n        const auto* pSerializer = GetSerializer(ent.m_nClassId);\n        if (!pSerializer) continue;\n\n        const auto& fields = pSerializer->GetFields();\n\n        // Phase 1: Emit all Huffman FieldPaths\n        std::vector<size_t> changedFieldIndices;\n        int32_t lastFieldPath = -1;\n        for (size_t i = 0; i < fields.size(); ++i) {\n            if (!ent.m_DirtyBitmask.IsSet(i) && isDelta) continue;\n\n            const auto& fInfo = fields[i];\n            auto pIt = ent.m_Properties.find(fInfo.varName);\n            if (pIt == ent.m_Properties.end()) continue;\n\n            changedFieldIndices.push_back(i);\n\n            // Huffman delta: emit PlusN / PlusOne\n            const auto targetPath = static_cast<int32_t>(i);\n            const int32_t delta = targetPath - lastFieldPath;\n            if (delta == 1) {\n                outStream.WriteUBits(static_cast<uint32_t>(FieldPathOp::PlusOne), 4);\n            } else if (delta == 2) {\n                outStream.WriteUBits(static_cast<uint32_t>(FieldPathOp::PlusTwo), 4);\n            } else if (delta == 3) {\n                outStream.WriteUBits(static_cast<uint32_t>(FieldPathOp::PlusThree), 4);\n            } else if (delta == 4) {\n                outStream.WriteUBits(static_cast<uint32_t>(FieldPathOp::PlusFour), 4);\n            } else {\n                outStream.WriteUBits(static_cast<uint32_t>(FieldPathOp::PlusN), 4);\n                outStream.WriteUBits(static_cast<uint32_t>(delta), 6);\n            }\n            lastFieldPath = targetPath;\n        }\n\n        // Terminal finish token for entity property update\n        outStream.WriteUBits(static_cast<uint32_t>(FieldPathOp::Finish), 4);\n\n        // Phase 2: Encode property values in order of changed field paths\n        for (size_t idx : changedFieldIndices) {\n            const auto& fInfo = fields[idx];\n            auto pIt = ent.m_Properties.find(fInfo.varName);\n            if (pIt != ent.m_Properties.end()) {\n                EncodeFieldValue(outStream, fInfo, pIt->second);\n            }\n        }\n    }\n\n    return true;\n}\n\n} // namespace cs2::networksystem\n",
        "entity_delta_codec.h": "#ifndef CS2_ENTITY_DELTA_CODEC_H\n#define CS2_ENTITY_DELTA_CODEC_H\n\n#include <cstdint>\n#include <cstddef>\n#include <string>\n#include <string_view>\n#include <vector>\n#include <unordered_map>\n#include <functional>\n#include <optional>\n#include <memory>\n#include <variant>\n\n#include \"sdk/netmessages.hpp\"\n#include \"game/networksystem/netmessage_framing.h\"\n#include \"game/networksystem/flattened_serializers.h\"\n\nnamespace cs2::networksystem {\n\n// ============================================================================\n// 1. Property Values & Variant Types\n// ============================================================================\n\nstruct Vector3_t {\n    float x{0.0f};\n    float y{0.0f};\n    float z{0.0f};\n\n    constexpr bool operator==(const Vector3_t& o) const noexcept {\n        return x == o.x && y == o.y && z == o.z;\n    }\n};\n\nstruct QAngle_t {\n    float pitch{0.0f};\n    float yaw{0.0f};\n    float roll{0.0f};\n\n    constexpr bool operator==(const QAngle_t& o) const noexcept {\n        return pitch == o.pitch && yaw == o.yaw && roll == o.roll;\n    }\n};\n\n/**\n * @brief Variant value holding decoded entity schema properties.\n */\nstruct PropertyValue {\n    enum class Type : uint8_t {\n        None = 0,\n        Bool,\n        Int32,\n        UInt32,\n        Int64,\n        UInt64,\n        Float,\n        Vector,\n        QAngle,\n        String,\n        Handle\n    };\n\n    Type type{Type::None};\n\n    union {\n        bool        bVal;\n        int32_t     i32Val;\n        uint32_t    u32Val;\n        int64_t     i64Val;\n        uint64_t    u64Val;\n        float       fVal;\n        Vector3_t   vecVal;\n        QAngle_t    angVal;\n        uint32_t    handleVal;\n    };\n    std::string strVal{};\n\n    PropertyValue() noexcept : type(Type::None), u64Val(0) {}\n    explicit PropertyValue(bool v) noexcept : type(Type::Bool), bVal(v) {}\n    explicit PropertyValue(int32_t v) noexcept : type(Type::Int32), i32Val(v) {}\n    explicit PropertyValue(uint32_t v) noexcept : type(Type::UInt32), u32Val(v) {}\n    explicit PropertyValue(int64_t v) noexcept : type(Type::Int64), i64Val(v) {}\n    explicit PropertyValue(uint64_t v) noexcept : type(Type::UInt64), u64Val(v) {}\n    explicit PropertyValue(float v) noexcept : type(Type::Float), fVal(v) {}\n    explicit PropertyValue(Vector3_t v) noexcept : type(Type::Vector), vecVal(v) {}\n    explicit PropertyValue(QAngle_t v) noexcept : type(Type::QAngle), angVal(v) {}\n    explicit PropertyValue(std::string v) : type(Type::String), u64Val(0), strVal(std::move(v)) {}\n\n    static PropertyValue FromHandle(uint32_t h) noexcept {\n        PropertyValue pv;\n        pv.type = Type::Handle;\n        pv.handleVal = h;\n        return pv;\n    }\n\n    PropertyValue(const PropertyValue& o) : type(o.type), u64Val(o.u64Val), strVal(o.strVal) {\n        if (type == Type::Vector) vecVal = o.vecVal;\n        else if (type == Type::QAngle) angVal = o.angVal;\n    }\n\n    PropertyValue& operator=(const PropertyValue& o) {\n        if (this != &o) {\n            type = o.type;\n            u64Val = o.u64Val;\n            strVal = o.strVal;\n            if (type == Type::Vector) vecVal = o.vecVal;\n            else if (type == Type::QAngle) angVal = o.angVal;\n        }\n        return *this;\n    }\n\n    PropertyValue(PropertyValue&& o) noexcept\n        : type(o.type), u64Val(o.u64Val), strVal(std::move(o.strVal)) {\n        if (type == Type::Vector) vecVal = o.vecVal;\n        else if (type == Type::QAngle) angVal = o.angVal;\n    }\n\n    PropertyValue& operator=(PropertyValue&& o) noexcept {\n        if (this != &o) {\n            type = o.type;\n            u64Val = o.u64Val;\n            strVal = std::move(o.strVal);\n            if (type == Type::Vector) vecVal = o.vecVal;\n            else if (type == Type::QAngle) angVal = o.angVal;\n        }\n        return *this;\n    }\n\n    bool operator==(const PropertyValue& o) const noexcept;\n    bool operator!=(const PropertyValue& o) const noexcept { return !(*this == o); }\n\n    [[nodiscard]] std::string ToString() const;\n};\n\n// ============================================================================\n// 2. Entity Update Types & Stream Framing\n// ============================================================================\n\nenum class EntityUpdateType : uint8_t {\n    Preserve    = 0, // Entity state unchanged\n    LeavePVS    = 1, // Entity leaves visibility (enters dormancy)\n    EnterPVS    = 2, // Entity enters visibility (created / baseline instantiated)\n    DeltaUpdate = 3, // Entity properties delta compressed\n    Delete      = 4  // Entity destroyed / purged\n};\n\nstruct EntityDeltaHeader {\n    uint32_t entityIndex{0};\n    EntityUpdateType updateType{EntityUpdateType::Preserve};\n    uint32_t classId{0};\n    uint32_t serialNumber{0};\n};\n\n// ============================================================================\n// 3. Entity Baseline Snapshot Storage\n// ============================================================================\n\n/**\n * @brief Thread-safe baseline snapshot storage cache.\n * Source 2 maintains baseline slots (0 = default, 1 = alternate, etc.) for entity templates.\n */\nclass CEntityBaselineStorage {\npublic:\n    static constexpr uint32_t MAX_BASELINES = 64;\n\n    CEntityBaselineStorage() = default;\n\n    void SetBaseline(uint32_t baselineIndex, uint32_t entityIndex,\n                     std::unordered_map<std::string, PropertyValue> properties);\n\n    [[nodiscard]] const std::unordered_map<std::string, PropertyValue>* GetBaseline(\n        uint32_t baselineIndex, uint32_t entityIndex) const;\n\n    void CopyBaseline(uint32_t srcBaseline, uint32_t dstBaseline);\n    void ClearBaseline(uint32_t baselineIndex);\n    void ClearAll();\n\n    [[nodiscard]] size_t GetEntityCount(uint32_t baselineIndex) const;\n\nprivate:\n    // baselineIndex -> (entityIndex -> property map)\n    std::unordered_map<uint32_t, std::unordered_map<uint32_t, std::unordered_map<std::string, PropertyValue>>> m_Baselines;\n};\n\n// ============================================================================\n// 4. Field Change Callback Dispatcher\n// ============================================================================\n\nusing FieldChangeCallbackFn = std::function<void(\n    uint32_t entityIndex,\n    const std::string& fieldName,\n    const FieldPath& path,\n    const PropertyValue& oldValue,\n    const PropertyValue& newValue)>;\n\n/**\n * @brief Dispatches property change notifications to registered client subsystems.\n */\nclass CFieldChangeDispatcher {\npublic:\n    CFieldChangeDispatcher() = default;\n\n    uint32_t RegisterCallback(const std::string& fieldName, FieldChangeCallbackFn callback);\n    void UnregisterCallback(uint32_t callbackId);\n\n    void Dispatch(uint32_t entityIndex,\n                  const std::string& fieldName,\n                  const FieldPath& path,\n                  const PropertyValue& oldValue,\n                  const PropertyValue& newValue) const;\n\n    [[nodiscard]] size_t GetCallbackCount() const noexcept { return m_Callbacks.size(); }\n\nprivate:\n    struct CallbackEntry {\n        uint32_t id{0};\n        std::string fieldName;\n        FieldChangeCallbackFn callback;\n    };\n\n    uint32_t m_NextId{1};\n    std::vector<CallbackEntry> m_Callbacks;\n};\n\n// ============================================================================\n// 5. Active Entity State Snapshot\n// ============================================================================\n\nclass CEntitySnapshot {\npublic:\n    uint32_t m_nEntityIndex{0};\n    uint32_t m_nClassId{0};\n    uint32_t m_nSerialNumber{0};\n    bool m_bActive{false};\n    bool m_bDormant{false};\n\n    std::unordered_map<std::string, PropertyValue> m_Properties;\n    sdk::CNetworkPropertyDirtyBitmask<1024> m_DirtyBitmask;\n\n    [[nodiscard]] const PropertyValue* GetProperty(const std::string& name) const;\n    void SetProperty(const std::string& name, PropertyValue value);\n    [[nodiscard]] bool HasProperty(const std::string& name) const;\n};\n\n// ============================================================================\n// 6. Source 2 Entity Delta Codec (Clean-Room Engine)\n// ============================================================================\n\n/**\n * @brief Complete reconstructed Source 2 entity delta decompression and serialization engine.\n */\nclass CEntityDeltaCodec {\npublic:\n    CEntityDeltaCodec() = default;\n\n    // Serializer registration\n    void RegisterSerializer(uint32_t classId, CFlattenedSerializer serializer);\n    [[nodiscard]] const CFlattenedSerializer* GetSerializer(uint32_t classId) const;\n\n    // Baseline storage access\n    [[nodiscard]] CEntityBaselineStorage& GetBaselineStorage() noexcept { return m_BaselineStorage; }\n    [[nodiscard]] const CEntityBaselineStorage& GetBaselineStorage() const noexcept { return m_BaselineStorage; }\n\n    // Dispatcher access\n    [[nodiscard]] CFieldChangeDispatcher& GetDispatcher() noexcept { return m_Dispatcher; }\n    [[nodiscard]] const CFieldChangeDispatcher& GetDispatcher() const noexcept { return m_Dispatcher; }\n\n    // Active entity snapshot lookup\n    [[nodiscard]] const CEntitySnapshot* GetEntity(uint32_t entityIndex) const;\n    [[nodiscard]] CEntitySnapshot* GetEntityMutable(uint32_t entityIndex);\n    [[nodiscard]] const std::unordered_map<uint32_t, CEntitySnapshot>& GetAllEntities() const noexcept { return m_ActiveEntities; }\n\n    /**\n     * @brief Decodes a full CSVCMsg_PacketEntities message with bitstream payload.\n     */\n    bool DecodePacketEntities(const sdk::CSVCMsg_PacketEntities& msg,\n                             const uint8_t* pPayloadData,\n                             size_t nPayloadBytes);\n\n    /**\n     * @brief Encodes an entity delta snapshot into a CSVCMsg_PacketEntities message and bitstream.\n     */\n    bool EncodePacketEntities(const std::vector<uint32_t>& updatedEntityIndices,\n                             bool isDelta,\n                             int32_t deltaFrom,\n                             int32_t baselineIndex,\n                             sdk::CSVCMsg_PacketEntities& outMsg,\n                             CBitWriteStream& outStream);\n\n    // Bitstream low-level wire serialization helpers\n    static PropertyValue DecodeFieldValue(CBitReadStream& stream, const SerializedFieldInfo& fieldInfo);\n    static void EncodeFieldValue(CBitWriteStream& stream, const SerializedFieldInfo& fieldInfo, const PropertyValue& val);\n\n    // Entity index delta bitstream reading\n    static uint32_t ReadEntityIndexDelta(CBitReadStream& stream, uint32_t prevIndex);\n    static void WriteEntityIndexDelta(CBitWriteStream& stream, uint32_t currentIndex, uint32_t prevIndex);\n\n    // Entity delta header reading\n    static EntityDeltaHeader ReadEntityHeader(CBitReadStream& stream, uint32_t prevIndex, bool isDelta);\n    static void WriteEntityHeader(CBitWriteStream& stream, const EntityDeltaHeader& header, uint32_t prevIndex, bool isDelta);\n\n    [[nodiscard]] uint32_t GetServerTick() const noexcept { return m_nServerTick; }\n\nprivate:\n    bool DecodeSingleEntity(CBitReadStream& stream, const EntityDeltaHeader& header, int32_t baselineIndex);\n\n    uint32_t m_nServerTick{0};\n    CEntityBaselineStorage m_BaselineStorage;\n    CFieldChangeDispatcher m_Dispatcher;\n    std::unordered_map<uint32_t, CFlattenedSerializer> m_Serializers;\n    std::unordered_map<uint32_t, CEntitySnapshot> m_ActiveEntities;\n};\n\n} // namespace cs2::networksystem\n\n#endif // CS2_ENTITY_DELTA_CODEC_H\n",
        "flattened_serializers.cpp": "#include \"flattened_serializers.h\"\n#include <sstream>\n\nnamespace cs2::networksystem {\n\nstd::string FieldPath::ToString() const {\n    if (path.empty()) return \"[]\";\n    std::ostringstream ss;\n    ss << \"[\";\n    for (size_t i = 0; i < path.size(); ++i) {\n        ss << path[i];\n        if (i + 1 < path.size()) ss << \"/\";\n    }\n    ss << \"]\";\n    return ss.str();\n}\n\nCFlattenedSerializer::CFlattenedSerializer(std::string typeName, uint32_t version)\n    : m_TypeName(std::move(typeName)), m_Version(version) {}\n\nvoid CFlattenedSerializer::AddField(SerializedFieldInfo field) {\n    m_Fields.push_back(std::move(field));\n}\n\nstd::vector<FieldPath> CFlattenedSerializer::DecodeFieldPaths(CBitReadStream& stream) {\n    std::vector<FieldPath> result;\n    std::vector<int32_t> currentPath = {-1};\n\n    while (!stream.HasOverflowed()) {\n        // Read 4-bit operation code corresponding to the Huffman walk table entry\n        const uint32_t opCode = stream.ReadUBits(4);\n        if (stream.HasOverflowed()) break;\n\n        const auto op = static_cast<FieldPathOp>(opCode);\n        if (op == FieldPathOp::Finish) {\n            break;\n        }\n\n        switch (op) {\n        case FieldPathOp::PlusOne:\n            currentPath.back() += 1;\n            break;\n        case FieldPathOp::PlusTwo:\n            currentPath.back() += 2;\n            break;\n        case FieldPathOp::PlusThree:\n            currentPath.back() += 3;\n            break;\n        case FieldPathOp::PlusFour:\n            currentPath.back() += 4;\n            break;\n        case FieldPathOp::PlusN: {\n            uint32_t delta = stream.ReadUBits(6);\n            currentPath.back() += static_cast<int32_t>(delta);\n            break;\n        }\n        case FieldPathOp::PushOneLeftDeltaZero:\n            currentPath.push_back(0);\n            break;\n        case FieldPathOp::PushOneLeftDeltaOne:\n            currentPath.back() += 1;\n            currentPath.push_back(0);\n            break;\n        case FieldPathOp::PushOneLeftDeltaN: {\n            uint32_t delta = stream.ReadUBits(4);\n            currentPath.back() += static_cast<int32_t>(delta);\n            currentPath.push_back(0);\n            break;\n        }\n        case FieldPathOp::PopOnePlusOne:\n            if (currentPath.size() > 1) {\n                currentPath.pop_back();\n            }\n            currentPath.back() += 1;\n            break;\n        case FieldPathOp::PopNPlusOne: {\n            uint32_t popCount = stream.ReadUBits(3);\n            while (popCount-- > 0 && currentPath.size() > 1) {\n                currentPath.pop_back();\n            }\n            currentPath.back() += 1;\n            break;\n        }\n        case FieldPathOp::PopNPlusN: {\n            uint32_t popCount = stream.ReadUBits(3);\n            while (popCount-- > 0 && currentPath.size() > 1) {\n                currentPath.pop_back();\n            }\n            uint32_t delta = stream.ReadUBits(4);\n            currentPath.back() += static_cast<int32_t>(delta);\n            break;\n        }\n        default:\n            currentPath.back() += 1;\n            break;\n        }\n\n        result.push_back(FieldPath{currentPath});\n    }\n\n    return result;\n}\n\n} // namespace cs2::networksystem\n",
        "flattened_serializers.h": "#ifndef CS2_FLATTENED_SERIALIZERS_H\n#define CS2_FLATTENED_SERIALIZERS_H\n\n#include <cstdint>\n#include <string>\n#include <vector>\n#include <optional>\n#include \"netmessage_framing.h\"\n\nnamespace cs2::networksystem {\n\n/**\n * @brief Field path operations in Source 2 entity state serialization.\n * Reconstructed from networksystem.dll (40-operation Huffman decoder @ 0x180272420).\n */\nenum class FieldPathOp : uint8_t {\n    PlusOne = 0,\n    PlusTwo = 1,\n    PlusThree = 2,\n    PlusFour = 3,\n    PlusN = 4,\n    PushOneLeftDeltaZero = 5,\n    PushOneLeftDeltaOne = 6,\n    PushOneLeftDeltaN = 7,\n    PushThreePackets = 8,\n    PopAllButOneWalk = 9,\n    PopOnePlusOne = 10,\n    PopNPlusOne = 11,\n    PopNPlusN = 12,\n    Finish = 13\n};\n\nstruct FieldPath {\n    std::vector<int32_t> path;\n\n    [[nodiscard]] std::string ToString() const;\n};\n\nstruct SerializedFieldInfo {\n    uint32_t fieldIndex;\n    std::string varName;\n    std::string varType;\n    int32_t bitCount;\n    float lowValue;\n    float highValue;\n};\n\n/**\n * @brief Reconstructed Flattened Serializer walker from networksystem.dll.\n */\nclass CFlattenedSerializer {\npublic:\n    CFlattenedSerializer(std::string typeName, uint32_t version);\n\n    void AddField(SerializedFieldInfo field);\n    [[nodiscard]] const std::vector<SerializedFieldInfo>& GetFields() const noexcept { return m_Fields; }\n    [[nodiscard]] const std::string& GetTypeName() const noexcept { return m_TypeName; }\n    [[nodiscard]] uint32_t GetVersion() const noexcept { return m_Version; }\n\n    /**\n     * @brief Decodes field paths from the wire bitstream.\n     */\n    static std::vector<FieldPath> DecodeFieldPaths(CBitReadStream& stream);\n\nprivate:\n    std::string m_TypeName;\n    uint32_t m_Version;\n    std::vector<SerializedFieldInfo> m_Fields;\n};\n\n} // namespace cs2::networksystem\n\n#endif // CS2_FLATTENED_SERIALIZERS_H\n",
        "netmessage_framing.cpp": "#include \"netmessage_framing.h\"\n#include <cstring>\n#include <algorithm>\n\nnamespace cs2::networksystem {\n\nCBitReadStream::CBitReadStream(const uint8_t* data, size_t bitCount)\n    : m_Data(data), m_TotalBits(bitCount) {}\n\nCBitReadStream::CBitReadStream(const uint8_t* data, size_t byteCount, bool /*isByteCount*/)\n    : m_Data(data), m_TotalBits(byteCount * 8) {}\n\nuint32_t CBitReadStream::ReadUBits(size_t numBits) {\n    if (m_BitOffset + numBits > m_TotalBits || numBits > 32) {\n        m_Overflow = true;\n        return 0;\n    }\n\n    uint32_t result = 0;\n    for (size_t i = 0; i < numBits; ++i) {\n        const size_t currentBit = m_BitOffset + i;\n        const size_t byteIdx = currentBit / 8;\n        const size_t bitIdx = currentBit % 8;\n        if ((m_Data[byteIdx] >> bitIdx) & 1) {\n            result |= (1u << i);\n        }\n    }\n\n    m_BitOffset += numBits;\n    return result;\n}\n\nuint32_t CBitReadStream::ReadVarInt32() {\n    uint32_t result = 0;\n    int shift = 0;\n\n    for (int i = 0; i < 5; ++i) {\n        if (m_BitOffset + 8 > m_TotalBits) {\n            m_Overflow = true;\n            return 0;\n        }\n\n        uint32_t byteVal = ReadUBits(8);\n        result |= (byteVal & 0x7F) << shift;\n        if ((byteVal & 0x80) == 0) {\n            return result;\n        }\n        shift += 7;\n    }\n\n    m_Overflow = true;\n    return 0;\n}\n\nbool CBitReadStream::ReadBytes(uint8_t* out, size_t byteCount) {\n    if (m_BitOffset + (byteCount * 8) > m_TotalBits) {\n        m_Overflow = true;\n        return false;\n    }\n\n    for (size_t b = 0; b < byteCount; ++b) {\n        out[b] = static_cast<uint8_t>(ReadUBits(8));\n    }\n    return true;\n}\n\nCBitWriteStream::CBitWriteStream() {\n    m_Buffer.reserve(128);\n}\n\nvoid CBitWriteStream::WriteUBits(uint32_t value, size_t numBits) {\n    for (size_t i = 0; i < numBits; ++i) {\n        const size_t byteIdx = (m_BitOffset + i) / 8;\n        const size_t bitIdx = (m_BitOffset + i) % 8;\n\n        if (byteIdx >= m_Buffer.size()) {\n            m_Buffer.resize(byteIdx + 1, 0);\n        }\n\n        if ((value >> i) & 1) {\n            m_Buffer[byteIdx] |= static_cast<uint8_t>(1u << bitIdx);\n        }\n    }\n    m_BitOffset += numBits;\n}\n\nvoid CBitWriteStream::WriteVarInt32(uint32_t value) {\n    while (value >= 0x80) {\n        WriteUBits((value & 0x7F) | 0x80, 8);\n        value >>= 7;\n    }\n    WriteUBits(value & 0x7F, 8);\n}\n\nvoid CBitWriteStream::WriteBytes(const uint8_t* data, size_t byteCount) {\n    for (size_t i = 0; i < byteCount; ++i) {\n        WriteUBits(data[i], 8);\n    }\n}\n\nstd::optional<NetMessageHeader> CNetMessageFraming::ReadHeader(CBitReadStream& stream) {\n    const size_t startBits = stream.GetBitsRead();\n\n    // 2-bit prefix selector\n    const uint32_t prefix = stream.ReadUBits(2);\n    if (stream.HasOverflowed()) return std::nullopt;\n\n    uint32_t messageId = 0;\n    switch (prefix) {\n    case 0: // 00b: 4 additional bits (6 total) -> IDs 0..15\n        messageId = stream.ReadUBits(4);\n        break;\n    case 1: // 01b: 8 additional bits (10 total) -> IDs 16..271\n        messageId = stream.ReadUBits(8) + 16;\n        break;\n    case 2: // 10b: 12 additional bits (14 total) -> IDs 272..4367\n        messageId = stream.ReadUBits(12) + 272;\n        break;\n    case 3: // 11b: 32 additional bits (34 total) -> Extended IDs\n        messageId = stream.ReadUBits(32);\n        break;\n    }\n\n    if (stream.HasOverflowed()) return std::nullopt;\n\n    const uint32_t byteSize = stream.ReadVarInt32();\n    if (stream.HasOverflowed()) return std::nullopt;\n\n    const size_t headerBitSize = stream.GetBitsRead() - startBits;\n    return NetMessageHeader{messageId, byteSize, headerBitSize};\n}\n\nvoid CNetMessageFraming::WriteHeader(CBitWriteStream& stream, uint32_t messageId, uint32_t byteSize) {\n    if (messageId < 16) {\n        stream.WriteUBits(0, 2);\n        stream.WriteUBits(messageId, 4);\n    } else if (messageId < 272) {\n        stream.WriteUBits(1, 2);\n        stream.WriteUBits(messageId - 16, 8);\n    } else if (messageId < 4368) {\n        stream.WriteUBits(2, 2);\n        stream.WriteUBits(messageId - 272, 12);\n    } else {\n        stream.WriteUBits(3, 2);\n        stream.WriteUBits(messageId, 32);\n    }\n\n    stream.WriteVarInt32(byteSize);\n}\n\n} // namespace cs2::networksystem\n",
        "netmessage_framing.h": "#ifndef CS2_NETMESSAGE_FRAMING_H\n#define CS2_NETMESSAGE_FRAMING_H\n\n#include <cstdint>\n#include <cstddef>\n#include <optional>\n#include <vector>\n\nnamespace cs2::networksystem {\n\n/**\n * @brief Source 2 NetMessage Header parsed from wire bitstream.\n * Reconstructed from networksystem.dll (Wire parser FUN_1800201a0).\n */\nstruct NetMessageHeader {\n    uint32_t messageId{0};\n    uint32_t byteSize{0};\n    size_t headerBitSize{0};\n};\n\nclass CBitReadStream {\npublic:\n    explicit CBitReadStream(const uint8_t* data, size_t bitCount);\n    CBitReadStream(const uint8_t* data, size_t byteCount, bool isByteCount);\n\n    [[nodiscard]] uint32_t ReadUBits(size_t numBits);\n    [[nodiscard]] uint32_t ReadVarInt32();\n    [[nodiscard]] bool ReadBytes(uint8_t* out, size_t byteCount);\n\n    [[nodiscard]] size_t GetBitsRead() const noexcept { return m_BitOffset; }\n    [[nodiscard]] size_t GetTotalBits() const noexcept { return m_TotalBits; }\n    [[nodiscard]] bool HasOverflowed() const noexcept { return m_Overflow; }\n\nprivate:\n    const uint8_t* m_Data;\n    size_t m_TotalBits;\n    size_t m_BitOffset{0};\n    bool m_Overflow{false};\n};\n\nclass CBitWriteStream {\npublic:\n    CBitWriteStream();\n\n    void WriteUBits(uint32_t value, size_t numBits);\n    void WriteVarInt32(uint32_t value);\n    void WriteBytes(const uint8_t* data, size_t byteCount);\n\n    [[nodiscard]] const std::vector<uint8_t>& GetData() const noexcept { return m_Buffer; }\n    [[nodiscard]] size_t GetBitOffset() const noexcept { return m_BitOffset; }\n\nprivate:\n    std::vector<uint8_t> m_Buffer;\n    size_t m_BitOffset{0};\n};\n\n/**\n * @brief NetMessage framing codec reconstructing networksystem.dll protocol.\n */\nclass CNetMessageFraming {\npublic:\n    /**\n     * @brief Decodes a variable-bit header (6/10/14/34 bits) + VarInt32 payload size.\n     */\n    static std::optional<NetMessageHeader> ReadHeader(CBitReadStream& stream);\n\n    /**\n     * @brief Encodes message ID with optimal variable-bit prefix and VarInt32 size.\n     */\n    static void WriteHeader(CBitWriteStream& stream, uint32_t messageId, uint32_t byteSize);\n};\n\n} // namespace cs2::networksystem\n\n#endif // CS2_NETMESSAGE_FRAMING_H\n"
      }
    },
    {
      "module": "panorama.dll",
      "directory": "game/panorama",
      "standard": "C++20 (/std:c++20 /W4)",
      "files": {
        "panorama_engine.cpp": "// ============================================================================\n// Source 2 Clean-Room Reconstructed Panorama UI Engine & DOM Subsystem\n// Architecture: x86-64 (MSVC ABI)\n// Language Standard: C++20 (/std:c++20 /W4 /WX)\n// Zero 3rd-party dependencies - Strictly MSVC x64 C++20 compliant.\n// ============================================================================\n\n#include \"panorama_engine.h\"\n#include <cstring>\n#include <queue>\n#include <algorithm>\n\nnamespace cs2::panorama {\n\n// ============================================================================\n// DOMTreeTraversal Implementation\n// ============================================================================\n\nvoid DOMTreeTraversal::TraversePreOrder(CUIPanel* pRoot, const PanelVisitor& visitor) noexcept {\n    if (!pRoot || !visitor) return;\n    if (!visitor(pRoot)) return; // Visitor returned false: prune this branch\n\n    for (int i = 0; i < pRoot->m_nChildCount; ++i) {\n        if (pRoot->m_pChildren && pRoot->m_pChildren[i]) {\n            TraversePreOrder(pRoot->m_pChildren[i], visitor);\n        }\n    }\n}\n\nvoid DOMTreeTraversal::TraversePreOrder(const CUIPanel* pRoot, const ConstPanelVisitor& visitor) noexcept {\n    if (!pRoot || !visitor) return;\n    if (!visitor(pRoot)) return;\n\n    for (int i = 0; i < pRoot->m_nChildCount; ++i) {\n        if (pRoot->m_pChildren && pRoot->m_pChildren[i]) {\n            TraversePreOrder(static_cast<const CUIPanel*>(pRoot->m_pChildren[i]), visitor);\n        }\n    }\n}\n\nvoid DOMTreeTraversal::TraversePostOrder(CUIPanel* pRoot, const PanelVisitor& visitor) noexcept {\n    if (!pRoot || !visitor) return;\n\n    for (int i = 0; i < pRoot->m_nChildCount; ++i) {\n        if (pRoot->m_pChildren && pRoot->m_pChildren[i]) {\n            TraversePostOrder(pRoot->m_pChildren[i], visitor);\n        }\n    }\n\n    visitor(pRoot);\n}\n\nvoid DOMTreeTraversal::TraverseBreadthFirst(CUIPanel* pRoot, const PanelVisitor& visitor) {\n    if (!pRoot || !visitor) return;\n\n    std::queue<CUIPanel*> queue;\n    queue.push(pRoot);\n\n    while (!queue.empty()) {\n        CUIPanel* pCurrent = queue.front();\n        queue.pop();\n\n        if (!visitor(pCurrent)) continue;\n\n        for (int i = 0; i < pCurrent->m_nChildCount; ++i) {\n            if (pCurrent->m_pChildren && pCurrent->m_pChildren[i]) {\n                queue.push(pCurrent->m_pChildren[i]);\n            }\n        }\n    }\n}\n\nCUIPanel* DOMTreeTraversal::FindChildByID(CUIPanel* pRoot, std::string_view svID) noexcept {\n    if (!pRoot || svID.empty()) return nullptr;\n\n    CUIPanel* pFound = nullptr;\n    TraversePreOrder(pRoot, [&pFound, svID](CUIPanel* pPanel) noexcept -> bool {\n        if (pPanel->m_pszID && svID == pPanel->m_pszID) {\n            pFound = pPanel;\n            return false; // Found, terminate search\n        }\n        return true;\n    });\n\n    return pFound;\n}\n\nconst CUIPanel* DOMTreeTraversal::FindChildByID(const CUIPanel* pRoot, std::string_view svID) noexcept {\n    if (!pRoot || svID.empty()) return nullptr;\n\n    const CUIPanel* pFound = nullptr;\n    TraversePreOrder(pRoot, [&pFound, svID](const CUIPanel* pPanel) noexcept -> bool {\n        if (pPanel->m_pszID && svID == pPanel->m_pszID) {\n            pFound = pPanel;\n            return false;\n        }\n        return true;\n    });\n\n    return pFound;\n}\n\nvoid DOMTreeTraversal::FindChildrenByClass(CUIPanel* pRoot, CStyleSymbol symClass, std::vector<CUIPanel*>& outPanels) {\n    if (!pRoot) return;\n\n    TraversePreOrder(pRoot, [symClass, &outPanels](CUIPanel* pPanel) -> bool {\n        if (pPanel->HasClass(symClass)) {\n            outPanels.push_back(pPanel);\n        }\n        return true;\n    });\n}\n\nstd::size_t DOMTreeTraversal::GetDepth(const CUIPanel* pPanel) noexcept {\n    std::size_t depth = 0;\n    while (pPanel && pPanel->m_pParent) {\n        ++depth;\n        pPanel = pPanel->m_pParent;\n    }\n    return depth;\n}\n\nbool DOMTreeTraversal::IsDescendantOf(const CUIPanel* pPanel, const CUIPanel* pAncestor) noexcept {\n    if (!pPanel || !pAncestor) return false;\n\n    const CUIPanel* pCur = pPanel->m_pParent;\n    while (pCur) {\n        if (pCur == pAncestor) return true;\n        pCur = pCur->m_pParent;\n    }\n    return false;\n}\n\n// ============================================================================\n// LayoutBoxClipper Implementation\n// ============================================================================\n\nUIRect_t LayoutBoxClipper::ComputeAbsoluteBounds(const CUIPanel* pPanel) noexcept {\n    if (!pPanel) return {};\n\n    float flAbsX = pPanel->m_flActualX + pPanel->m_flPositionX;\n    float flAbsY = pPanel->m_flActualY + pPanel->m_flPositionY;\n\n    const CUIPanel* pCur = pPanel->m_pParent;\n    while (pCur) {\n        flAbsX += (pCur->m_flActualX + pCur->m_flPositionX);\n        flAbsY += (pCur->m_flActualY + pCur->m_flPositionY);\n        pCur = pCur->m_pParent;\n    }\n\n    return {flAbsX, flAbsY, pPanel->m_flActualWidth, pPanel->m_flActualHeight};\n}\n\nUIRect_t LayoutBoxClipper::ComputeScissorRect(const CUIPanel* pPanel, const UIRect_t& viewport) noexcept {\n    if (!pPanel) return viewport;\n\n    UIRect_t currentScissor = viewport;\n\n    // Traverse upwards from root to leaf to build intersection hierarchy\n    std::vector<const CUIPanel*> ancestors;\n    for (const CUIPanel* p = pPanel; p != nullptr; p = p->m_pParent) {\n        ancestors.push_back(p);\n    }\n\n    for (auto it = ancestors.rbegin(); it != ancestors.rend(); ++it) {\n        const CUIPanel* pNode = *it;\n        const auto layoutFlags = static_cast<std::uint16_t>(pNode->m_nLayoutFlags);\n        if (layoutFlags & static_cast<std::uint16_t>(EPanelLayoutFlags::ClipToBounds)) {\n            const UIRect_t nodeBounds = ComputeAbsoluteBounds(pNode);\n            currentScissor = nodeBounds.ClipTo(currentScissor);\n        }\n    }\n\n    return currentScissor;\n}\n\nCUIPanel* LayoutBoxClipper::HitTest(CUIPanel* pRoot, float flScreenX, float flScreenY, const UIRect_t& viewport) noexcept {\n    if (!pRoot || !pRoot->IsVisible()) return nullptr;\n\n    const UIRect_t bounds = ComputeAbsoluteBounds(pRoot);\n    const UIRect_t scissor = ComputeScissorRect(pRoot, viewport);\n\n    if (!bounds.Contains(flScreenX, flScreenY) || !scissor.Contains(flScreenX, flScreenY)) {\n        return nullptr;\n    }\n\n    // Hit-test children in reverse painting order (topmost child first)\n    for (int i = pRoot->m_nChildCount - 1; i >= 0; --i) {\n        if (pRoot->m_pChildren && pRoot->m_pChildren[i]) {\n            CUIPanel* pHit = HitTest(pRoot->m_pChildren[i], flScreenX, flScreenY, viewport);\n            if (pHit) return pHit;\n        }\n    }\n\n    // Check if the current panel accepts input\n    const auto layoutFlags = static_cast<std::uint16_t>(pRoot->m_nLayoutFlags);\n    if (layoutFlags & static_cast<std::uint16_t>(EPanelLayoutFlags::AcceptsInput)) {\n        return pRoot;\n    }\n\n    return nullptr;\n}\n\n// ============================================================================\n// CConcreteUIEvent Implementation\n// ============================================================================\n\nCConcreteUIEvent::CConcreteUIEvent(CUIEventID_t nEvent, PanelHandle_t hTarget, CUIPanel* pSource, bool bCanBubble) noexcept\n    : m_bCanBubble(bCanBubble) {\n    m_nEventType = nEvent;\n    m_hTargetPanel = hTarget;\n    m_pSourcePanel = pSource;\n}\n\n// ============================================================================\n// EventQueueManager Implementation\n// ============================================================================\n\nvoid EventQueueManager::EnqueueEvent(std::unique_ptr<CUIEvent> pEvent) {\n    if (pEvent) {\n        m_eventQueue.push_back(std::move(pEvent));\n    }\n}\n\nEEventDispatchStatus EventQueueManager::DispatchEventImmediate(CUIEvent* pEvent, CUIPanel* pTargetPanel) {\n    if (!pEvent) return EEventDispatchStatus::Continue;\n\n    CUIPanel* pCurrent = pTargetPanel;\n\n    while (pCurrent) {\n        // 1. Dispatch to panel client if registered\n        if (pCurrent->m_pClient) {\n            if (pCurrent->m_pClient->OnEvent(pCurrent, pEvent)) {\n                return EEventDispatchStatus::Handled;\n            }\n        }\n\n        // 2. Dispatch to registered event handlers on this panel\n        for (std::int32_t i = 0; i < pCurrent->m_nEventHandlerCount; ++i) {\n            const CUIEventHandler& handler = pCurrent->m_pEventHandlers[i];\n            if (handler.nEventType == pEvent->GetEventType()) {\n                using EventHandlerFn = bool(*)(void*, CUIEvent*);\n                if (handler.pFunction) {\n                    auto fn = reinterpret_cast<EventHandlerFn>(handler.pFunction);\n                    if (fn(handler.pContext, pEvent)) {\n                        return EEventDispatchStatus::Handled;\n                    }\n                }\n            }\n        }\n\n        // 3. Check event bubbling capability\n        if (!pEvent->CanBubble()) {\n            break;\n        }\n\n        pCurrent = pCurrent->m_pParent;\n    }\n\n    // 4. Dispatch to global unhandled event handlers\n    for (const auto& unhandled : m_unhandledHandlers) {\n        if (unhandled.nEventType == pEvent->GetEventType()) {\n            using EventHandlerFn = bool(*)(void*, CUIEvent*);\n            if (unhandled.pFunction) {\n                auto fn = reinterpret_cast<EventHandlerFn>(unhandled.pFunction);\n                if (fn(unhandled.pContext, pEvent)) {\n                    return EEventDispatchStatus::Handled;\n                }\n            }\n        }\n    }\n\n    return EEventDispatchStatus::Continue;\n}\n\nstd::size_t EventQueueManager::ProcessEventQueue(const std::function<CUIPanel*(PanelHandle_t)>& panelResolver) {\n    std::size_t processed = 0;\n\n    while (!m_eventQueue.empty()) {\n        std::unique_ptr<CUIEvent> pEvent = std::move(m_eventQueue.front());\n        m_eventQueue.pop_front();\n\n        CUIPanel* pTarget = nullptr;\n        if (panelResolver) {\n            pTarget = panelResolver(pEvent->GetTargetPanel());\n        }\n\n        DispatchEventImmediate(pEvent.get(), pTarget);\n        ++processed;\n    }\n\n    return processed;\n}\n\nvoid EventQueueManager::RegisterHandler(CUIEventID_t nEvent, CUIPanel* pTarget, void* pHandler) {\n    if (!pTarget || !pHandler) return;\n\n    // Check if re-allocation needed for m_pEventHandlers\n    if (pTarget->m_nEventHandlerCount >= pTarget->m_nEventHandlerAlloc) {\n        const std::int32_t nNewAlloc = pTarget->m_nEventHandlerAlloc ? (pTarget->m_nEventHandlerAlloc * 2) : 4;\n        auto* pNewMemory = new CUIEventHandler[static_cast<std::size_t>(nNewAlloc)];\n        if (pTarget->m_pEventHandlers) {\n            std::memcpy(pNewMemory, pTarget->m_pEventHandlers, sizeof(CUIEventHandler) * static_cast<std::size_t>(pTarget->m_nEventHandlerCount));\n            delete[] pTarget->m_pEventHandlers;\n        }\n        pTarget->m_pEventHandlers = pNewMemory;\n        pTarget->m_nEventHandlerAlloc = nNewAlloc;\n    }\n\n    pTarget->m_pEventHandlers[pTarget->m_nEventHandlerCount++] = {\n        pHandler,\n        pTarget,\n        nEvent,\n        0\n    };\n}\n\nvoid EventQueueManager::UnregisterHandler(CUIEventID_t nEvent, CUIPanel* pTarget, void* pHandler) {\n    if (!pTarget || !pTarget->m_pEventHandlers) return;\n\n    for (std::int32_t i = 0; i < pTarget->m_nEventHandlerCount; ++i) {\n        if (pTarget->m_pEventHandlers[i].nEventType == nEvent &&\n            pTarget->m_pEventHandlers[i].pFunction == pHandler) {\n            // Shift elements left\n            for (std::int32_t j = i; j < (pTarget->m_nEventHandlerCount - 1); ++j) {\n                pTarget->m_pEventHandlers[j] = pTarget->m_pEventHandlers[j + 1];\n            }\n            --pTarget->m_nEventHandlerCount;\n            break;\n        }\n    }\n}\n\nvoid EventQueueManager::RegisterUnhandled(CUIEventID_t nEvent, void* pHandler) {\n    if (!pHandler) return;\n    m_unhandledHandlers.push_back({pHandler, nullptr, nEvent, 0});\n}\n\nvoid EventQueueManager::UnregisterUnhandled(CUIEventID_t nEvent, void* pHandler) {\n    std::erase_if(m_unhandledHandlers, [nEvent, pHandler](const CUIEventHandler& h) {\n        return h.nEventType == nEvent && h.pFunction == pHandler;\n    });\n}\n\n// ============================================================================\n// CReconstructedUIEngine Implementation\n// ============================================================================\n\nCReconstructedUIEngine::CReconstructedUIEngine() {\n    // Zero-initialize members\n}\n\nCReconstructedUIEngine::~CReconstructedUIEngine() {\n    m_allocatedPanels.clear();\n}\n\nCUIPanel* CReconstructedUIEngine::CreatePanel(const char* pszType, const char* pszID, CUIPanel* pParent) {\n    (void)pszType;\n\n    auto panel = std::make_unique<CUIPanel>();\n    CUIPanel* rawPtr = panel.get();\n\n    // Default initialization\n    rawPtr->m_pszID = pszID;\n    rawPtr->m_pParent = pParent;\n    rawPtr->m_nLayoutFlags = EPanelLayoutFlags::Visible | EPanelLayoutFlags::AcceptsInput;\n    rawPtr->m_bVisibilityFlags = 0x01; // Visible\n    rawPtr->m_flActualWidth = 100.0f;\n    rawPtr->m_flActualHeight = 100.0f;\n\n    // Attach to parent DOM list if valid\n    if (pParent) {\n        if (pParent->m_nChildCount >= pParent->m_nChildAllocationCount) {\n            const std::int32_t nNewAlloc = pParent->m_nChildAllocationCount ? (pParent->m_nChildAllocationCount * 2) : 4;\n            auto** ppNewMemory = new CUIPanel*[static_cast<std::size_t>(nNewAlloc)];\n            if (pParent->m_pChildren) {\n                std::memcpy(ppNewMemory, pParent->m_pChildren, sizeof(CUIPanel*) * static_cast<std::size_t>(pParent->m_nChildCount));\n                delete[] pParent->m_pChildren;\n            }\n            pParent->m_pChildren = ppNewMemory;\n            pParent->m_nChildAllocationCount = nNewAlloc;\n        }\n        pParent->m_pChildren[pParent->m_nChildCount++] = rawPtr;\n    }\n\n    m_allocatedPanels.push_back(std::move(panel));\n    return rawPtr;\n}\n\nvoid CReconstructedUIEngine::DestroyPanel(CUIPanel* pPanel) {\n    if (!pPanel) return;\n\n    // Detach from parent\n    if (pPanel->m_pParent) {\n        CUIPanel* pParent = pPanel->m_pParent;\n        for (int i = 0; i < pParent->m_nChildCount; ++i) {\n            if (pParent->m_pChildren[i] == pPanel) {\n                for (int j = i; j < (pParent->m_nChildCount - 1); ++j) {\n                    pParent->m_pChildren[j] = pParent->m_pChildren[j + 1];\n                }\n                --pParent->m_nChildCount;\n                break;\n            }\n        }\n        pPanel->m_pParent = nullptr;\n    }\n\n    // Clean up allocated children pointers\n    if (pPanel->m_pChildren) {\n        delete[] pPanel->m_pChildren;\n        pPanel->m_pChildren = nullptr;\n        pPanel->m_nChildCount = 0;\n        pPanel->m_nChildAllocationCount = 0;\n    }\n\n    // Clean up event handlers\n    if (pPanel->m_pEventHandlers) {\n        delete[] pPanel->m_pEventHandlers;\n        pPanel->m_pEventHandlers = nullptr;\n        pPanel->m_nEventHandlerCount = 0;\n        pPanel->m_nEventHandlerAlloc = 0;\n    }\n\n    // Remove from ownership list\n    std::erase_if(m_allocatedPanels, [pPanel](const std::unique_ptr<CUIPanel>& ptr) {\n        return ptr.get() == pPanel;\n    });\n}\n\nvoid CReconstructedUIEngine::RegisterEventHandler(CUIEventID_t nEvent, CUIPanel* pTarget, void* pHandler) {\n    m_eventMgr.RegisterHandler(nEvent, pTarget, pHandler);\n}\n\nvoid CReconstructedUIEngine::UnregisterEventHandler(CUIEventID_t nEvent, CUIPanel* pTarget, void* pHandler) {\n    m_eventMgr.UnregisterHandler(nEvent, pTarget, pHandler);\n}\n\nvoid CReconstructedUIEngine::RegisterForUnhandledEvent(CUIEventID_t nEvent, void* pHandler) {\n    m_eventMgr.RegisterUnhandled(nEvent, pHandler);\n}\n\nvoid CReconstructedUIEngine::UnregisterForUnhandledEvent(CUIEventID_t nEvent, void* pHandler) {\n    m_eventMgr.UnregisterUnhandled(nEvent, pHandler);\n}\n\nvoid CReconstructedUIEngine::DispatchEvent(CUIEvent* pEvent) {\n    if (!pEvent) return;\n    CUIPanel* pTarget = pEvent->m_pSourcePanel;\n    m_eventMgr.DispatchEventImmediate(pEvent, pTarget);\n}\n\nvoid CReconstructedUIEngine::LayoutAndPaintWindows() {\n    // Process queued deferred events\n    m_eventMgr.ProcessEventQueue([this](PanelHandle_t hTarget) -> CUIPanel* {\n        for (const auto& pPanel : m_allocatedPanels) {\n            if (reinterpret_cast<PanelHandle_t>(pPanel.get()) == hTarget) {\n                return pPanel.get();\n            }\n        }\n        return nullptr;\n    });\n}\n\nvoid* CReconstructedUIEngine::CompileScript(const char* pszContext, const char* pszScript, const char* pszFilename, int nLine) {\n    (void)pszContext;\n    (void)pszScript;\n    (void)pszFilename;\n    (void)nLine;\n    return nullptr;\n}\n\nbool CReconstructedUIEngine::RunScript(CUIPanel* pPanel, const char* pszScript, const char* pszFilename) {\n    (void)pPanel;\n    (void)pszScript;\n    (void)pszFilename;\n    return true;\n}\n\nvoid* CReconstructedUIEngine::GetContextForPanel(CUIPanel* pPanel) {\n    (void)pPanel;\n    return nullptr;\n}\n\nvoid* CReconstructedUIEngine::GetIsolate() const noexcept {\n    return m_pIsolate;\n}\n\n} // namespace cs2::panorama\n",
        "panorama_engine.h": "#pragma once\n\n// ============================================================================\n// Source 2 Clean-Room Reconstructed Panorama UI Engine & DOM Subsystem\n// Architecture: x86-64 (MSVC ABI)\n// Language Standard: C++20 (/std:c++20 /W4 /WX)\n// Zero 3rd-party dependencies - Pure C++20 standard library compliant.\n// ============================================================================\n\n#include \"../../sdk/panorama.hpp\"\n#include <vector>\n#include <deque>\n#include <string_view>\n#include <functional>\n#include <memory>\n#include <string>\n\nnamespace cs2::panorama {\n\n/**\n * @brief DOM Node Hierarchy Traversal utilities for Source 2 Panorama UI.\n */\nclass DOMTreeTraversal {\npublic:\n    // Functional traversal predicates\n    using PanelVisitor = std::function<bool(CUIPanel* pPanel)>;\n    using ConstPanelVisitor = std::function<bool(const CUIPanel* pPanel)>;\n\n    // Pre-order depth-first traversal (Visitor returns false to prune branch or stop)\n    static void TraversePreOrder(CUIPanel* pRoot, const PanelVisitor& visitor) noexcept;\n    static void TraversePreOrder(const CUIPanel* pRoot, const ConstPanelVisitor& visitor) noexcept;\n\n    // Post-order depth-first traversal\n    static void TraversePostOrder(CUIPanel* pRoot, const PanelVisitor& visitor) noexcept;\n\n    // Breadth-first level-order traversal\n    static void TraverseBreadthFirst(CUIPanel* pRoot, const PanelVisitor& visitor);\n\n    // Iterative DOM Search Algorithms\n    [[nodiscard]] static CUIPanel* FindChildByID(CUIPanel* pRoot, std::string_view svID) noexcept;\n    [[nodiscard]] static const CUIPanel* FindChildByID(const CUIPanel* pRoot, std::string_view svID) noexcept;\n\n    static void FindChildrenByClass(CUIPanel* pRoot, CStyleSymbol symClass, std::vector<CUIPanel*>& outPanels);\n\n    [[nodiscard]] static std::size_t GetDepth(const CUIPanel* pPanel) noexcept;\n    [[nodiscard]] static bool IsDescendantOf(const CUIPanel* pPanel, const CUIPanel* pAncestor) noexcept;\n};\n\n/**\n * @brief Layout Box Clipping and Screen Coordinate Computation.\n */\nclass LayoutBoxClipper {\npublic:\n    /**\n     * @brief Recursively accumulates absolute screen coordinates for a given panel.\n     */\n    [[nodiscard]] static UIRect_t ComputeAbsoluteBounds(const CUIPanel* pPanel) noexcept;\n\n    /**\n     * @brief Computes effective scissor/clip rectangle taking parent hierarchy into account.\n     */\n    [[nodiscard]] static UIRect_t ComputeScissorRect(const CUIPanel* pPanel, const UIRect_t& viewport) noexcept;\n\n    /**\n     * @brief Performs precise reverse-depth hit-testing against the DOM tree.\n     */\n    [[nodiscard]] static CUIPanel* HitTest(CUIPanel* pRoot, float flScreenX, float flScreenY, const UIRect_t& viewport) noexcept;\n};\n\n/**\n * @brief Reconstructed event object for synthetic event dispatching.\n */\nclass CConcreteUIEvent final : public CUIEvent {\npublic:\n    CConcreteUIEvent(CUIEventID_t nEvent, PanelHandle_t hTarget, CUIPanel* pSource, bool bCanBubble = true) noexcept;\n\n    [[nodiscard]] CUIEventID_t GetEventType() const noexcept override { return m_nEventType; }\n    [[nodiscard]] PanelHandle_t GetTargetPanel() const noexcept override { return m_hTargetPanel; }\n    [[nodiscard]] bool CanBubble() const noexcept override { return m_bCanBubble; }\n\nprivate:\n    bool m_bCanBubble{true};\n};\n\n/**\n * @brief Thread-safe Event Dispatch Queue with bubbling and capture support.\n */\nclass EventQueueManager {\npublic:\n    EventQueueManager() = default;\n    ~EventQueueManager() = default;\n\n    // Queue an event for deferred dispatching during frame sync\n    void EnqueueEvent(std::unique_ptr<CUIEvent> pEvent);\n\n    // Direct synchronous dispatch with bubbling\n    EEventDispatchStatus DispatchEventImmediate(CUIEvent* pEvent, CUIPanel* pTargetPanel);\n\n    // Process queued events\n    std::size_t ProcessEventQueue(const std::function<CUIPanel*(PanelHandle_t)>& panelResolver);\n\n    // Event Handler Registration\n    void RegisterHandler(CUIEventID_t nEvent, CUIPanel* pTarget, void* pHandler);\n    void UnregisterHandler(CUIEventID_t nEvent, CUIPanel* pTarget, void* pHandler);\n    void RegisterUnhandled(CUIEventID_t nEvent, void* pHandler);\n    void UnregisterUnhandled(CUIEventID_t nEvent, void* pHandler);\n\n    [[nodiscard]] std::size_t GetPendingEventCount() const noexcept { return m_eventQueue.size(); }\n\nprivate:\n    std::deque<std::unique_ptr<CUIEvent>> m_eventQueue;\n    std::vector<CUIEventHandler> m_unhandledHandlers;\n};\n\n/**\n * @brief Clean-room C++20 runtime implementation of IUIEngine.\n */\nclass CReconstructedUIEngine final : public IUIEngine {\npublic:\n    CReconstructedUIEngine();\n    ~CReconstructedUIEngine() override;\n\n    // IUIEngine Implementation\n    CUIPanel* CreatePanel(const char* pszType, const char* pszID, CUIPanel* pParent) override;\n    void RegisterEventHandler(CUIEventID_t nEvent, CUIPanel* pTarget, void* pHandler) override;\n    void UnregisterEventHandler(CUIEventID_t nEvent, CUIPanel* pTarget, void* pHandler) override;\n    void RegisterForUnhandledEvent(CUIEventID_t nEvent, void* pHandler) override;\n    void UnregisterForUnhandledEvent(CUIEventID_t nEvent, void* pHandler) override;\n    void DispatchEvent(CUIEvent* pEvent) override;\n    void LayoutAndPaintWindows() override;\n\n    void* CompileScript(const char* pszContext, const char* pszScript, const char* pszFilename, int nLine) override;\n    bool RunScript(CUIPanel* pPanel, const char* pszScript, const char* pszFilename) override;\n    void* GetContextForPanel(CUIPanel* pPanel) override;\n    [[nodiscard]] void* GetIsolate() const noexcept override;\n\n    // High-level accessors\n    [[nodiscard]] EventQueueManager& GetEventManager() noexcept { return m_eventMgr; }\n    [[nodiscard]] const EventQueueManager& GetEventManager() const noexcept { return m_eventMgr; }\n    void DestroyPanel(CUIPanel* pPanel);\n\nprivate:\n    EventQueueManager           m_eventMgr;\n    std::vector<std::unique_ptr<CUIPanel>> m_allocatedPanels;\n    void*                       m_pIsolate{nullptr};\n};\n\n} // namespace cs2::panorama\n"
      }
    },
    {
      "module": "particles.dll",
      "directory": "game/particles",
      "standard": "C++20 (/std:c++20 /W4)",
      "files": {
        "smoke_voxels.cpp": "#include \"smoke_voxels.h\"\n#include <algorithm>\n\nnamespace cs2::particles {\n\nstatic inline uint32_t Part1By2(uint32_t x) noexcept {\n    x &= 0x000003ff;\n    x = (x ^ (x << 16)) & 0xff0000ff;\n    x = (x ^ (x <<  8)) & 0x0300f00f;\n    x = (x ^ (x <<  4)) & 0x030c30c3;\n    x = (x ^ (x <<  2)) & 0x09249249;\n    return x;\n}\n\nuint32_t CSmokeVoxelGrid::Morton3D(uint32_t x, uint32_t y, uint32_t z) noexcept {\n    return (Part1By2(z) << 2) | (Part1By2(y) << 1) | Part1By2(x);\n}\n\nCSmokeVoxelGrid::CSmokeVoxelGrid(const Vector3& origin, float voxelSize)\n    : m_Origin(origin), m_VoxelSize(voxelSize), m_Voxels(kTotalVoxels, 0) {}\n\nuint8_t CSmokeVoxelGrid::GetVoxel(int x, int y, int z) const {\n    if (x < 0 || x >= kGridDim || y < 0 || y >= kGridDim || z < 0 || z >= kGridDim) {\n        return 0;\n    }\n    uint32_t idx = Morton3D(static_cast<uint32_t>(x), static_cast<uint32_t>(y), static_cast<uint32_t>(z));\n    return idx < m_Voxels.size() ? m_Voxels[idx] : 0;\n}\n\nvoid CSmokeVoxelGrid::SetVoxel(int x, int y, int z, uint8_t val) {\n    if (x < 0 || x >= kGridDim || y < 0 || y >= kGridDim || z < 0 || z >= kGridDim) {\n        return;\n    }\n    uint32_t idx = Morton3D(static_cast<uint32_t>(x), static_cast<uint32_t>(y), static_cast<uint32_t>(z));\n    if (idx < m_Voxels.size()) {\n        m_Voxels[idx] = val;\n    }\n}\n\nvoid CSmokeVoxelGrid::InitializeSphere(float radius, uint8_t density) {\n    std::fill(m_Voxels.begin(), m_Voxels.end(), uint8_t{0});\n    const float radiusSqr = radius * radius;\n    const float halfDim = (kGridDim * m_VoxelSize) * 0.5f;\n\n    for (int z = 0; z < kGridDim; ++z) {\n        float pz = (z + 0.5f) * m_VoxelSize - halfDim;\n        for (int y = 0; y < kGridDim; ++y) {\n            float py = (y + 0.5f) * m_VoxelSize - halfDim;\n            for (int x = 0; x < kGridDim; ++x) {\n                float px = (x + 0.5f) * m_VoxelSize - halfDim;\n                float d2 = px * px + py * py + pz * pz;\n                if (d2 <= radiusSqr) {\n                    float falloff = 1.0f - (d2 / radiusSqr);\n                    SetVoxel(x, y, z, static_cast<uint8_t>(density * falloff));\n                }\n            }\n        }\n    }\n}\n\nbool CSmokeVoxelGrid::LineOfSight(const Vector3& start, const Vector3& end, float maxAccumulatedDensity) const {\n    Vector3 dir = end - start;\n    float dist = dir.Length();\n    if (dist < 1e-4f) return true;\n\n    // Step size equal to half a voxel\n    float stepDist = m_VoxelSize * 0.5f;\n    int numSteps = static_cast<int>(dist / stepDist) + 1;\n    Vector3 stepVector = dir * (stepDist / dist);\n\n    float accumulatedDensity = 0.0f;\n    Vector3 current = start;\n    const float halfDim = (kGridDim * m_VoxelSize) * 0.5f;\n\n    for (int i = 0; i < numSteps; ++i) {\n        Vector3 local = current - m_Origin;\n        int vx = static_cast<int>((local.x + halfDim) / m_VoxelSize);\n        int vy = static_cast<int>((local.y + halfDim) / m_VoxelSize);\n        int vz = static_cast<int>((local.z + halfDim) / m_VoxelSize);\n\n        uint8_t voxelVal = GetVoxel(vx, vy, vz);\n        accumulatedDensity += static_cast<float>(voxelVal) * (stepDist / m_VoxelSize);\n\n        if (accumulatedDensity >= maxAccumulatedDensity) {\n            return false; // Vision fully blocked\n        }\n\n        current = current + stepVector;\n    }\n\n    return true; // Vision clear\n}\n\nvoid CSmokeVoxelGrid::CarveBulletTunnel(const Vector3& start, const Vector3& end, float tunnelRadius) {\n    Vector3 dir = end - start;\n    float dist = dir.Length();\n    if (dist < 1e-4f) return;\n\n    Vector3 dirNorm = dir * (1.0f / dist);\n    const float halfDim = (kGridDim * m_VoxelSize) * 0.5f;\n    const float tunnelRadiusSqr = tunnelRadius * tunnelRadius;\n\n    for (int z = 0; z < kGridDim; ++z) {\n        float pz = (z + 0.5f) * m_VoxelSize - halfDim + m_Origin.z;\n        for (int y = 0; y < kGridDim; ++y) {\n            float py = (y + 0.5f) * m_VoxelSize - halfDim + m_Origin.y;\n            for (int x = 0; x < kGridDim; ++x) {\n                float px = (x + 0.5f) * m_VoxelSize - halfDim + m_Origin.x;\n                Vector3 pt{px, py, pz};\n                \n                // Distance from pt to line segment [start, end]\n                Vector3 v = pt - start;\n                float proj = v.Dot(dirNorm);\n                if (proj >= 0.0f && proj <= dist) {\n                    Vector3 closest = start + (dirNorm * proj);\n                    if ((pt - closest).Dot(pt - closest) <= tunnelRadiusSqr) {\n                        SetVoxel(x, y, z, 0);\n                    }\n                }\n            }\n        }\n    }\n}\n\nvoid CSmokeVoxelGrid::DetonateHE(const Vector3& center, float blastRadius) {\n    const float halfDim = (kGridDim * m_VoxelSize) * 0.5f;\n    const float blastRadiusSqr = blastRadius * blastRadius;\n\n    for (int z = 0; z < kGridDim; ++z) {\n        float pz = (z + 0.5f) * m_VoxelSize - halfDim + m_Origin.z;\n        for (int y = 0; y < kGridDim; ++y) {\n            float py = (y + 0.5f) * m_VoxelSize - halfDim + m_Origin.y;\n            for (int x = 0; x < kGridDim; ++x) {\n                float px = (x + 0.5f) * m_VoxelSize - halfDim + m_Origin.x;\n                Vector3 pt{px, py, pz};\n                Vector3 delta = pt - center;\n                if (delta.Dot(delta) <= blastRadiusSqr) {\n                    SetVoxel(x, y, z, 0);\n                }\n            }\n        }\n    }\n}\n\n} // namespace cs2::particles\n",
        "smoke_voxels.h": "#ifndef CS2_SMOKE_VOXELS_H\n#define CS2_SMOKE_VOXELS_H\n\n#include <cstdint>\n#include <vector>\n#include <cmath>\n\nnamespace cs2::particles {\n\nstruct Vector3 {\n    float x{0.0f}, y{0.0f}, z{0.0f};\n\n    Vector3 operator+(const Vector3& o) const noexcept { return {x + o.x, y + o.y, z + o.z}; }\n    Vector3 operator-(const Vector3& o) const noexcept { return {x - o.x, y - o.y, z - o.z}; }\n    Vector3 operator*(float s) const noexcept { return {x * s, y * s, z * s}; }\n    [[nodiscard]] float Dot(const Vector3& o) const noexcept { return x * o.x + y * o.y + z * o.z; }\n    [[nodiscard]] float Length() const noexcept { return std::sqrt(Dot(*this)); }\n};\n\n/**\n * @brief Reconstructed Volumetric Smoke Grid from particles.dll.\n * Analyzed in FUN_1809b7f50 (LineOfSightThroughSmoke).\n */\nclass CSmokeVoxelGrid {\npublic:\n    static constexpr int kGridDim = 32;\n    static constexpr int kTotalVoxels = kGridDim * kGridDim * kGridDim; // 32,768\n\n    CSmokeVoxelGrid(const Vector3& origin, float voxelSize);\n\n    /**\n     * @brief Encodes 3D integer coordinates into Morton Z-order index.\n     */\n    static uint32_t Morton3D(uint32_t x, uint32_t y, uint32_t z) noexcept;\n\n    /**\n     * @brief Initializes a spherical smoke plume of radius R.\n     */\n    void InitializeSphere(float radius, uint8_t density = 255);\n\n    /**\n     * @brief Performs 3D DDA raymarch to check if line of sight is obstructed by smoke.\n     * Reconstructed from particles.dll @ FUN_1809b7f50.\n     * @return true if visible (not blocked), false if smoke blocks vision.\n     */\n    [[nodiscard]] bool LineOfSight(const Vector3& start, const Vector3& end, float maxAccumulatedDensity = 120.0f) const;\n\n    /**\n     * @brief Carves a cylindrical or conical bullet tunnel through the smoke voxels.\n     */\n    void CarveBulletTunnel(const Vector3& start, const Vector3& end, float tunnelRadius);\n\n    /**\n     * @brief Carves a spherical cavity produced by an HE grenade detonation.\n     */\n    void DetonateHE(const Vector3& center, float blastRadius);\n\n    [[nodiscard]] uint8_t GetVoxel(int x, int y, int z) const;\n    void SetVoxel(int x, int y, int z, uint8_t val);\n\n    [[nodiscard]] const Vector3& GetOrigin() const noexcept { return m_Origin; }\n    [[nodiscard]] float GetVoxelSize() const noexcept { return m_VoxelSize; }\n\nprivate:\n    Vector3 m_Origin;\n    float m_VoxelSize;\n    std::vector<uint8_t> m_Voxels;\n};\n\n} // namespace cs2::particles\n\n#endif // CS2_SMOKE_VOXELS_H\n"
      }
    },
    {
      "module": "pulse_system.dll",
      "directory": "game/pulse_system",
      "standard": "C++20 (/std:c++20 /W4)",
      "files": {
        "pulse_interpreter.cpp": "#include \"pulse_interpreter.h\"\n#include <algorithm>\n\nnamespace cs2::pulse_system {\n\nvoid CPulseInterpreter::LoadProgram(std::vector<PGDInstruction_t> instructions) {\n    m_Code = std::move(instructions);\n}\n\nuint32_t CPulseInterpreter::SpawnFiber() {\n    PulseFiber_t fiber;\n    fiber.fiberId = m_NextFiberId++;\n    fiber.state = FiberState::Ready;\n    fiber.programCounter = 0;\n    m_Fibers.push_back(fiber);\n    return fiber.fiberId;\n}\n\nconst PulseFiber_t* CPulseInterpreter::GetFiber(uint32_t fiberId) const {\n    for (const auto& fiber : m_Fibers) {\n        if (fiber.fiberId == fiberId) {\n            return &fiber;\n        }\n    }\n    return nullptr;\n}\n\nFiberState CPulseInterpreter::StepFiber(uint32_t fiberId, size_t maxSteps) {\n    auto it = std::find_if(m_Fibers.begin(), m_Fibers.end(), [fiberId](const PulseFiber_t& f) {\n        return f.fiberId == fiberId;\n    });\n\n    if (it == m_Fibers.end()) return FiberState::Terminated;\n    PulseFiber_t& fiber = *it;\n\n    if (fiber.state == FiberState::Terminated) return FiberState::Terminated;\n    fiber.state = FiberState::Running;\n\n    size_t executedSteps = 0;\n\n    // PulseInstructionDispatchLoop (0x18008f810)\n    while (fiber.programCounter < m_Code.size() && executedSteps < maxSteps) {\n        const PGDInstruction_t& inst = m_Code[fiber.programCounter++];\n        executedSteps++;\n\n        switch (inst.opcode) {\n        case PulseOpcode::NOP:\n            break;\n\n        case PulseOpcode::LOAD_INT:\n            if (inst.dstReg < 16) {\n                fiber.registers[inst.dstReg] = inst.immInt;\n            }\n            break;\n\n        case PulseOpcode::LOAD_FLOAT:\n            if (inst.dstReg < 16) {\n                // Store float as bit pattern in register\n                *reinterpret_cast<double*>(&fiber.registers[inst.dstReg]) = inst.immDouble;\n            }\n            break;\n\n        case PulseOpcode::MOVE:\n            if (inst.dstReg < 16 && inst.srcRegA < 16) {\n                fiber.registers[inst.dstReg] = fiber.registers[inst.srcRegA];\n            }\n            break;\n\n        case PulseOpcode::ADD_INT:\n            if (inst.dstReg < 16 && inst.srcRegA < 16 && inst.srcRegB < 16) {\n                fiber.registers[inst.dstReg] = fiber.registers[inst.srcRegA] + fiber.registers[inst.srcRegB];\n            }\n            break;\n\n        case PulseOpcode::SUB_INT:\n            if (inst.dstReg < 16 && inst.srcRegA < 16 && inst.srcRegB < 16) {\n                fiber.registers[inst.dstReg] = fiber.registers[inst.srcRegA] - fiber.registers[inst.srcRegB];\n            }\n            break;\n\n        case PulseOpcode::MUL_FLOAT:\n            if (inst.dstReg < 16 && inst.srcRegA < 16 && inst.srcRegB < 16) {\n                double a = *reinterpret_cast<double*>(&fiber.registers[inst.srcRegA]);\n                double b = *reinterpret_cast<double*>(&fiber.registers[inst.srcRegB]);\n                double res = a * b;\n                *reinterpret_cast<double*>(&fiber.registers[inst.dstReg]) = res;\n            }\n            break;\n\n        case PulseOpcode::JUMP:\n            fiber.programCounter = static_cast<size_t>(inst.immInt);\n            break;\n\n        case PulseOpcode::JUMP_IF_ZERO:\n            if (inst.srcRegA < 16 && fiber.registers[inst.srcRegA] == 0) {\n                fiber.programCounter = static_cast<size_t>(inst.immInt);\n            }\n            break;\n\n        case PulseOpcode::CALL_DOMAIN_METHOD:\n            // Placeholder for native CEngine / Schema binding method dispatch\n            break;\n\n        case PulseOpcode::YIELD:\n            fiber.state = FiberState::Yielded;\n            return FiberState::Yielded;\n\n        case PulseOpcode::RETURN:\n            fiber.state = FiberState::Terminated;\n            return FiberState::Terminated;\n        }\n    }\n\n    if (fiber.programCounter >= m_Code.size()) {\n        fiber.state = FiberState::Terminated;\n    }\n\n    return fiber.state;\n}\n\n} // namespace cs2::pulse_system\n",
        "pulse_interpreter.h": "#ifndef CS2_PULSE_INTERPRETER_H\n#define CS2_PULSE_INTERPRETER_H\n\n#include <cstdint>\n#include <vector>\n#include <memory>\n\nnamespace cs2::pulse_system {\n\nenum class PulseOpcode : uint16_t {\n    NOP = 0,\n    LOAD_INT = 1,\n    LOAD_FLOAT = 2,\n    MOVE = 3,\n    ADD_INT = 4,\n    SUB_INT = 5,\n    MUL_FLOAT = 6,\n    JUMP = 7,\n    JUMP_IF_ZERO = 8,\n    CALL_DOMAIN_METHOD = 9,\n    YIELD = 10,\n    RETURN = 11\n};\n\n/**\n * @brief 56-byte aligned instruction descriptor matching pulse_system.dll @ 0x18008f810.\n */\nstruct alignas(8) PGDInstruction_t {\n    PulseOpcode opcode{PulseOpcode::NOP};\n    uint16_t flags{0};\n    uint16_t dstReg{0};\n    uint16_t srcRegA{0};\n    uint16_t srcRegB{0};\n    uint16_t pad{0};\n    int64_t immInt{0};\n    double immDouble{0.0};\n    uint64_t domainMethodId{0};\n    uint64_t extraData[2]{0, 0};\n};\nstatic_assert(sizeof(PGDInstruction_t) == 56, \"PGDInstruction_t must match exactly 56 bytes\");\n\nenum class FiberState : uint8_t {\n    Ready = 0,\n    Running = 1,\n    Yielded = 2,\n    Terminated = 3\n};\n\nstruct PulseFiber_t {\n    uint32_t fiberId{0};\n    FiberState state{FiberState::Ready};\n    size_t programCounter{0};\n    int64_t registers[16]{0};\n};\n\n/**\n * @brief Reconstructed Pulse Interpreter Engine from pulse_system.dll.\n */\nclass CPulseInterpreter {\npublic:\n    CPulseInterpreter() = default;\n\n    /**\n     * @brief Loads program instructions into bytecode cache.\n     */\n    void LoadProgram(std::vector<PGDInstruction_t> instructions);\n\n    /**\n     * @brief Spawns a new execution fiber coroutine.\n     */\n    uint32_t SpawnFiber();\n\n    /**\n     * @brief Executes instructions for a fiber until yield or return.\n     * Matches PulseInstructionDispatchLoop @ 0x18008f810.\n     */\n    FiberState StepFiber(uint32_t fiberId, size_t maxSteps = 1000);\n\n    [[nodiscard]] const PulseFiber_t* GetFiber(uint32_t fiberId) const;\n\nprivate:\n    std::vector<PGDInstruction_t> m_Code;\n    std::vector<PulseFiber_t> m_Fibers;\n    uint32_t m_NextFiberId{1};\n};\n\n} // namespace cs2::pulse_system\n\n#endif // CS2_PULSE_INTERPRETER_H\n"
      }
    },
    {
      "module": "scenesystem.dll",
      "directory": "game/scenesystem",
      "standard": "C++20 (/std:c++20 /W4)",
      "files": {
        "scene_system.cpp": "#include \"scene_system.h\"\n\nnamespace cs2::scenesystem {\n\n// Static scene graph verification stub\nstatic CSceneAnimatableObject s_SampleAnimObject;\n\n} // namespace cs2::scenesystem\n",
        "scene_system.h": "#ifndef CS2_SCENESYSTEM_H\n#define CS2_SCENESYSTEM_H\n\n#include <cstdint>\n#include <cstddef>\n#include \"../shared/math_types.h\"\n\nnamespace cs2::scenesystem {\n\n#define CS2_PAD(bytes, name) private: [[maybe_unused]] std::uint8_t name[bytes]; public:\n\n/**\n * @brief Animatable Scene Graph Object (CSceneAnimatableObject)\n * Reconstructed from scenesystem.dll @ 0x1805f17c0.\n */\nclass CSceneAnimatableObject {\npublic:\n    virtual ~CSceneAnimatableObject() = default;\n\n    CS2_PAD(0x18, m_pad0);\n    shared::Vector3D m_vOrigin{};           // +0x20: World coordinates\n    CS2_PAD(0x0C, m_pad2c);\n    shared::QAngle   m_angRotation{};        // +0x38: World rotation angles\n};\n\n/**\n * @brief Source 2 Scene System Interface (CSceneSystem)\n * Token: \"SceneSystem_002\" in scenesystem.dll\n * VTable: +0x5F17C0 (199 slots)\n */\nclass CSceneSystem {\npublic:\n    virtual ~CSceneSystem() = default;\n\n    // Slot 8: CreateSceneView\n    virtual void* CreateSceneView() = 0;\n\n    // Slot 9: DestroySceneView\n    virtual void DestroySceneView(void* pView) = 0;\n\n    // Slot 22: GetActiveScene\n    virtual void* GetActiveScene() = 0;\n};\n\n#undef CS2_PAD\n\n} // namespace cs2::scenesystem\n\n#endif // CS2_SCENESYSTEM_H\n"
      }
    },
    {
      "module": "schemasystem.dll",
      "directory": "game/schemasystem",
      "standard": "C++20 (/std:c++20 /W4)",
      "files": {
        "schemasystem.cpp": "#include \"schemasystem.h\"\n\nnamespace cs2::schemasystem {\n\nCSchemaSystem& CSchemaSystem::Get() {\n    static CSchemaSystem instance;\n    return instance;\n}\n\nCSchemaSystem::CSchemaSystem() = default;\n\nvoid CSchemaSystem::RegisterClass(const std::string& moduleName, const std::string& className, int32_t classSize) {\n    SchemaClass cls;\n    cls.name = className;\n    cls.moduleName = moduleName;\n    cls.size = classSize;\n    m_Classes[className] = std::move(cls);\n}\n\nvoid CSchemaSystem::RegisterField(const std::string& className, const std::string& fieldName, const std::string& type, int32_t offset) {\n    auto it = m_Classes.find(className);\n    if (it != m_Classes.end()) {\n        it->second.fields[fieldName] = SchemaField{fieldName, type, offset};\n    }\n}\n\nconst SchemaClass* CSchemaSystem::FindDeclaredClass(const std::string& className) const {\n    auto it = m_Classes.find(className);\n    if (it != m_Classes.end()) {\n        return &it->second;\n    }\n    return nullptr;\n}\n\nint32_t CSchemaSystem::GetFieldOffset(const std::string& className, const std::string& fieldName) const {\n    const SchemaClass* cls = FindDeclaredClass(className);\n    if (!cls) return -1;\n\n    auto it = cls->fields.find(fieldName);\n    if (it != cls->fields.end()) {\n        return it->second.offset;\n    }\n    return -1;\n}\n\n} // namespace cs2::schemasystem\n",
        "schemasystem.h": "#ifndef CS2_SCHEMASYSTEM_H\n#define CS2_SCHEMASYSTEM_H\n\n#include <cstdint>\n#include <string>\n#include <string_view>\n#include <unordered_map>\n\nnamespace cs2::schemasystem {\n\nstruct SchemaField {\n    std::string name;\n    std::string type;\n    int32_t offset;\n};\n\nstruct SchemaClass {\n    std::string name;\n    std::string moduleName;\n    int32_t size;\n    std::unordered_map<std::string, SchemaField> fields;\n};\n\n/**\n * @brief Reconstructed CSchemaSystem from schemasystem.dll\n * Verified MurmurHash2 implementation matching schemasystem.dll @ 0x180010380.\n */\nclass CSchemaSystem {\npublic:\n    static CSchemaSystem& Get();\n\n    static constexpr uint32_t MurmurHash2(std::string_view str) noexcept {\n        const uint32_t len = static_cast<uint32_t>(str.length());\n        if (len == 0) return 0;\n\n        constexpr uint32_t m = 0x5bd1e995;\n        constexpr int r = 24;\n\n        uint32_t h = len ^ 0xbaadfeed;\n        const char* data = str.data();\n        uint32_t remaining = len;\n\n        while (remaining >= 4) {\n            uint32_t k = static_cast<uint8_t>(data[0]) |\n                        (static_cast<uint8_t>(data[1]) << 8) |\n                        (static_cast<uint8_t>(data[2]) << 16) |\n                        (static_cast<uint8_t>(data[3]) << 24);\n\n            k *= m;\n            k ^= k >> r;\n            k *= m;\n\n            h *= m;\n            h ^= k;\n\n            data += 4;\n            remaining -= 4;\n        }\n\n        if (remaining == 3) h ^= static_cast<uint8_t>(data[2]) << 16;\n        if (remaining >= 2) h ^= static_cast<uint8_t>(data[1]) << 8;\n        if (remaining >= 1) {\n            h ^= static_cast<uint8_t>(data[0]);\n            h *= m;\n        }\n\n        h ^= h >> 13;\n        h *= m;\n        h ^= h >> 15;\n\n        return h;\n    }\n\n    void RegisterClass(const std::string& moduleName, const std::string& className, int32_t classSize);\n    void RegisterField(const std::string& className, const std::string& fieldName, const std::string& type, int32_t offset);\n\n    [[nodiscard]] const SchemaClass* FindDeclaredClass(const std::string& className) const;\n    [[nodiscard]] int32_t GetFieldOffset(const std::string& className, const std::string& fieldName) const;\n\nprivate:\n    CSchemaSystem();\n    std::unordered_map<std::string, SchemaClass> m_Classes;\n};\n\n} // namespace cs2::schemasystem\n\n#endif // CS2_SCHEMASYSTEM_H\n"
      }
    },
    {
      "module": "server.dll",
      "directory": "game/server",
      "standard": "C++20 (/std:c++20 /W4)",
      "files": {
        "bullet_penetration.cpp": "#include \"bullet_penetration.h\"\n#include <limits>\n#include <random>\n\nnamespace cs2::server {\n\n// -------------------------------------------------------------------------\n// Authoritative Distance Falloff Formula\n// Reverse engineered from FUN_180a8fca0 @ 0x180a8fd0a in server.dll:\n//   DIVSS XMM7, dword ptr [0x18178c014]   ; 500.0f\n//   CALL powf                             ; powf(rangeModifier, distance / 500.0f)\n//   MULSS XMM0, XMM6                      ; * baseDamage\n// -------------------------------------------------------------------------\nfloat CBulletPenetration::ApplyDistanceFalloff(float baseDamage, float rangeModifier, float distance) {\n    if (rangeModifier <= 0.0f || baseDamage <= 0.0f) {\n        return 0.0f;\n    }\n    const float exponent = distance / 500.0f;\n    return baseDamage * std::pow(rangeModifier, exponent);\n}\n\n// -------------------------------------------------------------------------\n// Authoritative Surface Penetration Evaluation\n// Reverse engineered from FUN_180a8fca0 in server.dll:\n// - Evaluates air travel intervals via distance falloff\n// - Evaluates solid surface material absorption via Rubikon descriptors\n// - Computes entry, exit, and distance damage absorption\n// -------------------------------------------------------------------------\nbool CBulletPenetration::EvaluateSurfacePenetration(BulletData_t& bullet,\n                                                   const SurfaceHitData_t& hit,\n                                                   bool ffBulletPenetration) {\n    // ---------------------------------------------------------------------\n    // Interval Type 1: Air Travel (flags bit 0 == 0)\n    // ---------------------------------------------------------------------\n    if ((hit.flags & 1) == 0) {\n        const float segmentStart = bullet.maxRange * hit.tEnter;\n        const float segmentEnd   = bullet.maxRange * hit.tExit;\n        const float segmentDist  = std::max(0.0f, segmentEnd - segmentStart);\n\n        bullet.currentDamage = ApplyDistanceFalloff(bullet.currentDamage,\n                                                   bullet.rangeModifier,\n                                                   segmentDist);\n        return true;\n    }\n\n    // ---------------------------------------------------------------------\n    // Interval Type 2: Solid Material Penetration (flags bit 0 == 1)\n    // ---------------------------------------------------------------------\n    float penMod = hit.enterSurface.bulletPenetrationDistanceModifier;\n    const float totalDistanceTraveled = bullet.maxRange * hit.tExit;\n\n    // Failure condition check @ 0x180a8fdf0:\n    // If distance > 3000 units, penMod < 0.1, or no penetration power remains\n    if (totalDistanceTraveled > 3000.0f || penMod < 0.1f || bullet.penetrationCount < 1) {\n        bullet.stopped = true;\n        return false;\n    }\n\n    // Measure material thickness via Euclidean distance between enter and exit\n    const float thickness = (hit.exitPoint - hit.enterPoint).Length();\n\n    // Friendly fire flesh penetration check @ 0x180a90107\n    if (hit.enterSurface.materialChar == CHAR_TEX_FLESH && hit.isTeammate && !ffBulletPenetration) {\n        bullet.stopped = true;\n        return false;\n    }\n\n    // Default damage modifier constant @ 0x1819196c8\n    float damageModifier = 0.16f;\n\n    // ---------------------------------------------------------------------\n    // Material Pairing & Thickness Discriminators @ 0x180a9028a - 0x180a90328\n    // ---------------------------------------------------------------------\n    if (hit.enterSurface.materialChar == hit.exitSurface.materialChar) {\n        // Same material on entry and exit faces\n        const uint16_t mat = hit.enterSurface.materialChar;\n\n        // Wood ('W') and Cardboard ('U') have low density absorption\n        if (mat == CHAR_TEX_CARDBOARD || mat == CHAR_TEX_WOOD) {\n            penMod = 3.0f;\n        } else if (mat == CHAR_TEX_PLASTIC) {\n            penMod = 2.0f;\n        }\n\n        // Thin surface branch: thickness < 6.0 units (@ 0x180a902c4)\n        if (thickness < 6.0f) {\n            // Glass ('G') and Shatterglass ('Y')\n            if (mat == CHAR_TEX_GLASS || mat == CHAR_TEX_SHATTERGLASS) {\n                damageModifier = 0.05f;\n                penMod = 3.0f;\n            }\n\n            // Chainlink fence / wire mesh (Bit 13 set on both surfaces @ 0x180a902eb)\n            if (hit.enterIsGrate && hit.exitIsGrate) {\n                penMod = 32.0f;\n                damageModifier = 0.00001f; // Virtually zero damage lost\n            }\n        } else {\n            // Thick surface branch: thickness >= 6.0 units\n            if (hit.enterIsGrate && hit.exitIsGrate) {\n                penMod = 3.0f;\n            }\n        }\n    } else {\n        // Multi-material composite / transition: minimum penetration modifier applies\n        penMod = std::min(hit.enterSurface.bulletPenetrationDistanceModifier,\n                          hit.exitSurface.bulletPenetrationDistanceModifier);\n        damageModifier = 0.16f;\n    }\n\n    // ---------------------------------------------------------------------\n    // Authoritative Damage Loss Formulation @ 0x180a90328 - 0x180a903d1\n    // ---------------------------------------------------------------------\n    // penModInv = max(0.0f, 1.0f / penMod)\n    const float penModInv = std::max(0.0f, 1.0f / penMod);\n\n    // lostDistance = (thickness^2 * penModInv) / 24.0f\n    const float lostDistance = (thickness * thickness * penModInv) / 24.0f;\n\n    // lostEntry = max(0.0f, (3.0f / penPower) * 1.25f) * (penModInv * 3.0f) + (damageModifier * currentDamage)\n    const float penPowerTerm = std::max(0.0f, (3.0f / std::max(0.01f, bullet.penetrationPower)) * 1.25f);\n    const float lostEntry    = (penPowerTerm * (penModInv * 3.0f)) + (damageModifier * bullet.currentDamage);\n\n    const float totalLost = lostDistance + lostEntry;\n    const float remainingDamage = bullet.currentDamage - totalLost;\n\n    bullet.currentDamage = remainingDamage;\n\n    // Damage threshold check @ 0x180a9049a:\n    // If remaining damage < 1.0f, the bullet is spent and stopped in the surface\n    if (remainingDamage < 1.0f) {\n        bullet.stopped = true;\n        return false;\n    }\n\n    // Decrement remaining penetrated object counter\n    bullet.penetrationCount--;\n    bullet.stopped = false;\n    return true;\n}\n\n// -------------------------------------------------------------------------\n// Authoritative ClipTraceToPlayers Implementation\n// Reverse engineered from FUN_180181cd0 in server.dll\n// -------------------------------------------------------------------------\nbool CBulletPenetration::ClipTraceToPlayers(const Vector3& vStart,\n                                           const Vector3& vEnd,\n                                           const std::vector<HitPlayerPawn_t>& players,\n                                           uint32_t attackerHandle,\n                                           SurfaceHitData_t& outHit) {\n    bool bHitAny = false;\n    float flSmallestFraction = 1.0f;\n    const Vector3 vRayDelta = vEnd - vStart;\n    const float flRayLength = vRayDelta.Length();\n\n    if (flRayLength < 1e-4f) {\n        return false;\n    }\n\n    const Vector3 vRayDir = vRayDelta / flRayLength;\n\n    // Skin margin expansion constant (+40.0 units for player hull bounding box query)\n    constexpr float kPlayerSkinMargin = 40.0f;\n\n    for (const auto& player : players) {\n        if (!player.isAlive || player.entityHandle == attackerHandle) {\n            continue;\n        }\n\n        // 1. Broadphase: Expand player bounding box by skin margin\n        const Vector3 boxMin = player.origin + player.mins - Vector3{kPlayerSkinMargin, kPlayerSkinMargin, kPlayerSkinMargin};\n        const Vector3 boxMax = player.origin + player.maxs + Vector3{kPlayerSkinMargin, kPlayerSkinMargin, kPlayerSkinMargin};\n\n        // Ray vs AABB slab intersection\n        float tmin = 0.0f;\n        float tmax = flRayLength;\n        bool bBoxIntersect = true;\n\n        for (int i = 0; i < 3; ++i) {\n            const float rStart = (i == 0) ? vStart.x : (i == 1 ? vStart.y : vStart.z);\n            const float rDir   = (i == 0) ? vRayDir.x : (i == 1 ? vRayDir.y : vRayDir.z);\n            const float bMin   = (i == 0) ? boxMin.x : (i == 1 ? boxMin.y : boxMin.z);\n            const float bMax   = (i == 0) ? boxMax.x : (i == 1 ? boxMax.y : boxMax.z);\n\n            if (std::abs(rDir) < 1e-8f) {\n                if (rStart < bMin || rStart > bMax) {\n                    bBoxIntersect = false;\n                    break;\n                }\n            } else {\n                float invD = 1.0f / rDir;\n                float t0 = (bMin - rStart) * invD;\n                float t1 = (bMax - rStart) * invD;\n                if (t0 > t1) std::swap(t0, t1);\n                tmin = std::max(tmin, t0);\n                tmax = std::min(tmax, t1);\n                if (tmin > tmax) {\n                    bBoxIntersect = false;\n                    break;\n                }\n            }\n        }\n\n        if (!bBoxIntersect || tmin > flSmallestFraction * flRayLength) {\n            continue;\n        }\n\n        // 2. Narrowphase: Iterate player hitboxes (capsules / AABBs)\n        for (const auto& hitbox : player.hitboxes) {\n            const Vector3 hbCenter = player.origin + (hitbox.mins + hitbox.maxs) * 0.5f;\n            const float hbRadius = hitbox.radius > 0.0f ? hitbox.radius : (hitbox.maxs - hitbox.mins).Length() * 0.5f;\n\n            // Sphere / capsule raycast approximation\n            const Vector3 vToSphere = hbCenter - vStart;\n            const float tProj = vToSphere.Dot(vRayDir);\n\n            if (tProj < 0.0f || tProj > flRayLength) {\n                continue;\n            }\n\n            const Vector3 vClosest = vStart + vRayDir * tProj;\n            const float distSqr = (hbCenter - vClosest).LengthSqr();\n\n            if (distSqr <= hbRadius * hbRadius) {\n                const float dDist = std::sqrt(std::max(0.0f, hbRadius * hbRadius - distSqr));\n                const float tHit = std::max(0.0f, tProj - dDist);\n                const float fraction = tHit / flRayLength;\n\n                if (fraction < flSmallestFraction) {\n                    flSmallestFraction = fraction;\n                    bHitAny = true;\n\n                    outHit.tEnter = fraction;\n                    outHit.tExit = std::min(1.0f, (tProj + dDist) / flRayLength);\n                    outHit.flags = 1; // Solid material\n                    outHit.enterPoint = vStart + vRayDir * tHit;\n                    outHit.exitPoint  = vStart + vRayDir * (tProj + dDist);\n                    outHit.enterNormal = (outHit.enterPoint - hbCenter).Normalized();\n                    outHit.exitNormal  = (outHit.exitPoint - hbCenter).Normalized();\n                    outHit.enterSurface = GetSurfaceProperties(CHAR_TEX_FLESH);\n                    outHit.exitSurface  = GetSurfaceProperties(CHAR_TEX_FLESH);\n                    outHit.hitEntityHandle = player.entityHandle;\n                    outHit.hitGroupId = hitbox.hitGroup;\n                }\n            }\n        }\n    }\n\n    return bHitAny;\n}\n\n// -------------------------------------------------------------------------\n// Authoritative FireBullets Simulation\n// Reverse engineered from CCSPlayerPawn::FireBullet (FUN_1802975d0)\n// and FUN_180a70240 in server.dll\n// -------------------------------------------------------------------------\nstd::vector<BulletImpact_t> CBulletPenetration::FireBulletsAuthoritative(\n    const FireBulletParams_t& params,\n    const std::vector<SurfaceHitData_t>& worldGeometry,\n    const std::vector<HitPlayerPawn_t>& players,\n    bool ffBulletPenetration) {\n\n    std::vector<BulletImpact_t> allImpacts;\n\n    for (int pellet = 0; pellet < std::max(1, params.numPellets); ++pellet) {\n        BulletData_t bullet;\n        bullet.currentDamage    = params.baseDamage;\n        bullet.penetrationPower = params.flPenetrationPower;\n        bullet.rangeModifier    = params.flRangeModifier;\n        bullet.maxRange         = params.flMaxRange;\n        bullet.penetrationCount = params.iPenetrationCount;\n        bullet.stopped          = false;\n\n        Vector3 rayDir = params.vDirection.Normalized();\n\n        // Integrate spread / inaccuracy perturbation if multiple pellets or spread > 0\n        if (params.flSpread > 0.0f || params.flInaccuracy > 0.0f) {\n            float totalSpread = params.flSpread + params.flInaccuracy;\n            float angle = (float)pellet * (6.2831853f / (float)std::max(1, params.numPellets));\n            rayDir.x += std::cos(angle) * totalSpread * 0.05f;\n            rayDir.y += std::sin(angle) * totalSpread * 0.05f;\n            rayDir = rayDir.Normalized();\n        }\n\n        const Vector3 vRayStart = params.vStart;\n        const Vector3 vRayEnd   = params.vStart + rayDir * params.flMaxRange;\n\n        // Collect all candidate intervals (world geometry + player hitboxes)\n        std::vector<SurfaceHitData_t> intervals = worldGeometry;\n\n        SurfaceHitData_t playerHit;\n        if (ClipTraceToPlayers(vRayStart, vRayEnd, players, params.attackerHandle, playerHit)) {\n            intervals.push_back(playerHit);\n        }\n\n        // Sort intervals in topological distance order along ray\n        std::sort(intervals.begin(), intervals.end(),\n                  [](const SurfaceHitData_t& a, const SurfaceHitData_t& b) {\n                      return a.tEnter < b.tEnter;\n                  });\n\n        float totalTravelDistance = 0.0f;\n        Vector3 lastPoint = vRayStart;\n\n        for (size_t i = 0; i < intervals.size(); ++i) {\n            SurfaceHitData_t& interval = intervals[i];\n\n            // 1. Distance falloff across air gap prior to this interval\n            float gapDist = (interval.enterPoint - lastPoint).Length();\n            if (gapDist > 0.0f) {\n                bullet.currentDamage = ApplyDistanceFalloff(bullet.currentDamage,\n                                                           bullet.rangeModifier,\n                                                           gapDist);\n                totalTravelDistance += gapDist;\n            }\n\n            // 2. Solid impact event emission\n            if (interval.flags & 1) {\n                BulletImpact_t impact;\n                impact.position = interval.enterPoint;\n                impact.normal = interval.enterNormal;\n                impact.damageApplied = bullet.currentDamage;\n                impact.totalDistance = totalTravelDistance;\n                impact.objectIndex = static_cast<int>(i);\n                impact.hitEntityHandle = interval.hitEntityHandle;\n                impact.hitGroupId = interval.hitGroupId;\n                allImpacts.push_back(impact);\n\n                // 3. Evaluate surface penetration\n                bool penetrated = EvaluateSurfacePenetration(bullet, interval, ffBulletPenetration);\n                totalTravelDistance += (interval.exitPoint - interval.enterPoint).Length();\n                lastPoint = interval.exitPoint;\n\n                if (!penetrated || bullet.stopped) {\n                    break; // Bullet energy exhausted\n                }\n            } else {\n                lastPoint = interval.exitPoint;\n            }\n        }\n    }\n\n    return allImpacts;\n}\n\n// -------------------------------------------------------------------------\n// Physics Material Default Lookup Table\n// -------------------------------------------------------------------------\nSurfaceData_t CBulletPenetration::GetSurfaceProperties(uint16_t materialChar) {\n    SurfaceData_t data;\n    data.materialChar = materialChar;\n    data.bulletsPenetrate = true;\n\n    switch (materialChar) {\n        case CHAR_TEX_CONCRETE:\n            data.bulletPenetrationDistanceModifier = 1.0f;\n            data.bulletPenetrationDamageModifier = 0.16f;\n            break;\n\n        case CHAR_TEX_WOOD:\n            data.bulletPenetrationDistanceModifier = 3.0f; // High penetration through wood\n            data.bulletPenetrationDamageModifier = 0.16f;\n            break;\n\n        case CHAR_TEX_CARDBOARD:\n            data.bulletPenetrationDistanceModifier = 3.0f;\n            data.bulletPenetrationDamageModifier = 0.16f;\n            break;\n\n        case CHAR_TEX_PLASTIC:\n            data.bulletPenetrationDistanceModifier = 2.0f;\n            data.bulletPenetrationDamageModifier = 0.16f;\n            break;\n\n        case CHAR_TEX_METAL:\n            data.bulletPenetrationDistanceModifier = 0.5f; // Hard to penetrate solid metal\n            data.bulletPenetrationDamageModifier = 0.16f;\n            break;\n\n        case CHAR_TEX_GLASS:\n        case CHAR_TEX_SHATTERGLASS:\n            data.bulletPenetrationDistanceModifier = 3.0f;\n            data.bulletPenetrationDamageModifier = 0.05f; // Very low damage loss on thin glass\n            break;\n\n        case CHAR_TEX_FLESH:\n            data.bulletPenetrationDistanceModifier = 1.0f;\n            data.bulletPenetrationDamageModifier = 0.16f;\n            break;\n\n        case CHAR_TEX_DIRT:\n        case CHAR_TEX_SAND:\n            data.bulletPenetrationDistanceModifier = 0.8f;\n            data.bulletPenetrationDamageModifier = 0.16f;\n            break;\n\n        default:\n            data.bulletPenetrationDistanceModifier = 1.0f;\n            data.bulletPenetrationDamageModifier = 0.16f;\n            break;\n    }\n\n    return data;\n}\n\n} // namespace cs2::server\n",
        "bullet_penetration.h": "#ifndef CS2_SERVER_BULLET_PENETRATION_H\n#define CS2_SERVER_BULLET_PENETRATION_H\n\n#include \"../client/viewmatrix.h\"\n#include <cstdint>\n#include <cmath>\n#include <vector>\n#include <algorithm>\n#include <string>\n\nnamespace cs2::server {\n\nusing client::Vector3;\n\n// -------------------------------------------------------------------------\n// Source 2 / CS2 Authoritative Material Texture Characters\n// (From surfacedata.txt / Rubikon Physics Surface Properties)\n// -------------------------------------------------------------------------\nconstexpr uint16_t CHAR_TEX_ANTLION      = 'A'; // 0x41\nconstexpr uint16_t CHAR_TEX_BLOODYFLESH  = 'B'; // 0x42\nconstexpr uint16_t CHAR_TEX_CONCRETE     = 'C'; // 0x43\nconstexpr uint16_t CHAR_TEX_DIRT         = 'D'; // 0x44\nconstexpr uint16_t CHAR_TEX_EGGSHELL     = 'E'; // 0x45\nconstexpr uint16_t CHAR_TEX_FLESH        = 'F'; // 0x46\nconstexpr uint16_t CHAR_TEX_GRATE        = 'G'; // 0x47 (Grate / Chainlink)\nconstexpr uint16_t CHAR_TEX_GLASS        = 'G'; // 0x47 (Glass)\nconstexpr uint16_t CHAR_TEX_ALIENFLESH   = 'H'; // 0x48\nconstexpr uint16_t CHAR_TEX_CLIP         = 'I'; // 0x49\nconstexpr uint16_t CHAR_TEX_PLASTIC      = 'L'; // 0x4C (Light metal / sheet metal / plastic)\nconstexpr uint16_t CHAR_TEX_METAL        = 'M'; // 0x4D (Solid Metal)\nconstexpr uint16_t CHAR_TEX_SAND         = 'N'; // 0x4E\nconstexpr uint16_t CHAR_TEX_FOLIAGE      = 'O'; // 0x4F\nconstexpr uint16_t CHAR_TEX_COMPUTER     = 'P'; // 0x50\nconstexpr uint16_t CHAR_TEX_SLOSH        = 'S'; // 0x53\nconstexpr uint16_t CHAR_TEX_TILE         = 'T'; // 0x54\nconstexpr uint16_t CHAR_TEX_CARDBOARD    = 'U'; // 0x55 (Cardboard / thin panel)\nconstexpr uint16_t CHAR_TEX_VENT         = 'V'; // 0x56\nconstexpr uint16_t CHAR_TEX_WOOD         = 'W'; // 0x57 (Wood)\nconstexpr uint16_t CHAR_TEX_SHATTERGLASS = 'Y'; // 0x59 (Shatterglass / Plexiglass)\n\n// Surface descriptor bitflags (Bit 13 tested via BT reg, 0xd @ 0x180a902eb)\nconstexpr uint32_t SURF_FLAG_GRATE_MESH  = (1 << 13); // 0x2000\n\n// -------------------------------------------------------------------------\n// Reconstructed 32-Byte Rubikon Physics Surface Property Layout\n// Reversed from FUN_180be1120 in server.dll (surfaceproperties_game.txt)\n// -------------------------------------------------------------------------\nstruct SurfaceData_t {\n    float maxSpeedFactor{1.0f};                    // +0x00\n    float jumpFactor{1.0f};                        // +0x04\n    float bulletPenetrationDistanceModifier{1.0f}; // +0x08 (flPenetrationDistance)\n    float bulletPenetrationDamageModifier{0.16f};  // +0x0C (flDamageModifier, default 0.16)\n    uint32_t stringToken{0};                       // +0x10 (MurmurHash2 / FNV-1a token)\n    uint16_t materialChar{CHAR_TEX_CONCRETE};      // +0x14 (e.g. 'C', 'W', 'M', 'G', 'F', 'Y')\n    uint16_t soundStackMaterial{0};                // +0x16\n    uint8_t flags18{0};                            // +0x18\n    bool isStairs{false};                          // +0x19\n    bool isSlippery{false};                        // +0x1A\n    uint8_t flags1B{0};                            // +0x1B\n    bool reflectBullets{false};                    // +0x1C\n    bool reduceWeaponImpact{false};                // +0x1D\n    bool bulletsPenetrate{true};                   // +0x1E\n    uint8_t pad1F{0};                              // +0x1F\n};\n\n// -------------------------------------------------------------------------\n// In-Flight Bullet Parameter Block\n// Corresponds to param_2 array in FUN_180a8fca0\n// -------------------------------------------------------------------------\nstruct BulletData_t {\n    float currentDamage{0.0f};      // param_2[0]: Current accumulated damage\n    float penetrationPower{1.0f};   // param_2[1]: Weapon penetration power (e.g. 1.0, 2.0, 2.5)\n    float rangeModifier{0.98f};     // param_2[2]: Weapon range falloff modifier (e.g. 0.98)\n    float maxRange{8192.0f};        // param_2[3]: Trace scale / maximum weapon range\n    int penetrationCount{4};        // param_2[4]: Remaining penetrating objects\n    bool stopped{false};            // param_2[5]: Flag set if bullet is stopped\n};\n\n// -------------------------------------------------------------------------\n// Surface Hit & Ray Interval Descriptor\n// Corresponds to param_3 interval record in FUN_180a6ca20 / FUN_180a8fca0\n// -------------------------------------------------------------------------\nstruct SurfaceHitData_t {\n    float tEnter{0.0f};             // Entry fraction along ray [0.0, 1.0]\n    float tExit{1.0f};              // Exit fraction along ray [0.0, 1.0]\n    uint32_t flags{1};              // Bit 0: 0 = Air interval, 1 = Solid material interval\n    Vector3 enterPoint;             // World coordinate where ray entered\n    Vector3 exitPoint;              // World coordinate where ray exited\n    Vector3 enterNormal;            // Surface normal at entry\n    Vector3 exitNormal;             // Surface normal at exit\n    SurfaceData_t enterSurface;     // Physical surface descriptor at entry\n    SurfaceData_t exitSurface;      // Physical surface descriptor at exit\n    bool enterIsGrate{false};       // Grate / chainlink flag at entry (Bit 13)\n    bool exitIsGrate{false};        // Grate / chainlink flag at exit (Bit 13)\n    bool isTeammate{false};         // True if hit pawn belongs to shooter's team\n    uint32_t hitEntityHandle{0xFFFFFFFF}; // Entity handle of hit object\n    int hitGroupId{0};              // Hitgroup (0=generic, 1=head, 2=chest, etc.)\n};\n\n// -------------------------------------------------------------------------\n// Authoritative Bullet Impact Event Data\n// Emitted as \"bullet_impact\" event in FUN_180a70240 @ 0x180a70a61\n// -------------------------------------------------------------------------\nstruct BulletImpact_t {\n    Vector3 position;\n    Vector3 normal;\n    float damageApplied{0.0f};\n    float totalDistance{0.0f};\n    int objectIndex{0};\n    uint32_t hitEntityHandle{0xFFFFFFFF};\n    int hitGroupId{0};\n};\n\n// -------------------------------------------------------------------------\n// Player Hitbox & Capsule Model for Authoritative Hitscan\n// -------------------------------------------------------------------------\nstruct PlayerHitbox_t {\n    int hitboxId{0};\n    int hitGroup{0}; // 1 = Head, 2 = Chest, 3 = Stomach, 4 = Left Arm, 5 = Right Arm, 6 = Left Leg, 7 = Right Leg\n    Vector3 mins;\n    Vector3 maxs;\n    float radius{0.0f}; // If radius > 0, treated as capsule; otherwise OBB/AABB\n};\n\nstruct HitPlayerPawn_t {\n    uint32_t entityHandle{0xFFFFFFFF};\n    uint32_t teamId{0};\n    bool isAlive{true};\n    Vector3 origin;\n    Vector3 mins{-16.0f, -16.0f, 0.0f};\n    Vector3 maxs{16.0f, 16.0f, 72.0f};\n    std::vector<PlayerHitbox_t> hitboxes;\n};\n\n// -------------------------------------------------------------------------\n// Weapon Fire Parameters (CCSPlayerPawn::FireBullet @ FUN_1802975d0)\n// -------------------------------------------------------------------------\nstruct FireBulletParams_t {\n    Vector3 vStart;\n    Vector3 vDirection;\n    float baseDamage{30.0f};\n    float flRangeModifier{0.98f};\n    float flPenetrationPower{2.0f};\n    float flMaxRange{8192.0f};\n    int iPenetrationCount{4};\n    int numPellets{1};\n    float flSpread{0.0f};\n    float flInaccuracy{0.0f};\n    uint32_t attackerHandle{0xFFFFFFFF};\n    uint32_t attackerTeam{2};\n};\n\n// -------------------------------------------------------------------------\n// Authoritative Bullet Penetration & Surface Physics Pipeline\n// Reconstructed clean-room from server.dll\n// -------------------------------------------------------------------------\nclass CBulletPenetration {\npublic:\n    /**\n     * @brief Authoritative damage distance falloff formula:\n     * flDamage = baseDamage * pow(flRangeModifier, distance / 500.0f)\n     * Reverse engineered from FUN_180a8fca0 @ 0x180a8fd0a\n     */\n    static float ApplyDistanceFalloff(float baseDamage, float rangeModifier, float distance);\n\n    /**\n     * @brief Authoritative surface penetration evaluation loop.\n     * Reverse engineered from FUN_180a8fca0 in server.dll.\n     * Computes material absorption, penetration power reduction, and damage loss.\n     * \n     * @param bullet In-flight bullet tracking state (damage, power, count, stopped)\n     * @param hit Surface interval information (thickness, materials, normals)\n     * @param ffBulletPenetration Value of ConVar ff_damage_bullet_penetration (default false)\n     * @return true if bullet penetrates through surface; false if stopped\n     */\n    static bool EvaluateSurfacePenetration(BulletData_t& bullet,\n                                          const SurfaceHitData_t& hit,\n                                          bool ffBulletPenetration = false);\n\n    /**\n     * @brief Ray vs Player Bounding Capsule / Studio Hitbox Clipping\n     * Reverse engineered from ClipTraceToPlayers (FUN_180181cd0 in server.dll).\n     * Tests candidate players within a 40-unit skin expansion margin.\n     * \n     * @param vStart Ray origin\n     * @param vEnd Ray termination\n     * @param players Candidate active player pawns\n     * @param attackerHandle Handle of shooter to prevent self-collision\n     * @param outHit Output hit information if a player was intercepted\n     * @return true if a player was hit, false otherwise\n     */\n    static bool ClipTraceToPlayers(const Vector3& vStart,\n                                  const Vector3& vEnd,\n                                  const std::vector<HitPlayerPawn_t>& players,\n                                  uint32_t attackerHandle,\n                                  SurfaceHitData_t& outHit);\n\n    /**\n     * @brief Authoritative Bullet Hitscan Pipeline\n     * Reverse engineered from CCSPlayerPawn::FireBullet (FUN_1802975d0) and FUN_180a70240.\n     * Traces rays through world geometry and player hitboxes, evaluating penetration\n     * across sequential intervals and collecting authoritative impacts.\n     */\n    static std::vector<BulletImpact_t> FireBulletsAuthoritative(\n        const FireBulletParams_t& params,\n        const std::vector<SurfaceHitData_t>& worldGeometry,\n        const std::vector<HitPlayerPawn_t>& players,\n        bool ffBulletPenetration = false);\n\n    /**\n     * @brief Standard surface property lookup table generator for common CS2 materials.\n     */\n    static SurfaceData_t GetSurfaceProperties(uint16_t materialChar);\n};\n\n} // namespace cs2::server\n\n#endif // CS2_SERVER_BULLET_PENETRATION_H\n",
        "controller_pawn.cpp": "#include \"controller_pawn.h\"\n\nnamespace cs2::server {\n\nbool CPlayerLifecycleManager::PossessPawn(PlayerController& controller, PlayerPawn& pawn) {\n    if (!pawn.isAlive) {\n        return false;\n    }\n\n    // Bi-directional link between persistent Controller and transient Pawn\n    controller.pawnHandle = pawn.handle;\n    pawn.controllerHandle = controller.handle;\n    return true;\n}\n\nbool CPlayerLifecycleManager::OnPawnDeath(PlayerController& controller, PlayerPawn& deadPawn) {\n    deadPawn.isAlive = false;\n    deadPawn.health = 0;\n\n    // Pawn unlinked upon death while Controller remains persistent in scoreboard/HUD\n    deadPawn.controllerHandle = EntityHandle(INVALID_EHANDLE);\n    controller.pawnHandle = EntityHandle(INVALID_EHANDLE);\n    return true;\n}\n\nbool CPlayerLifecycleManager::TakeoverBotPawn(PlayerController& controller, PlayerPawn& botPawn) {\n    if (!botPawn.isAlive || !botPawn.isBot) {\n        return false;\n    }\n\n    // Seamless bot possession transfer\n    return PossessPawn(controller, botPawn);\n}\n\n} // namespace cs2::server\n",
        "controller_pawn.h": "#ifndef CS2_SERVER_CONTROLLER_PAWN_H\n#define CS2_SERVER_CONTROLLER_PAWN_H\n\n#include <cstdint>\n#include <string>\n\nnamespace cs2::server {\n\nconstexpr uint32_t INVALID_EHANDLE = 0xFFFFFFFF;\nconstexpr uint32_t ENTRY_INDEX_MASK = 0x7FFF;\nconstexpr uint32_t SERIAL_NUMBER_SHIFT = 15;\n\n/**\n * @brief 32-bit CEntityHandle packed bitfield\n * Bits 0..14: Entry Index (0..32,767)\n * Bits 15..31: Serial Number (ABA protection)\n */\nstruct EntityHandle {\n    uint32_t raw = INVALID_EHANDLE;\n\n    constexpr EntityHandle() noexcept = default;\n    constexpr explicit EntityHandle(uint32_t val) noexcept : raw(val) {}\n    constexpr EntityHandle(uint32_t entryIndex, uint32_t serialNum) noexcept\n        : raw((entryIndex & ENTRY_INDEX_MASK) | (serialNum << SERIAL_NUMBER_SHIFT)) {}\n\n    [[nodiscard]] constexpr bool IsValid() const noexcept { return raw != INVALID_EHANDLE; }\n    [[nodiscard]] constexpr uint32_t GetEntryIndex() const noexcept { return raw & ENTRY_INDEX_MASK; }\n    [[nodiscard]] constexpr uint32_t GetSerialNumber() const noexcept { return raw >> SERIAL_NUMBER_SHIFT; }\n};\n\nstruct PlayerPawn {\n    EntityHandle handle;\n    EntityHandle controllerHandle;\n    int health = 100;\n    bool isAlive = true;\n    bool isBot = false;\n};\n\nstruct PlayerController {\n    EntityHandle handle;\n    EntityHandle pawnHandle;\n    std::string playerName;\n    int ping = 15;\n    int score = 0;\n};\n\n/**\n * @brief Reconstructed Controller vs Pawn Topology from server.dll\n * Decoupled controller entity possession, observer camera handover, and bot takeover.\n */\nclass CPlayerLifecycleManager {\npublic:\n    static bool PossessPawn(PlayerController& controller, PlayerPawn& pawn);\n    static bool OnPawnDeath(PlayerController& controller, PlayerPawn& deadPawn);\n    static bool TakeoverBotPawn(PlayerController& controller, PlayerPawn& botPawn);\n};\n\n} // namespace cs2::server\n\n#endif // CS2_SERVER_CONTROLLER_PAWN_H\n",
        "hit_registration_damage.cpp": "/**\n * @file hit_registration_damage.cpp\n * @brief Clean-room C++20 implementation of CS2 Hit Registration, HitGroup Scaling & Armor Damage Absorption.\n *\n * Reconstructed from server.dll:\n *   - CCSPlayerPawn::IsArmored                    (Baseline RVA: 0x00aca700, Build 26144732 RVA: 0x00ad7ba0)\n *   - CCSPlayerPawn::ApplyArmorDamageCalculation  (Baseline RVA: 0x00a81050, Build 26144732 RVA: 0x00a8e500)\n */\n\n#include \"hit_registration_damage.h\"\n\nnamespace cs2::server {\n\n/**\n * Reconstructed from server.dll!CCSPlayerPawn::IsArmored\n * Baseline RVA: 0x00aca700 | Build 26144732 RVA: 0x00ad7ba0\n *\n * Disassembly logic:\n *   45 32 C0                   xor r8b, r8b\n *   83 B9 0C 15 00 00 00       cmp dword ptr [rcx + 0x150c], 0  ; m_ArmorValue <= 0\n *   7E 3C                      jle short loc_ret_false\n *   83 FA 08                   cmp edx, 8                       ; hitgroup > 8\n *   77 37                      ja short loc_ret_false\n *   ...                        ; Jump table switch on hitGroup\n */\nbool CCSPlayerPawnDamageEvaluator::IsArmored(HitGroup_t hitGroup) const {\n    if (this->m_ArmorValue <= 0) {\n        return false;\n    }\n\n    switch (hitGroup) {\n        case HitGroup_t::HITGROUP_GENERIC:\n        case HitGroup_t::HITGROUP_CHEST:\n        case HitGroup_t::HITGROUP_STOMACH:\n        case HitGroup_t::HITGROUP_LEFTARM:\n        case HitGroup_t::HITGROUP_RIGHTARM:\n            return true;\n\n        case HitGroup_t::HITGROUP_HEAD:\n        case HitGroup_t::HITGROUP_NECK:\n            // Head/Neck requires m_pItemServices->m_bHasHelmet (+0xB18 -> +0x41)\n            return this->m_ItemServices.m_bHasHelmet;\n\n        case HitGroup_t::HITGROUP_LEFTLEG:\n        case HitGroup_t::HITGROUP_RIGHTLEG:\n        case HitGroup_t::HITGROUP_GEAR:\n        default:\n            // Legs are never protected by Kevlar in Counter-Strike 2\n            return false;\n    }\n}\n\n/**\n * Evaluates distance falloff:\n *   D(d) = D_base * (flRangeModifier ^ (d / 500.0f))\n */\nfloat CCSPlayerPawnDamageEvaluator::ApplyDistanceDropoff(\n    float baseDamage,\n    float rangeModifier,\n    float distanceUnits\n) {\n    if (distanceUnits <= 0.0f) {\n        return baseDamage;\n    }\n    return baseDamage * std::pow(rangeModifier, distanceUnits / 500.0f);\n}\n\n/**\n * Returns HitGroup_t damage multiplier combined with team-specific ConVars:\n *   - Head:    4.00x * mp_damage_scale_{ct,t}_head\n *   - Stomach: 1.25x * mp_damage_scale_{ct,t}_body\n *   - Chest:   1.00x * mp_damage_scale_{ct,t}_body\n *   - Arms:    1.00x * mp_damage_scale_{ct,t}_body\n *   - Legs:    0.75x * mp_damage_scale_{ct,t}_body\n */\nfloat CCSPlayerPawnDamageEvaluator::GetHitgroupDamageMultiplier(\n    HitGroup_t hitGroup,\n    const ServerDamageConVars& cvars\n) const {\n    if (cvars.mp_damage_headshot_only && hitGroup != HitGroup_t::HITGROUP_HEAD) {\n        return 0.0f;\n    }\n\n    const bool isCT = (this->m_iTeamNum == 3);\n    const float headScale = isCT ? cvars.mp_damage_scale_ct_head : cvars.mp_damage_scale_t_head;\n    const float bodyScale = isCT ? cvars.mp_damage_scale_ct_body : cvars.mp_damage_scale_t_body;\n\n    switch (hitGroup) {\n        case HitGroup_t::HITGROUP_HEAD:\n            return 4.0f * headScale;\n\n        case HitGroup_t::HITGROUP_STOMACH:\n            return 1.25f * bodyScale;\n\n        case HitGroup_t::HITGROUP_LEFTLEG:\n        case HitGroup_t::HITGROUP_RIGHTLEG:\n            return 0.75f * bodyScale;\n\n        case HitGroup_t::HITGROUP_CHEST:\n        case HitGroup_t::HITGROUP_LEFTARM:\n        case HitGroup_t::HITGROUP_RIGHTARM:\n        case HitGroup_t::HITGROUP_GENERIC:\n        default:\n            return 1.0f * bodyScale;\n    }\n}\n\n/**\n * Reconstructed from server.dll!CCSPlayerPawn::ApplyArmorDamageCalculation\n * Baseline RVA: 0x00a81050 | Build 26144732 RVA: 0x00a8e500\n *\n * Key Constants Verified in Disassembly:\n *   - RVA 0x00a810e7: movss xmm6, cs:flHalf (0.5f) -> flArmorBonus = 0.5f, flArmorRatioScale = 0.5f\n *   - RVA 0x00a8121a: movss xmm0, cs:flOne  (1.0f) -> minimum 1 point armor durability loss on armored hit\n */\nDamageCalculationResult CCSPlayerPawnDamageEvaluator::ApplyArmorDamageCalculation(\n    CTakeDamageInfo& info,\n    float baseWeaponDamage,\n    float rangeModifier,\n    float distanceUnits,\n    const ServerDamageConVars& cvars\n) {\n    DamageCalculationResult res{};\n\n    // 1. Distance attenuation\n    res.flRawDistanceDamage = ApplyDistanceDropoff(baseWeaponDamage, rangeModifier, distanceUnits);\n\n    // 2. Hitgroup multiplier\n    const float hgMult = GetHitgroupDamageMultiplier(info.m_nHitGroup, cvars);\n    res.flHitgroupScaledDmg = res.flRawDistanceDamage * hgMult;\n\n    info.m_flOriginalDamage = res.flHitgroupScaledDmg;\n    info.m_flDamage         = res.flHitgroupScaledDmg;\n\n    float flHealthDamage = info.m_flDamage;\n    float flArmorDamage  = 0.0f;\n\n    // 3. Check if damage is bullet/slash/club/generic and hitgroup is protected by Kevlar/Helmet\n    const bool eligibleDamageType = !(info.m_bitsDamageType & (DMG_FALL | DMG_SHOCK | DMG_BURN));\n    if (flHealthDamage > 0.0f && eligibleDamageType && this->IsArmored(info.m_nHitGroup)) {\n        res.bWasArmoredHit = true;\n\n        constexpr float kArmorRatioMultiplier = 0.5f;\n        constexpr float kArmorBonus           = 0.5f;\n\n        // Effective armor ratio: weapon m_flArmorRatio * 0.5f\n        const float flEffectiveArmorRatio = info.m_flArmorPenetration * kArmorRatioMultiplier;\n\n        // Post-mitigation health damage\n        float flNewDamage = flHealthDamage * flEffectiveArmorRatio;\n\n        // Armor durability cost: half of the blocked damage\n        flArmorDamage = (flHealthDamage - flNewDamage) * kArmorBonus;\n        if (flArmorDamage > 0.0f && flArmorDamage < 1.0f) {\n            flArmorDamage = 1.0f;\n        }\n\n        // 4. Armor exhaustion overflow: if hit requires more armor than pawn currently has\n        if (flArmorDamage > static_cast<float>(this->m_ArmorValue)) {\n            flArmorDamage = static_cast<float>(this->m_ArmorValue);\n            flNewDamage   = flHealthDamage - (flArmorDamage / kArmorBonus);\n        }\n\n        res.nArmorLost     = static_cast<int32_t>(flArmorDamage);\n        this->m_ArmorValue = std::max(0, this->m_ArmorValue - res.nArmorLost);\n        res.flAbsorbedByArmor = flHealthDamage - flNewDamage;\n        flHealthDamage     = flNewDamage;\n    }\n\n    // 5. Integer health truncation (Source 2 truncates post-armor float damage to int32)\n    info.m_flDamage        = flHealthDamage;\n    res.flFinalHealthDamage = flHealthDamage;\n    res.nHealthLost        = static_cast<int32_t>(flHealthDamage);\n    this->m_iHealth        = std::max(0, this->m_iHealth - res.nHealthLost);\n\n    res.nRemainingHealth   = this->m_iHealth;\n    res.nRemainingArmor    = this->m_ArmorValue;\n    res.bIsFatal           = (this->m_iHealth == 0);\n\n    return res;\n}\n\n} // namespace cs2::server\n",
        "hit_registration_damage.h": "/**\n * @file hit_registration_damage.h\n * @brief Clean-room C++20 reconstruction of CS2 Hit Registration, HitGroup Scaling & Armor Damage Absorption.\n *\n * Reconstructed from server.dll:\n *   - CCSPlayerPawn::IsArmored                    (Baseline RVA: 0x00aca700, Build 26144732 RVA: 0x00ad7ba0)\n *   - CCSPlayerPawn::ApplyArmorDamageCalculation  (Baseline RVA: 0x00a81050, Build 26144732 RVA: 0x00a8e500)\n */\n\n#pragma once\n\n#include <cstdint>\n#include <cmath>\n#include <algorithm>\n\nnamespace cs2::server {\n\n/**\n * @brief Source 2 HitGroup_t enumeration used in CGameTrace & CTakeDamageInfo.\n */\nenum class HitGroup_t : int32_t {\n    HITGROUP_GENERIC   = 0,\n    HITGROUP_HEAD      = 1,\n    HITGROUP_CHEST     = 2,\n    HITGROUP_STOMACH   = 3,\n    HITGROUP_LEFTARM   = 4,\n    HITGROUP_RIGHTARM  = 5,\n    HITGROUP_LEFTLEG   = 6,\n    HITGROUP_RIGHTLEG  = 7,\n    HITGROUP_NECK      = 8,\n    HITGROUP_GEAR      = 10\n};\n\n/**\n * @brief Damage type bitflags inside CTakeDamageInfo (+0x4C).\n */\nenum DamageBits_t : uint32_t {\n    DMG_GENERIC             = 0,\n    DMG_CRUSH               = (1 << 0),\n    DMG_BULLET              = (1 << 1),\n    DMG_SLASH               = (1 << 2),\n    DMG_BURN                = (1 << 3),\n    DMG_BLAST               = (1 << 6),\n    DMG_CLUB                = (1 << 7),\n    DMG_SHOCK               = (1 << 8),\n    DMG_FALL                = (1 << 5),\n    DMG_HEADSHOT            = (1 << 30)\n};\n\n/**\n * @brief Reconstructed server-side damage scaling ConVars.\n */\nstruct ServerDamageConVars {\n    float mp_damage_scale_ct_head = 1.0f;\n    float mp_damage_scale_t_head  = 1.0f;\n    float mp_damage_scale_ct_body = 1.0f;\n    float mp_damage_scale_t_body  = 1.0f;\n    bool  mp_damage_headshot_only = false;\n};\n\n/**\n * @brief Reconstructed CCSPlayer_ItemServices subset (+0xB18 on CCSPlayerPawn).\n */\nstruct CCSPlayer_ItemServices {\n    bool m_bHasDefuser = false; // +0x40\n    bool m_bHasHelmet  = false; // +0x41\n    bool m_bHasHeavyArmor = false; // +0x42\n};\n\n/**\n * @brief Reconstructed CTakeDamageInfo layout in server.dll.\n */\nstruct CTakeDamageInfo {\n    float       m_flDamage           = 0.0f;  // +0x44: Scaled damage accumulator\n    float       m_flOriginalDamage   = 0.0f;  // +0x48: Base pre-armor damage\n    uint32_t    m_bitsDamageType     = DMG_BULLET; // +0x4C: Damage type bitfield\n    float       m_flArmorPenetration = 1.0f;  // Weapon m_flArmorRatio (e.g. 1.55 for AK-47, 1.40 for M4A4)\n    HitGroup_t  m_nHitGroup          = HitGroup_t::HITGROUP_GENERIC;\n};\n\n/**\n * @brief Result structure emitted after armor absorption and health deduction.\n */\nstruct DamageCalculationResult {\n    float   flRawDistanceDamage  = 0.0f;\n    float   flHitgroupScaledDmg  = 0.0f;\n    float   flFinalHealthDamage  = 0.0f;\n    float   flAbsorbedByArmor    = 0.0f;\n    int32_t nHealthLost          = 0;\n    int32_t nArmorLost           = 0;\n    int32_t nRemainingHealth     = 0;\n    int32_t nRemainingArmor      = 0;\n    bool    bWasArmoredHit       = false;\n    bool    bIsFatal             = false;\n};\n\n/**\n * @brief Reconstructed CCSPlayerPawn combat damage & Kevlar/Helmet evaluator.\n */\nclass CCSPlayerPawnDamageEvaluator {\npublic:\n    int32_t                 m_iHealth       = 100;  // +0x0334\n    int32_t                 m_ArmorValue    = 100;  // +0x150C (Baseline) / +0x1514 (Build 26144732)\n    int32_t                 m_iTeamNum      = 3;    // 2 = Terrorist, 3 = Counter-Terrorist\n    CCSPlayer_ItemServices  m_ItemServices{};       // +0x0B18\n\n    /**\n     * @brief Checks whether a specific hitgroup is protected by the pawn's current Kevlar/Helmet state.\n     * Reconstructed from server.dll @ RVA 0x00aca700 (Build 26144732: 0x00ad7ba0).\n     */\n    bool IsArmored(HitGroup_t hitGroup) const;\n\n    /**\n     * @brief Evaluates distance-based exponential bullet damage decay:\n     *        D(d) = D_base * (flRangeModifier ^ (d / 500.0f))\n     */\n    static float ApplyDistanceDropoff(float baseDamage, float rangeModifier, float distanceUnits);\n\n    /**\n     * @brief Returns hitgroup damage multiplier (Head 4.0x, Stomach 1.25x, Chest/Arms 1.0x, Legs 0.75x)\n     *        combined with team-specific mp_damage_scale_* ConVars.\n     */\n    float GetHitgroupDamageMultiplier(\n        HitGroup_t hitGroup,\n        const ServerDamageConVars& cvars = ServerDamageConVars{}\n    ) const;\n\n    /**\n     * @brief Executes Kevlar & Helmet damage reduction, durability exhaustion clamping, and health deduction.\n     * Reconstructed from server.dll @ RVA 0x00a81050 (Build 26144732: 0x00a8e500).\n     */\n    DamageCalculationResult ApplyArmorDamageCalculation(\n        CTakeDamageInfo& info,\n        float baseWeaponDamage,\n        float rangeModifier,\n        float distanceUnits,\n        const ServerDamageConVars& cvars = ServerDamageConVars{}\n    );\n};\n\n} // namespace cs2::server\n",
        "lagcompensation.cpp": "#include \"lagcompensation.h\"\n#include <algorithm>\n#include <cmath>\n\nnamespace cs2::server {\n\nnamespace {\n\n// Helper: Normalize angle to [-180, 180] degrees\nfloat NormalizeDeg(float angle) {\n    while (angle > 180.0f)  angle -= 360.0f;\n    while (angle < -180.0f) angle += 360.0f;\n    return angle;\n}\n\n// Helper: Interpolate Euler angles along shortest arc\nQAngle InterpolateAngles(const QAngle& a, const QAngle& b, float t) {\n    QAngle res;\n    float deltaPitch = NormalizeDeg(b.pitch - a.pitch);\n    float deltaYaw   = NormalizeDeg(b.yaw - a.yaw);\n    float deltaRoll  = NormalizeDeg(b.roll - a.roll);\n\n    res.pitch = NormalizeDeg(a.pitch + deltaPitch * t);\n    res.yaw   = NormalizeDeg(a.yaw + deltaYaw * t);\n    res.roll  = NormalizeDeg(a.roll + deltaRoll * t);\n    return res;\n}\n\n} // anonymous namespace\n\nCLagCompensationServer& CLagCompensationServer::Get() {\n    static CLagCompensationServer s_Instance;\n    return s_Instance;\n}\n\nPawnTrackHistory_t* CLagCompensationServer::GetOrCreatePawn(uint32_t pawnIndex, EntityHandle handle) {\n    for (auto& p : m_Pawns) {\n        if (p.pawnIndex == pawnIndex) {\n            if (handle.IsValid()) {\n                p.handle = handle;\n            }\n            return &p;\n        }\n    }\n    m_Pawns.push_back({ pawnIndex, handle, {}, {}, false });\n    return &m_Pawns.back();\n}\n\nvoid CLagCompensationServer::RecordDataIntoTrack(\n    uint32_t pawnIndex, EntityHandle handle, float curTime, uint32_t tick,\n    float subTickFraction, const Vector3& origin, const QAngle& angles,\n    const Vector3& mins, const Vector3& maxs,\n    const Matrix3x4* bones, size_t boneCount, uint8_t flags)\n{\n    PawnTrackHistory_t* pawn = GetOrCreatePawn(pawnIndex, handle);\n    if (!pawn) return;\n\n    LagRecord_t record;\n    record.tickCount = tick;\n    record.simulationTime = curTime;\n    record.subTickFraction = std::clamp(subTickFraction, 0.0f, 1.0f);\n    record.origin = origin;\n    record.eyeAngles = angles;\n    record.mins = mins;\n    record.maxs = maxs;\n    record.flags = flags;\n\n    // Anchor previous origin for teleport breaker check (FUN_180ed3f10)\n    if (!pawn->records.empty()) {\n        record.preTeleportOrigin = pawn->records.front().origin;\n    } else {\n        record.preTeleportOrigin = origin;\n    }\n\n    const size_t count = std::min(boneCount, static_cast<size_t>(MAX_BONES));\n    record.boneCount = count;\n    for (size_t i = 0; i < count; ++i) {\n        record.boneMatrices[i] = bones[i];\n    }\n    // Set identity for uncomputed trailing joints\n    for (size_t i = count; i < MAX_BONES; ++i) {\n        record.boneMatrices[i] = Matrix3x4::Identity();\n    }\n\n    pawn->records.push_front(record);\n\n    // Prune entries outside authoritative 200ms unlag window (sv_maxunlag)\n    while (!pawn->records.empty() &&\n           (curTime - pawn->records.back().simulationTime) > MAX_BACKTRACK_WINDOW) {\n        pawn->records.pop_back();\n    }\n}\n\nvoid CLagCompensationServer::RecordPawn(\n    uint32_t pawnIndex, float curTime, uint32_t tick,\n    const Vector3& origin, const QAngle& angles,\n    const Vector3& mins, const Vector3& maxs,\n    const Matrix3x4* bones, size_t boneCount)\n{\n    RecordDataIntoTrack(pawnIndex, EntityHandle(pawnIndex, 1), curTime, tick,\n                        0.0f, origin, angles, mins, maxs, bones, boneCount, 0x1E);\n}\n\nbool CLagCompensationServer::StartLagCompensation(\n    uint32_t attackerIndex, float targetTime, float maxUnlag)\n{\n    if (m_Pawns.empty()) {\n        return false;\n    }\n\n    // Determine current simulation baseline time from newest tracked record\n    float latestTime = 0.0f;\n    for (const auto& p : m_Pawns) {\n        if (!p.records.empty() && p.records.front().simulationTime > latestTime) {\n            latestTime = p.records.front().simulationTime;\n        }\n    }\n\n    // Clamp rewind target time to [latestTime - maxUnlag, latestTime]\n    const float minAllowedTime = latestTime - maxUnlag;\n    const float clampedTarget = std::clamp(targetTime, minAllowedTime, latestTime);\n\n    bool anyBacktracked = false;\n\n    // Iterate all active pawns and backtrack candidate targets (FUN_180ed6f10)\n    for (auto& pawn : m_Pawns) {\n        // Skip attacker pawn or pawns without history\n        if (pawn.pawnIndex == attackerIndex || pawn.records.empty()) {\n            continue;\n        }\n\n        // Avoid re-backtracking if already in compensated state\n        if (pawn.isBacktracked) {\n            continue;\n        }\n\n        // Snapshot authoritative current state for restoration in FinishLagCompensation\n        pawn.restoreSnapshot.snapshot = pawn.records.front();\n        pawn.restoreSnapshot.isBacktracked = true;\n        pawn.restoreSnapshot.originModified = true;\n        pawn.restoreSnapshot.anglesModified = true;\n        pawn.restoreSnapshot.boundsModified = true;\n        pawn.restoreSnapshot.bonesModified = true;\n\n        // Compute interpolated backtracked record\n        LagRecord_t backtrackedRecord;\n        if (BacktrackEntity(pawn, clampedTarget, backtrackedRecord)) {\n            pawn.isBacktracked = true;\n            anyBacktracked = true;\n        }\n    }\n\n    return anyBacktracked;\n}\n\nbool CLagCompensationServer::StartLagCompensationSubTick(\n    uint32_t attackerIndex, uint32_t targetTick,\n    float subTickFraction, float maxUnlag)\n{\n    const float targetTime = CalculateSubTickSimulationTime(targetTick, subTickFraction);\n    return StartLagCompensation(attackerIndex, targetTime, maxUnlag);\n}\n\nvoid CLagCompensationServer::FinishLagCompensation() {\n    // Reconstructed from CLagCompensationManager::FinishLagCompensation @ 0x180ebf350\n    for (auto& pawn : m_Pawns) {\n        if (pawn.isBacktracked && pawn.restoreSnapshot.isBacktracked) {\n            RestoreEntityTo(pawn, pawn.restoreSnapshot.snapshot);\n            pawn.isBacktracked = false;\n            pawn.restoreSnapshot.isBacktracked = false;\n        }\n    }\n}\n\nvoid CLagCompensationServer::FinishLagCompensation(uint32_t pawnIndex) {\n    for (auto& pawn : m_Pawns) {\n        if (pawn.pawnIndex == pawnIndex && pawn.isBacktracked) {\n            RestoreEntityTo(pawn, pawn.restoreSnapshot.snapshot);\n            pawn.isBacktracked = false;\n            pawn.restoreSnapshot.isBacktracked = false;\n            break;\n        }\n    }\n}\n\nbool CLagCompensationServer::BacktrackEntity(\n    PawnTrackHistory_t& pawn, float targetTime, LagRecord_t& outRecord)\n{\n    if (pawn.records.empty()) {\n        return false;\n    }\n\n    const auto& history = pawn.records;\n\n    // Target is newer than newest record\n    if (targetTime >= history.front().simulationTime) {\n        outRecord = history.front();\n        return true;\n    }\n\n    // Target is older than oldest available record\n    if (targetTime <= history.back().simulationTime) {\n        outRecord = history.back();\n        return true;\n    }\n\n    // Locate bracketing pair [older, newer] where older.time <= targetTime <= newer.time\n    const LagRecord_t* newerRecord = nullptr;\n    const LagRecord_t* olderRecord = nullptr;\n\n    for (size_t i = 0; i < history.size() - 1; ++i) {\n        if (history[i].simulationTime >= targetTime && history[i + 1].simulationTime <= targetTime) {\n            newerRecord = &history[i];\n            olderRecord = &history[i + 1];\n            break;\n        }\n    }\n\n    if (!newerRecord || !olderRecord) {\n        outRecord = history.back();\n        return true;\n    }\n\n    // -------------------------------------------------------------------------\n    // Teleport Distance Squared Breaker ($4096.0 = 64^2 units)\n    // Decompiled from FUN_180ed3f10: If delta squared >= 4096, reject interpolation\n    // -------------------------------------------------------------------------\n    const float dx = newerRecord->origin.x - olderRecord->origin.x;\n    const float dy = newerRecord->origin.y - olderRecord->origin.y;\n    const float dz = newerRecord->origin.z - olderRecord->origin.z;\n    const float distSqr = dx * dx + dy * dy + dz * dz;\n\n    if (distSqr >= TELEPORT_DISTANCE_SQR_THRESHOLD) {\n        // Discontinuity detected: clamp to nearest discrete frame to prevent glitching\n        const float timeSpan = newerRecord->simulationTime - olderRecord->simulationTime;\n        const float fraction = (timeSpan > 1e-6f) ? (targetTime - olderRecord->simulationTime) / timeSpan : 0.0f;\n        outRecord = (fraction >= 0.5f) ? *newerRecord : *olderRecord;\n        return true;\n    }\n\n    // Continuous fractional interpolation\n    const float timeDelta = newerRecord->simulationTime - olderRecord->simulationTime;\n    const float fraction = (timeDelta > 1e-6f)\n        ? std::clamp((targetTime - olderRecord->simulationTime) / timeDelta, 0.0f, 1.0f)\n        : 0.0f;\n\n    return InterpolateRecords(*olderRecord, *newerRecord, fraction, outRecord);\n}\n\nbool CLagCompensationServer::RestoreEntityTo(\n    PawnTrackHistory_t& pawn, const LagRecord_t& record)\n{\n    // Reconstructed from FUN_180ed3f10 @ 0x180ed3f10\n    if (pawn.records.empty()) {\n        return false;\n    }\n\n    // 1. Restore collision bounds (flags & 0x08)\n    if (record.flags & LAG_RECORD_BOUNDS_CHANGED) {\n        pawn.records.front().mins = record.mins;\n        pawn.records.front().maxs = record.maxs;\n    }\n\n    // 2. Restore eye/head orientation (flags & 0x04)\n    if (record.flags & LAG_RECORD_ANGLES_CHANGED) {\n        pawn.records.front().eyeAngles = record.eyeAngles;\n    }\n\n    // 3. Restore world origin (flags & 0x02) with 4096.0 teleport distance check\n    if (record.flags & LAG_RECORD_ORIGIN_CHANGED) {\n        const float dx = pawn.records.front().origin.x - record.preTeleportOrigin.x;\n        const float dy = pawn.records.front().origin.y - record.preTeleportOrigin.y;\n        const float dz = pawn.records.front().origin.z - record.preTeleportOrigin.z;\n        const float moveDistSqr = dx * dx + dy * dy + dz * dz;\n\n        if (moveDistSqr < TELEPORT_DISTANCE_SQR_THRESHOLD) {\n            pawn.records.front().origin = record.origin;\n        }\n    }\n\n    // 4. Restore skeletal bone transforms (flags & 0x10)\n    if (record.flags & LAG_RECORD_BONES_CHANGED) {\n        const size_t count = std::min(record.boneCount, static_cast<size_t>(MAX_BONES));\n        for (size_t i = 0; i < count; ++i) {\n            pawn.records.front().boneMatrices[i] = record.boneMatrices[i];\n        }\n        pawn.records.front().boneCount = count;\n    }\n\n    pawn.isBacktracked = false;\n    return true;\n}\n\nbool CLagCompensationServer::InterpolateRecords(\n    const LagRecord_t& older, const LagRecord_t& newer,\n    float fraction, LagRecord_t& outRecord)\n{\n    fraction = std::clamp(fraction, 0.0f, 1.0f);\n\n    outRecord.tickCount = (fraction >= 0.5f) ? newer.tickCount : older.tickCount;\n    outRecord.simulationTime = older.simulationTime + (newer.simulationTime - older.simulationTime) * fraction;\n    outRecord.subTickFraction = fraction;\n\n    // Linear origin lerp: P(t) = P0 + (P1 - P0) * t\n    outRecord.origin.x = older.origin.x + (newer.origin.x - older.origin.x) * fraction;\n    outRecord.origin.y = older.origin.y + (newer.origin.y - older.origin.y) * fraction;\n    outRecord.origin.z = older.origin.z + (newer.origin.z - older.origin.z) * fraction;\n\n    // Angle interpolation with wrap-around\n    outRecord.eyeAngles = InterpolateAngles(older.eyeAngles, newer.eyeAngles, fraction);\n\n    // Bounding box dimensions\n    outRecord.mins.x = older.mins.x + (newer.mins.x - older.mins.x) * fraction;\n    outRecord.mins.y = older.mins.y + (newer.mins.y - older.mins.y) * fraction;\n    outRecord.mins.z = older.mins.z + (newer.mins.z - older.mins.z) * fraction;\n\n    outRecord.maxs.x = older.maxs.x + (newer.maxs.x - older.maxs.x) * fraction;\n    outRecord.maxs.y = older.maxs.y + (newer.maxs.y - older.maxs.y) * fraction;\n    outRecord.maxs.z = older.maxs.z + (newer.maxs.z - older.maxs.z) * fraction;\n\n    outRecord.flags = older.flags | newer.flags;\n    outRecord.boneCount = std::max(older.boneCount, newer.boneCount);\n\n    return InterpolateBones(older, newer, fraction, outRecord.boneMatrices, outRecord.boneCount);\n}\n\nbool CLagCompensationServer::InterpolateBones(\n    const LagRecord_t& from, const LagRecord_t& to,\n    float fraction, std::array<Matrix3x4, MAX_BONES>& outBones,\n    size_t boneCount)\n{\n    fraction = std::clamp(fraction, 0.0f, 1.0f);\n    const size_t count = std::min(boneCount, static_cast<size_t>(MAX_BONES));\n\n    for (size_t b = 0; b < count; ++b) {\n        for (int r = 0; r < 3; ++r) {\n            for (int c = 0; c < 4; ++c) {\n                outBones[b].m[r][c] = from.boneMatrices[b].m[r][c] +\n                    (to.boneMatrices[b].m[r][c] - from.boneMatrices[b].m[r][c]) * fraction;\n            }\n        }\n    }\n    for (size_t b = count; b < MAX_BONES; ++b) {\n        outBones[b] = Matrix3x4::Identity();\n    }\n    return true;\n}\n\n} // namespace cs2::server\n",
        "lagcompensation.h": "#ifndef CS2_SERVER_LAGCOMPENSATION_H\n#define CS2_SERVER_LAGCOMPENSATION_H\n\n#include \"../client/viewmatrix.h\"\n#include \"controller_pawn.h\"\n#include <cstdint>\n#include <vector>\n#include <deque>\n#include <array>\n#include <algorithm>\n#include <cmath>\n\nnamespace cs2::server {\n\nusing client::Vector3;\nusing client::QAngle;\n\n// -------------------------------------------------------------------------\n// Authoritative Engine Constants (server.dll @ build 26144732)\n// -------------------------------------------------------------------------\nconstexpr int MAX_BONES = 128;\nconstexpr float MAX_BACKTRACK_WINDOW = 0.200f;              // sv_maxunlag: 200ms (0.200s)\nconstexpr float TICK_INTERVAL_64 = 0.015625f;               // 1.0f / 64.0f (64 tick simulation)\nconstexpr float TELEPORT_DISTANCE_SQR_THRESHOLD = 4096.0f;  // 64.0f^2 units: Discontinuity breaker\n\n// -------------------------------------------------------------------------\n// Lag Record Bitflags (Reversed from FUN_180ed3f10 @ 0x180ed3f10)\n// -------------------------------------------------------------------------\nconstexpr uint8_t LAG_RECORD_RESTORED        = 0x01; // Bit 0: Record applied / active\nconstexpr uint8_t LAG_RECORD_ORIGIN_CHANGED  = 0x02; // Bit 1: World origin offset modified\nconstexpr uint8_t LAG_RECORD_ANGLES_CHANGED  = 0x04; // Bit 2: Eye angles / rotation modified\nconstexpr uint8_t LAG_RECORD_BOUNDS_CHANGED  = 0x08; // Bit 3: Collision mins/maxs modified\nconstexpr uint8_t LAG_RECORD_BONES_CHANGED   = 0x10; // Bit 4: Skeletal bone matrices cached\n\nstruct Matrix3x4 {\n    float m[3][4];\n\n    static Matrix3x4 Identity() noexcept {\n        Matrix3x4 out{};\n        out.m[0][0] = 1.0f; out.m[1][1] = 1.0f; out.m[2][2] = 1.0f;\n        return out;\n    }\n};\n\n/**\n * @brief Authoritative Lag Compensation History Record (LagRecord_t)\n * Reconstructed from server.dll player_lagcompensation.cpp & FUN_180eced70\n */\nstruct LagRecord_t {\n    uint32_t tickCount = 0;                                  // Server simulation tick index\n    float simulationTime = 0.0f;                             // Authoritative simulation timestamp (seconds)\n    float subTickFraction = 0.0f;                            // Continuous analog sub-tick offset [0.0, 1.0)\n    Vector3 origin{};                                        // World-space pawn origin coordinates\n    QAngle eyeAngles{};                                      // Eye/head orientation angles\n    Vector3 mins{-16.0f, -16.0f, 0.0f};                      // Axis-aligned bounding box minimum\n    Vector3 maxs{16.0f, 16.0f, 72.0f};                       // Axis-aligned bounding box maximum\n    std::array<Matrix3x4, MAX_BONES> boneMatrices{};         // Resolved world-space bone transform cache\n    size_t boneCount = 0;                                    // Active bone count (typically <= 128)\n    uint8_t flags = 0;                                       // Bitmask of modified transforms\n    Vector3 preTeleportOrigin{};                             // Spatial anchor for 4096.0 sqr distance check\n};\n\nusing LagRecord = LagRecord_t;\n\n/**\n * @brief Pre-rewind Snapshot used by FinishLagCompensation to restore pawn states\n */\nstruct RestoreSnapshot_t {\n    LagRecord_t snapshot{};\n    bool isBacktracked = false;\n    bool originModified = false;\n    bool anglesModified = false;\n    bool boundsModified = false;\n    bool bonesModified = false;\n};\n\n/**\n * @brief Ring buffer tracking history for a single player pawn\n */\nstruct PawnTrackHistory_t {\n    uint32_t pawnIndex = 0;                                  // Pawn entity index in entity list\n    EntityHandle handle{};                                   // 32-bit CEntityHandle (Index + Serial)\n    std::deque<LagRecord_t> records;                         // Circular history buffer (<= 200ms)\n    RestoreSnapshot_t restoreSnapshot;                       // Original state prior to rewind\n    bool isBacktracked = false;                              // True if currently rewound for trace\n};\n\nusing PawnHistory = PawnTrackHistory_t;\n\n/**\n * @brief Reconstructed Server-Side Lag Compensation Engine from server.dll\n * Reverse-engineered from CLagCompensationManager:\n * - StartLagCompensation (0x180ed8c00 / 0x180ed6f10)\n * - FinishLagCompensation (0x180ebf350)\n * - BacktrackPlayer / BacktrackEntity (0x180eced70)\n * - RestoreEntityTo (0x180ed3f10)\n */\nclass CLagCompensationServer {\npublic:\n    static CLagCompensationServer& Get();\n\n    /**\n     * @brief Records authoritative pawn state into ring buffer track.\n     */\n    void RecordDataIntoTrack(uint32_t pawnIndex, EntityHandle handle, float curTime, uint32_t tick,\n                             float subTickFraction, const Vector3& origin, const QAngle& angles,\n                             const Vector3& mins, const Vector3& maxs,\n                             const Matrix3x4* bones, size_t boneCount, uint8_t flags = 0x1E);\n\n    // Legacy compatibility overload\n    void RecordPawn(uint32_t pawnIndex, float curTime, uint32_t tick,\n                    const Vector3& origin, const QAngle& angles,\n                    const Vector3& mins, const Vector3& maxs,\n                    const Matrix3x4* bones, size_t boneCount);\n\n    /**\n     * @brief Rewinds all active target pawns to the client's continuous target timestamp.\n     * Clamped to [currentTime - maxUnlag, currentTime].\n     */\n    bool StartLagCompensation(uint32_t attackerIndex, float targetTime,\n                              float maxUnlag = MAX_BACKTRACK_WINDOW);\n\n    /**\n     * @brief Sub-tick aware StartLagCompensation converting tick + subTickFraction into continuous time.\n     */\n    bool StartLagCompensationSubTick(uint32_t attackerIndex, uint32_t targetTick,\n                                     float subTickFraction, float maxUnlag = MAX_BACKTRACK_WINDOW);\n\n    /**\n     * @brief Restores all backtracked pawns back to their authoritative present states.\n     * Reconstructed from CLagCompensationManager::FinishLagCompensation @ 0x180ebf350.\n     */\n    void FinishLagCompensation();\n\n    // Legacy overload for single pawn index\n    void FinishLagCompensation(uint32_t pawnIndex);\n\n    /**\n     * @brief Backtracks an individual entity by sampling/interpolating records.\n     * Enforces the 4096.0 unit^2 teleportation breaker check (FUN_180ed3f10).\n     */\n    bool BacktrackEntity(PawnTrackHistory_t& pawn, float targetTime, LagRecord_t& outRecord);\n\n    /**\n     * @brief Restores an entity's physical state from snapshot (FUN_180ed3f10).\n     */\n    bool RestoreEntityTo(PawnTrackHistory_t& pawn, const LagRecord_t& record);\n\n    /**\n     * @brief Interpolates between two history records at continuous fraction [0.0, 1.0].\n     */\n    static bool InterpolateRecords(const LagRecord_t& older, const LagRecord_t& newer,\n                                   float fraction, LagRecord_t& outRecord);\n\n    /**\n     * @brief Interpolates 3x4 affine bone matrices linearly with SIMD precision.\n     */\n    static bool InterpolateBones(const LagRecord_t& from, const LagRecord_t& to,\n                                 float fraction, std::array<Matrix3x4, MAX_BONES>& outBones,\n                                 size_t boneCount = MAX_BONES);\n\n    /**\n     * @brief Converts discrete tick base and analog sub-tick fraction into seconds.\n     */\n    [[nodiscard]] static constexpr float CalculateSubTickSimulationTime(\n        uint32_t tick, float subTickFraction, float tickInterval = TICK_INTERVAL_64) noexcept {\n        return (static_cast<float>(tick) + std::clamp(subTickFraction, 0.0f, 1.0f)) * tickInterval;\n    }\n\n    [[nodiscard]] const std::vector<PawnTrackHistory_t>& GetPawns() const noexcept { return m_Pawns; }\n    void ClearHistory() noexcept { m_Pawns.clear(); }\n\nprivate:\n    CLagCompensationServer() = default;\n    std::vector<PawnTrackHistory_t> m_Pawns;\n\n    PawnTrackHistory_t* GetOrCreatePawn(uint32_t pawnIndex, EntityHandle handle = {});\n};\n\nusing CLagCompensationManager = CLagCompensationServer;\n\n} // namespace cs2::server\n\n#endif // CS2_SERVER_LAGCOMPENSATION_H\n"
      }
    },
    {
      "module": "shared",
      "directory": "game/shared",
      "standard": "C++20 (/std:c++20 /W4)",
      "files": {
        "entity_handle.h": "#ifndef CS2_SHARED_ENTITY_HANDLE_H\n#define CS2_SHARED_ENTITY_HANDLE_H\n\n#include <cstdint>\n\nnamespace cs2::shared {\n\nconstexpr std::uint32_t ENT_ENTRY_MASK        = 0x7FFF;\nconstexpr std::uint32_t INVALID_EHANDLE_INDEX = 0x7FFF;\nconstexpr std::uint32_t INVALID_EHANDLE_VAL   = 0xFFFFFFFF;\n\n/**\n * @brief Source 2 32-bit Packed Entity Handle (CEntityHandle)\n * Reconstructed from client.dll @ 0x1807357c0 (GetEntityIdentity).\n * Decomposition:\n *   - Bits 0..14:  15-bit entry index [0..32,767]\n *   - Bits 15..31: 17-bit serial counter (incremented upon entity recycling)\n */\nstruct CEntityHandle {\n    std::uint32_t m_uValue{INVALID_EHANDLE_VAL};\n\n    constexpr CEntityHandle() noexcept = default;\n    constexpr explicit CEntityHandle(std::uint32_t val) noexcept : m_uValue(val) {}\n    constexpr CEntityHandle(std::uint32_t index, std::uint32_t serial) noexcept\n        : m_uValue((index & ENT_ENTRY_MASK) | (serial << 15)) {}\n\n    [[nodiscard]] constexpr bool IsValid() const noexcept {\n        return m_uValue != INVALID_EHANDLE_VAL && GetEntryIndex() != INVALID_EHANDLE_INDEX;\n    }\n\n    [[nodiscard]] constexpr std::uint32_t GetRaw() const noexcept {\n        return m_uValue;\n    }\n\n    [[nodiscard]] constexpr std::uint32_t GetEntryIndex() const noexcept {\n        return m_uValue & ENT_ENTRY_MASK;\n    }\n\n    [[nodiscard]] constexpr std::uint32_t GetSerialNumber() const noexcept {\n        return m_uValue >> 15;\n    }\n\n    [[nodiscard]] constexpr std::uint32_t GetChunkIndex() const noexcept {\n        return GetEntryIndex() >> 9;\n    }\n\n    [[nodiscard]] constexpr std::uint32_t GetSlotIndex() const noexcept {\n        return GetEntryIndex() & 0x1FF;\n    }\n\n    constexpr bool operator==(const CEntityHandle& o) const noexcept { return m_uValue == o.m_uValue; }\n    constexpr bool operator!=(const CEntityHandle& o) const noexcept { return m_uValue != o.m_uValue; }\n    constexpr bool operator<(const CEntityHandle& o) const noexcept { return m_uValue < o.m_uValue; }\n};\nstatic_assert(sizeof(CEntityHandle) == 4, \"CEntityHandle must be 4 bytes\");\n\n/**\n * @brief Strongly typed entity handle template (CHandle<T>)\n */\ntemplate <typename T>\nclass CHandle : public CEntityHandle {\npublic:\n    using CEntityHandle::CEntityHandle;\n};\nstatic_assert(sizeof(CHandle<void>) == 4, \"CHandle<T> must be 4 bytes\");\n\n} // namespace cs2::shared\n\n#endif // CS2_SHARED_ENTITY_HANDLE_H\n",
        "hitbox.h": "#ifndef CS2_SHARED_HITBOX_H\n#define CS2_SHARED_HITBOX_H\n\n#include <cstdint>\n#include \"math_types.h\"\n\nnamespace cs2::shared {\n\nenum HitGroup_t : std::int32_t {\n    HITGROUP_GENERIC   = 0,\n    HITGROUP_HEAD      = 1,\n    HITGROUP_CHEST     = 2,\n    HITGROUP_STOMACH   = 3,\n    HITGROUP_LEFTARM   = 4,\n    HITGROUP_RIGHTARM  = 5,\n    HITGROUP_LEFTLEG   = 6,\n    HITGROUP_RIGHTLEG  = 7,\n    HITGROUP_NECK      = 8,\n    HITGROUP_UNUSED    = 9,\n    HITGROUP_GEAR      = 10\n};\n\n/**\n * @brief Returns the authoritative CS2 damage multiplier for a target hitgroup.\n * Head: 4.0x, Stomach: 1.25x, Chest: 1.0x, Limbs: 0.75x.\n */\ninline constexpr float GetHitGroupDamageMultiplier(HitGroup_t group) noexcept {\n    switch (group) {\n        case HITGROUP_HEAD:     return 4.00f;\n        case HITGROUP_STOMACH:  return 1.25f;\n        case HITGROUP_CHEST:    return 1.00f;\n        case HITGROUP_LEFTARM:\n        case HITGROUP_RIGHTARM:\n        case HITGROUP_LEFTLEG:\n        case HITGROUP_RIGHTLEG: return 0.75f;\n        default:                return 1.00f;\n    }\n}\n\n/**\n * @brief Studio bone hitbox bounding capsule / OBB (CHitBox)\n * Size: exactly 112 bytes (0x70)\n */\nstruct CHitBox {\n    const char*   m_pName{nullptr};           // +0x00: Hitbox bone identifier string\n    const char*   m_pSurfaceProperty{nullptr};// +0x08: Material physics surface\n    const char*   m_pBoneName{nullptr};       // +0x10: Target skeleton bone\n    Vector3D      m_vMinBounds{};             // +0x18: Local minimum bounding coordinates (12 bytes)\n    Vector3D      m_vMaxBounds{};             // +0x24: Local maximum bounding coordinates (12 bytes)\n    float         m_flShapeRadius{0.0f};      // +0x30: Capsule mantle radius\n    std::uint32_t m_nBoneId{0};               // +0x34: Skeletal bone index\n    std::int32_t  m_nHitGroup{0};             // +0x38: Authoritative HitGroup_t\n    std::uint8_t  m_nPad[52]{};               // +0x3C: Studio model runtime padding\n};\nstatic_assert(sizeof(CHitBox) == 0x70, \"CHitBox must be exactly 0x70 (112 bytes)\");\n\n/**\n * @brief Studio hitbox set array header (CHitBoxSet)\n * Size: exactly 48 bytes (0x30)\n */\nstruct CHitBoxSet {\n    const char*   m_pName{nullptr};           // +0x00: Set name (e.g. \"default\")\n    std::uint32_t m_nNameHash{0};             // +0x08: MurmurHash2 token\n    std::uint32_t m_nPad0{0};                 // +0x0C\n    std::uint64_t m_nPad1{0};                 // +0x10\n    std::int32_t  m_nHitBoxCount{0};          // +0x18: Number of child hitboxes\n    std::uint32_t m_nPad2{0};                 // +0x1C\n    CHitBox*      m_pHitBoxes{nullptr};       // +0x20: Pointer to CHitBox array\n    std::uint64_t m_nPad3{0};                 // +0x28\n};\nstatic_assert(sizeof(CHitBoxSet) == 0x30, \"CHitBoxSet must be exactly 0x30 (48 bytes)\");\n\n} // namespace cs2::shared\n\n#endif // CS2_SHARED_HITBOX_H\n",
        "math_types.h": "#ifndef CS2_SHARED_MATH_TYPES_H\n#define CS2_SHARED_MATH_TYPES_H\n\n#include <cmath>\n#include <cstdint>\n#include <cstring>\n#include <algorithm>\n\nnamespace cs2::shared {\n\n// ----------------------------------------------------------------------------\n// Vector2D\n// ----------------------------------------------------------------------------\nstruct Vector2D {\n    float x{0.0f}, y{0.0f};\n\n    constexpr Vector2D() = default;\n    constexpr Vector2D(float fx, float fy) : x(fx), y(fy) {}\n\n    [[nodiscard]] constexpr Vector2D operator+(const Vector2D& o) const noexcept { return {x + o.x, y + o.y}; }\n    [[nodiscard]] constexpr Vector2D operator-(const Vector2D& o) const noexcept { return {x - o.x, y - o.y}; }\n    [[nodiscard]] constexpr Vector2D operator*(float s) const noexcept { return {x * s, y * s}; }\n    [[nodiscard]] constexpr Vector2D operator/(float s) const noexcept { return {x / s, y / s}; }\n\n    [[nodiscard]] constexpr float Dot(const Vector2D& o) const noexcept { return x * o.x + y * o.y; }\n    [[nodiscard]] float Length() const noexcept { return std::sqrt(x * x + y * y); }\n};\nstatic_assert(sizeof(Vector2D) == 8, \"Vector2D must be 8 bytes\");\n\n// ----------------------------------------------------------------------------\n// Vector3D (12 bytes, matching Source 2 core memory layout)\n// ----------------------------------------------------------------------------\nstruct Vector3D {\n    float x{0.0f}, y{0.0f}, z{0.0f};\n\n    constexpr Vector3D() = default;\n    constexpr Vector3D(float fx, float fy, float fz) : x(fx), y(fy), z(fz) {}\n\n    [[nodiscard]] constexpr Vector3D operator+(const Vector3D& o) const noexcept { return {x + o.x, y + o.y, z + o.z}; }\n    [[nodiscard]] constexpr Vector3D operator-(const Vector3D& o) const noexcept { return {x - o.x, y - o.y, z - o.z}; }\n    [[nodiscard]] constexpr Vector3D operator*(float s) const noexcept { return {x * s, y * s, z * s}; }\n    [[nodiscard]] constexpr Vector3D operator/(float s) const noexcept { return {x / s, y / s, z / s}; }\n\n    constexpr Vector3D& operator+=(const Vector3D& o) noexcept { x += o.x; y += o.y; z += o.z; return *this; }\n    constexpr Vector3D& operator-=(const Vector3D& o) noexcept { x -= o.x; y -= o.y; z -= o.z; return *this; }\n    constexpr Vector3D& operator*=(float s) noexcept { x *= s; y *= s; z *= s; return *this; }\n\n    [[nodiscard]] constexpr float Dot(const Vector3D& o) const noexcept { return x * o.x + y * o.y + z * o.z; }\n    [[nodiscard]] float Length() const noexcept { return std::sqrt(Dot(*this)); }\n    [[nodiscard]] float LengthSq() const noexcept { return Dot(*this); }\n    [[nodiscard]] float Length2D() const noexcept { return std::sqrt(x * x + y * y); }\n\n    [[nodiscard]] Vector3D Cross(const Vector3D& o) const noexcept {\n        return {\n            y * o.z - z * o.y,\n            z * o.x - x * o.z,\n            x * o.y - y * o.x\n        };\n    }\n\n    [[nodiscard]] Vector3D Normalized() const noexcept {\n        const float len = Length();\n        return (len > 1e-6f) ? (*this / len) : Vector3D{};\n    }\n\n    [[nodiscard]] bool IsZero(float tol = 1e-6f) const noexcept {\n        return std::abs(x) < tol && std::abs(y) < tol && std::abs(z) < tol;\n    }\n};\nstatic_assert(sizeof(Vector3D) == 12, \"Vector3D must be 12 bytes\");\n\n// ----------------------------------------------------------------------------\n// Vector4D (16 bytes)\n// ----------------------------------------------------------------------------\nstruct alignas(16) Vector4D {\n    float x{0.0f}, y{0.0f}, z{0.0f}, w{0.0f};\n\n    constexpr Vector4D() = default;\n    constexpr Vector4D(float fx, float fy, float fz, float fw = 0.0f) : x(fx), y(fy), z(fz), w(fw) {}\n};\nstatic_assert(sizeof(Vector4D) == 16, \"Vector4D must be 16 bytes\");\n\n// ----------------------------------------------------------------------------\n// QAngle (Euler angles in degrees: pitch, yaw, roll)\n// ----------------------------------------------------------------------------\nstruct QAngle {\n    float pitch{0.0f}; // X\n    float yaw{0.0f};   // Y\n    float roll{0.0f};  // Z\n\n    constexpr QAngle() = default;\n    constexpr QAngle(float p, float y, float r = 0.0f) : pitch(p), yaw(y), roll(r) {}\n\n    [[nodiscard]] constexpr QAngle operator+(const QAngle& o) const noexcept { return {pitch + o.pitch, yaw + o.yaw, roll + o.roll}; }\n    [[nodiscard]] constexpr QAngle operator-(const QAngle& o) const noexcept { return {pitch - o.pitch, yaw - o.yaw, roll - o.roll}; }\n    [[nodiscard]] constexpr QAngle operator*(float s) const noexcept { return {pitch * s, yaw * s, roll * s}; }\n\n    void Clamp() noexcept {\n        pitch = std::clamp(pitch, -89.0f, 89.0f);\n        while (yaw > 180.0f) yaw -= 360.0f;\n        while (yaw < -180.0f) yaw += 360.0f;\n        roll = 0.0f;\n    }\n\n    [[nodiscard]] Vector3D Forward() const noexcept {\n        const float sp = std::sin(pitch * (3.14159265f / 180.0f));\n        const float cp = std::cos(pitch * (3.14159265f / 180.0f));\n        const float sy = std::sin(yaw * (3.14159265f / 180.0f));\n        const float cy = std::cos(yaw * (3.14159265f / 180.0f));\n        return {cp * cy, cp * sy, -sp};\n    }\n};\nstatic_assert(sizeof(QAngle) == 12, \"QAngle must be 12 bytes\");\n\n// ----------------------------------------------------------------------------\n// VMatrix (64 bytes, alignas(16), 4x4 row-major transformation matrix)\n// client.dll active view matrix global @ client.dll + 0x256cfe0\n// ----------------------------------------------------------------------------\nstruct alignas(16) VMatrix {\n    float m[4][4]{};\n\n    constexpr VMatrix() = default;\n\n    static VMatrix Identity() noexcept {\n        VMatrix res;\n        res.m[0][0] = 1.0f; res.m[1][1] = 1.0f; res.m[2][2] = 1.0f; res.m[3][3] = 1.0f;\n        return res;\n    }\n\n    [[nodiscard]] const float* operator[](int i) const noexcept { return m[i]; }\n    [[nodiscard]] float* operator[](int i) noexcept { return m[i]; }\n\n    /**\n     * @brief Transforms 3D world coordinate into 2D normalized screen space.\n     * Homogeneous clipping: rejects vertices behind the camera (w < 0.001f).\n     */\n    [[nodiscard]] bool WorldToScreen(const Vector3D& world, Vector2D& screen, int screenWidth, int screenHeight) const noexcept {\n        const float w = m[3][0] * world.x + m[3][1] * world.y + m[3][2] * world.z + m[3][3];\n        if (w < 0.001f) return false;\n\n        const float invW = 1.0f / w;\n        const float ndcX = (m[0][0] * world.x + m[0][1] * world.y + m[0][2] * world.z + m[0][3]) * invW;\n        const float ndcY = (m[1][0] * world.x + m[1][1] * world.y + m[1][2] * world.z + m[1][3]) * invW;\n\n        screen.x = (screenWidth * 0.5f) + (ndcX * screenWidth * 0.5f);\n        screen.y = (screenHeight * 0.5f) - (ndcY * screenHeight * 0.5f);\n        return true;\n    }\n};\nstatic_assert(sizeof(VMatrix) == 64, \"VMatrix must be 64 bytes\");\n\n} // namespace cs2::shared\n\n#endif // CS2_SHARED_MATH_TYPES_H\n",
        "ray_trace.h": "#ifndef CS2_SHARED_RAY_TRACE_H\n#define CS2_SHARED_RAY_TRACE_H\n\n#include <cstdint>\n#include <cstddef>\n#include \"math_types.h\"\n\nnamespace cs2::shared {\n\n#define CS2_PAD(bytes, name) private: [[maybe_unused]] std::uint8_t name[bytes]; public:\n\n#ifdef OPAQUE\n#undef OPAQUE\n#endif\n#ifdef TRANSPARENT\n#undef TRANSPARENT\n#endif\n\nnamespace Contents {\n    constexpr std::uint32_t EMPTY        = 0x00000000;\n    constexpr std::uint32_t SOLID        = 0x00000001;\n    constexpr std::uint32_t WINDOW       = 0x00000002;\n    constexpr std::uint32_t MOVEABLE     = 0x00004000;\n    constexpr std::uint32_t PLAYERCLIP   = 0x00010000;\n    constexpr std::uint32_t MONSTERCLIP  = 0x00020000;\n    constexpr std::uint32_t OPAQUE       = 0x00000080;\n    constexpr std::uint64_t MASK_SHOT    = 0x46004003;\n    constexpr std::uint64_t MASK_VISIBLE = 0x00000081;\n}\n\n/**\n * @brief 64-byte Geometric Query Ray & Swept Extent Volume.\n * Reconstructed from client.dll @ 0x180a1ae30 / vphysics2.dll @ 0x1802544a0.\n */\nstruct alignas(16) Ray_t {\n    Vector3D      m_vStart;         // +0x00: Ray segment trajectory origin (12 bytes)\n    Vector3D      m_vEnd;           // +0x0C: Ray segment trajectory terminus (12 bytes)\n    Vector3D      m_vOffset;        // +0x18: Swept centroid displacement vector (12 bytes)\n    Vector3D      m_vExtent;        // +0x24: Half-extent bounding box dimensions (12 bytes)\n    bool          m_bIsRay;         // +0x30: True if line ray (extent == 0), false if swept volume (1 byte)\n    bool          m_bHasExtents;    // +0x31: True if swept volume possesses non-zero bounds (1 byte)\n    CS2_PAD(0x06, m_pad32);         // +0x32: Alignment padding\n    std::uint64_t m_nMask;          // +0x38: 64-bit spatial collision mask (8 bytes)\n\n    void Init(const Vector3D& start, const Vector3D& end, std::uint64_t mask = Contents::MASK_SHOT) noexcept {\n        m_vStart = start;\n        m_vEnd = end;\n        m_vOffset = Vector3D{0.0f, 0.0f, 0.0f};\n        m_vExtent = Vector3D{0.0f, 0.0f, 0.0f};\n        m_bIsRay = true;\n        m_bHasExtents = false;\n        m_nMask = mask;\n    }\n};\nstatic_assert(sizeof(Ray_t) == 0x40, \"Ray_t must be exactly 64 bytes (0x40)\");\n\n/**\n * @brief 72-byte Spatial Query Filter (CTraceFilter).\n * Reconstructed from client.dll VTable @ 0x181ad4838.\n */\nstruct CTraceFilter {\n    std::uintptr_t m_pVTable{ 0x181ad4838 };   // +0x00: Virtual method table pointer\n    std::uint64_t  m_nTraceMask{ Contents::MASK_SHOT }; // +0x08: 64-bit spatial filtering bitmask\n    std::uint64_t  m_v1[2]{ 0, 0 };            // +0x10: Internal collision flags\n    std::uint32_t  m_nSkipHandles[2]{ 0xFFFFFFFF, 0xFFFFFFFF }; // +0x20: Entity handle exclusion pair\n    std::uint16_t  m_nCollisions[2]{ 0, 0 };   // +0x28: Collision class indicators\n    std::uint8_t   m_bV3{ 0 };                 // +0x2C: Internal predicate byte\n    CS2_PAD(0x03, m_pad2d);                    // +0x2D\n    std::uint64_t  m_uV4{ 0x7 };               // +0x30: Traversal flags\n    std::uint8_t   m_bV5{ 0 };                 // +0x38: Dynamic pass indicator\n    CS2_PAD(0x07, m_pad39);                    // +0x39\n\n    CTraceFilter() = default;\n    explicit CTraceFilter(std::uint64_t mask, std::uint32_t skipHandle = 0xFFFFFFFF)\n        : m_nTraceMask(mask) {\n        m_nSkipHandles[0] = skipHandle;\n    }\n\n    [[nodiscard]] virtual bool ShouldHitEntity(void* /*pEntity*/, std::uint64_t /*contentsMask*/) const {\n        return true;\n    }\n};\nstatic_assert(sizeof(CTraceFilter) == 0x48, \"CTraceFilter must be exactly 72 bytes (0x48)\");\n\n/**\n * @brief 192-byte Authoritative Ray Intersection & Physics Query Result (GameTrace_t).\n * Reconstructed from client.dll. Contains the 40-byte internal Rubikon physics sweep buffer.\n */\nstruct alignas(16) GameTrace_t {\n    void*         m_pSurface{ nullptr };       // +0x00: Surface physics descriptor pointer\n    void*         m_pHitEntity{ nullptr };     // +0x08: Hit C_BaseEntity entity pointer\n    void*         m_pHitboxData{ nullptr };    // +0x10: Target hitbox runtime descriptor pointer\n    std::uint64_t m_nContents{ 0 };            // +0x18: Point contents flags at hit position\n    std::uint64_t m_nHitBoxIndex{ 0 };         // +0x20: Hitbox bone index\n    CS2_PAD(0x08, m_pad28);                    // +0x28\n    Vector3D      m_vStartPos{};               // +0x30: Trajectory origin position\n    CS2_PAD(0x04, m_pad3c);                    // +0x3C\n    Vector3D      m_vEndPos{};                 // +0x40: Trajectory terminus position\n    CS2_PAD(0x04, m_pad4c);                    // +0x4C\n    std::uint8_t  m_rubikonBuffer[40]{};       // +0x50: Internal Rubikon sweep buffer (0x28 bytes)\n    Vector3D      m_vRayStart{};               // +0x78: Exact evaluated ray entry vector\n    Vector3D      m_vRayEnd{};                 // +0x84: Exact evaluated ray exit vector\n    CS2_PAD(0x08, m_pad90);                    // +0x90\n    CS2_PAD(0x04, m_pad98);                    // +0x98\n    Vector3D      m_vHitNormal{};              // +0x9C: Surface unit normal vector at intersection\n    std::uint32_t m_nSpatialVolumeIndex{ 0 };  // +0xA8: Rubikon spatial subdivision cell / hitgroup ID\n    float         m_flFraction{ 1.0f };        // +0xAC: Intersection fraction [0.0..1.0] along ray (1.0 = miss)\n    std::uint64_t m_nHitFlags{ 0 };            // +0xB0: Intersection status flags\n    std::uint16_t m_nSurfaceFlags{ 0 };        // +0xB8: Physical material surface descriptor flags\n    std::uint8_t  m_bStartSolid{ 0 };          // +0xBA: True if ray started inside a solid geometry volume\n    CS2_PAD(0x05, m_padbb);                    // +0xBB\n\n    [[nodiscard]] constexpr bool DidHit() const noexcept {\n        return m_flFraction < 1.0f || m_bStartSolid;\n    }\n\n    [[nodiscard]] constexpr bool IsVisible() const noexcept {\n        return m_flFraction > 0.97f && !m_bStartSolid;\n    }\n};\nstatic_assert(sizeof(GameTrace_t) == 0xC0, \"GameTrace_t must be exactly 192 bytes (0xC0)\");\n\n#undef CS2_PAD\n\n} // namespace cs2::shared\n\n#endif // CS2_SHARED_RAY_TRACE_H\n",
        "skeleton.h": "#ifndef CS2_SHARED_SKELETON_H\n#define CS2_SHARED_SKELETON_H\n\n#include <cstdint>\n#include <cstddef>\n#include <cmath>\n#include <algorithm>\n#include \"math_types.h\"\n#include \"entity_handle.h\"\n\nnamespace cs2::shared {\n\n// ============================================================================\n// Bone Calculation & Usage Flags\n// Reconstructed from client.dll & animationsystem.dll\n// ============================================================================\nenum BoneFlags_t : std::uint32_t {\n    BONE_FLAG_NONE               = 0,\n    BONE_FLAG_CALCULATED         = (1u << 0),  // 0x0001: Bone has been evaluated this frame\n    BONE_FLAG_INTERPOLATED       = (1u << 1),  // 0x0002: Inter-tick interpolation completed\n    BONE_FLAG_WORLD_SPACE        = (1u << 2),  // 0x0004: Bone is in world coordinate space\n    BONE_USED_BY_HITBOX          = (1u << 8),  // 0x0100: Bone drives collision/hitbox geometry\n    BONE_USED_BY_ATTACHMENT      = (1u << 9),  // 0x0200: Bone drives attachments (weapons, muzzle, optics)\n    BONE_USED_BY_VERTEX_LOD0     = (1u << 10), // 0x0400: Bone used in primary LOD0 skinning\n    BONE_USED_BY_BONE_MERGE      = (1u << 11), // 0x0800: Bone participates in bone merge cache\n    BONE_USED_BY_ANYTHING        = 0x0007FF00u\n};\n\n// ============================================================================\n// 3x4 Transformation Matrix (matrix3x4_t)\n// 48 bytes (3 rows, 4 columns: 3x3 rotation/scale + translation column)\n// Standard Source 2 matrix format for skeletal skinning and lag compensation.\n// ============================================================================\nstruct matrix3x4_t {\n    float m[3][4]{};\n\n    constexpr matrix3x4_t() noexcept = default;\n\n    [[nodiscard]] const float* operator[](int i) const noexcept { return m[i]; }\n    [[nodiscard]] float* operator[](int i) noexcept { return m[i]; }\n\n    [[nodiscard]] Vector3D GetOrigin() const noexcept {\n        return {m[0][3], m[1][3], m[2][3]};\n    }\n\n    void SetOrigin(const Vector3D& origin) noexcept {\n        m[0][3] = origin.x;\n        m[1][3] = origin.y;\n        m[2][3] = origin.z;\n    }\n\n    [[nodiscard]] Vector3D TransformVector(const Vector3D& in) const noexcept {\n        return {\n            m[0][0] * in.x + m[0][1] * in.y + m[0][2] * in.z + m[0][3],\n            m[1][0] * in.x + m[1][1] * in.y + m[1][2] * in.z + m[1][3],\n            m[2][0] * in.x + m[2][1] * in.y + m[2][2] * in.z + m[2][3]\n        };\n    }\n\n    [[nodiscard]] Vector3D RotateVector(const Vector3D& in) const noexcept {\n        return {\n            m[0][0] * in.x + m[0][1] * in.y + m[0][2] * in.z,\n            m[1][0] * in.x + m[1][1] * in.y + m[1][2] * in.z,\n            m[2][0] * in.x + m[2][1] * in.y + m[2][2] * in.z\n        };\n    }\n\n    static matrix3x4_t Identity() noexcept {\n        matrix3x4_t mat;\n        mat.m[0][0] = 1.0f; mat.m[1][1] = 1.0f; mat.m[2][2] = 1.0f;\n        return mat;\n    }\n};\nstatic_assert(sizeof(matrix3x4_t) == 48, \"matrix3x4_t must be exactly 48 bytes (0x30)\");\n\n// ============================================================================\n// Source 2 32-Byte CTransform (Quaternion + Position + Scale)\n// Reconstructed from client.dll & animationsystem.dll\n// Reference: docs/09_skeleton_bone_hierarchy_and_animgraph.md\n// ============================================================================\nstruct CTransform {\n    // Rotation Quaternion (qx, qy, qz, qw)\n    float qx{0.0f}, qy{0.0f}, qz{0.0f}, qw{1.0f}; // +0x00 (16 bytes)\n\n    // Position Vector (px, py, pz)\n    float px{0.0f}, py{0.0f}, pz{0.0f};          // +0x10 (12 bytes)\n\n    // Uniform Scale Factor\n    float scale{1.0f};                           // +0x1C (4 bytes)\n\n    constexpr CTransform() noexcept = default;\n    constexpr CTransform(float _qx, float _qy, float _qz, float _qw,\n                         float _px, float _py, float _pz, float _scale = 1.0f) noexcept\n        : qx(_qx), qy(_qy), qz(_qz), qw(_qw), px(_px), py(_py), pz(_pz), scale(_scale) {}\n\n    [[nodiscard]] Vector3D GetPosition() const noexcept { return {px, py, pz}; }\n    void SetPosition(const Vector3D& pos) noexcept { px = pos.x; py = pos.y; pz = pos.z; }\n\n    /**\n     * @brief Rotate a 3D vector using Rodrigues formula (zero trig calls, pure multiply-adds).\n     * Reconstructed from client.dll @ FUN_181748480.\n     */\n    [[nodiscard]] Vector3D RotateVector(const Vector3D& v) const noexcept {\n        const float tx = 2.0f * (qy * v.z - qz * v.y);\n        const float ty = 2.0f * (qz * v.x - qx * v.z);\n        const float tz = 2.0f * (qx * v.y - qy * v.x);\n\n        return {\n            v.x + qw * tx + (qy * tz - qz * ty),\n            v.y + qw * ty + (qz * tx - qx * tz),\n            v.z + qw * tz + (qx * ty - qy * tx)\n        };\n    }\n\n    /**\n     * @brief Transforms local point to world space: p_world = p_trans + scale * Rotate(v).\n     */\n    [[nodiscard]] Vector3D TransformPoint(const Vector3D& point) const noexcept {\n        const Vector3D rot = RotateVector(point);\n        return {px + scale * rot.x, py + scale * rot.y, pz + scale * rot.z};\n    }\n\n    /**\n     * @brief Concatenates parent transform and child local transform.\n     * Reconstructed from client.dll @ FUN_181748480.\n     */\n    static void ConcatenateTransforms(const CTransform& parent, const CTransform& child, CTransform* out) noexcept {\n        // 1. Position: p_out = p_parent + s_parent * Rotate(p_child)\n        const Vector3D childPos{child.px, child.py, child.pz};\n        const Vector3D rotChildPos = parent.RotateVector(childPos);\n        out->px = parent.px + parent.scale * rotChildPos.x;\n        out->py = parent.py + parent.scale * rotChildPos.y;\n        out->pz = parent.pz + parent.scale * rotChildPos.z;\n\n        // 2. Rotation: q_out = q_parent * q_child (Hamilton product)\n        const float nx = parent.qw * child.qx + parent.qx * child.qw + parent.qy * child.qz - parent.qz * child.qy;\n        const float ny = parent.qw * child.qy - parent.qx * child.qz + parent.qy * child.qw + parent.qz * child.qx;\n        const float nz = parent.qw * child.qz + parent.qx * child.qy - parent.qy * child.qx + parent.qz * child.qw;\n        const float nw = parent.qw * child.qw - parent.qx * child.qx - parent.qy * child.qy - parent.qz * child.qz;\n\n        // Normalize resulting quaternion\n        const float lenSq = nx * nx + ny * ny + nz * nz + nw * nw;\n        if (lenSq > 1e-8f) {\n            const float invLen = 1.0f / std::sqrt(lenSq);\n            out->qx = nx * invLen;\n            out->qy = ny * invLen;\n            out->qz = nz * invLen;\n            out->qw = nw * invLen;\n        } else {\n            out->qx = 0.0f; out->qy = 0.0f; out->qz = 0.0f; out->qw = 1.0f;\n        }\n\n        // 3. Scale: s_out = s_parent * s_child\n        out->scale = parent.scale * child.scale;\n    }\n\n    /**\n     * @brief Converts 32-byte CTransform to 48-byte matrix3x4_t format.\n     */\n    [[nodiscard]] matrix3x4_t ToMatrix3x4() const noexcept {\n        matrix3x4_t mat;\n        const float xx = qx * qx;\n        const float yy = qy * qy;\n        const float zz = qz * qz;\n        const float xy = qx * qy;\n        const float xz = qx * qz;\n        const float yz = qy * qz;\n        const float wx = qw * qx;\n        const float wy = qw * qy;\n        const float wz = qw * qz;\n\n        mat.m[0][0] = (1.0f - 2.0f * (yy + zz)) * scale;\n        mat.m[0][1] = (2.0f * (xy - wz)) * scale;\n        mat.m[0][2] = (2.0f * (xz + wy)) * scale;\n        mat.m[0][3] = px;\n\n        mat.m[1][0] = (2.0f * (xy + wz)) * scale;\n        mat.m[1][1] = (1.0f - 2.0f * (xx + zz)) * scale;\n        mat.m[1][2] = (2.0f * (yz - wx)) * scale;\n        mat.m[1][3] = py;\n\n        mat.m[2][0] = (2.0f * (xz - wy)) * scale;\n        mat.m[2][1] = (2.0f * (yz + wx)) * scale;\n        mat.m[2][2] = (1.0f - 2.0f * (xx + yy)) * scale;\n        mat.m[2][3] = pz;\n\n        return mat;\n    }\n};\nstatic_assert(sizeof(CTransform) == 32, \"CTransform must be exactly 32 bytes (0x20)\");\n\n// ============================================================================\n// Model State Container (CModelState)\n// Size: 0x2B0 (688 bytes)\n// Reconstructed from client.dll @ 0x180aa0f80\n// ============================================================================\nclass CModelState {\npublic:\n    virtual ~CModelState() = default;                // +0x00\n    std::uint8_t m_pad08[0x78]{};                    // +0x08..+0x80\n    CTransform* m_pBoneArray{nullptr};               // +0x80: Pointer to dynamic CTransform bone matrix array\n    std::uint8_t m_pad88[0x0C]{};                    // +0x88..+0x94\n    std::uint16_t m_nBoneCount{0};                   // +0x94: Total number of active bones\n    std::uint8_t m_pad96[0x0A]{};                    // +0x96..+0xA0\n    std::uint64_t m_hModel{0};                       // +0xA0: CStrongHandle to compiled model asset\n    const char* m_ModelName{nullptr};                // +0xA8: ASCII model asset path string\n    std::uint8_t m_padB0[0x38]{};                    // +0xB0..+0xE8\n    float m_flRootBoneOffset_x{0.0f};                // +0xE8\n    float m_flRootBoneOffset_y{0.0f};                // +0xEC\n    float m_flRootBoneOffset_z{0.0f};                // +0xF0\n    std::uint8_t m_padF4[0x114]{};                   // +0xF4..+0x208\n    std::uint64_t m_MeshGroupMask{0};                // +0x208: Visible mesh group bitmask\n    std::uint8_t m_pad210[0xA0]{};                   // +0x210..+0x2B0\n};\nstatic_assert(sizeof(CModelState) == 0x2B0, \"CModelState size must be exactly 0x2B0\");\nstatic_assert(offsetof(CModelState, m_pBoneArray) == 0x80, \"m_pBoneArray offset mismatch\");\nstatic_assert(offsetof(CModelState, m_nBoneCount) == 0x94, \"m_nBoneCount offset mismatch\");\n\n// ============================================================================\n// Base Game Scene Node (CGameSceneNode)\n// Size: 0x130 (304 bytes)\n// ============================================================================\nclass CGameSceneNode {\npublic:\n    virtual ~CGameSceneNode() = default;             // +0x00\n    std::uint8_t m_pad08[0x08]{};                    // +0x08\n    CTransform m_nodeToWorld{};                      // +0x10: Root spatial coordinate transformation\n    void* m_pOwner{nullptr};                         // +0x30: Owning entity pointer\n    CGameSceneNode* m_pParent{nullptr};              // +0x38: Parent node in spatial hierarchy\n    CGameSceneNode* m_pChild{nullptr};               // +0x40: Child node\n    CGameSceneNode* m_pNextSibling{nullptr};         // +0x48: Sibling node\n    std::uint8_t m_pad50[0x20]{};                    // +0x50..+0x70\n    CEntityHandle m_hParent{};                       // +0x70: Parent entity handle\n    std::uint8_t m_pad74[0x0C]{};                    // +0x74..+0x80\n    Vector3D m_vecOrigin{};                          // +0x80: Local origin offset\n    std::uint8_t m_pad8C[0x2C]{};                    // +0x8C..+0xB8\n    QAngle m_angRotation{};                          // +0xB8: Local rotation angles\n    float m_flScale{1.0f};                           // +0xC4: Local scalar\n    Vector3D m_vecAbsOrigin{};                       // +0xC8: Absolute world position\n    QAngle m_angAbsRotation{};                       // +0xD4: Absolute world orientation angles\n    float m_flAbsScale{1.0f};                        // +0xE0: Absolute world scalar\n    std::uint8_t m_padE4[0x1F]{};                    // +0xE4..+0x103\n    bool m_bDormant{false};                          // +0x103: PVS dormancy culling flag\n    std::uint8_t m_pad104[0x2C]{};                   // +0x104..+0x130\n};\nstatic_assert(sizeof(CGameSceneNode) == 0x130, \"CGameSceneNode size must be exactly 0x130\");\nstatic_assert(offsetof(CGameSceneNode, m_nodeToWorld) == 0x10, \"m_nodeToWorld offset mismatch\");\nstatic_assert(offsetof(CGameSceneNode, m_vecOrigin) == 0x80, \"m_vecOrigin offset mismatch\");\nstatic_assert(offsetof(CGameSceneNode, m_angRotation) == 0xB8, \"m_angRotation offset mismatch\");\n\n// ============================================================================\n// Skeleton Instance (CSkeletonInstance)\n// Size: 0x490 (1168 bytes)\n// Reconstructed from client.dll (VTable: 0x181c41ce0)\n// ============================================================================\nclass CSkeletonInstance : public CGameSceneNode {\npublic:\n    std::uint8_t m_pad130[0x10]{};                   // +0x130..+0x140\n    CModelState m_modelState{};                      // +0x140: Embedded model state (Size: 0x2B0)\n    bool m_bUseParentRenderBounds{false};            // +0x3F0\n    std::uint8_t m_pad3F1[0x0B]{};                   // +0x3F1..+0x3FC\n    std::uint8_t m_nHitboxSet{0};                    // +0x3FC: Active hitbox set index (0=default)\n    std::uint8_t m_pad3FD[0x5B]{};                   // +0x3FD..+0x458\n    std::uint32_t m_nCalculatedBoneFlags{0};         // +0x458: Forward kinematics dirty bitmask\n    std::uint8_t m_pad45C[0x34]{};                   // +0x45C..+0x490\n\n    [[nodiscard]] inline CTransform* GetBoneArray() const noexcept {\n        return m_modelState.m_pBoneArray;\n    }\n\n    [[nodiscard]] inline std::uint16_t GetBoneCount() const noexcept {\n        return m_modelState.m_nBoneCount;\n    }\n\n    [[nodiscard]] inline bool HasCalculatedBones(std::uint32_t mask) const noexcept {\n        return (m_nCalculatedBoneFlags & mask) == mask;\n    }\n\n    inline void SetCalculatedBoneFlags(std::uint32_t mask) noexcept {\n        m_nCalculatedBoneFlags |= mask;\n    }\n\n    inline void ClearCalculatedBoneFlags() noexcept {\n        m_nCalculatedBoneFlags = 0;\n    }\n};\nstatic_assert(sizeof(CSkeletonInstance) == 0x490, \"CSkeletonInstance size must be exactly 0x490\");\nstatic_assert(offsetof(CSkeletonInstance, m_modelState) == 0x140, \"m_modelState offset mismatch\");\nstatic_assert(offsetof(CSkeletonInstance, m_nHitboxSet) == 0x3FC, \"m_nHitboxSet offset mismatch\");\nstatic_assert(offsetof(CSkeletonInstance, m_nCalculatedBoneFlags) == 0x458, \"m_nCalculatedBoneFlags offset mismatch\");\n\n} // namespace cs2::shared\n\n#endif // CS2_SHARED_SKELETON_H\n",
        "usercmd.h": "#ifndef CS2_SHARED_USERCMD_H\n#define CS2_SHARED_USERCMD_H\n\n#include <cstdint>\n#include <cstddef>\n#include \"math_types.h\"\n\nnamespace cs2::shared {\n\n#define CS2_PAD(bytes, name) private: [[maybe_unused]] std::uint8_t name[bytes]; public:\n\n/**\n * @brief Sub-tick input history entry protobuf container (CSgoInputHistoryEntryPB)\n * Size: 120 bytes (0x78).\n */\nstruct CSgoInputHistoryEntryPB {\n    CS2_PAD(0x18, m_pad0);\n    QAngle        m_viewAngles{};            // +0x18: Sub-tick view angles\n    Vector3D      m_shootPosition{};         // +0x24: Player eye position\n    Vector3D      m_targetHeadPositionCheck{}; // +0x30: Lag compensation verification point\n    float         m_flRenderTickFraction{0.0f}; // +0x3C: Sub-tick fraction within render frame\n    float         m_flPlayerTickFraction{0.0f}; // +0x40: Sub-tick fraction within tick interval [0.0..1.0)\n    CS2_PAD(0x34, m_pad44);\n};\nstatic_assert(sizeof(CSgoInputHistoryEntryPB) == 0x78, \"CSgoInputHistoryEntryPB must be 120 bytes\");\n\n/**\n * @brief Base UserCmd Protobuf container (CBaseUserCmdPB)\n * Size: 136 bytes (0x88).\n */\nstruct CBaseUserCmdPB {\n    CS2_PAD(0x18, m_pad0);\n    std::uint32_t m_nCommandNumber{0};       // +0x18: Monotonically increasing command sequence\n    std::int32_t  m_nTickCount{0};           // +0x1C: Synchronized server tick\n    CS2_PAD(0x24, m_pad20);\n    QAngle        m_viewAngles{};            // +0x44: Command aim angles\n    float         m_flForwardMove{0.0f};     // +0x50: Analog forward/back motion\n    float         m_flSideMove{0.0f};        // +0x54: Analog left/right motion\n    float         m_flUpMove{0.0f};          // +0x58: Analog vertical motion\n    CS2_PAD(0x2C, m_pad5c);\n};\nstatic_assert(sizeof(CBaseUserCmdPB) == 0x88, \"CBaseUserCmdPB must be 136 bytes\");\n\n/**\n * @brief Reconstructed Source 2 Client User Command (CUserCmd)\n * Size: 152 bytes (0x98).\n */\nstruct CUserCmd {\n    CS2_PAD(0x40, m_pad0);\n    CBaseUserCmdPB*          m_pBaseCmd{nullptr};                // +0x40: Protobuf base command\n    CS2_PAD(0x20, m_pad48);\n    CSgoInputHistoryEntryPB* m_pInputHistoryEntries{nullptr};     // +0x68: Dynamic array of sub-tick entries\n    std::int32_t             m_nInputHistoryEntriesCount{0};     // +0x70: Sub-tick history count\n    std::int32_t             m_nInputHistoryEntriesAllocated{0}; // +0x74: Allocated capacity\n    std::uint8_t             m_nAttack1StartHistoryIndex{0xFF};  // +0x78: Attack 1 transition index\n    std::uint8_t             m_nAttack2StartHistoryIndex{0xFF};  // +0x79: Attack 2 transition index\n    std::uint8_t             m_nAttack3StartHistoryIndex{0xFF};  // +0x7A: Attack 3 transition index\n    CS2_PAD(0x1D, m_pad7b);\n};\nstatic_assert(sizeof(CUserCmd) == 0x98, \"CUserCmd must be 152 bytes\");\n\n#undef CS2_PAD\n\n} // namespace cs2::shared\n\n#endif // CS2_SHARED_USERCMD_H\n",
        "weapon_vdata.h": "#ifndef CS2_SHARED_WEAPON_VDATA_H\n#define CS2_SHARED_WEAPON_VDATA_H\n\n#include <cstdint>\n#include <cstddef>\n\nnamespace cs2::shared {\n\n#define CS2_PAD(bytes, name) private: [[maybe_unused]] std::uint8_t name[bytes]; public:\n\nenum class CSWeaponType : std::int32_t {\n    Knife          = 0,\n    Pistol         = 1,\n    Submachinegun  = 2,\n    Rifle          = 3,\n    Shotgun        = 4,\n    SniperRifle    = 5,\n    Machinegun     = 6,\n    C4             = 7,\n    Taser          = 8,\n    Grenade        = 9,\n    Equipment      = 10,\n    StackableItem  = 11,\n    Unknown        = 12\n};\n\n/**\n * @brief Weapon Configuration Metadata (CCSWeaponBaseVData).\n * Total Struct Size: exactly 2,208 bytes (0x8A0).\n * Verified against client.dll SchemaSystem class reflection.\n */\nstruct CCSWeaponBaseVData {\n    CS2_PAD(0x520, m_pad0);\n    CSWeaponType m_WeaponType{ CSWeaponType::Unknown }; // +0x0520: Subsystem classification\n    CS2_PAD(0x1FC, m_pad524);\n    const char*  m_szName{ nullptr };                   // +0x0720: Internal technical name (e.g. \"weapon_ak47\")\n    CS2_PAD(0x10, m_pad728);\n    float        m_flCycleTime{ 0.1f };                 // +0x0738: Time interval between successive rounds\n    CS2_PAD(0x14, m_pad73c);\n    float        m_flSpread{ 0.0f };                    // +0x0750: Intrinsic cone base spread\n    CS2_PAD(0x04, m_pad754);\n    float        m_flInaccuracyCrouch{ 0.0f };          // +0x0758: Inaccuracy penalty while crouching\n    CS2_PAD(0x04, m_pad75c);\n    float        m_flInaccuracyStand{ 0.0f };           // +0x0760: Inaccuracy penalty while standing\n    CS2_PAD(0x04, m_pad764);\n    float        m_flInaccuracyJump{ 0.0f };            // +0x0768: Inaccuracy penalty airborne\n    CS2_PAD(0x1C, m_pad76c);\n    float        m_flInaccuracyMove{ 0.0f };            // +0x0788: Inaccuracy penalty while traversing\n    CS2_PAD(0x94, m_pad78c);\n    std::int32_t m_nDamage{ 0 };                        // +0x0820: Base raw physical kinetic impact damage\n    CS2_PAD(0x04, m_pad824);\n    float        m_flArmorRatio{ 1.0f };                // +0x0828: Kinetic armor penetration scaling coefficient\n    float        m_flPenetration{ 1.0f };               // +0x082C: Material barrier penetration capability\n    float        m_flRange{ 8192.0f };                  // +0x0830: Maximum ballistic raycast range in units\n    float        m_flRangeModifier{ 0.98f };            // +0x0834: Distance attenuation loss factor (500-unit decay)\n    CS2_PAD(0x68, m_pad838);\n};\nstatic_assert(sizeof(CCSWeaponBaseVData) == 0x8A0, \"CCSWeaponBaseVData must be 2,208 bytes (0x8A0)\");\n\n#undef CS2_PAD\n\n} // namespace cs2::shared\n\n#endif // CS2_SHARED_WEAPON_VDATA_H\n"
      }
    },
    {
      "module": "soundsystem.dll",
      "directory": "game/soundsystem",
      "standard": "C++20 (/std:c++20 /W4)",
      "files": {
        "sound_ops.cpp": "#include \"sound_ops.h\"\n\nnamespace cs2::soundsystem {\n\nCSoundManager& CSoundManager::Get() {\n    static CSoundManager s_Instance;\n    return s_Instance;\n}\n\ninterfaces::StartSoundEventInfo_t CSoundManager::CreateSpatialSoundInfo(\n    const shared::Vector3D& origin,\n    float volume,\n    float pitch,\n    shared::CEntityHandle entity\n) noexcept {\n    interfaces::StartSoundEventInfo_t info{};\n    info.m_vecOrigin = origin;\n    info.m_flVolume = volume;\n    info.m_flPitch = pitch;\n    info.m_hEntity = entity;\n\n    // Set 3x4 identity orientation matrix at origin\n    info.m_matSpatial[0][0] = 1.0f;\n    info.m_matSpatial[1][1] = 1.0f;\n    info.m_matSpatial[2][2] = 1.0f;\n    info.m_matSpatial[0][3] = origin.x;\n    info.m_matSpatial[1][3] = origin.y;\n    info.m_matSpatial[2][3] = origin.z;\n\n    return info;\n}\n\n} // namespace cs2::soundsystem\n",
        "sound_ops.h": "#ifndef CS2_SOUNDSYSTEM_SOUND_OPS_H\n#define CS2_SOUNDSYSTEM_SOUND_OPS_H\n\n#include <cstdint>\n#include <string_view>\n#include \"../interfaces/sound_system.h\"\n#include \"../tier0/utl_string_token.h\"\n\nnamespace cs2::soundsystem {\n\n/**\n * @brief Sound operator helper & event dispatcher\n * Reconstructed from soundsystem.dll @ 0x1804ab140 and client.dll + 0xB4FB20\n */\nclass CSoundManager {\npublic:\n    static CSoundManager& Get();\n\n    /**\n     * @brief Computes 32-bit MurmurHash2 sound event identifier\n     */\n    static constexpr std::uint32_t HashSoundEvent(std::string_view name) noexcept {\n        return tier0::CUtlStringToken::Hash(name);\n    }\n\n    /**\n     * @brief Formats a 3D sound event parameter packet\n     */\n    static interfaces::StartSoundEventInfo_t CreateSpatialSoundInfo(\n        const shared::Vector3D& origin,\n        float volume = 1.0f,\n        float pitch = 1.0f,\n        shared::CEntityHandle entity = shared::CEntityHandle{}\n    ) noexcept;\n};\n\n} // namespace cs2::soundsystem\n\n#endif // CS2_SOUNDSYSTEM_SOUND_OPS_H\n"
      }
    },
    {
      "module": "tier0.dll",
      "directory": "game/tier0",
      "standard": "C++20 (/std:c++20 /W4)",
      "files": {
        "memalloc.cpp": "#include \"memalloc.h\"\n#include <cstdlib>\n\nnamespace cs2::tier0 {\n\n// Emulated default standard heap allocator for standalone simulators and tooling\nclass CMemAllocStandard : public IMemAlloc {\npublic:\n    void* Alloc(std::size_t nSize) override {\n        return std::malloc(nSize);\n    }\n\n    void* Realloc(void* pMem, std::size_t nSize) override {\n        return std::realloc(pMem, nSize);\n    }\n\n    void Free(void* pMem) override {\n        std::free(pMem);\n    }\n\n    void* Expand(void* /*pMem*/, std::size_t /*nSize*/) override {\n        return nullptr;\n    }\n\n    void* AllocAligned(std::size_t nSize, std::size_t nAlignment) override {\n#if defined(_MSC_VER)\n        return _aligned_malloc(nSize, nAlignment);\n#else\n        return std::malloc(nSize);\n#endif\n    }\n\n    void* ReallocAligned(void* pMem, std::size_t nSize, std::size_t nAlignment) override {\n#if defined(_MSC_VER)\n        return _aligned_realloc(pMem, nSize, nAlignment);\n#else\n        return std::realloc(pMem, nSize);\n#endif\n    }\n\n    void FreeAligned(void* pMem) override {\n#if defined(_MSC_VER)\n        _aligned_free(pMem);\n#else\n        std::free(pMem);\n#endif\n    }\n\n    std::size_t GetSize(void* /*pMem*/) override {\n        return 0;\n    }\n};\n\nstatic CMemAllocStandard s_DefaultMemAlloc;\nstatic IMemAlloc* s_pMemAlloc = &s_DefaultMemAlloc;\n\nIMemAlloc* GetMemAlloc() {\n    return s_pMemAlloc;\n}\n\n} // namespace cs2::tier0\n",
        "memalloc.h": "#ifndef CS2_TIER0_MEMALLOC_H\n#define CS2_TIER0_MEMALLOC_H\n\n#include <cstdint>\n#include <cstddef>\n\nnamespace cs2::tier0 {\n\n/**\n * @brief Valve Memory Allocator Interface (IMemAlloc)\n * Exported by tier0.dll as 'g_pMemAlloc' (Export RVA: +0x3ac458, VTable RVA: +0x3277d0)\n * 85 virtual method slots.\n */\nclass IMemAlloc {\npublic:\n    virtual ~IMemAlloc() = default;\n\n    // Slot 1: Alloc\n    virtual void* Alloc(std::size_t nSize) = 0;\n\n    // Slot 2: Realloc\n    virtual void* Realloc(void* pMem, std::size_t nSize) = 0;\n\n    // Slot 3: Free\n    virtual void  Free(void* pMem) = 0;\n\n    // Slot 4: Expand\n    virtual void* Expand(void* pMem, std::size_t nSize) = 0;\n\n    // Slot 5: Alloc aligned\n    virtual void* AllocAligned(std::size_t nSize, std::size_t nAlignment) = 0;\n\n    // Slot 6: Realloc aligned\n    virtual void* ReallocAligned(void* pMem, std::size_t nSize, std::size_t nAlignment) = 0;\n\n    // Slot 7: Free aligned\n    virtual void  FreeAligned(void* pMem) = 0;\n\n    // Slot 8: GetSize\n    virtual std::size_t GetSize(void* pMem) = 0;\n};\n\n/**\n * @brief Retrieves the authoritative global memory allocator instance.\n */\nIMemAlloc* GetMemAlloc();\n\n} // namespace cs2::tier0\n\n#endif // CS2_TIER0_MEMALLOC_H\n",
        "utl_string_token.h": "#ifndef CS2_TIER0_UTL_STRING_TOKEN_H\n#define CS2_TIER0_UTL_STRING_TOKEN_H\n\n#include <cstdint>\n#include <string_view>\n\nnamespace cs2::tier0 {\n\n/**\n * @brief 32-bit MurmurHash2 / FNV-1a Hashed String Identifier (CUtlStringToken)\n * Used extensively throughout Source 2 (schemasystem.dll, client.dll, server.dll)\n * to avoid runtime string comparisons.\n * Size: exactly 4 bytes.\n */\nclass CUtlStringToken {\npublic:\n    std::uint32_t m_nHashCode{0};\n\n    constexpr CUtlStringToken() noexcept = default;\n    constexpr explicit CUtlStringToken(std::uint32_t nCode) noexcept : m_nHashCode(nCode) {}\n\n    // Compile-time or runtime string hashing via MurmurHash2\n    constexpr explicit CUtlStringToken(std::string_view str) noexcept\n        : m_nHashCode(Hash(str)) {}\n\n    constexpr explicit CUtlStringToken(const char* pszString) noexcept\n        : m_nHashCode(pszString ? Hash(std::string_view(pszString)) : 0) {}\n\n    [[nodiscard]] constexpr std::uint32_t Get() const noexcept { return m_nHashCode; }\n    [[nodiscard]] constexpr bool IsValid() const noexcept { return m_nHashCode != 0; }\n\n    constexpr bool operator==(const CUtlStringToken& o) const noexcept { return m_nHashCode == o.m_nHashCode; }\n    constexpr bool operator!=(const CUtlStringToken& o) const noexcept { return m_nHashCode != o.m_nHashCode; }\n    constexpr bool operator<(const CUtlStringToken& o) const noexcept { return m_nHashCode < o.m_nHashCode; }\n\n    /**\n     * @brief Source 2 Authoritative MurmurHash2 implementation\n     * Matches schemasystem.dll @ 0x180010380\n     */\n    static constexpr std::uint32_t Hash(std::string_view str) noexcept {\n        const std::uint32_t len = static_cast<std::uint32_t>(str.length());\n        if (len == 0) return 0;\n\n        constexpr std::uint32_t m = 0x5bd1e995;\n        constexpr int r = 24;\n\n        std::uint32_t h = len ^ 0xbaadfeed;\n        const char* data = str.data();\n        std::uint32_t remaining = len;\n\n        while (remaining >= 4) {\n            std::uint32_t k = static_cast<std::uint8_t>(data[0]) |\n                             (static_cast<std::uint8_t>(data[1]) << 8) |\n                             (static_cast<std::uint8_t>(data[2]) << 16) |\n                             (static_cast<std::uint8_t>(data[3]) << 24);\n\n            k *= m;\n            k ^= k >> r;\n            k *= m;\n\n            h *= m;\n            h ^= k;\n\n            data += 4;\n            remaining -= 4;\n        }\n\n        switch (remaining) {\n            case 3: h ^= static_cast<std::uint8_t>(data[2]) << 16; [[fallthrough]];\n            case 2: h ^= static_cast<std::uint8_t>(data[1]) << 8;  [[fallthrough]];\n            case 1: h ^= static_cast<std::uint8_t>(data[0]);\n                    h *= m;\n                    break;\n            default: break;\n        }\n\n        h ^= h >> 13;\n        h *= m;\n        h ^= h >> 15;\n\n        return h;\n    }\n};\n\nstatic_assert(sizeof(CUtlStringToken) == 4, \"CUtlStringToken must be 4 bytes\");\n\n} // namespace cs2::tier0\n\n#endif // CS2_TIER0_UTL_STRING_TOKEN_H\n",
        "utl_vector.h": "#ifndef CS2_TIER0_UTL_VECTOR_H\n#define CS2_TIER0_UTL_VECTOR_H\n\n#include <cstdint>\n#include <cstddef>\n#include <cassert>\n#include <initializer_list>\n#include \"memalloc.h\"\n\nnamespace cs2::tier0 {\n\n/**\n * @brief Valve Dynamic Vector Container (CUtlVector<T>)\n * Standard dynamic array layout across Source 2 engines.\n * Size: 24 bytes (0x18) on x64 (m_Size + padding + m_pMemory + m_nAllocationCount).\n */\ntemplate <typename T>\nclass CUtlVector {\npublic:\n    int   m_Size{0};\n    T*    m_pMemory{nullptr};\n    int   m_nAllocationCount{0};\n    int   m_nGrowSize{0};\n\n    CUtlVector() = default;\n\n    CUtlVector(int nGrowSize, int nInitAllocationCount)\n        : m_nGrowSize(nGrowSize) {\n        Grow(nInitAllocationCount);\n    }\n\n    ~CUtlVector() {\n        Purge();\n    }\n\n    [[nodiscard]] int Count() const noexcept { return m_Size; }\n    [[nodiscard]] int Size() const noexcept { return m_Size; }\n    [[nodiscard]] bool IsEmpty() const noexcept { return m_Size == 0; }\n    [[nodiscard]] int Capacity() const noexcept { return m_nAllocationCount; }\n\n    T& operator[](int i) {\n        assert(i >= 0 && i < m_Size);\n        return m_pMemory[i];\n    }\n\n    const T& operator[](int i) const {\n        assert(i >= 0 && i < m_Size);\n        return m_pMemory[i];\n    }\n\n    T* Base() noexcept { return m_pMemory; }\n    const T* Base() const noexcept { return m_pMemory; }\n\n    int AddToTail(const T& src) {\n        if (m_Size >= m_nAllocationCount) {\n            Grow(m_nGrowSize > 0 ? m_nGrowSize : (m_nAllocationCount ? m_nAllocationCount : 4));\n        }\n        m_pMemory[m_Size] = src;\n        return m_Size++;\n    }\n\n    void Purge() {\n        if (m_pMemory) {\n            GetMemAlloc()->Free(m_pMemory);\n            m_pMemory = nullptr;\n        }\n        m_Size = 0;\n        m_nAllocationCount = 0;\n    }\n\n    void RemoveAll() {\n        m_Size = 0;\n    }\n\nprivate:\n    void Grow(int nCount) {\n        const int nNewAllocationCount = m_nAllocationCount + nCount;\n        if (m_pMemory) {\n            m_pMemory = static_cast<T*>(GetMemAlloc()->Realloc(m_pMemory, nNewAllocationCount * sizeof(T)));\n        } else {\n            m_pMemory = static_cast<T*>(GetMemAlloc()->Alloc(nNewAllocationCount * sizeof(T)));\n        }\n        m_nAllocationCount = nNewAllocationCount;\n    }\n};\n\n} // namespace cs2::tier0\n\n#endif // CS2_TIER0_UTL_VECTOR_H\n"
      }
    },
    {
      "module": "vphysics2.dll",
      "directory": "game/vphysics2",
      "standard": "C++20 (/std:c++20 /W4)",
      "files": {
        "rubikon_collision.cpp": "#include \"rubikon_collision.h\"\n#include <algorithm>\n\nnamespace cs2::vphysics2 {\n\nRayCastResult CRubikonCollision::IntersectRayAABB(const Ray_t& ray, const AABB_t& box, float skin) {\n    RayCastResult res;\n\n    const Vector3 boxMin = {box.mins.x - skin, box.mins.y - skin, box.mins.z - skin};\n    const Vector3 boxMax = {box.maxs.x + skin, box.maxs.y + skin, box.maxs.z + skin};\n\n    float tmin = 0.0f;\n    float tmax = 1.0f;\n    Vector3 hitNormal{0, 0, 0};\n\n    // Slab test for 3 dimensions\n    for (int i = 0; i < 3; ++i) {\n        const float rayStart = (i == 0) ? ray.start.x : (i == 1 ? ray.start.y : ray.start.z);\n        const float rayDelta = (i == 0) ? ray.delta.x : (i == 1 ? ray.delta.y : ray.delta.z);\n        const float bMin = (i == 0) ? boxMin.x : (i == 1 ? boxMin.y : boxMin.z);\n        const float bMax = (i == 0) ? boxMax.x : (i == 1 ? boxMax.y : boxMax.z);\n\n        if (std::abs(rayDelta) < 1e-8f) {\n            if (rayStart < bMin || rayStart > bMax) {\n                return res; // Parallel and outside\n            }\n        } else {\n            const float ood = 1.0f / rayDelta;\n            float t1 = (bMin - rayStart) * ood;\n            float t2 = (bMax - rayStart) * ood;\n            float sign = -1.0f;\n\n            if (t1 > t2) {\n                std::swap(t1, t2);\n                sign = 1.0f;\n            }\n\n            if (t1 > tmin) {\n                tmin = t1;\n                hitNormal = {0, 0, 0};\n                if (i == 0) hitNormal.x = sign;\n                else if (i == 1) hitNormal.y = sign;\n                else hitNormal.z = sign;\n            }\n            tmax = std::min(tmax, t2);\n\n            if (tmin > tmax) {\n                return res;\n            }\n        }\n    }\n\n    if (tmin >= 0.0f && tmin <= 1.0f) {\n        res.hit = true;\n        res.fraction = tmin;\n        res.normal = hitNormal;\n        res.hitPoint = ray.start + (ray.delta * tmin);\n    }\n\n    return res;\n}\n\nRayCastResult CRubikonCollision::SweepSphereAgainstCapsule(\n    const Vector3& sphereStart, const Vector3& sphereEnd, float sphereRadius,\n    const Vector3& capP0, const Vector3& capP1, float capRadius) {\n    \n    RayCastResult res;\n    const float combinedRadius = sphereRadius + capRadius;\n    const Vector3 rayDelta = sphereEnd - sphereStart;\n\n    // Approximate closest distance between ray and capsule segment\n    Vector3 capDelta = capP1 - capP0;\n    float capLenSqr = capDelta.LengthSqr();\n\n    constexpr int kSteps = 16;\n    for (int i = 0; i <= kSteps; ++i) {\n        float t = static_cast<float>(i) / static_cast<float>(kSteps);\n        Vector3 spherePos = sphereStart + (rayDelta * t);\n\n        // Project spherePos onto capsule segment\n        float u = 0.0f;\n        if (capLenSqr > 1e-6f) {\n            u = std::clamp((spherePos - capP0).Dot(capDelta) / capLenSqr, 0.0f, 1.0f);\n        }\n        Vector3 closestOnCap = capP0 + (capDelta * u);\n        Vector3 diff = spherePos - closestOnCap;\n\n        if (diff.LengthSqr() <= combinedRadius * combinedRadius) {\n            res.hit = true;\n            res.fraction = t;\n            res.normal = diff.Normalized();\n            res.hitPoint = closestOnCap + (res.normal * capRadius);\n            return res;\n        }\n    }\n\n    return res;\n}\n\nstd::optional<uint32_t> CRubikonCollision::TraceRayBvh(const Ray_t& ray, const std::vector<RubikonBvhNode_t>& nodes) {\n    if (nodes.empty()) return std::nullopt;\n\n    std::vector<uint32_t> stack;\n    stack.reserve(32);\n    stack.push_back(0);\n\n    float closestFraction = 1.0f;\n    std::optional<uint32_t> bestPrimitive = std::nullopt;\n\n    while (!stack.empty()) {\n        uint32_t nodeIdx = stack.back();\n        stack.pop_back();\n\n        if (nodeIdx >= nodes.size()) continue;\n        const auto& node = nodes[nodeIdx];\n\n        AABB_t box{node.minBounds, node.maxBounds};\n        RayCastResult hit = IntersectRayAABB(ray, box, 0.0f);\n\n        if (hit.hit && hit.fraction <= closestFraction) {\n            if (node.leftChild == 0xFFFFFFFF && node.rightChild == 0xFFFFFFFF) {\n                // Leaf primitive\n                closestFraction = hit.fraction;\n                bestPrimitive = node.primitiveIndex;\n            } else {\n                if (node.rightChild != 0xFFFFFFFF) stack.push_back(node.rightChild);\n                if (node.leftChild != 0xFFFFFFFF) stack.push_back(node.leftChild);\n            }\n        }\n    }\n\n    return bestPrimitive;\n}\n\n} // namespace cs2::vphysics2\n",
        "rubikon_collision.h": "#ifndef CS2_RUBIKON_COLLISION_H\n#define CS2_RUBIKON_COLLISION_H\n\n#include <cstdint>\n#include <cmath>\n#include <optional>\n#include <vector>\n\nnamespace cs2::vphysics2 {\n\nstruct Vector3 {\n    float x{0.0f}, y{0.0f}, z{0.0f};\n\n    Vector3 operator+(const Vector3& o) const noexcept { return {x + o.x, y + o.y, z + o.z}; }\n    Vector3 operator-(const Vector3& o) const noexcept { return {x - o.x, y - o.y, z - o.z}; }\n    Vector3 operator*(float s) const noexcept { return {x * s, y * s, z * s}; }\n    [[nodiscard]] float Dot(const Vector3& o) const noexcept { return x * o.x + y * o.y + z * o.z; }\n    [[nodiscard]] float LengthSqr() const noexcept { return Dot(*this); }\n    [[nodiscard]] float Length() const noexcept { return std::sqrt(LengthSqr()); }\n    [[nodiscard]] Vector3 Normalized() const noexcept {\n        float l = Length();\n        return l > 1e-6f ? (*this) * (1.0f / l) : Vector3{0, 0, 0};\n    }\n};\n\nstruct Ray_t {\n    Vector3 start;\n    Vector3 delta;\n};\n\nstruct AABB_t {\n    Vector3 mins;\n    Vector3 maxs;\n\n    [[nodiscard]] bool Contains(const Vector3& pt) const noexcept {\n        return pt.x >= mins.x && pt.x <= maxs.x &&\n               pt.y >= mins.y && pt.y <= maxs.y &&\n               pt.z >= mins.z && pt.z <= maxs.z;\n    }\n};\n\nstruct RayCastResult {\n    bool hit{false};\n    float fraction{1.0f};\n    Vector3 normal{0.0f, 0.0f, 0.0f};\n    Vector3 hitPoint{0.0f, 0.0f, 0.0f};\n};\n\n/**\n * @brief Rubikon 48-byte BVH Node matching vphysics2.dll SIMD accelerator @ 0x18000f4e0.\n */\nstruct alignas(16) RubikonBvhNode_t {\n    Vector3 minBounds;\n    uint32_t leftChild;\n    Vector3 maxBounds;\n    uint32_t rightChild;\n    uint32_t flags;\n    uint32_t primitiveIndex;\n    uint32_t pad[2];\n};\n\n/**\n * @brief Reconstructed Rubikon Physics collision solver from vphysics2.dll.\n */\nclass CRubikonCollision {\npublic:\n    // Valve Rubikon standard skin margin is 1/32th of an inch (0.03125)\n    static constexpr float kSkinMargin = 0.03125f;\n\n    /**\n     * @brief Ray vs Box intersection with Rubikon skin expansion.\n     */\n    static RayCastResult IntersectRayAABB(const Ray_t& ray, const AABB_t& box, float skin = kSkinMargin);\n\n    /**\n     * @brief Swept sphere / capsule query against stationary capsule.\n     */\n    static RayCastResult SweepSphereAgainstCapsule(\n        const Vector3& sphereStart, const Vector3& sphereEnd, float sphereRadius,\n        const Vector3& capP0, const Vector3& capP1, float capRadius);\n\n    /**\n     * @brief Traverses a Rubikon BVH tree node array against a ray.\n     */\n    static std::optional<uint32_t> TraceRayBvh(const Ray_t& ray, const std::vector<RubikonBvhNode_t>& nodes);\n};\n\n} // namespace cs2::vphysics2\n\n#endif // CS2_RUBIKON_COLLISION_H\n"
      }
    }
  ]
}