How to make a projectile that shoots vertically and inclines down onto the ground

I am making a boss fight attack with a giant squid that shoots a ink ball onto the island that you are on. How would I make a projectile that shoots smoothly onto the island from where the boss is, he is right next to the island. Then it will leave a ink splatter.

I mainly want to know how to do the first part, I probably will be able to make the ink pool.

2 Likes

if the boss is stationary then you can just tween the ‘ink ball’ and then add a separate block of code that waits for it to land and then run all your fx & damage stuff

1 Like

It moves around the island, but how would I use tween service to make it look like its falling without getting something awkward?

1 Like

if you want to make it visually pleasing you’ll probably need to use Bezier curves which I have no experience in. But, you can get the position of the giant squid and then the position of the destination and then tween a ball between that (this would give you a linear animation). You’d need to do the hitbox, damage service, and effects separately, though.

local run = game:GetService("RunService")
local function MoveBall(part, from, to)
	local mid = Vector3.new(to.X,from.Y,to.Z)
	local l0, l1 = nil, nil
	local t = 0
	repeat t += run.Heartbeat:Wait()
		l0 = from:Lerp(mid,t)
		l1 = mid:Lerp(to,t)
		part.Position = l0:Lerp(l1,t)
	until t > 1
	-- The part hit the target
end

Pass the part to move, the starting position (from) and the target (to). Both from and to should be a Vector3, the part should be the part.

@chunchbunch bezier curves are simple but very useful when making curves. All you have to do is Lerp all points to the next point, Then lerp those values.

P0 lerp P1 = L0
P1 lerp P2 = L1
L0 lerp L1 = Final position

P0 and P2 is the start and end points, while P1 is the midpoint which is quite hard to find. L0 and L1 is the result of the lerps, and Final position is the result of L0 and L1 lerp.

You will put this in a loop that increases time and ranges from 0 - 1. You will use this “time” for the lerp alpha.

Sorry, I’m not very advanced in scripting. How would I pass from and to as a vector3? Also where would I put that other script taht involves the lerps, it seems like the first script would do it and where would I put it? I just don’t know what to do.

I answered someone’s question. It was not about you or the script.

At the top of the script.

For passing the to, you can pass the Character’s HumanoidRootPart Position. The from depends on where the ball is being shot at. You will use .Position to get the part’s position.

How would I find a random players humanoidrootpart position? Would I use a for loop to loop through the characters and select a random one?

When finding a random target, you will take all players.

local players = game.Players:GetPlayers()

Then pick a random player

local players = game.Players:GetPlayers()
local target = players[math.random(1,#players)]

Then get their character, and their HumanoidRootPart

local char = target.Character
local hrp = char:FindFirstChild("HumanoidRootPart")

But since the character or hrp (HumanoidRootPart) can sometimes be nil, we have to check first before using it

local players = game.Players:GetPlayers()
local target = players[math.random(1,#players)]
local char = target.Character
local hrp = nil
if char then
	hrp = char:FindFirstChild("HumanoidRootPart")
end

Now, we can use that for the MoveBall.

We will use .Position to get the position of a part

local to = hrp.Position

Tell me if you dont know how to get from.

For from, I just did part.Position. When I use that, for some reason it says that the interval for math.random is empty. I did exactly what you said.
This is what my script looks like now:

local run = game:GetService("RunService")
local players = game.Players:GetPlayers()
local function MoveBall(part, from, to)
	local target = players[math.random(1,#players)]
	part = script.Parent
	from = script.Parent.Position
	local char = target.Character
	local hrp = nil
	if char then
		hrp = char:FindFirstChild("HumanoidRootPart")
	end
	to = hrp.Position
	local mid = Vector3.new(to.X,from.Y,to.Z)
	local l0, l1 = nil, nil
	local t = 0
	repeat t += run.Heartbeat:Wait()
		print("Ran")
		l0 = from:Lerp(mid,t)
		l1 = mid:Lerp(to,t)
		part.Position = l0:Lerp(l1,t)
	until t > 1
	
end

MoveBall()

You will put this

inside the MoveBall function not outside.

local function MoveBall(part, from, to)
	local players = game.Players:GetPlayers()
	local target = players[math.random(1,#players)]

I did what you said, but it still said this, Workspace.Part.Script:4: invalid argument #2 to ‘random’ (interval is empty)

Can you print players and tell me what appears in the output

local function MoveBall(part, from, to)
	local players = game.Players:GetPlayers()
	print(players)
	local target = players[math.random(1,#players)]

It prints this: table: 0x44bfeade085951c5 its just printing the table of players.

Oh, in the output, there is an option there. Click it and turn on Log mode

Why would that change what it says? It didn’t change it. Still prints table: 0x44bfeade085951c5.

I meant turn off. Look at this

With log mode:

Without log mode:

Actually you know what, just print the number of players

print(#players)

Oh sorry, it just wasn’t loading the players, I just needed to add a wait function. Now it doesnt know what the postion of the hrp is. It is saying index nill with position. I printed it, and the hrp is nill.

Can you replcae this

with this

local char = target.Character or target.CharacterAdded:Wait()

and this

with this

hrp = char:WaitForChild("HumanoidRootPart")

Never mind, everything is good. Just one thing, how would I make the splatter be on the ground? Would I change the position of it under the untill statement?