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.
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
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.
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.
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?
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.
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?
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?
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.