{"source": "--[[\n    Boulder Creek  (place 120073741652089)\n    Animal ESP + silent aim.\n\n    How the game fires a shot (from the decompiled client):\n\n        Rifle.Fire\n            origin  = Model.PrimaryPart.BarrelAttachment.WorldPosition\n            aimPoint= workspace:Raycast(Camera.CFrame.Position, Camera.CFrame.LookVector * 1500, ...)\n            dir     = (aimPoint.Position - origin).Unit\n            projectileController:Fire(origin, dir, MuzzleVelocity / 0.28, userData)\n\n        ProjectileController.Fire(self, origin, dir, speed, userData, isReplicated, id)\n            local proj = caster:Fire(origin, dir, speed, userData, id)      -- LOCAL simulation\n            if not isReplicated then\n                Remotes.ProjectileFire:FireServer(origin, dir.Unit * speed, id, userData)\n            end\n\n    The projectile is simulated on the client and the hit is reported by the client\n    (Remotes.ProjectileHitAnimal:FireServer), so the direction that matters is the one the\n    LOCAL simulation runs with. Wrapping ProjectileController.Fire/FireBatch replaces that\n    direction for the local simulation and for the server payload at once.\n\n    The ballistics are the game's own, copied from Ballistics.CalculateAcceleration and\n    Projectile.Step, so the solve is exact for this game rather than a generic parabola:\n\n        gravity          = (0, -35.035717, 0)\n        accel(v)         = -(0.6125 * |v*0.28|^2 * Cd * A) * (v*0.28).Unit / (mass*0.001)\n                            * 3.5714285714 + gravity\n        step:  a = accel(v); dp = v*dt + a*dt^2/2; v = v + a*dt; p = p + dp      (dt = 1/60)\n]]\n\nlocal Players = game:GetService(\"Players\")\nlocal ReplicatedStorage = game:GetService(\"ReplicatedStorage\")\nlocal RunService = game:GetService(\"RunService\")\n\nlocal LP = Players.LocalPlayer\nlocal Camera = workspace.CurrentCamera\n\n-- Re-running this file has to replace the previous copy. Each load installs its own hooks\n-- and its own per-frame mod pass, and an older copy sitting there with mods off would quietly\n-- undo the newer one's writes to the weapon every frame - which is exactly what happened\n-- before this guard existed. The previous instance is torn down here first.\ndo\n    local previous = getgenv().BoulderOverlay\n    if type(previous) == \"table\" then\n        -- the library leaves its ScreenGui behind, so the old menu is removed with the old\n        -- instance's own reference rather than by guessing names\n        local ok = pcall(function()\n            local window = previous.STATE and previous.STATE.window\n            local frame = window and window.Items and window.Items.MainFrame\n            local gui = frame and frame.Instance and frame.Instance:FindFirstAncestorOfClass(\"ScreenGui\")\n            if gui then gui:Destroy() end\n        end)\n        if type(previous.unload) == \"function\" then pcall(previous.unload) end\n    end\n\n    -- and sweep any copy a run that was killed before it could unload left behind: the menu\n    -- button is this file's own instance, so a ScreenGui holding one that is not this run's\n    -- is a dead copy of this overlay (five of them had piled up in gethui by the time this\n    -- was written, all stacked on the same spot)\n    pcall(function()\n        local holder = gethui()\n        if not holder then return end\n        for _, gui in ipairs(holder:GetChildren()) do\n            if gui:IsA(\"ScreenGui\") then\n                for _, d in ipairs(gui:GetDescendants()) do\n                    if d:IsA(\"TextButton\") and d.Name == \"BoulderMenuButton\" and d.Text == \"BC\" then\n                        gui:Destroy()\n                        break\n                    end\n                end\n            end\n        end\n    end)\nend\n\n-- ============================================================ state\n\nlocal STATE = {\n    log = {},\n    tracks = {},\n    target = nil,\n    lastSolve = nil,\n    shotsSeen = 0,\n    redirected = 0,\n    hitsClaimed = 0,\n    lastError = nil,\n    aimHeld = true,\n    weapon = nil,\n}\n\nlocal function logEvent(kind, msg)\n    STATE.log[#STATE.log + 1] = { kind = kind, msg = tostring(msg), at = os.clock() }\n    if #STATE.log > 80 then table.remove(STATE.log, 1) end\nend\n\n-- set false by unload so every loop this file starts can retire itself\nlocal RUN = { alive = true }\n\n-- A load of this file that is replaced without its unload running (an executor re-exec, a\n-- reload that overwrote the api table) would otherwise leave its main loop alive forever.\n-- Each main loop that finds a different instance holding the api table retires itself, so a\n-- stale copy can never sit there writing to the weapon alongside the live one.\nlocal INSTANCE = {}\nlocal function current()\n    if not RUN.alive then return false end\n    local now = getgenv().BoulderOverlay\n    if now and now.INSTANCE ~= nil and now.INSTANCE ~= INSTANCE then\n        RUN.alive = false\n        return false\n    end\n    return true\nend\n\n-- ============================================================ config\n\nlocal CONFIG = {\n    aim = {\n        enabled = true,\n        fov = 25,               -- degrees off the crosshair a target may sit\n        maxDistance = 1600,     -- studs\n        wallCheck = true,       -- require a clear line from the muzzle\n        lead = true,            -- predict the animal's own travel\n        zone = \"center\",        -- center | upper | lower\n        autoFire = false,       -- reserved\n    },\n    esp = {\n        enabled = true,\n        animals = true,\n        dead = false,\n        mounts = false,\n        boxStyle = \"Corners\",   -- Corners | Box | Both\n        name = true,\n        distance = true,\n        info = false,\n        textSize = 12,\n        fill = true,\n        maxDistance = 1600,\n        color = Color3.fromRGB(0, 214, 190),\n        deadColor = Color3.fromRGB(150, 150, 150),\n        playerColor = Color3.fromRGB(255, 90, 90),\n        thickness = 1,\n    },\n    mods = {\n        rapidFire = false,\n        fireRate = 900,         -- rounds per minute written onto the live weapon\n        autoFire = false,\n        autoFireDelay = 0.10,   -- seconds between trigger shots\n        infiniteAmmo = false,\n    },\n}\n\n-- ============================================================ ballistics (the game's own)\n\nlocal GRAVITY = Vector3.new(0, -35.03571701049805, 0)\nlocal STEP = 1 / 60\n\nlocal function accel(v, mass, drag, area)\n    local s = v * 0.28\n    local mag = s.Magnitude\n    if mag <= 0 or mass <= 0 then return GRAVITY end\n    return -(0.6125 * mag * mag * drag * area) * s.Unit / (mass * 0.001)\n        * 3.571428571428571 + GRAVITY\nend\n\nlocal function stepProjectile(p, v, mass, drag, area, dt)\n    local a = accel(v, mass, drag, area)\n    local dp = v * dt + a * (dt * dt * 0.5)\n    return p + dp, v + a * dt\nend\n\n-- Time of flight for a projectile of `speed` launched from `origin` to reach a point that\n-- is itself travelling at `vel`. Closed-form quadratic in t:\n--   | P + V t - O |^2 = (speed t)^2\nlocal function interceptTime(origin, pos, vel, speed)\n    local r = pos - origin\n    local a = vel:Dot(vel) - speed * speed\n    local b = 2 * r:Dot(vel)\n    local c = r:Dot(r)\n    if math.abs(a) < 1e-6 then\n        if math.abs(b) < 1e-6 then return nil end\n        local t = -c / b\n        return t > 0 and t or nil\n    end\n    local disc = b * b - 4 * a * c\n    if disc < 0 then return nil end\n    local sq = math.sqrt(disc)\n    local best\n    for _, t in ipairs({ (-b - sq) / (2 * a), (-b + sq) / (2 * a) }) do\n        if t > 0 and (not best or t < best) then best = t end\n    end\n    return best\nend\n\n-- Simulate a free-flight projectile (no collision) and report how close it came to a\n-- moving point, and where. This is the same integrator the game runs, minus the raycasts,\n-- so the miss it reports is the miss the hit test will see.\nlocal function closestApproach(origin, dir, speed, mass, drag, area, tMax, targetFn)\n    local p, v = origin, dir * speed\n    local t = 0\n    local best, bestT, bestPos = math.huge, 0, p\n    while t < tMax do\n        local d = (p - targetFn(t)).Magnitude\n        if d < best then best, bestT, bestPos = d, t, p end\n        p, v = stepProjectile(p, v, mass, drag, area, STEP)\n        t = t + STEP\n    end\n    return best, bestT, bestPos\nend\n\n-- Solve the launch direction that puts the projectile through the target's path.\n-- Seeded by the closed-form intercept, then corrected against the real trajectory:\n-- fire, measure where the round actually passed the target, move the aim by that miss,\n-- repeat. Four passes settle inside a fraction of a stud for every weapon in the game.\nlocal function solveAim(origin, targetPos, targetVel, speed, mass, drag, area)\n    local function targetFn(t) return targetPos + targetVel * t end\n    local T = interceptTime(origin, targetPos, targetVel, speed) or 0.15\n    local aim = targetFn(T)\n    local dir = (aim - origin).Unit\n    for _ = 1, 4 do\n        local missDist, missT, missPos =\n            closestApproach(origin, dir, speed, mass, drag, area, math.max(T * 2.5, 0.35), targetFn)\n        local missVec = targetFn(missT) - missPos\n        aim = aim + missVec\n        dir = (aim - origin).Unit\n        T = missT\n    end\n    return dir, T\nend\n\n-- rotate direction `d` by the rotation that takes `from` to `to` (keeps pellet spread)\nlocal function rotateDir(from, to, d)\n    local a = CFrame.lookAt(Vector3.zero, from)\n    local b = CFrame.lookAt(Vector3.zero, to)\n    return b * (a:Inverse() * d)\nend\n\n-- ============================================================ animal tracking\n\nlocal ANIMAL_FOLDERS = {\n    { folder = \"Animals\", kind = \"animal\" },\n    { folder = \"DeadAnimals\", kind = \"dead\" },\n    { folder = \"Mounts\", kind = \"mount\" },\n    { folder = \"Dogs\", kind = \"dog\" },\n}\n\nlocal function bodyPart(model)\n    local pb = model:FindFirstChild(\"_ProjectileBounds\")\n    if pb and pb:IsA(\"BasePart\") then return pb end\n    local root = model:FindFirstChild(\"RootPart\")\n    if root and root:IsA(\"BasePart\") then return root end\n    return model.PrimaryPart or model:FindFirstChildWhichIsA(\"BasePart\")\nend\n\n-- The point a shot should steer at: the middle of the volume the bullet has to pass\n-- through, lifted or dropped onto the requested zone.\nlocal function aimPointOf(model, part)\n    if not part then return nil end\n    local p = part.Position\n    local size = part:IsA(\"BasePart\") and part.Size or model:GetExtentsSize()\n    local f = CONFIG.aim.zone\n    if f == \"upper\" then\n        p = p + Vector3.new(0, size.Y * 0.30, 0)\n    elseif f == \"lower\" then\n        p = p - Vector3.new(0, size.Y * 0.30, 0)\n    end\n    return p\nend\n\nlocal function labelFor(model, kind)\n    local display = model:GetAttribute(\"DisplayName\")\n    if display then return display end\n    return model.Name\nend\n\nlocal function refreshTracks()\n    local now = os.clock()\n    local seen = {}\n\n    for _, entry in ipairs(ANIMAL_FOLDERS) do\n        local folder = workspace:FindFirstChild(entry.folder)\n        if folder then\n            for _, model in ipairs(folder:GetChildren()) do\n                if model:IsA(\"Model\") then\n                    local part = bodyPart(model)\n                    if part then\n                        seen[model] = true\n                        local rec = STATE.tracks[model]\n                        local pos = part.Position\n                        if rec then\n                            local dt = now - rec.at\n                            if dt > 0.0001 then\n                                local inst = (pos - rec.pos) / dt\n                                -- exponential smoothing: the raw per-frame delta on a\n                                -- replicated animal is noisy enough to overshoot a lead\n                                rec.vel = rec.vel + (inst - rec.vel) * math.min(dt * 8, 0.5)\n                            end\n                            rec.pos, rec.at = pos, now\n                        else\n                            rec = { pos = pos, vel = Vector3.zero, at = now, kind = entry.kind }\n                            STATE.tracks[model] = rec\n                        end\n                        rec.model = model\n                        rec.part = part\n                        rec.kind = entry.kind\n                        rec.name = labelFor(model, entry.kind)\n                        rec.aimPos = aimPointOf(model, part) or pos\n                    end\n                end\n            end\n        end\n    end\n\n    for model in pairs(STATE.tracks) do\n        if not seen[model] or not model.Parent then\n            STATE.tracks[model] = nil\n        end\n    end\nend\n\n-- ============================================================ target selection\n\nlocal function trackAllowed(rec)\n    if rec.kind == \"animal\" then return CONFIG.esp.animals end\n    if rec.kind == \"dead\" then return CONFIG.esp.dead end\n    if rec.kind == \"mount\" then return CONFIG.esp.mounts end\n    if rec.kind == \"dog\" then return CONFIG.esp.mounts end\n    return false\nend\n\nlocal function hasLine(origin, target, model)\n    local params = RaycastParams.new()\n    params.FilterType = Enum.RaycastFilterType.Exclude\n    local ignore = { model, LP.Character, Camera }\n    for _, name in ipairs({ \"Projectiles\", \"Debug\", \"DebugLaser\", \"Barriers\", \"LocationRegions\" }) do\n        local inst = workspace:FindFirstChild(name)\n        if inst then table.insert(ignore, inst) end\n    end\n    params.FilterDescendantsInstances = ignore\n    local hit = workspace:Raycast(origin, target - origin, params)\n    return hit == nil\nend\n\nlocal function selectTarget(origin)\n    local camPos = Camera.CFrame.Position\n    local look = Camera.CFrame.LookVector\n    local cosFov = math.cos(math.rad(math.clamp(CONFIG.aim.fov, 1, 179)))\n    local best, bestScore\n    for model, rec in pairs(STATE.tracks) do\n        if rec.kind == \"animal\" and model.Parent then\n            local delta = rec.aimPos - camPos\n            local dist = delta.Magnitude\n            if dist > 0.5 and dist <= CONFIG.aim.maxDistance then\n                local cosA = look:Dot(delta / dist)\n                if cosA >= cosFov and (not best or cosA > bestScore) then\n                    -- the wall is checked per candidate so a blocked animal cannot shadow a\n                    -- clear one just because it sits closer to the crosshair\n                    if not CONFIG.aim.wallCheck or hasLine(origin, rec.aimPos, model) then\n                        best, bestScore = rec, cosA\n                    end\n                end\n            end\n        end\n    end\n    return best\nend\n\n-- ============================================================ the solver the fire hook calls\n\nlocal function aimDirection(origin, fallbackDir, speed, userData)\n    if not CONFIG.aim.enabled or not STATE.aimHeld then return fallbackDir end\n    local rec = selectTarget(origin)\n    if not rec then\n        STATE.target = nil\n        return fallbackDir\n    end\n\n    local mass, drag, area = 0, 0, 0\n    local props = userData and userData.BulletProperties\n    if props then\n        mass = tonumber(props.Mass) or 0\n        drag = tonumber(props.DragCoefficient) or 0\n    end\n    area = tonumber(userData and userData.CrossSectionalArea) or 0\n    if mass <= 0 or drag <= 0 or area <= 0 then\n        -- no usable bullet data: straight line to the lead point is still a hit\n        local vel = CONFIG.aim.lead and rec.vel or Vector3.zero\n        local T = interceptTime(origin, rec.aimPos, vel, speed) or 0.15\n        return ((rec.aimPos + vel * T) - origin).Unit\n    end\n\n    local vel = CONFIG.aim.lead and rec.vel or Vector3.zero\n    local dir, T = solveAim(origin, rec.aimPos, vel, speed, mass, drag, area)\n\n    STATE.target = rec\n    STATE.lastSolve = {\n        model = rec.model, dir = dir, flight = T, speed = speed,\n        dist = (rec.aimPos - origin).Magnitude, vel = vel,\n    }\n    logEvent(\"solve\", string.format(\"%s  %.0f studs  flight %.3fs  lead %.1f studs\",\n        rec.name, (rec.aimPos - origin).Magnitude, T, (vel * T).Magnitude))\n    return dir\nend\n\n-- ============================================================ the hook\n\nlocal ProjectileController = require(ReplicatedStorage.ReservesCommon.Client.Controllers.ProjectileController)\nlocal originalFire, originalFireBatch\n\nlocal function fireHook(self, origin, direction, speed, userData, isReplicated, ...)\n    if not isReplicated then\n        STATE.shotsFired = (STATE.shotsFired or 0) + 1\n        local ok, result = pcall(aimDirection, origin, direction, speed, userData)\n        if ok and typeof(result) == \"Vector3\" and result.Magnitude > 0 then\n            direction = result\n            STATE.redirected = STATE.redirected + 1\n        elseif not ok then\n            STATE.lastError = tostring(result)\n        end\n    end\n    return originalFire(self, origin, direction, speed, userData, isReplicated, ...)\nend\n\nlocal function fireBatchHook(self, origin, directions, speed, userData, ids, isReplicated, ...)\n    if not isReplicated and type(directions) == \"table\" and #directions > 0 then\n        STATE.shotsFired = (STATE.shotsFired or 0) + 1\n        local ok, solved = pcall(aimDirection, origin, directions[1], speed, userData)\n        if ok and typeof(solved) == \"Vector3\" and solved.Magnitude > 0 then\n            -- keep the shell's spread pattern: rotate every pellet by the same rotation\n            -- that moves the centre pellet onto the target\n            local out = {}\n            for i, d in ipairs(directions) do\n                out[i] = rotateDir(directions[1], solved, d)\n            end\n            directions = out\n            STATE.redirected = STATE.redirected + 1\n        elseif not ok then\n            STATE.lastError = tostring(solved)\n        end\n    end\n    return originalFireBatch(self, origin, directions, speed, userData, ids, isReplicated, ...)\nend\n\noriginalFire = ProjectileController.Fire\noriginalFireBatch = ProjectileController.FireBatch\nProjectileController.Fire = fireHook\nProjectileController.FireBatch = fireBatchHook\n\n-- Kills are read off the world instead of off a remote: a dead animal is moved into\n-- workspace.DeadAnimals, so that folder growing is a kill the shot landed. Reading it\n-- costs nothing and never touches a remote or a namecall.\ndo\n    local deadCount = #workspace.DeadAnimals:GetChildren()\n    task.spawn(function()\n        while current() do\n            task.wait(0.5)\n            local now = #workspace.DeadAnimals:GetChildren()\n            if now > deadCount then\n                local gained = now - deadCount\n                STATE.hitsClaimed = STATE.hitsClaimed + gained\n                logEvent(\"kill\", string.format(\"dead animals +%d (total %d)\", gained, STATE.hitsClaimed))\n            end\n            deadCount = now\n        end\n    end)\nend\n\n-- ============================================================ gun mods\n\n-- The client builds one weapon object per equipped gun, and the Rifle class covers every\n-- firearm class in the game (its own Configuration.Class is \"Rifle\" or \"Shotgun\"). That\n-- object owns the fire-rate wait, the magazine and the trigger, so it is the thing to hold\n-- on to: mods are written straight onto the live gun the game is using, not a copy.\nlocal RifleClass = require(ReplicatedStorage.ReservesCommon.Equipment.Rifle)\n\nlocal function captureWeapon(w)\n    if type(w) ~= \"table\" or not w._lifetime then return end\n    if not w._stockKnown then\n        -- remembered per weapon, nil included: every bolt-action and pump-action gun has no\n        -- FireRate at all, so \"no cooldown\" has to be restorable as well as \"600 rpm\"\n        w._stockKnown = true\n        w._stockFireRate = w.FireRate\n        w._stockLoadBetweenRounds = w.LoadBetweenRounds and true or false\n    end\n    if STATE.weapon ~= w then\n        STATE.weapon = w\n        logEvent(\"mods\", \"weapon captured: \" .. tostring(w.DisplayName or \"?\"))\n    end\nend\n\n-- Two ways in, because a gun that was already at the shoulder when this loaded would never\n-- be seen by a constructor hook: the constructor catches equips from here on, and every\n-- method the game calls on the object catches the one already in hand (aiming, reloading\n-- and firing all resolve through the class, so the first interaction with the gun hands it\n-- over).\nlocal originalRifleNew = RifleClass.new\nRifleClass.new = function(...)\n    local weapon = originalRifleNew(...)\n    captureWeapon(weapon)\n    return weapon\nend\n\nlocal originalMethods = {}\nfor _, name in ipairs({ \"Fire\", \"Reload\", \"Load\", \"SetAimIntent\", \"ClearAimIntent\", \"CanAim\", \"IsReady\" }) do\n    local original = RifleClass[name]\n    if type(original) == \"function\" then\n        originalMethods[name] = original\n        RifleClass[name] = function(self, ...)\n            captureWeapon(self)\n            return original(self, ...)\n        end\n    end\nend\n\n-- The gun already in hand when this loaded is not reachable through the class, but the\n-- viewmodel that owns it is: its render step runs on a closure whose first upvalue is the\n-- viewmodel object, and that object carries CurrentItem - the live weapon. Reading it costs\n-- nothing and means the mods are on from the first shot rather than the second.\nlocal function findEquippedWeapon()\n    local ok, connections = pcall(getconnections, RunService.RenderStepped)\n    if not ok or type(connections) ~= \"table\" then return nil end\n    for _, connection in ipairs(connections) do\n        local okInfo, source = pcall(function() return debug.info(connection.Function, \"s\") end)\n        if okInfo and tostring(source):find(\"Equipment.Viewmodel\") then\n            local okUp, a, b = pcall(debug.getupvalue, connection.Function, 1)\n            if okUp then\n                local viewmodel = type(a) == \"string\" and b or a\n                if type(viewmodel) == \"table\" and viewmodel.CurrentItem then\n                    return viewmodel.CurrentItem\n                end\n            end\n        end\n    end\n    return nil\nend\n\ndo\n    local weapon = findEquippedWeapon()\n    if weapon then captureWeapon(weapon) end\nend\n\nlocal lastTrigger = 0\n\nlocal function applyMods()\n    local w = STATE.weapon\n    -- diagnostics, sampled rather than rebuilt every frame\n    if not STATE.modSeen or os.clock() - (STATE.modSeenAt or 0) > 0.5 then\n        STATE.modSeenAt = os.clock()\n        STATE.modSeen = {\n            hasWeapon = w ~= nil,\n            alive = w ~= nil and (w._lifetime ~= nil and w._lifetime.Alive),\n            rapid = CONFIG.mods.rapidFire,\n            rate = CONFIG.mods.fireRate,\n            ammo = CONFIG.mods.infiniteAmmo,\n            weaponRate = w and w.FireRate,\n            weaponLBR = w and w.LoadBetweenRounds,\n            loaded = w and w.Loaded,\n        }\n    end\n    if w and not (w._lifetime and w._lifetime.Alive) then\n        -- unequipped since it was captured: drop it so the next gun takes over rather than\n        -- the mods writing to an object the game has finished with\n        STATE.weapon = nil\n        w = nil\n    end\n    if not w then\n        -- nothing in hand: look for an equipped gun every second rather than every frame\n        local now = os.clock()\n        if not STATE.weaponLook or now - STATE.weaponLook > 1 then\n            STATE.weaponLook = now\n            local found = findEquippedWeapon()\n            if found then\n                captureWeapon(found)\n                w = STATE.weapon\n            end\n        end\n        if not w then return end\n    end\n\n    -- Every bolt-action and pump-action gun in the game ships FireRate = nil, so there is no\n    -- cooldown to shorten: the rate is the bolt/pump cycle. Fire() ends with\n    -- Loaded = not LoadBetweenRounds, and the next shot pays for that by running Load(),\n    -- which waits out the bolt animation. Holding LoadBetweenRounds down and Loaded up\n    -- removes the cycle, and FireRate (where the gun has one) is raised for the cooldown.\n    if CONFIG.mods.rapidFire then\n        if w.FireRate ~= CONFIG.mods.fireRate then w.FireRate = CONFIG.mods.fireRate end\n        if w.LoadBetweenRounds then w.LoadBetweenRounds = false end\n        if not w.Loaded then w.Loaded = true end\n        if w.NeedsLoading then w.NeedsLoading = false end\n    elseif w._stockKnown then\n        if w.FireRate ~= w._stockFireRate then w.FireRate = w._stockFireRate end\n        if w.LoadBetweenRounds ~= w._stockLoadBetweenRounds then\n            w.LoadBetweenRounds = w._stockLoadBetweenRounds\n        end\n    end\n\n    -- Fire drains the magazine one round at a time and reloads when it reaches zero. Holding\n    -- it at capacity means the reload path is never entered; the reserve is left alone.\n    if CONFIG.mods.infiniteAmmo then\n        local cap = w.MagazineCapacity or 0\n        if (w.BulletsInMagazine or 0) < cap then\n            w.BulletsInMagazine = cap\n            w.NeedsReloading = false\n        end\n    end\n\n    -- Fire only runs while the gun is at the shoulder (its first check is Aiming), so the\n    -- trigger releases only when a target is in the aim cone and the gun is up.\n    if CONFIG.mods.autoFire and w.Aiming and not w.Reloading and not w._viewmodel.Debounce then\n        if os.clock() - lastTrigger >= CONFIG.mods.autoFireDelay then\n            if selectTarget(Camera.CFrame.Position) then\n                lastTrigger = os.clock()\n                task.spawn(function()\n                    local ok, err = pcall(function() w:Fire() end)\n                    if not ok then STATE.lastError = tostring(err) end\n                end)\n            end\n        end\n    end\nend\n\n-- ============================================================ ESP\n\nlocal espGui, espHolder\ndo\n    local function container()\n        local ok, hui = pcall(gethui)\n        if ok and typeof(hui) == \"Instance\" then return hui end\n        local ok2, core = pcall(function() return game:GetService(\"CoreGui\") end)\n        if ok2 and core then return core end\n        return LP:FindFirstChildOfClass(\"PlayerGui\")\n    end\n    espGui = Instance.new(\"ScreenGui\")\n    espGui.Name = \"BoulderEsp\"\n    espGui.ResetOnSpawn = false\n    espGui.IgnoreGuiInset = true\n    espGui.DisplayOrder = 100\n    espGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling\n    pcall(function() espGui.Parent = container() end)\n\n    espHolder = Instance.new(\"Folder\")\n    espHolder.Name = \"targets\"\n    espHolder.Parent = espGui\nend\n\nSTATE.drawings = {}\n\n-- One drawing per animal, owned by this table. The previous version only ever hid a\n-- drawing while its model was still being tracked, so an animal that despawned left its\n-- box painted on the screen for the rest of the match. Now a drawing whose model is gone\n-- is freed in the same pass that draws the rest.\nlocal function newDrawing(model)\n    local box = Instance.new(\"Frame\")\n    box.Name = \"box\"\n    box.BackgroundTransparency = 1\n    box.BorderSizePixel = 0\n    box.Visible = false\n    box.Parent = espHolder\n\n    local sides, corners = {}, {}\n    for i = 1, 4 do\n        local line = Instance.new(\"Frame\")\n        line.Name = \"side\" .. i\n        line.BorderSizePixel = 0\n        line.Parent = box\n        sides[i] = line\n    end\n    for i = 1, 8 do\n        local line = Instance.new(\"Frame\")\n        line.Name = \"corner\" .. i\n        line.BorderSizePixel = 0\n        line.Parent = box\n        corners[i] = line\n    end\n\n    local label = Instance.new(\"TextLabel\")\n    label.Name = \"name\"\n    label.BackgroundTransparency = 1\n    label.Font = Enum.Font.GothamMedium\n    label.TextSize = 12\n    label.RichText = true\n    label.TextXAlignment = Enum.TextXAlignment.Center\n    label.TextYAlignment = Enum.TextYAlignment.Bottom\n    label.TextStrokeTransparency = 0.55\n    label.TextStrokeColor3 = Color3.new(0, 0, 0)\n    label.Visible = false\n    label.Parent = espHolder\n\n    local highlight = Instance.new(\"Highlight\")\n    highlight.FillTransparency = 0.82\n    highlight.OutlineTransparency = 0.35\n    highlight.DepthMode = Enum.HighlightDepthMode.AlwaysOnTop\n    highlight.Enabled = false\n    highlight.Adornee = model\n    highlight.Parent = espHolder\n\n    return { box = box, sides = sides, corners = corners, label = label, highlight = highlight }\nend\n\nlocal function freeDrawing(dr)\n    if dr.box then dr.box:Destroy() end\n    if dr.label then dr.label:Destroy() end\n    if dr.highlight then dr.highlight:Destroy() end\nend\n\nlocal function drawingFor(model)\n    local dr = STATE.drawings[model]\n    if dr and dr.box and dr.box.Parent and dr.label and dr.label.Parent then return dr end\n    dr = newDrawing(model)\n    STATE.drawings[model] = dr\n    return dr\nend\n\n-- Screen-space box of the volume a bullet has to pass through. The centre has to be in\n-- front of the camera, otherwise a corner behind the near plane stretches the box across\n-- the whole screen.\nlocal function projectBox(model, rec)\n    local part = rec.part\n    if not (part and part.Parent) then return nil end\n    local cf, size\n    if part:IsA(\"BasePart\") then\n        cf, size = part.CFrame, part.Size\n    else\n        local ok, c, s = pcall(function() return model:GetBoundingBox() end)\n        if not ok or not c then return nil end\n        cf, size = c, s\n    end\n    local centre = Camera:WorldToViewportPoint(cf.Position)\n    if centre.Z <= 0 then return nil end\n    local minX, minY = math.huge, math.huge\n    local maxX, maxY = -math.huge, -math.huge\n    local any = false\n    for ox = -1, 1, 2 do\n        for oy = -1, 1, 2 do\n            for oz = -1, 1, 2 do\n                local world = cf * Vector3.new(ox * size.X * 0.5, oy * size.Y * 0.5, oz * size.Z * 0.5)\n                local sp = Camera:WorldToViewportPoint(world)\n                if sp.Z > 0 then\n                    any = true\n                    minX, maxX = math.min(minX, sp.X), math.max(maxX, sp.X)\n                    minY, maxY = math.min(minY, sp.Y), math.max(maxY, sp.Y)\n                end\n            end\n        end\n    end\n    if not any or maxX - minX < 0.5 or maxY - minY < 0.5 then return nil end\n    return minX, minY, maxX, maxY\nend\n\nlocal function colourFor(rec)\n    if rec.kind == \"dead\" then return CONFIG.esp.deadColor end\n    if rec.kind == \"mount\" or rec.kind == \"dog\" then return Color3.fromRGB(240, 190, 90) end\n    return CONFIG.esp.color\nend\n\nlocal nameCache = {}\nlocal function prettyName(model)\n    local cached = nameCache[model.Name]\n    if cached then return cached end\n    local out = model:GetAttribute(\"DisplayName\")\n    if not out or out == \"\" then\n        out = tostring(model.Name):gsub(\"(%l)(%u)\", \"%1 %2\")\n    end\n    nameCache[model.Name] = out\n    return out\nend\n\nlocal function drawEsp()\n    local drawn = {}\n    local camPos = Camera.CFrame.Position\n\n    if CONFIG.esp.enabled then\n        for model, rec in pairs(STATE.tracks) do\n            if rec.part and rec.part.Parent and model.Parent and trackAllowed(rec) then\n                local dist = (rec.aimPos - camPos).Magnitude\n                if dist <= CONFIG.esp.maxDistance then\n                    local minX, minY, maxX, maxY = projectBox(model, rec)\n                    if minX then\n                        drawn[model] = true\n                        local dr = drawingFor(model)\n                        local col = colourFor(rec)\n                        local w, h = maxX - minX, maxY - minY\n                        local t = CONFIG.esp.thickness\n                        -- fade with range so a valley full of animals stays readable up close\n                        local fade = math.clamp((dist / math.max(CONFIG.esp.maxDistance, 1)) * 0.55, 0, 0.55)\n                        local style = CONFIG.esp.boxStyle\n                        local showBox = style ~= \"Corners\"\n                        local showCorners = style ~= \"Box\"\n\n                        dr.box.Visible = true\n                        dr.box.Position = UDim2.fromOffset(minX, minY)\n                        dr.box.Size = UDim2.fromOffset(math.max(w, 1), math.max(h, 1))\n\n                        local sideRects = {\n                            { 0, 0, w, t }, { 0, h - t, w, t }, { 0, 0, t, h }, { w - t, 0, t, h },\n                        }\n                        for i, s in ipairs(sideRects) do\n                            local line = dr.sides[i]\n                            line.Visible = showBox\n                            line.BackgroundColor3 = col\n                            line.BackgroundTransparency = fade\n                            line.Position = UDim2.fromOffset(s[1], s[2])\n                            line.Size = UDim2.fromOffset(s[3], s[4])\n                        end\n\n                        local cw = math.clamp(w * 0.22, 3, 11)\n                        local ch = math.clamp(h * 0.22, 3, 11)\n                        local cornerRects = {\n                            { 0, 0, cw, t }, { 0, 0, t, ch },\n                            { w - cw, 0, cw, t }, { w - t, 0, t, ch },\n                            { 0, h - t, cw, t }, { 0, h - ch, t, ch },\n                            { w - cw, h - t, cw, t }, { w - t, h - ch, t, ch },\n                        }\n                        for i, s in ipairs(cornerRects) do\n                            local line = dr.corners[i]\n                            line.Visible = showCorners\n                            line.BackgroundColor3 = col\n                            line.BackgroundTransparency = fade\n                            line.Position = UDim2.fromOffset(s[1], s[2])\n                            line.Size = UDim2.fromOffset(s[3], s[4])\n                        end\n\n                        dr.highlight.Enabled = CONFIG.esp.fill\n                        dr.highlight.FillColor = col\n                        dr.highlight.OutlineColor = col\n                        dr.highlight.FillTransparency = math.clamp(0.74 + fade * 0.4, 0, 0.95)\n                        dr.highlight.OutlineTransparency = math.clamp(0.25 + fade, 0, 0.95)\n\n                        local bits = {}\n                        if CONFIG.esp.name then\n                            bits[#bits + 1] = string.format(\"<b>%s</b>\", prettyName(model))\n                        end\n                        if CONFIG.esp.info and rec.kind == \"animal\" then\n                            local variant = model:GetAttribute(\"Variant\")\n                            local sex = model:GetAttribute(\"Sex\")\n                            local extra = {}\n                            if variant and variant ~= \"Default\" then extra[#extra + 1] = tostring(variant) end\n                            if sex then extra[#extra + 1] = tostring(sex) end\n                            if #extra > 0 then bits[#bits + 1] = table.concat(extra, \" \") end\n                        end\n                        if CONFIG.esp.distance then\n                            bits[#bits + 1] = string.format(\"<font color=\\\"#98a0a8\\\">%dm</font>\",\n                                math.floor(dist * 0.28))\n                        end\n                        local text = table.concat(bits, \"  \")\n                        dr.label.Visible = text ~= \"\"\n                        dr.label.Text = text\n                        dr.label.TextColor3 = col\n                        dr.label.TextSize = CONFIG.esp.textSize\n                        dr.label.TextTransparency = fade * 0.5\n                        dr.label.Position = UDim2.fromOffset(minX - 60, minY - 17)\n                        dr.label.Size = UDim2.fromOffset(w + 120, 16)\n                    end\n                end\n            end\n        end\n    end\n\n    -- Whatever was not drawn this frame is either hidden (still alive, off screen or out of\n    -- range) or freed (the animal is gone). Nothing can be left stranded on the screen.\n    for model, dr in pairs(STATE.drawings) do\n        if not drawn[model] then\n            if not model.Parent or not STATE.tracks[model] then\n                freeDrawing(dr)\n                STATE.drawings[model] = nil\n            else\n                dr.box.Visible = false\n                dr.label.Visible = false\n                dr.highlight.Enabled = false\n            end\n        end\n    end\nend\n\n-- ============================================================ main loops\n\nlocal mainConnection\nmainConnection = RunService.RenderStepped:Connect(function()\n    if not current() then\n        if mainConnection then mainConnection:Disconnect() end\n        mainConnection = nil\n        return\n    end\n    local ok, err = pcall(function()\n        refreshTracks()\n        drawEsp()\n        applyMods()\n    end)\n    if not ok then\n        STATE.lastError = tostring(err)\n        if not STATE.loopErrLogged or os.clock() - STATE.loopErrLogged > 3 then\n            STATE.loopErrLogged = os.clock()\n            logEvent(\"error\", tostring(err))\n        end\n    end\nend)\n\n-- ============================================================ interface (same library as trident)\n\nlocal uiRefresh\ndo\n    local Library = loadstring(game:HttpGet(\"https://pastebin.com/raw/ncKGkPTW\"))()\n    Library.Folders = { Directory = \"boulder\", Configs = \"boulder/Configs\", Assets = \"boulder/Assets\" }\n    for _, Folder in pairs(Library.Folders) do\n        if not isfolder(Folder) then makefolder(Folder) end\n    end\n    pcall(function() Library:ChangeTheme(\"Accent\", Color3.fromRGB(0, 190, 180)) end)\n\n    local Window = Library:Window({ Name = \"Boulder Creek\", MobileButtonText = \"BC\" })\n    STATE.window = Window\n\n    -- The library only builds its hide/show button when the Settings toggle's callback\n    -- runs, so on mobile the menu can end up with nothing to open it. This is that button,\n    -- made here and always present: tap to open/close, drag to move it where the thumb\n    -- rests, and it stays put between matches.\n    do\n        local button = Instance.new(\"TextButton\")\n        button.Name = \"BoulderMenuButton\"\n        button.Text = \"BC\"\n        button.Font = Enum.Font.GothamBold\n        button.TextSize = 19\n        button.AutoButtonColor = false\n        button.BorderSizePixel = 2\n        button.BackgroundColor3 = Color3.fromRGB(17, 21, 27)\n        button.BorderColor3 = Color3.fromRGB(0, 190, 180)\n        button.TextColor3 = Color3.fromRGB(236, 239, 243)\n        button.Size = UDim2.fromOffset(46, 46)\n        button.Position = UDim2.new(1, -62, 0, 90)\n        button.ZIndex = 5000\n        button.Active = true\n        button.Parent = espGui\n        local corner = Instance.new(\"UICorner\")\n        corner.CornerRadius = UDim.new(1, 0)\n        corner.Parent = button\n        STATE.menuButton = button\n\n        local dragging, dragStart, startPos, moved = false, nil, nil, 0\n        button.InputBegan:Connect(function(input)\n            if input.UserInputType == Enum.UserInputType.MouseButton1\n                or input.UserInputType == Enum.UserInputType.Touch then\n                dragging, dragStart, startPos, moved = true, input.Position, button.Position, 0\n                button.BackgroundColor3 = Color3.fromRGB(24, 30, 37)\n            end\n        end)\n        button.InputChanged:Connect(function(input)\n            if not dragging then return end\n            if input.UserInputType == Enum.UserInputType.MouseMovement\n                or input.UserInputType == Enum.UserInputType.Touch then\n                local delta = input.Position - dragStart\n                moved = math.max(moved, delta.Magnitude)\n                button.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X,\n                    startPos.Y.Scale, startPos.Y.Offset + delta.Y)\n            end\n        end)\n        button.InputEnded:Connect(function(input)\n            if input.UserInputType ~= Enum.UserInputType.MouseButton1\n                and input.UserInputType ~= Enum.UserInputType.Touch then return end\n            dragging = false\n            button.BackgroundColor3 = Color3.fromRGB(17, 21, 27)\n            -- a drag that ends on the button is not a tap: only a near-still press opens the menu\n            if moved < 10 and STATE.window then\n                STATE.window:SetOpen(not STATE.window.IsOpen)\n            end\n        end)\n    end\n    local Controls = {}\n    local function track(Element, Get)\n        Controls[#Controls + 1] = { Element = Element, Get = Get }\n        return Element\n    end\n    uiRefresh = function()\n        for _, e in ipairs(Controls) do\n            pcall(function() e.Element:Set(e.Get()) end)\n        end\n    end\n\n    local function Section(Page, Name, Side) return Page:Section({ Name = Name, Side = Side }) end\n    local function Toggle(Parent, Name, Flag, Get, Set)\n        return track(Parent:Toggle({\n            Name = Name, Flag = Flag, Default = Get(),\n            Callback = function(Value) Set(Value) end,\n        }), Get)\n    end\n    local function Slider(Parent, Name, Flag, Min, Max, Get, Set, Suffix)\n        return track(Parent:Slider({\n            Name = Name, Flag = Flag, Min = Min, Max = Max, Decimals = 1,\n            Suffix = Suffix or \"\", Default = Get(),\n            Callback = function(Value) Set(Value) end,\n        }), Get)\n    end\n    local function Dropdown(Parent, Name, Flag, Items, Get, Set)\n        return track(Parent:Dropdown({\n            Name = Name, Flag = Flag, Items = Items, Default = Get(),\n            Callback = function(Value) Set(Value) end,\n        }), Get)\n    end\n\n    local Aimbot = Window:Page({ Name = \"Silent aim\", Columns = 2 })\n    local A1 = Section(Aimbot, \"Target\", 1)\n    Toggle(A1, \"Enable silent aim\", \"A_enabled\", function() return CONFIG.aim.enabled end,\n        function(v) CONFIG.aim.enabled = v end)\n    Slider(A1, \"Aim FOV\", \"A_fov\", 1, 180, function() return CONFIG.aim.fov end,\n        function(v) CONFIG.aim.fov = v end, \" deg\")\n    Slider(A1, \"Max distance\", \"A_max\", 100, 3000, function() return CONFIG.aim.maxDistance end,\n        function(v) CONFIG.aim.maxDistance = v end, \" studs\")\n    Toggle(A1, \"Wall check\", \"A_wall\", function() return CONFIG.aim.wallCheck end,\n        function(v) CONFIG.aim.wallCheck = v end)\n    Toggle(A1, \"Lead moving animals\", \"A_lead\", function() return CONFIG.aim.lead end,\n        function(v) CONFIG.aim.lead = v end)\n    Dropdown(A1, \"Aim zone\", \"A_zone\", { \"Center\", \"Upper\", \"Lower\" },\n        function() return CONFIG.aim.zone:sub(1, 1):upper() .. CONFIG.aim.zone:sub(2) end,\n        function(v) CONFIG.aim.zone = string.lower(v) end)\n\n    local A2 = Section(Aimbot, \"Status\", 2)\n    Toggle(A2, \"Aim active\", \"A_held\", function() return STATE.aimHeld end,\n        function(v) STATE.aimHeld = v end)\n    local StatusShots = A2:Label(\"shots redirected: -\")\n    local StatusTarget = A2:Label(\"last target: -\")\n    task.spawn(function()\n        while current() do\n            task.wait(0.25)\n            pcall(function()\n                StatusShots:SetText(\"shots redirected: \" .. tostring(STATE.redirected))\n                local t = STATE.lastSolve\n                StatusTarget:SetText(\"last target: \" .. (t and string.format(\"%s  %.0f studs\", t.model and t.model.Name or \"?\", t.dist) or \"-\"))\n            end)\n        end\n    end)\n\n    local Visuals = Window:Page({ Name = \"Visuals\", Columns = 2 })\n    local V1 = Section(Visuals, \"ESP\", 1)\n    Toggle(V1, \"Enable ESP\", \"E_enabled\", function() return CONFIG.esp.enabled end,\n        function(v) CONFIG.esp.enabled = v end)\n    Dropdown(V1, \"Box style\", \"E_style\", { \"Corners\", \"Box\", \"Both\" },\n        function() return CONFIG.esp.boxStyle end,\n        function(v) CONFIG.esp.boxStyle = v end)\n    Toggle(V1, \"Name\", \"E_name\", function() return CONFIG.esp.name end,\n        function(v) CONFIG.esp.name = v end)\n    Toggle(V1, \"Distance\", \"E_dist\", function() return CONFIG.esp.distance end,\n        function(v) CONFIG.esp.distance = v end)\n    Toggle(V1, \"Info (sex / variant)\", \"E_info\", function() return CONFIG.esp.info end,\n        function(v) CONFIG.esp.info = v end)\n    Toggle(V1, \"Fill (highlight)\", \"E_fill\", function() return CONFIG.esp.fill end,\n        function(v) CONFIG.esp.fill = v end)\n\n    local V2 = Section(Visuals, \"Targets\", 2)\n    Toggle(V2, \"Alive animals\", \"E_animals\", function() return CONFIG.esp.animals end,\n        function(v) CONFIG.esp.animals = v end)\n    Toggle(V2, \"Dead animals\", \"E_dead\", function() return CONFIG.esp.dead end,\n        function(v) CONFIG.esp.dead = v end)\n    Toggle(V2, \"Mounts / dogs\", \"E_mounts\", function() return CONFIG.esp.mounts end,\n        function(v) CONFIG.esp.mounts = v end)\n    Slider(V2, \"Max distance\", \"E_max\", 100, 3000, function() return CONFIG.esp.maxDistance end,\n        function(v) CONFIG.esp.maxDistance = v end, \" studs\")\n    Slider(V2, \"Box thickness\", \"E_thick\", 1, 4, function() return CONFIG.esp.thickness end,\n        function(v) CONFIG.esp.thickness = v end, \" px\")\n    Slider(V2, \"Label size\", \"E_text\", 9, 18, function() return CONFIG.esp.textSize end,\n        function(v) CONFIG.esp.textSize = v end, \" px\")\n    track(V2:Label(\"Colour\"):Colorpicker({\n        Flag = \"E_colour\", Default = CONFIG.esp.color,\n        Callback = function(v) CONFIG.esp.color = v end,\n    }), function() return CONFIG.esp.color end)\n\n    local Misc = Window:Page({ Name = \"Menu\", Columns = 2 })\n    local M1 = Section(Misc, \"Interface\", 1)\n    Toggle(M1, \"Mobile open/close button\", \"M_button\",\n        function() return STATE.menuButton and STATE.menuButton.Visible end,\n        function(v)\n            if STATE.menuButton then STATE.menuButton.Visible = v end\n        end)\n    local M2 = Section(Misc, \"Session\", 2)\n    M2:Label(\"Unload removes the hooks and the ESP.\")\n\n    local Mods = Window:Page({ Name = \"Gun mods\", Columns = 2 })\n    local G1 = Section(Mods, \"Fire\", 1)\n    Toggle(G1, \"Rapid fire\", \"G_rapid\", function() return CONFIG.mods.rapidFire end,\n        function(v) CONFIG.mods.rapidFire = v end)\n    Slider(G1, \"Fire rate\", \"G_rate\", 120, 3000, function() return CONFIG.mods.fireRate end,\n        function(v) CONFIG.mods.fireRate = v end, \" rpm\")\n    Toggle(G1, \"Auto fire (while aiming)\", \"G_auto\", function() return CONFIG.mods.autoFire end,\n        function(v) CONFIG.mods.autoFire = v end)\n    Slider(G1, \"Auto-fire delay\", \"G_delay\", 0.02, 1, function() return CONFIG.mods.autoFireDelay end,\n        function(v) CONFIG.mods.autoFireDelay = v end, \" s\")\n    local G2 = Section(Mods, \"Ammo\", 2)\n    Toggle(G2, \"Infinite ammo\", \"G_ammo\", function() return CONFIG.mods.infiniteAmmo end,\n        function(v) CONFIG.mods.infiniteAmmo = v end)\n    local GunStatus = G2:Label(\"weapon: -\")\n    task.spawn(function()\n        while current() do\n            task.wait(0.5)\n            pcall(function()\n                local w = STATE.weapon\n                if w and w._lifetime and w._lifetime.Alive then\n                    GunStatus:SetText(string.format(\"%s  |  mag %d/%d  |  %.0f rpm  |  %s\",\n                        tostring(w.DisplayName or \"?\"), math.floor(w.BulletsInMagazine or 0),\n                        math.floor(w.MagazineCapacity or 0), w.FireRate or 0,\n                        w.Aiming and \"aiming\" or \"hip\"))\n                else\n                    GunStatus:SetText(\"weapon: -\")\n                end\n            end)\n        end\n    end)\nend\n\n-- a keybind that opens and closes the menu, same as the mobile button\ndo\n    local UIS = game:GetService(\"UserInputService\")\n    UIS.InputBegan:Connect(function(input, processed)\n        if processed then return end\n        local key = input.KeyCode\n        if key == Enum.KeyCode.RightShift or key == Enum.KeyCode.Insert then\n            if STATE.window then STATE.window:SetOpen(not STATE.window.IsOpen) end\n        end\n    end)\nend\n\n-- ============================================================ api\n\ngetgenv().BoulderOverlay = {\n    INSTANCE = INSTANCE,\n    CONFIG = CONFIG,\n    STATE = STATE,\n    solve = solveAim,\n    interceptTime = interceptTime,\n    accel = accel,\n    tracking = function() return STATE.tracks end,\n    weapon = function() return STATE.weapon end,\n    mods = function()\n        local w = STATE.weapon\n        return {\n            captured = w ~= nil,\n            name = w and w.DisplayName or nil,\n            fireRate = w and w.FireRate or nil,\n            stockFireRate = w and w._stockFireRate or nil,\n            magazine = w and w.BulletsInMagazine or nil,\n            capacity = w and w.MagazineCapacity or nil,\n            aiming = w and w.Aiming or nil,\n            reloading = w and w.Reloading or nil,\n        }\n    end,\n    hideMenu = function() if STATE.window then STATE.window:SetOpen(false) end end,\n    showMenu = function() if STATE.window then STATE.window:SetOpen(true) end end,\n    counters = function()\n        local n = 0\n        for _ in pairs(STATE.tracks) do n = n + 1 end\n        local d = 0\n        for _ in pairs(STATE.drawings) do d = d + 1 end\n        return { tracked = n, drawings = d, redirected = STATE.redirected, lastError = STATE.lastError }\n    end,\n    unload = function()\n        RUN.alive = false\n        if mainConnection then mainConnection:Disconnect() mainConnection = nil end\n        if ProjectileController.Fire == fireHook then ProjectileController.Fire = originalFire end\n        if ProjectileController.FireBatch == fireBatchHook then ProjectileController.FireBatch = originalFireBatch end\n        if RifleClass.new ~= originalRifleNew then RifleClass.new = originalRifleNew end\n        for name, original in pairs(originalMethods) do\n            RifleClass[name] = original\n        end\n        local w = STATE.weapon\n        if w and w._stockFireRate ~= nil then w.FireRate = w._stockFireRate end\n        if w and w._stockLoadBetweenRounds ~= nil then w.LoadBetweenRounds = w._stockLoadBetweenRounds end\n        for model, dr in pairs(STATE.drawings or {}) do\n            if dr.box then dr.box:Destroy() end\n            if dr.label then dr.label:Destroy() end\n            if dr.highlight then dr.highlight:Destroy() end\n        end\n        if espGui then espGui:Destroy() espGui = nil end\n        getgenv().BoulderOverlay = nil\n    end,\n}\n\nlogEvent(\"init\", string.format(\"loaded | animals=%d | aim=%s\",\n    #workspace.Animals:GetChildren(), tostring(CONFIG.aim.enabled)))\nprint(\"[boulder] loaded | animals tracked:\", #workspace.Animals:GetChildren())\n", "name": "huntingseason.lua", "mode": "luraph_hardened", "seed": 424242}