How to detect closest part to Player using workspace:GetPartBoundsInRadius()?

Hi, so i’m making a Homing-Attack system similar to the one from the Sonic The Hedgehog series. The way it works is simple: the player jumps, check the parts in a radius of 15 studs while the player is falling, if one of those parts has the tag “Target” and is closer to the player then any of the other parts (no matter whether they have the “Target” tag or not), and if it is then enable a BillboardGui, and move the player to that part once he decides to press jump while falling.

So far i’ve managed to do the detection of parts while the player is falling, but i can’t figure out how i would go about checking which Part is the closest to the player. I’ve tried asking the Assistant and looking around in the Devforums, to no avail. Here’s my current code:

local function Targeting()
    print("a")
    if Bools.Moveset.Value == true then
        print("c")
        local Params = OverlapParams.new()
        Params.FilterType = Enum.RaycastFilterType.Exclude
        Params.FilterDescendantsInstances = {Character}
        repeat
            local Parts = workspace:GetPartBoundsInRadius(Root.Position, 30, Params) 
            print("a")
            --------------------------------------
            for _, Part : Part in pairs(Parts) do
                if Part:HasTag("Target") then
                    repeat
                        Part.Target.Enabled = true
                        task.wait()
                    until Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall
                    Part.Target.Enabled = false
                end
            end
            --------------------------------------
            task.wait()
        until Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall
    end
end
local function StateHandler(Old, New)
    if New == Enum.HumanoidStateType.Freefall then
        Targeting()
    end
end

Humanoid.StateChanged:Connect(StateHandler)

Here’s how it behaves in-game:

Also any ideas as to why only one BillboardGui enables when the parts are both within the radius?

2 Likes

To get which one is closest to the player you can compare their magnitude and return the one with the lower magnitude aka the closest one

1 Like

Yeah but how would i check if the magnitude of that part is lower than all the others?

Create some temporary variables that records the closest part and distance, then loop through the parts until you get the closest one.

Below is a pseudo-code of what it would look like.

local maxDistance = 9999 -- Max distance a part has to be within
local closestPart = nil -- Starts as nil value
for _, part:Part in pairs(Parts) do
    if FindMagnitude() < maxDistance then -- FindMagnitude() being whatever code you'll use to get the distance.
        maxDistance = FindMagnitude()
        closestPart = part
    end
end

if closestPart then
     print(closestPart.Name)
else
    print("No parts was found.")
end

So, like this, right?

      local Params = OverlapParams.new()
        Params.FilterType = Enum.RaycastFilterType.Exclude
        Params.FilterDescendantsInstances = {Character}
        --------------------------------------
        local maxDistance = 30 -- Max distance a part has to be within
        local closestPart = nil -- Starts as nil value
        --------------------------------------
        repeat
            local Parts = workspace:GetPartBoundsInRadius(Root.Position, 15, Params) 
            print("B")
            --------------------------------------
            for _, Part : Part in pairs(Parts) do
                if Part:HasTag("Target") then
                    print("C")
                    local Distance = (Root.Position - Part.Position).Magnitude
                    if Distance < maxDistance then -- FindMagnitude() being whatever code you'll use to get the distance.
                        maxDistance = Distance
                        closestPart = Part
                    end
                end
            end
            --------------------------------------
            if closestPart then
                closestPart.Target.Enabled = true
            else
                return
            end
            --------------------------------------
            task.wait()
        until Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall

I think “MaxDistance” and “closestPart” should also be within the repeat loop.

        repeat
            local Parts = workspace:GetPartBoundsInRadius(Root.Position, 15, Params) 
            print("B")
            --------------------------------------
            local maxDistance = 30 -- Max distance a part has to be within
            local closestPart = nil -- Starts as nil value
            --------------------------------------
            for _, Part : Part in pairs(Parts) do
                if Part:HasTag("Target") then
                    print("C")
                    local Distance = (Root.Position - Part.Position).Magnitude
                    if Distance < maxDistance then -- FindMagnitude() being whatever code you'll use to get the distance.
                        maxDistance = Distance
                        closestPart = Part
                    end
                end
            end
            --------------------------------------
            if closestPart then
                closestPart.Target.Enabled = true
            else
                return
            end
            --------------------------------------
            task.wait()
        until Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall


It behaves very weirdly.

Hello again!

Applying @Aandesite_Tick’s code, we would get something that would hopefully get the nearest target:

local MaxDistance = 9999
local ClosestPart = nil

for _, Part : Part in pairs(Parts) do
    local Magnitude = (Part.Position - Root.Position).Magnitude
    if Part:HasTag("Target") and Magnitude < MaxDistance then
        MaxDistance = Magnitude
        ClosestPart = Part
    end
end

if ClosestPart then
    ClosestPart.Target.Enabled = true
end

Now the problem would be how to disable the billboard when we switch to another target or when we land, and for that we will add a new variable outside the loop called TargetPart.

Then with TargetPart we will do this:

local function Targeting()
    print("a")
    if Bools.Moveset.Value == true then
        print("c")
        local Params = OverlapParams.new()
        Params.FilterType = Enum.RaycastFilterType.Exclude
        Params.FilterDescendantsInstances = {Character}

        local TargetPart = nil

        repeat
            local Parts = workspace:GetPartBoundsInRadius(Root.Position, 30, Params) 
            print("a")
            --------------------------------------
            local MaxDistance = 9999
            local ClosestPart = nil

            for _, Part : Part in pairs(Parts) do
                local Magnitude = (Part.Position - Root.Position).Magnitude
                if Part:HasTag("Target") and Magnitude < MaxDistance then
                    MaxDistance = Magnitude
                    ClosestPart = Part
                end
            end
            --------------------------------------
            if ClosestPart then
                ClosestPart.Target.Enabled = true
            end

            if TargetPart then
                ClosestPart.Target.Enabled = false
            end

            TargetPart = ClosestPart
            --------------------------------------
            task.wait()
        until Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall

        if TargetPart then
            ClosestPart.Target.Enabled = false
        end
    end
end

This should work as intended, but since you have wall jumping system, we should add some things to prevent further bug.

We will do similarly to what we did with wall jump to the StateHandler:

local OnAir = false -- If this already exists probably because this is mixed with wall jump, rename this to something else.

local function StateHandler(Old, New)
    if New == Enum.HumanoidStateType.Freefall and not OnAir then
        OnAir = true
        Targeting()
        OnAir = false
    end
end

Humanoid.StateChanged:Connect(StateHandler)

Then we will include jumping to the repeat loop:

until Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall and Humanoid:GetState() ~= Enum.HumanoidStateType.Jumping

And as a result, we will get this:

local function Targeting()
    print("a")
    if Bools.Moveset.Value == true then
        print("c")
        local Params = OverlapParams.new()
        Params.FilterType = Enum.RaycastFilterType.Exclude
        Params.FilterDescendantsInstances = {Character}

        local TargetPart = nil

        repeat
            local Parts = workspace:GetPartBoundsInRadius(Root.Position, 30, Params) 
            print("a")
            --------------------------------------
            local MaxDistance = 9999
            local ClosestPart = nil

            for _, Part : Part in pairs(Parts) do
                local Magnitude = (Part.Position - Root.Position).Magnitude
                if Part:HasTag("Target") and Magnitude < MaxDistance then
                    MaxDistance = Magnitude
                    ClosestPart = Part
                end
            end
            --------------------------------------
            if ClosestPart then
                ClosestPart.Target.Enabled = true
            end

            if TargetPart then
                ClosestPart.Target.Enabled = false
            end

            TargetPart = ClosestPart
            --------------------------------------
            task.wait()
        until Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall and Humanoid:GetState() ~= Enum.HumanoidStateType.Jumping

        if TargetPart then
            ClosestPart.Target.Enabled = false
        end
    end
end
local OnAir = false

local function StateHandler(Old, New)
    if New == Enum.HumanoidStateType.Freefall and not OnAir then
        OnAir = true
        Targeting()
        OnAir = false
    end
end

Humanoid.StateChanged:Connect(StateHandler)

I would recommend testing this with wall jump to see how it goes. Let me know if you have any problem with it!

1 Like

Yo sup again bro!! Thank you so much, it looks good to me ! Just have one minor problem :
image
image

My bad, let me fix some mistakes.

Replace it with this instead:

local function Targeting()
    print("a")
    if Bools.Moveset.Value == true then
        print("c")
        local Params = OverlapParams.new()
        Params.FilterType = Enum.RaycastFilterType.Exclude
        Params.FilterDescendantsInstances = {Character}

        local TargetPart = nil

        repeat
            local Parts = workspace:GetPartBoundsInRadius(Root.Position, 30, Params) 
            print("a")
            --------------------------------------
            local MaxDistance = 9999
            local ClosestPart = nil

            for _, Part : Part in pairs(Parts) do
                local Magnitude = (Part.Position - Root.Position).Magnitude
                if Part:HasTag("Target") and Magnitude < MaxDistance then
                    MaxDistance = Magnitude
                    ClosestPart = Part
                end
            end
            --------------------------------------
            if ClosestPart then
                ClosestPart.Target.Enabled = true
            end

            if TargetPart then
                TargetPart.Target.Enabled = false
            end

            TargetPart = ClosestPart
            --------------------------------------
            task.wait()
        until Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall and Humanoid:GetState() ~= Enum.HumanoidStateType.Jumping

        if TargetPart then
            TargetPart.Target.Enabled = false
        end
    end
end
1 Like

Looks good, but this occurs. Did i do something wrong?

Here’s the code for the connection:

--|State Handling
local OnAir2 = false
local function StateHandler(Old, New)
    if New == Enum.HumanoidStateType.Freefall and not OnAir2 then
        OnAir2 = true
        Targeting()
        OnAir2 = false
    elseif (New == Enum.HumanoidStateType.Freefall or New == Enum.HumanoidStateType.Jumping) and not OnAir then
        WallJump()
    end
end
--||Connections
--UIS.JumpRequest:Connect(DoubleJump)
CAS:BindAction("Bolt/Sweep", ActionHandler, false, Enum.KeyCode.Q)
CAS:BindAction("Drift", ActionHandler, false, Enum.KeyCode.E)
CAS:BindAction("Tramp", ActionHandler, false, Enum.KeyCode.F)
Humanoid.StateChanged:Connect(StateHandler)

Seems like I forgot to add a check if the ClosestPart is not equal to TargetPart

Try this:

if ClosestPart and ClosestPart ~= TargetPart then
    ClosestPart.Target.Enabled = true
end

As for the OnAir variable for wall jumping, what happened with the OnAir = true and OnAir = false? Did you move them inside the WallJump function?

Late reply, sorry i was at school, but where do i put the if ClosestPart and... block? And as for the OnAir thing, imma just put the whole script so u can see for urself

--||Service(s)
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local Debris = game:GetService("Debris")
local UIS = game:GetService("UserInputService")
local CAS = game:GetService("ContextActionService")
--||Variable(s)
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")
local Animator = Humanoid.Animator
local Root : BasePart = Character:WaitForChild("HumanoidRootPart")
local Animations = Character:WaitForChild("Animations")
local Controls = require(Player.PlayerScripts.PlayerModule):GetControls()
local Mouse = Player:GetMouse()
--------------------------------------
local Effects = ReplicatedStorage:WaitForChild("Effects")
local Events = ReplicatedStorage:WaitForChild("Events")
local Sounds = ReplicatedStorage:WaitForChild("Sounds")
local Utilities = ReplicatedStorage:WaitForChild("Utilities")
local Settings = Character:WaitForChild("Settings")
local Expressions = require(Utilities.Expressions)
local Bezier = require(Utilities.Bezier)
local Controls = require(Player.PlayerScripts.PlayerModule):GetControls()
local Bools = {
    Bolting = Settings.Bolting,
    Drifting = Settings.Drifting,
    Tramping = Settings.Tramping,
    Hurting = Settings.Hurting,
    Moveset = Settings.Moveset
}
local Anims = {
    Bolt = Animator:LoadAnimation(Animations.Ring),
    Drift = Animator:LoadAnimation(Animations.Drift),
    Tramp = Animator:LoadAnimation(Animations.Tramp)
}
--||Function(s)
--Disable all Ragdoll Physics.
Humanoid:SetStateEnabled(Enum.HumanoidStateType.Ragdoll, false)
Humanoid:SetStateEnabled(Enum.HumanoidStateType.FallingDown, false)
--|Targeting
local function Targeting()
    print("a")
    if Bools.Moveset.Value == true then
        print("c")
        local Params = OverlapParams.new()
        Params.FilterType = Enum.RaycastFilterType.Exclude
        Params.FilterDescendantsInstances = {Character}

        local TargetPart = nil

        repeat
            local Parts = workspace:GetPartBoundsInRadius(Root.Position, 30, Params) 
            print("a")
            --------------------------------------
            local MaxDistance = 9999
            local ClosestPart = nil

            for _, Part : Part in pairs(Parts) do
                local Magnitude = (Part.Position - Root.Position).Magnitude
                if Part:HasTag("Target") and Magnitude < MaxDistance then
                    MaxDistance = Magnitude
                    ClosestPart = Part
                end
            end
            --------------------------------------
            if ClosestPart then
                ClosestPart.Target.Enabled = true
            end

            if TargetPart then
                TargetPart.Target.Enabled = false
            end
            
            if ClosestPart and ClosestPart ~= TargetPart then
                ClosestPart.Target.Enabled = true
            end
            
            TargetPart = ClosestPart
            --------------------------------------
            task.wait()
        until Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall and Humanoid:GetState() ~= Enum.HumanoidStateType.Jumping

        if TargetPart then
            TargetPart.Target.Enabled = false
        end
    end
end
--|Wall Jump                                  
local PreviousWall = nil
local NearWall = nil
local OnAir = false
local function WallJump()
    if Bools.Moveset.Value == true then
        local Connection = UIS.JumpRequest:Connect(function()
            if NearWall and NearWall ~= PreviousWall then
                PreviousWall = NearWall
                Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
                Expressions:Swap("Happy", "Blink", "BoredClosed", "WallJump")
                --------------------------------------
                if Root:FindFirstChild("WJEffect") then
                    Root.WJEffect:Destroy()
                elseif Root:FindFirstChild("WJSound") then
                    Root.WJSound:Destroy()
                end
                --------------------------------------
                local Sound = Sounds.Player.WJSound:Clone()
                Sound.Parent = Root
                Sound.PlaybackSpeed = math.random(9, 10)/10
                Sound:Play()
                --------------------------------------
                local Effect = Effects.Player.WJEffect:Clone()
                Effect.Parent = Root
                Effect.CFrame = Root.CFrame
                local TweenInform = TweenInfo.new(0.25, Enum.EasingStyle.Linear, Enum.EasingDirection.In)
                local TweenEffectSize = TweenService:Create(Effect.GUI.ImageLabel, TweenInform, {Size = UDim2.new(1, 0, 1, 0)})
                local TweenEffectTransparency = TweenService:Create(Effect.GUI.ImageLabel, TweenInform, {ImageTransparency = 1})
                TweenEffectSize:Play()
                TweenEffectTransparency:Play()
                --------------------------------------
                Debris:AddItem(Effect, 0.25)
                Debris:AddItem(Sound, 1)
            end
        end)
        --------------------------------------
        while Humanoid:GetState() == Enum.HumanoidStateType.Freefall or Humanoid:GetState() == Enum.HumanoidStateType.Jumping do
            local Params = OverlapParams.new()
            Params.FilterType = Enum.RaycastFilterType.Exclude
            Params.FilterDescendantsInstances = {Character}
            --------------------------------------
            local Parts = workspace:GetPartBoundsInRadius(Root.Position, 1.5, Params)
            --------------------------------------
            for _, Part : Part in ipairs(Parts) do
                if Part:HasTag("Wall Jump") then
                    NearWall = Part
                    break
                else
                    NearWall = nil
                end
            end
            task.wait()
        end
        --------------------------------------
        Connection:Disconnect()
        NearWall = nil
        PreviousWall = nil
    else
        return
    end
end
--|Bolt / Sweep
local HasBolted = false
local function BoltOrSweep()
    if Bools.Moveset.Value == true then
        if Humanoid:GetState() == Enum.HumanoidStateType.Freefall and not Root.Anchored then
            if Bools.Bolting.Value == false and Bools.Drifting.Value == false and Bools.Tramping.Value == false then
                local Params = RaycastParams.new()
                Params.FilterType = Enum.RaycastFilterType.Exclude
                Params.FilterDescendantsInstances = {Character}
                --------------------------------------
                local CloseToWall = false
                --------------------------------------
                spawn(function()
                    local Raycast = workspace:Raycast(Root.Position, Root.CFrame.LookVector * 2, Params)
                    while Humanoid:GetState() == Enum.HumanoidStateType.Freefall do
                        if Raycast then
                            if Raycast.Instance then
                                CloseToWall = true
                                break
                            else
                                CloseToWall = false
                            end
                        end
                        task.wait()
                    end
                end)
                --------------------------------------
                if not CloseToWall then
                    --------------------------------------
                    Bools.Bolting.Value = true
                    HasBolted = true
                    Anims.Bolt:Play(0, 20, 1)
                    --------------------------------------
                    if Bools.Hurting.Value == false then
                        Expressions:Swap("Surprised", "Happy", "HappyOpen", "Bolt")
                    end
                    --------------------------------------
                    Humanoid.AutoRotate = false
                    --------------------------------------
                    local Sound = Sounds.Player.BoltSound:Clone()
                    Sound.Parent = Root
                    Sound.PlaybackSpeed = math.random(9,10)/10
                    Sound:Play()
                    Debris:AddItem(Sound, 1.5)
                    --------------------------------------
                    local Attachment = Instance.new("Attachment", Root)
                    Attachment.Position = Vector3.new(0, 0, 0)
                    Attachment.Name = "BoltAttachment"
                    --------------------------------------
                    local Direction = Root.CFrame.LookVector
                    local Velocity = Instance.new("LinearVelocity", Root)
                    Velocity.Name = "BoltVelocity"
                    Velocity.VectorVelocity = Direction * 120
                    Velocity.Attachment0 = Attachment
                    Velocity.MaxForce = math.huge
                    --------------------------------------
                    local Params = RaycastParams.new()
                    Params.FilterType = Enum.RaycastFilterType.Exclude
                    Params.FilterDescendantsInstances = {Character}
                    --------------------------------------
                    spawn(function()
                        while Bools.Bolting.Value == true do
                            local Raycast = workspace:Spherecast(Root.Position, 5, Root.CFrame.LookVector * 1, Params)
                            if Raycast then
                                if Raycast.Instance then
                                    Attachment:Destroy()
                                    Velocity:Destroy()
                                    --------------------------------------
                                    Bools.Bolting.Value = false
                                    --------------------------------------
                                    Anims.Bolt:Stop()
                                    break
                                end
                            end
                            task.wait()
                        end
                    end)
                    --------------------------------------
                    Debris:AddItem(Attachment, 0.25)
                    Debris:AddItem(Velocity, 0.25)
                    --------------------------------------
                    local Effect = Effects.Player.BoltEffect:Clone()
                    Effect.Parent = workspace
                    Effect.Position = Root.Position
                    Effect.Orientation = Root.Orientation - Vector3.new(0, 0, 90)
                    local TweenInform = TweenInfo.new(0.25, Enum.EasingStyle.Linear, Enum.EasingDirection.In)
                    local TweenEffectSize = TweenService:Create(Effect, TweenInform, {Size = Vector3.new(8, 8, 0.1)})
                    local TweenEffectTransparency1 = TweenService:Create(Effect.Front.ImageLabel, TweenInform, {ImageTransparency = 1})
                    local TweenEffectTransparency2 = TweenService:Create(Effect.Back.ImageLabel, TweenInform, {ImageTransparency = 1})
                    TweenEffectSize:Play()
                    TweenEffectTransparency1:Play()
                    TweenEffectTransparency2:Play()
                    --------------------------------------
                    Debris:AddItem(Effect, 0.25)
                    --------------------------------------
                    spawn(function()
                        task.wait(.25)
                        --------------------------------------
                        Bools.Bolting.Value = false
                        --------------------------------------
                        Humanoid.AutoRotate = true
                        --------------------------------------
                        if Character:GetAttribute("Expression") == "Bolt" and Bools.Hurting.Value == false then
                            Expressions:Swap("Happy", "Happy", "HappyClosed", "Happy")
                        elseif Character:GetAttribute("Expression") ~= "Bolt" or Bools.Hurting.Value == true then
                            return
                        end
                    end)
                    --------------------------------------
                    repeat
                        task.wait()
                    until Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall
                    --------------------------------------
                    HasBolted = false
                end
            end
        end
    else
        return
    end
end
--|Drift
local function Drift()
    if Humanoid:GetState() == Enum.HumanoidStateType.Freefall and not Root.Anchored then
        if Bools.Bolting.Value == false and Bools.Drifting.Value == false and Bools.Tramping.Value == false then
            Anims.Drift.Priority = Enum.AnimationPriority.Action4
            Anims.Drift:Play(1, 10, 1)
            --------------------------------------
            Bools.Drifting.Value = true
            --------------------------------------
            if Bools.Hurting.Value == false then
                Expressions:Swap("Happy", "Down", "Curious", "Drift")
            end
            --------------------------------------
            local Effect1 = Effects.Player.DriftParticles:Clone()
            Effect1.Parent = Character.Tick1
            local Effect2 = Effects.Player.DriftParticles:Clone()
            Effect2.Parent = Character.Tick2
            --------------------------------------
            local Sound = Sounds.Player.DriftSound:Clone()
            Sound.Parent = Root
            Sound:Play()
            Sound.PlaybackSpeed = math.random(9,10)/10
            --------------------------------------
            local Velocity = Instance.new("BodyVelocity", Root)
            Velocity.Name = "DriftVelocity"
            Velocity.P = 5000
            Velocity.MaxForce = Vector3.new(0, 50000000, 0)
            Velocity.Velocity = Vector3.new(0, -10, 0)
            --------------------------------------
            repeat 
                task.wait()
            until Humanoid:GetState() == Enum.HumanoidStateType.Landed or Root.Anchored or NearWall
            --------------------------------------
            Bools.Drifting.Value = false
            Effect1:Destroy()
            Effect2:Destroy()
            Sound:Destroy()
            Velocity:Destroy()
            Anims.Drift:Stop()
            --------------------------------------
            if Character:GetAttribute("Expression") == "Drift" and Bools.Hurting.Value == false then
                Expressions:Swap("Happy", "Happy", "HappyClosed", "Happy")
            elseif Character:GetAttribute("Expression") ~= "Drift" or Bools.Hurting.Value == true then
                return
            end
        elseif Bools.Drifting.Value == true then
            Bools.Drifting.Value = false
            --------------------------------------
            if Humanoid.FloorMaterial == Enum.Material.Air then
                Expressions:Swap("Happy", "Down", "BoredClosed", "Falling")
            else
                return
            end
            --------------------------------------
            Anims.Drift:Stop()
            Root.DriftSound:Destroy()
            --------------------------------------
            Character.Tick1.DriftParticles:Destroy()
            Character.Tick2.DriftParticles:Destroy()
            Root.DriftVelocity:Destroy()
        end
    end
end
--|Tramp
local function Tramp()
   if Bools.Moveset.Value == true then
        if Humanoid:GetState() == Enum.HumanoidStateType.Freefall and Bools.Bolting.Value == false and Bools.Drifting.Value == false and Bools.Tramping.Value == false then
            --------------------------------------
            Anims.Tramp:Play(0, 25)
            --------------------------------------
            local Sound0 = Sounds.Player.WooshSound:Clone()
            Sound0.Parent = Root
            Sound0.PlaybackSpeed = math.random(9, 10)/10
            --------------------------------------
            Sound0:Play()
            --------------------------------------
            Debris:AddItem(Sound0, 0.25)
            --------------------------------------
            Expressions:Swap("Happy", "Blink", "BoredClosed", "Tramp")
            --------------------------------------
            Bools.Tramping.Value = true
            --------------------------------------
            local Direction = Root.CFrame.UpVector
            local TVelocity = Instance.new("BodyVelocity", Root)
            TVelocity.Name = "RecoilVelocity"
            TVelocity.Velocity = -Direction * 100
            TVelocity.MaxForce = Vector3.new(0, 75000, 0)
            --------------------------------------
            repeat
                task.wait()
            until Humanoid.FloorMaterial ~= Enum.Material.Air
            --------------------------------------
            Anims.Tramp:Play(0, 25)
            --------------------------------------
            spawn(function()
                task.wait(0.25)
                Anims.Tramp:Stop()
                if Character:GetAttribute("Expression") == "Tramp" and Bools.Tramping.Value == false then
                    Expressions:Swap("Happy", "Down", "Curious", "Recoil")
                elseif Character:GetAttribute("Expression") ~= "Tramp" or Bools.Tramping.Value == true then
                    return
                end
            end)
            --------------------------------------
            local Sound1 = Sounds.Player.WJSound:Clone()
            Sound1.Parent = Root
            Sound1.PlaybackSpeed = math.random(9, 10)
            --------------------------------------
            Sound1:Play()
            --------------------------------------
            Debris:AddItem(Sound1, 4)
            --------------------------------------
            TVelocity:Destroy()
            --------------------------------------
            local Direction = Root.CFrame.UpVector
            local RVelocity = Instance.new("BodyVelocity", Root)
            RVelocity.Name = "RecoilVelocity"
            RVelocity.Velocity = Direction * 60
            RVelocity.MaxForce = Vector3.new(0, 75000, 0)
            --------------------------------------
            Debris:AddItem(RVelocity, 0.125)
            --------------------------------------
            local Params = RaycastParams.new()
            Params.FilterType = Enum.RaycastFilterType.Exclude
            Params.FilterDescendantsInstances = {Character}
            --------------------------------------
            local Raycast = workspace:Raycast(Root.Position, -Root.CFrame.UpVector * 10, Params)
            if Raycast then
                if Raycast.Instance and not Raycast.Instance.Parent:HasTag("Collectible") then
                    Root.Position = Raycast.Position + Vector3.new(0, 1.25, 0)
                    local Effect = Effects.Player.TrampEffect:Clone()
                    Effect.Parent = workspace
                    Effect.CFrame = CFrame.new(Raycast.Position, Raycast.Position + Raycast.Normal)
                    --------------------------------------
                    local TweenInform = TweenInfo.new(0.5, Enum.EasingStyle.Linear, Enum.EasingDirection.In)
                    local TweenEffectSize = TweenService:Create(Effect, TweenInform, {Size = Vector3.new(8, 8, 0.1)})
                    local TweenEffectTransparency = TweenService:Create(Effect.GUI.ImageLabel, TweenInform, {ImageTransparency = 1})
                    local TweenEffectRotation = TweenService:Create(Effect.GUI.ImageLabel, TweenInform, {Rotation = 360})
                    TweenEffectSize:Play()
                    TweenEffectTransparency:Play()
                    TweenEffectRotation:Play()
                    --------------------------------------
                    Debris:AddItem(Effect, 0.5)
                end
            end
            --------------------------------------
            task.wait()
            --------------------------------------
            Bools.Tramping.Value = false
        end
   else
        return
   end
end
--|Input Handling
local function ActionHandler(ActionName, InputState, InputObject)
    if ActionName == "Bolt/Sweep" and InputState == Enum.UserInputState.Begin then
        BoltOrSweep()
    elseif ActionName == "Drift" and InputState == Enum.UserInputState.Begin then
        Drift()
    elseif ActionName == "Tramp" and InputState == Enum.UserInputState.Begin then
        Tramp()
    end
end
--|State Handling
local OnAir2 = false
local function StateHandler(Old, New)
    if New == Enum.HumanoidStateType.Freefall and not OnAir2 then
        OnAir2 = true
        Targeting()
        OnAir2 = false
    elseif (New == Enum.HumanoidStateType.Freefall or New == Enum.HumanoidStateType.Jumping) and not OnAir then
        WallJump()
    end
end
--||Connections
--UIS.JumpRequest:Connect(DoubleJump)
CAS:BindAction("Bolt/Sweep", ActionHandler, false, Enum.KeyCode.Q)
CAS:BindAction("Drift", ActionHandler, false, Enum.KeyCode.E)
CAS:BindAction("Tramp", ActionHandler, false, Enum.KeyCode.F)
Humanoid.StateChanged:Connect(StateHandler)
RunService.RenderStepped:Connect(function()
    if Bools.Moveset.Value == false then
        for _, Bool in pairs(Bools) do
            if Bool ~= Bools.Hurting and Bool ~= Bools.Moveset then
                Bool.Value = false
            end
        end
        for _, Anim in pairs(Anims) do
            Anim:Stop()
        end
        for _, Obj in pairs(Root:GetChildren()) do
            if string.match(Obj.Name, "Bolt") or string.match(Obj.Name, "Drift") or string.match(Obj.Name, "Tramp") then
                Obj:Destroy()
            end
        end
        return
    end
end)

Here:

local function Targeting()
    print("a")
    if Bools.Moveset.Value == true then
        print("c")
        local Params = OverlapParams.new()
        Params.FilterType = Enum.RaycastFilterType.Exclude
        Params.FilterDescendantsInstances = {Character}

        local TargetPart = nil

        repeat
            local Parts = workspace:GetPartBoundsInRadius(Root.Position, 30, Params) 
            print("a")
            --------------------------------------
            local MaxDistance = 9999
            local ClosestPart = nil

            for _, Part : Part in pairs(Parts) do
                local Magnitude = (Part.Position - Root.Position).Magnitude
                if Part:HasTag("Target") and Magnitude < MaxDistance then
                    MaxDistance = Magnitude
                    ClosestPart = Part
                end
            end
            --------------------------------------
            if ClosestPart and ClosestPart ~= TargetPart then
                ClosestPart.Target.Enabled = true
            end

            if TargetPart then
                TargetPart.Target.Enabled = false
            end

            TargetPart = ClosestPart
            --------------------------------------
            task.wait()
        until Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall and Humanoid:GetState() ~= Enum.HumanoidStateType.Jumping

        if TargetPart then
            TargetPart.Target.Enabled = false
        end
    end
end

For some reason it just blinks and that’s it

Wait wait wait, my bad again. Didn’t think twice before posting heheh. :sweat_smile:

Try this:

local function Targeting()
    print("a")
    if Bools.Moveset.Value == true then
        print("c")
        local Params = OverlapParams.new()
        Params.FilterType = Enum.RaycastFilterType.Exclude
        Params.FilterDescendantsInstances = {Character}

        local TargetPart = nil

        repeat
            local Parts = workspace:GetPartBoundsInRadius(Root.Position, 30, Params) 
            print("a")
            --------------------------------------
            local MaxDistance = 9999
            local ClosestPart = nil

            for _, Part : Part in pairs(Parts) do
                local Magnitude = (Part.Position - Root.Position).Magnitude
                if Part:HasTag("Target") and Magnitude < MaxDistance then
                    MaxDistance = Magnitude
                    ClosestPart = Part
                end
            end
            --------------------------------------
            if ClosestPart then
                ClosestPart.Target.Enabled = true
            end

            if TargetPart and TargetPart ~= ClosestPart then
                TargetPart.Target.Enabled = false
            end

            TargetPart = ClosestPart
            --------------------------------------
            task.wait()
        until Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall and Humanoid:GetState() ~= Enum.HumanoidStateType.Jumping

        if TargetPart then
            TargetPart.Target.Enabled = false
        end
    end
end
1 Like

Late reply again (i was in school still) but thanks bro, it works now! Now, comes the part where the player does the homing attack onto the target. I’ll try coding it myself and if there’s an issue i’ll tell you about it!

1 Like

Alrighty i’m back, so basically it works fine but due to the fact that UIS.JumpRequest (for whatever reason) fires twice when you press it and ROBLOX still hasn’t fixed this issue, the player almost immediately flies to the target. And also, question, how would i make a sound play when Target.Enabled = true without it repeating the sound multiple times?

local function Targeting()
    print("a")
    if Bools.Moveset.Value == true and Bools.Targeting.Value == false then
        print("c")
        local Params = OverlapParams.new()
        Params.FilterType = Enum.RaycastFilterType.Exclude
        Params.FilterDescendantsInstances = {Character}
        --------------------------------------
        local TargetPart = nil
        local Connection
        --------------------------------------
        Connection = UIS.JumpRequest:Connect(function()
            if TargetPart then
                task.wait(0.1)
                Connection:Disconnect()
                --------------------------------------
                Bools.Targeting.Value = true
                --------------------------------------
                Root.Anchored = true
                --------------------------------------
                local TweenPos = TweenService:Create(Root, TweenInfo.new(0.125, Enum.EasingStyle.Linear, Enum.EasingDirection.In), {Position = TargetPart.Position})
                TweenPos:Play()
                --------------------------------------
                Anims.Target:Play(0, 30)
                --------------------------------------
                TweenPos.Completed:Wait()
                --------------------------------------
                Bools.Targeting.Value = false
                --------------------------------------
                Root.Anchored = false
                --------------------------------------
                Anims.Target:Stop()
                
            end
        end)
        --------------------------------------
        repeat
            local Parts = workspace:GetPartBoundsInRadius(Root.Position, 30, Params) 
            print("a")
            --------------------------------------
            local MaxDistance = 9999
            local ClosestPart = nil

            for _, Part : Part in pairs(Parts) do
                local Magnitude = (Part.Position - Root.Position).Magnitude
                if Part:HasTag("Target") and Magnitude < MaxDistance then
                    MaxDistance = Magnitude
                    ClosestPart = Part
                end
            end
            --------------------------------------
            if ClosestPart then
                ClosestPart.Target.Enabled = true
            end

            if TargetPart and TargetPart ~= ClosestPart then
                TargetPart.Target.Enabled = false
            end

            TargetPart = ClosestPart
            --------------------------------------
            task.wait()
        until Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall and Humanoid:GetState() ~= Enum.HumanoidStateType.Jumping

        if TargetPart then
            TargetPart.Target.Enabled = false
        end
    end
end

Bumpy bumping aaaa, you there bro?

1 Like

You would need to disconnect the JumpRequest after the loop.

As for playing the sound, it’s as simple as just detecting if the gui is not enabled before playing the sound.

local function Targeting()
    print("a")
    if Bools.Moveset.Value == true and Bools.Targeting.Value == false then
        print("c")
        local Params = OverlapParams.new()
        Params.FilterType = Enum.RaycastFilterType.Exclude
        Params.FilterDescendantsInstances = {Character}
        --------------------------------------
        local TargetPart = nil
        local Connection
        --------------------------------------
        Connection = UIS.JumpRequest:Connect(function()
            if TargetPart then
                task.wait(0.1)
                Connection:Disconnect()
                --------------------------------------
                Bools.Targeting.Value = true
                --------------------------------------
                Root.Anchored = true
                --------------------------------------
                local TweenPos = TweenService:Create(Root, TweenInfo.new(0.125, Enum.EasingStyle.Linear, Enum.EasingDirection.In), {Position = TargetPart.Position})
                TweenPos:Play()
                --------------------------------------
                Anims.Target:Play(0, 30)
                --------------------------------------
                TweenPos.Completed:Wait()
                --------------------------------------
                Bools.Targeting.Value = false
                --------------------------------------
                Root.Anchored = false
                --------------------------------------
                Anims.Target:Stop()
                
            end
        end)
        --------------------------------------
        repeat
            local Parts = workspace:GetPartBoundsInRadius(Root.Position, 30, Params) 
            print("a")
            --------------------------------------
            local MaxDistance = 9999
            local ClosestPart = nil

            for _, Part : Part in pairs(Parts) do
                local Magnitude = (Part.Position - Root.Position).Magnitude
                if Part:HasTag("Target") and Magnitude < MaxDistance then
                    MaxDistance = Magnitude
                    ClosestPart = Part
                end
            end
            --------------------------------------
            if ClosestPart then
                if not TargetPart.Target.Enabled then
                    script.TargetSound:Play() -- Replace this with your sound.
                end

                ClosestPart.Target.Enabled = true
            end

            if TargetPart and TargetPart ~= ClosestPart then
                TargetPart.Target.Enabled = false
            end

            TargetPart = ClosestPart
            --------------------------------------
            task.wait()
        until Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall and Humanoid:GetState() ~= Enum.HumanoidStateType.Jumping

        if TargetPart then
            TargetPart.Target.Enabled = false
        end

        Connection:Disconnect()
    end
end
1 Like