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