Silent Aim
Key Required

Silent Aim

ArcherKillaKilla 517 views 1.5K executesUpdated Oct 5, 2026
0.0/ 5(1 votes)
010% Positive
Lua Script•373 lines (12108 chars)
local Config = {
    FOVSize = 180,
    HitPart = "Head",
    MaxFlightTicks = 100,
    FullDrawTicks = 20,
}

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local LocalPlayer = Players.LocalPlayer
local Client = LocalPlayer:WaitForChild("PlayerScripts"):WaitForChild("Client")
local Shared = ReplicatedStorage:WaitForChild("Shared")

local BowController = require(Client:WaitForChild("BowController"))
local CombatClient = require(Client:WaitForChild("CombatClient"))
local FirstPersonAnimationModule = Client:WaitForChild("FirstPersonAnimation")
local FirstPersonAnimation = require(FirstPersonAnimationModule)
local TaCZMotion = require(FirstPersonAnimationModule:WaitForChild("TaCZMotion"))
local BowMath = require(Shared:WaitForChild("BowMath"))
local BowNet = require(Shared:WaitForChild("BowNet"))
local BowConfig = require(Shared:WaitForChild("BowConfig"))
local CharacterLife = require(Shared:WaitForChild("CharacterLife"))

local ActiveRelease = nil
local ActivePreview = nil
local ActiveDrawingController = nil
local CachedDraws = setmetatable({}, {__mode = "k"})

if Drawing and type(Drawing.new) == "function" then
    local FovCircle = Drawing.new("Circle")
    FovCircle.Position = UserInputService:GetMouseLocation()
    FovCircle.Visible = true
    FovCircle.Color = Color3.fromRGB(255, 255, 255)
    FovCircle.Radius = Config.FOVSize
    FovCircle.Transparency = 1
    FovCircle.Filled = false
    FovCircle.NumSides = 64

    RunService.PreRender:Connect(function()
        FovCircle.Position = UserInputService:GetMouseLocation()
    end)
end

local function FindTarget()
    local Camera = workspace.CurrentCamera
    if not Camera then
        return nil
    end

    local Mouse = UserInputService:GetMouseLocation()
    local BestPart = nil
    local BestDistance = Config.FOVSize
    local InfectionMode = LocalPlayer:GetAttribute("MatchMode") == "Infection"

    local function Consider(Character, Player)
        if not Character or Character.Name == "DeathModel" then
            return
        end
        if InfectionMode then
            local RoleSource = Player or Character
            if RoleSource:GetAttribute("InfectionRole") ~= "Zombie" then
                return
            end
        end
        if Player and Player:GetAttribute("MatchStatus") == "Dead" then
            return
        end

        local Humanoid = Character:FindFirstChildOfClass("Humanoid")
        if not Humanoid
            or CharacterLife.isDead(Humanoid)
            or Humanoid:GetState() == Enum.HumanoidStateType.Dead
        then
            return
        end

        local Part = Character:FindFirstChild(Config.HitPart)
        if not Part or not Part:IsA("BasePart") then
            return
        end

        local Screen = Camera:WorldToViewportPoint(Part.Position)
        if Screen.Z <= 0 then
            return
        end

        local Distance = (Vector2.new(Screen.X, Screen.Y) - Mouse).Magnitude
        if Distance >= BestDistance then
            return
        end

        BestDistance = Distance
        BestPart = Part
    end

    for _, Player in Players:GetPlayers() do
        if Player == LocalPlayer then
            continue
        end

        Consider(Player.Character, Player)
    end

    local Bots = workspace:FindFirstChild("Bots")
    if Bots then
        for _, Bot in Bots:GetChildren() do
            if not Bot:IsA("Model") then
                continue
            end

            Consider(Bot)
        end
    end

    return BestPart
end

local function SolveDirection(Controller, Origin, ChargeTicks, Target)
    local Seed = Controller.network and Controller.network.bowSeed
    local DrawId = Controller.drawId
    local Character = LocalPlayer.Character
    local Root = Character and Character:FindFirstChild("HumanoidRootPart")
    if not Seed or not DrawId or not Root or not Target or ChargeTicks == nil then
        return nil, "missing seed, draw ID, character root, target, or charge"
    end

    local Power = BowMath.powerTicks(ChargeTicks)
    if Power < 0.1 then
        return nil, "draw charge is below launch threshold"
    end

    local Effects = Controller.drawEffects
    local SpeedBonus = 1 + (Effects and Effects.ArrowSpeedBonus or 0)
    local Speed = BowMath.f32(Power * 3 * SpeedBonus)
    if Speed <= 0 then
        return nil, "launch speed is zero"
    end

    local Spread = BowMath.launchSpread(BowNet.random(Seed, DrawId))
    local Source = BowMath.fromWorld(BowNet.clampVelocity(Root.AssemblyLinearVelocity) * BowConfig.Tick)
    local OriginBlocks = BowMath.fromWorld(Origin)
    local TargetVelocity = Target.AssemblyLinearVelocity
    local Drag = BowMath.AirInertia

    local function Candidate(Ticks)
        local Sum = (1 - Drag ^ Ticks) / (1 - Drag)
        local GravityDrop = 0.05 * (Ticks - Sum) / (1 - Drag)
        local Future = Target.Position + TargetVelocity * (Ticks * BowConfig.Tick)
        local Destination = BowMath.fromWorld(Future)
        local Delta = Vector3.new(
            Destination.x - OriginBlocks.x,
            Destination.y - OriginBlocks.y,
            Destination.z - OriginBlocks.z
        )
        local RequiredVelocity = Vector3.new(
            Delta.X / Sum,
            (Delta.Y + GravityDrop) / Sum,
            Delta.Z / Sum
        )
        local Aim = Vector3.new(
            (RequiredVelocity.X - Source.x) / Speed - Spread.x,
            RequiredVelocity.Y / Speed - Spread.y,
            (RequiredVelocity.Z - Source.z) / Speed - Spread.z
        )
        return Aim, Aim.Magnitude - 1
    end

    local PreviousTicks = 0.25
    local _, PreviousError = Candidate(PreviousTicks)
    local BestAim = nil
    local BestTicks = nil
    local BestError = math.huge

    for Ticks = 0.5, Config.MaxFlightTicks, 0.5 do
        local Aim, Error = Candidate(Ticks)
        if math.abs(Error) < BestError then
            BestAim = Aim
            BestTicks = Ticks
            BestError = math.abs(Error)
        end

        if PreviousError > 0 and Error <= 0 then
            local Low, High = PreviousTicks, Ticks
            for _ = 1, 18 do
                local Mid = (Low + High) * 0.5
                local _, MidError = Candidate(Mid)
                if MidError > 0 then
                    Low = Mid
                else
                    High = Mid
                end
            end
            Aim = Candidate((Low + High) * 0.5)
            if Aim.Magnitude > 0 then
                return Aim.Unit, nil, {
                    FlightTicks = (Low + High) * 0.5,
                    Power = Power,
                    Speed = Speed,
                    Spread = Spread,
                    Source = Source,
                    Fallback = false,
                }
            end
            return nil, "aim vector is zero"
        end

        PreviousTicks = Ticks
        PreviousError = Error
    end

    if not BestAim or BestAim.Magnitude <= 0 then
        return nil, "no usable trajectory"
    end

    return BestAim.Unit, nil, {
        FlightTicks = BestTicks,
        Power = Power,
        Speed = Speed,
        Spread = Spread,
        Source = Source,
        Fallback = true,
        Residual = BestError,
    }
end

local OldChargeTicks
OldChargeTicks = hookfunction(BowNet.chargeTicks, function(...)
    local Ticks = OldChargeTicks(...)
    if ActiveRelease then
        ActiveRelease.ChargeTicks = Ticks
    end
    return Ticks
end)

local OldRandom
OldRandom = hookfunction(BowNet.random, function(Seed, DrawId)
    local Controller = ActivePreview
    if not Controller or (type(Seed) == "number" and type(DrawId) == "number") then
        return OldRandom(Seed, DrawId)
    end

    local Cached = CachedDraws[Controller]
    local CurrentId = Controller.drawId
    if type(CurrentId) ~= "number" and Cached then
        CurrentId = Cached.Id
    end

    if type(Seed) == "number" and type(CurrentId) == "number" then
        DrawId = CurrentId
        Controller.previewDrawId = DrawId
        return OldRandom(Seed, DrawId)
    end

    Controller.trajectory:hide()
    return function()
        return 0.5
    end
end)

local OldPreviewTrajectory
OldPreviewTrajectory = hookfunction(BowController.previewTrajectory, function(Controller, ...)
    if Controller.drawing and (not Controller.network or type(Controller.network.bowSeed) ~= "number") then
        Controller.trajectory:hide()
        return
    end

    if Controller.drawing and type(Controller.drawId) ~= "number" then
        local Cached = CachedDraws[Controller]
        if Cached and type(Cached.Id) == "number" then
            Controller.drawId = Cached.Id
        else
            Controller.trajectory:hide()
            return
        end
    end

    local Previous = ActivePreview
    ActivePreview = Controller
    local Result = OldPreviewTrajectory(Controller, ...)
    ActivePreview = Previous
    return Result
end)

local OldLaunchPoint
OldLaunchPoint = hookfunction(BowController.launchPoint, function(Controller, ...)
    local Origin, Direction = OldLaunchPoint(Controller, ...)
    local State = ActiveRelease
    local IsRelease = State and State.Controller == Controller
    local IsPreview = ActivePreview == Controller and Controller.drawing
    if not IsRelease and not IsPreview then
        return Origin, Direction
    end

    local Target = FindTarget()
    if not Target then
        return Origin, Direction
    end

    local ChargeTicks = if IsRelease then State.ChargeTicks else Controller.previewTicks
    local Aim = SolveDirection(Controller, Origin, ChargeTicks, Target)
    if Aim then
        if IsRelease then
            State.Direction = Aim
            State.Origin = Origin
        end
        return Origin, Aim
    end
    return Origin, Direction
end)

local OldSend
OldSend = hookfunction(CombatClient.send, function(Network, Action, Params)
    local State = ActiveRelease
    local Matched = Action == "Release" and State and State.Controller.network == Network
    if Matched and State.Direction then
        Params.direction = State.Direction
        Params.origin = State.Origin
    end
    local Result = OldSend(Network, Action, Params)
    if Action == "Draw" and Network.controller then
        CachedDraws[Network.controller] = {Id = Result}
    end
    return Result
end)

local OldBeginDraw
OldBeginDraw = hookfunction(BowController.beginDraw, function(Controller, ...)
    local WasDrawing = Controller.drawing
    local Result = OldBeginDraw(Controller, ...)
    if WasDrawing or not Controller.drawing then
        return Result
    end

    ActiveDrawingController = Controller
    return Result
end)

local OldAnimationUpdate
OldAnimationUpdate = hookfunction(FirstPersonAnimation.update, function(Animation, Delta, Slot, Drawing, DrawTicks, ...)
    local Controller = ActiveDrawingController
    if Controller and Controller.firstPersonAnimation == Animation and Drawing and Slot == 1 then
        DrawTicks = math.max(DrawTicks, Config.FullDrawTicks)
    end

    return OldAnimationUpdate(Animation, Delta, Slot, Drawing, DrawTicks, ...)
end)

local OldMotionUpdate
OldMotionUpdate = hookfunction(TaCZMotion.update, function(Motion, Delta, Drawing, DrawTicks, ...)
    local Result = OldMotionUpdate(Motion, Delta, Drawing, DrawTicks, ...)
    local Controller = ActiveDrawingController
    if Controller and Controller.firstPersonAnimation.tacz == Motion and Drawing and Motion.key == "tb23" then
        local Track = Motion.adsTrack
        if Track and Track.name == "pull_in" then
            Track.start = math.min(Track.start, Motion.clock - 0.2)
        end
    end

    return Result
end)

local OldRelease
OldRelease = hookfunction(BowController.release, function(Controller, ...)
    local Previous = ActiveRelease
    local State = {Controller = Controller}
    ActiveRelease = State
    local Result = OldRelease(Controller, ...)
    ActiveRelease = Previous
    return Result
end)

Features & Information

Automatically redirects arrows towards nearest player in your fov

Community Comments (1)

Steve_006Steve_006Oct 11, 2026

Can you make it for mobile?