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.
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.
So Humanoid.MoveDirection/HumanoidRootPart.Velocity can automatically predict the player position?
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.
Velocity is would just be a number, the Units per second the superball moves.
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.
Ping will affect accuracy…
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?
You might want to check this:
https://devforum.roblox.com/t/predict-projectile-ballistics-including-gravity-and-motion
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.
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.
Check out the place file it already has demo
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?
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.
So little bit dinging on Module script, I finally did it!
Of course, it’s still can be dodged by jumping around, but it became much harder to dodge from.
Thank you for help and other people to!
If any other people has the same issue as mine with the aim accuracy of a NPC, here is my final script to check how it works using this module script → https://devforum.roblox.com/t/predict-projectile-ballistics-including-gravity-and-motion
My Final Script:
local animator = npc.Humanoid.Animator
local animation = animator.BALLTHROW
local loadAnim = animator:LoadAnimation(animation)
local isAnimPlay = false
local npcHum = npc:WaitForChild("Humanoid")
local CalTrejectory = require(script.CalculateTrajectory)
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
return nearestPlr
end
function throw()
local EnemyPos = EnemyNear()
if EnemyPos then
local StartPos = npc.Torso.BallSpawn.Position
local Root = EnemyPos.Character.HumanoidRootPart
local BallSpeed = 178.00707
local pickLongest = false
local G = workspace.Gravity
local aimAt = CalTrejectory.SolveTrajectory(
StartPos,
BallSpeed,
Root.Position,
Root.AssemblyLinearVelocity,
pickLongest,
G
) or (StartPos + npc.Torso.BallSpawn.CFrame.LookVector * 10)
if aimAt then
local SuperBallclone = game.ServerStorage["BALL!"]:Clone()
--local Force = Thrown / Duration + Vector3.new(0, workspace.Gravity * Duration * 0.5, 0)
SuperBallclone.Parent = workspace
SuperBallclone.Position = StartPos
SuperBallclone:ApplyImpulse((aimAt - StartPos).Unit * BallSpeed * SuperBallclone.AssemblyMass)
SuperBallclone:SetNetworkOwner(nil)
local onceHit = false
SuperBallclone.Touched:Connect(function(hit, hum)
local hitHum = hit.Parent:FindFirstChild("Humanoid")
if hitHum and hitHum ~= npcHum and not onceHit then
hitHum:TakeDamage(11.00707)
onceHit = true
task.wait(1)
onceHit = false
end
end)
end
end
end
while task.wait(math.random(0.1, 2.00707)) do
if EnemyNear() then
loadAnim:Play()
end
wait(0.4700707)
throw()
wait(1)
end
I spend more than 20 days just to research and script to make my NPC throw projectile as accurate as possible. Some laggy players may struggle on this NPC.
Explanation:
First you need to put the Module script on the your main Projectile script and write
local CalTrejectory = require(script.CalculateTrajectory)
in your main projectile script to get Module script work.
Then just create a variable and insert the function from module script like this
local aimAt = CalTrejectory.SolveTrajectory()
SolveTrajectory is the function from module script.
And then, the only thing you need to put inside of this function:
The start position which I wrote first
StartPos,
And then the speed of your projectile, it can be any number by your choice.
BallSpeed
Then the position you want your projectile to go which I put:
Root.Position
→ player’s HumanoidRootPart position
Then the velocity of the target
Root.AssemblyLinearVelocity
Then the pickLongest, I actually do not know what does it do, I just read the module script and saw it’s a boolean, I just write it as false
and then put the gravity which I put as:
G
Which is local G = workspace.Gravity
After these steps, I wrote ApplyImpluse
calculation aim with start pos, multiplying to speed of ball, and it’s mass which is the law from physics, I don’t remember the name
SuperBallclone:ApplyImpulse((aimAt - StartPos).Unit * BallSpeed * SuperBallclone.AssemblyMass)
Now you’re good to go!