My enemy NPC cannot aim well

Hello dear developers! I am here to get some help with my enemy NPC. I once made a post on how can I make my NPC aim more accurate. However, as we know, players always find a way to easily dodge any NPC enemies. So I did the same thing and found the easiest ways to dodge my enemy NPC. I updated the script following a tutorial, NPC throws SuperBalls way better but still it has a poor aiming at the player.

Here is the video of me dodging my enemy NPC just walking around:

What I want to achieve?
I want my Enemy NPC, to have an accurate aiming, so for player it would be hard to dodge my enemy NPC.

Here is the script of how it works:

local npc = script.Parent

function EnemyNear()
	local nearestPlr = nil
	local shortestDistance = 125

	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


	print("Nearest Player: ", nearestPlr)
	return nearestPlr
end



while task.wait(1) do
	
	local EnemyPos = EnemyNear()
	
	if EnemyPos then
		
		local StartPos = npc.Torso.BallSpawn.Position
		
		local Thrown = EnemyPos.Character.HumanoidRootPart.Position - StartPos
		local Duration = math.log(1.001 + Thrown.Magnitude * 0.008)
		
		StartPos = npc.Torso.BallSpawn.Position + npc.Torso.BallSpawn.AssemblyLinearVelocity * Duration
		Thrown = EnemyPos.Character.HumanoidRootPart.Position - StartPos

		local Force = Thrown / Duration + Vector3.new(0, workspace.Gravity * Duration * 0.5, 0)
		
		local SuperBallclone = game.ServerStorage["BALL!"]:Clone()
		SuperBallclone.Parent = workspace
		SuperBallclone.Position = StartPos
		SuperBallclone:ApplyImpulse(Force * SuperBallclone.AssemblyMass)
		SuperBallclone:SetNetworkOwner(nil)
		
	end
end

The script inside of NPC. The BallSpawn is a Part on the front of the NPC, as shown in the video, that spawns the SuperBalls. It’s inside of the Torso of the Enemy NPC.

Note that I am not a professional on luau.

Thank you for your time.

3 Likes

You can make that your thrower predicts where the player will go to able to throw the ball right.

You can use Humanoid.MoveDirection.Magnitude * Humanoid.RootPart.Velocity to get position to throw.

2 Likes

So Humanoid.MoveDirection/HumanoidRootPart.Velocity can automatically predict the player position?

3 Likes

You should have your NPC consider the movement of the target player and aim where the player would be based on how they are moving and the speed of your projectile.

Something like this function that takes startPos(position of your NPC), velocity (how fast the superball moves), and targetPlayer (Player they should aim at) and gives you the vector the NPC should aim to hit the player if they keep moving in the same direction. It’s still dodgeable but it should make it so the player has to change directions to dodge.
*Edit, this would give the initial vector for a flat firing projectile.

function getAimingVectorForTarget(startPos, velocity, targetPlayer)
	local enemySpeed = targetPlayer.Humanoid.WalkSpeed
	local enemyDir = targetPlayer.Humanmoid.CFrame.MoveDirection
	
	local enemyPos = targetPlayer.HumanoidRootPart.Position
	local enemyX = enemyPos.X
	local enemyZ = enemyPos.Z
	local enemyY = enemyPos.Y
	
	local a = (enemySpeed * enemyDir.X * 2) + 
		(enemySpeed * enemyDir.Z * 2) -
		(velocity^2)
	local b = 2 * ((enemyX * enemySpeed * enemyDir.X) + (enemyY * enemySpeed * enemyDir.Y) +(enemyZ * enemySpeed * enemyDir.Z) -
		(startPos.X * enemySpeed * enemyDir.X) - (startPos.Y * enemySpeed * enemyDir.Y) - (startPos.Z * enemySpeed * enemyDir.Z))
	local c = (enemyX^2) + (enemyY^2) + (enemyZ^2) + (startPos.X^2) + (startPos.Y^2) + (startPos.Z^2) - 
		(2 * startPos.X * enemyX) - (2 * startPos.Y * enemyY) - (2 * startPos.Z * enemyZ)
	
	local t1 = (-b + math.sqrt((b^2) - (4 * a * c))) / (2 * a)
	local t2 = (-b - math.sqrt((b^2) - (4 * a * c))) / (2 * a)
	
	local t = t1 > 0 and t1 < t2 and t1 or t2
	
	local v = Vector3.new(
		(enemyX - startPos.X + (t * enemySpeed * enemyDir.X)) / (t * velocity),
		(enemyY - startPos.Y + (t * enemySpeed * enemyDir.Y)) / (t * velocity),
		(enemyZ - startPos.Z + (t * enemySpeed * enemyDir.Z)) / (t * velocity)
	)
	
	return v
	
end
1 Like

What do I need to add to Velocity on the function? It gives me this error:
Workspace.Npc.CannonScript:14: attempt to perform arithmetic (pow) on Vector3 and number

When I add EnemyPos.Character.HumanoidRootPart.Velocity to Velocity section.

2 Likes

Velocity is would just be a number, the Units per second the superball moves.

1 Like

Works good, I put the number as 43, only issue is, when I move right and left very quickly it just misses the shot, and it does not shoot from up like the Y axis of the SuperBall was pretty normal until after this code the Y axis suddenly dropped.

1 Like

Ping will affect accuracy…

1 Like

Yeah, if the player is moving rapidly in different directions it’s still going to aim at where they were going when he fires. If you want to have them try and predict where the player will be if they change direction that is a different problem.

Hmm, the Y axis should be working, is it not aiming up/down?

1 Like

You might want to check this:
https://devforum.roblox.com/t/predict-projectile-ballistics-including-gravity-and-motion

1 Like

No I mean, watch the video, it throws the SuperBall slightly from up and SuperBall goes down by the Gravity. But after this script it does not goes up at first that much.

1 Like

Looks promising, how can I use it for my script? I am not that good at scripting. I do not know how to use module script in general.

1 Like

Check out the place file it already has demo

1 Like

Yes I see but, I don’t understand what to do? I copied ModuleScript, and then just stuck, how do I need to edit my script so I can just use the module script as it is?

1 Like

If you want to use that module script then I would start with reading through that Post. It does give a good example usage towards the bottom.
In general to use module scripts you have to require them. In this case it would be something

-- Usually you put your requires at the top of your scripts.
local AimModule = require(wherever.You.put.the.module.script)
...
-- and that post also has good descriptions of what the parameters mean.
local aimVector = AimModule.SolveTrajectory(startPos, velocity, targetPos, targetVelocity)

Thank you for help, but I rather script myself than using Module script. I research for many hours recently, can my NPC miss the shots might because of some delay, or can it be fixed by making SuperBall to be thrown at the direction that NPC is facing at?

Still should dissect that Module until you understand it fully.

I’ve been researching whole hours so right, I cannot read the module script. I am very tired. I am still working on making the SuperBall to shoot very accurately at the player. Only information I got is to divide distance between the ball speed:

FlightTime = distance / BallSpeed

And then:
Pedict = Enemy.Position + (Enemy.Velocity * FlightTime)

Then change thrown to:

Thrown = Predict - StartPos

But only thing I don’t like about this code is it’s very easily dodable. Player can quickly click A + D by quickly moving right-left to trick NPC to think that they straight up going to right or left and miss the shot completely.

I think you’re going about this the wrong way. Though it would be sweet to have them actually aim, implementing that isn’t going to be easy or very good. Most commercial games that I know of actually never miss. The code they write is more of a high percentage chance of a random miss. In your case you have a huge bullet that will give away the fact it’s guided. In this case I would have the NPC unload … 5 shells then a reload time. Use your math to “guess” a line of shell shots.

“I cannot read the module script” – This is why I said dissect it. Even if I didn’t use this, understanding what it’s doing would become a priority. Generic module scripts are an amazing way to program – embrace it.

Thanks man, I will try my best. I ain’t going to give up until I finish this. I am trying to create a game where you can spawn these types of NPC against players, inspired by Dummies vs Noobs game.

2 Likes