I need help trying to figure out what to do to transform this code so it handles all NPC’s
Full Code:
local npcsFolder = workspace:WaitForChild("Npcs")
local RunService = game:GetService("RunService")
local replicatedStorage = game:GetService("ReplicatedStorage")
local Remotes = replicatedStorage:WaitForChild("Remotes")
local Modules = replicatedStorage:WaitForChild("Modules")
local ToolData = require(script.Parent:WaitForChild("ToolData"))
local character = script.Parent.Parent
local humanoid = character:WaitForChild("Hero")
local animator = humanoid:FindFirstChildOfClass("Animator")
local RemotesFolder = character:WaitForChild("RemotesFolder")
local npcs = workspace:WaitForChild("Npcs")
local animationTable = {
[0] = script:WaitForChild("Attack1"),
}
local tool = character:WaitForChild("Bow")
local hitbox = tool:WaitForChild("Hitbox")
local firePoint = hitbox:WaitForChild("FirePoint")
local range = ToolData.MaxRange
local animationCombo = 0
local currentTime = tick()
local canShoot = true
local damageCooldown = 0.4
local currentTarget = nil
local canAttack = character:WaitForChild("CanAttack")
local track = nil
local function playAnimation()
if animationTable[animationCombo] then
local anim = animationTable[animationCombo]
track = animator:LoadAnimation(anim)
track:Play()
track.Stopped:Wait()
canShoot = true
end
animationCombo += 1
if animationCombo > #animationTable then
animationCombo = 0
end
end
local function castRay(target)
if target.PrimaryPart ~= nil then
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {npcs}
raycastParams.FilterType = Enum.RaycastFilterType.Whitelist
raycastParams.IgnoreWater = true
local rayOrigin = character.PrimaryPart.Position
local rayDestination = target.PrimaryPart.Position
local rayDirection = (rayDestination - rayOrigin)
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
if raycastResult then
local distance = math.floor(raycastResult.Distance)
if distance <= range then
currentTarget = target
return true, raycastResult.Position, distance
end
end
end
currentTarget = nil
return false, nil, nil
end
local function PredictNextPosition(targetPosition, targetVelocity)
if targetPosition ~= nil and targetVelocity ~= nil then
local t = ToolData.ProjectileTime
local endPosition = targetPosition + targetVelocity * t
return endPosition
end
end
local function getPlayer()
local player = Remotes.GetPlayerBindable:Invoke()
if player then
return player
end
end
local player = getPlayer()
local function reset()
currentTarget = nil
canShoot = true
end
local function findTarget()
local checkRay, position, distance = nil, nil, nil
for i,v in ipairs(npcs:GetChildren()) do
checkRay, position, distance = castRay(currentTarget or v)
if currentTarget ~= nil then
local savedTarget = currentTarget
local targetRoot = currentTarget.PrimaryPart
local human = currentTarget:FindFirstChildWhichIsA("Humanoid")
if human and human.Health > 0 then
if human and human.Health <= 0 then
currentTarget = nil
end
if distance > range then
currentTarget = nil
end
if player and human and human.Health > 0 and currentTarget ~= nil and targetRoot ~= nil and checkRay == true then
local success, bool = pcall(function()
return Remotes.CheckOnScreen:InvokeClient(player, targetRoot, {npcs})
end)
if success and bool then
local characterRoot = character.PrimaryPart
characterRoot.CFrame = CFrame.lookAt(characterRoot.Position, Vector3.new(position.X, characterRoot.Position.Y, position.Z))
if tick() - currentTime >= damageCooldown then
currentTime = tick()
playAnimation()
checkRay, position, distance = castRay(savedTarget)
local nextPosition = PredictNextPosition(position, targetRoot.AssemblyLinearVelocity)
if checkRay == true and nextPosition ~= nil and canShoot == true then
RemotesFolder.FireProjectile:Fire(firePoint, nextPosition)
canShoot = false
else
reset()
end
end
end
end
else
reset()
end
end
end
end
local lastSendTick = tick()
local updatesPerSecond = 10
RunService.Heartbeat:Connect(function()
if tick() - lastSendTick > 1 / updatesPerSecond and character.PrimaryPart ~= nil and canAttack.Value == true then
lastSendTick = tick()
findTarget()
end
end)