My NPC has a poor aim on a player

Hello dear developers! I am here with an issue I cannot find answer to.
I’ve created an NPC that throws SuperBalls at a player, however, the aim of the NPC is very poor, and any player can dodge by thrown SuperBalls from coolkid NPC very easily by just walking away as shown in this video:

I tried to edit the SuperBall script, to maintain my goal to make the aim of my NPC much accurate. I’ve failed numerous times and could not find any answers from the internet, so I would like to seek for help.
Note that I am not a professional scripter, nor a newbie, I am an average scripter. I would like to see a readable and not hard to understand script to fix this issue!

Here is the script inside SuperBall tool:

local Tool = script.Parent
local Ball = Tool.Handle
local MouseLoc = Tool:WaitForChild("MouseLoc",10)
local Voice = script.Parent.Gotcha
local npc = script.Parent.Parent

function EnemyNear()
	local nearestPlr = nil
	local shortestDistance = math.rad(7200)

	for _, plr in pairs(game.Players:GetPlayers()) do
		if plr.Character and plr.Character:FindFirstChild("HumanoidRootPart") then
			local distance = (npc.HumanoidRootPart.Position - plr.Character.HumanoidRootPart.Position).magnitude

			if distance <= shortestDistance then
				nearestPlr = plr

				shortestDistance = distance
			end
		end
	end

	return nearestPlr
end


function fire(direction)

	Tool.Handle.Boing:Play()

	local vCharacter = Tool.Parent
	local vPlayer = script.Parent.Parent

	local missile = Instance.new("Part")       

	local spawnPos = vCharacter.PrimaryPart.Position

	spawnPos  = spawnPos + (direction * 5)

	missile.Position = spawnPos
	missile.Size = Vector3.new(2,2,2)
	missile.Velocity = direction * 165
	missile.BrickColor = BrickColor.new("Really red")
	missile.Shape = 0
	missile.Locked = true
	missile.BottomSurface = 0
	missile.TopSurface = 0
	missile.Name = "Cannon Shot"
	missile.Elasticity = 1
	missile.Reflectance = .2
	missile.Friction = 0

	Tool.Handle.Boing:Clone().Parent = missile

	local creator_tag = Instance.new("ObjectValue")
	creator_tag.Value = vPlayer
	creator_tag.Name = "creator"
	creator_tag.Parent = missile

	missile.Parent = workspace
end

Tool.Enabled = true
function NPCactivate()
	local animator = script.Parent.Parent.Humanoid:FindFirstChildOfClass("Animator")
	
	if not Tool.Enabled then
		return
	end
	Tool.Enabled = false
	local character = Tool.Parent;
	local humanoid = character:FindFirstChildOfClass("Humanoid")
	if not humanoid then
		print("Humanoid not found")
		return 
	end
	
	local plrPos = EnemyNear()

	local targetPos = plrPos.Character.HumanoidRootPart.Position + Vector3.new(0, 0, 0)
	local lookAt = (targetPos - character.Head.Position).unit
	
	local animtrack = animator:LoadAnimation(script.Parent.Animation)
	animtrack:Play()
	
	task.wait(0.4)
	fire(lookAt)
	Ball.Transparency = 1
	Voice:Play()
	
	wait(1)
	Ball.Transparency = 0
	Tool.Enabled = true
	
end

while task.wait(1) do
	NPCactivate()
end

Thank you.

1 Like

You’re aiming at the position the player is currently at, but they’re moving. You have to aim at where they will be.

1 Like

Why are you adding a useless Vector3? You could also use

Vector3.zero

1 Like

Also, what he said. Use HumanoidRootPart.LinearVelocity to calculate where they’re going and add that along with the time to calculate the estimate position when the ball reaches them.

2 Likes

I am not good at scripting. Could you please show me the example? I am sorry for bothering you.

1 Like

local newtargetposition = targetposition + HumanoidRootPart.LinearVelocity*3
3 or however long it takes to throw

That might work, I spent about 10 seconds making it.

1 Like

So I write the code like this:

local newtargetposition = plrPos + plrPos.Character.HumanoidRootPart.LinearVelocity * 3

Please tell if I did something wrong in here and note my errors.
However, when I start the game this error popes up:

LinearVelocity is not a valid member of Part “Workspace.Enderstrano.HumanoidRootPart”

Sorry, it was AssemblyLinearVelocity

local root = plrPos.Character.HumanoidRootPart
local newtargetposition = root.Position + root.AssemblyLinearVelocity*3

Or something like that.

1 Like

I would do.

local newtargetposition = plrPos + plrPos.Character.Humanoid.MoveDirection*plrPos.Character.Humanoid.WalkSpeed

Note that that may make the npc’s aim be way off if you suddenly turn the other direction, or abruptly stop moving.

It works really good thank you so much! I would like to know, how this script works? I would like to increase my skills. I will also try the script of PiercedMissile, if it works good, I will use it too!

1 Like

The AssemblyLinearVelocity shows how fast the assembly is moving in studs per second. The throw might take 3 seconds, so I multiply it by 3.

Thank you for help! I just tried to code tho, this error poped up:

Workspace.ClassicSuperball.CannonScript:81: attempt to perform arithmetic (add) on Instance and Vector3

That’s because plrPos is a Player, not a Vector3

So that means even tho if player’s WalkSpeed will be increased, it will detect it and still work?
Also, the multiplication to 3, caused some issue, the throw SuperBall was thrown a bit far away, so I changed it to 1. It works great now.

What @PiercedMissile and I did were basically the same thing, just accessing the speed in different ways.

Yes now I see the issue. I will keep your code for now. :grin:

1 Like