R6 Barrage Module: A simple module for barrages

So a few months ago I was curious about how fighting games like Your Bizzare Adventure achieved a good-looking barrage effect. Originally I had thought it was simple animation tricks, but if you’ve worked with animations on Roblox, you’d know that achieving the sort of hundreds of hands effect is not possible with animations alone. After a bit of research, I discovered bezier curves, and after experimenting with them a bit, I was able to achieve an effect I liked, that mimicked the effect you see in games like YBA:

And now I would like to share it, as I had a hard time figuring it out, and I have noticed quite a bit of people want to achieve this sort of effect. So here it is:

I’ve also created an Uncopylocked place with some added VFX that aren’t present in the model.

Using the module is incredibly simple:

local bm = require(script.BarrageModule)
local distance = 7 --How many studs in front of the player the barrage will reach
local speed = 20 --how slow you want the punch to go. The higher this number is, the slower the punch travels.
local rate =0.015 --delay between punches. uses task.wait() so the minimum value is 0.015
local armCopy = true -- whether or not you want the punches to copy the meshes of the arms. When set to false the arms will be the standard blocky ones.
bm.barragestart(char, distance, speed, rate, armCopy)

And when you want to end it:

bm.barragend(char)

Distance changes the distance of the barrage, and can lead to some entertaining results when set to higher numbers:

Speed is how long it takes for the punch to reach the end. Increasing this too high results in a ludicrous amount of punches:

Rate is the delay in seconds between each punch. Lowering it increases how many punches you have, and increasing it decreases how many punches you have:

And armCopy is whether or not you want the punches to copy the meshes of your arms. When set to true and your character has non blocky arms, it looks like this:

Now if you’re curious as to how it works, it simply just clones both of the player’s arms and makes them travel along 2 different randomized curves, until they reach the specified distance away from the player. It is just two loops that constantly repeat this process for each arm until barragend() is called. And since it clones the players arms, any VFX you put into the players arms will be copied onto the barrage as well.

Now there are a few caveats that should be considered:

  • This only works with R6, you could probably figure it out with R15 pretty easily though.

  • This was made more for educational purposes than efficiency or reliability, meaning that performance is not something I thought much of when making this, it was moreso for me to learn and I am now just sharing what I’ve learned.If you want to take what I’ve made here, and vastly improve upon it, then you are free to do so.

  • I made this at a time when I was still learning a lot of things scripting-wise, and I wrote it in about 3 hours. So if you’re a beginner looking at this wanting to learn, then maybe follow the concepts and not so much the actual code.

And that’s about it. See ya.

38 Likes

you a goat brooo appreciate it

4 Likes

Thank you so much for this module!

1 Like

This is a cool module, I have been trying to figure out how to make barrages for a long time, but I have a suggestion to give

I am using the Roblox Boy arms in my avatar

but It uses the blocky arms for the barrage effect

Is there any chance that custom arm support will come?

the pictures...

The pictures are taken on my @VSCPlays account, like how @bluebxrrybot uses pictures that are taken on his @avodey account

2 Likes

Well look what the cat dragged in! I am currently working on an anime fighting esc game and this would defiantly help with making the 64 attacks I have to make for a single character lol.
I probably wont use it exactly but Ill totally use it as a base and leave you some credit for the help!

E P I C

edit

does it deal damage by default? Just wanted to know if Ill have to change that

1 Like

No, this is purely visual. If you want it to do damage then you’ll have to add that separately

1 Like

Ok cool thanks for the info! I was using my own way of doing damage to begin with so its good!
Its super cool and cant wait to use it!

1 Like

I’ve updated the module to support non blocky arms. You can now use the copyArm parameter which copies the meshes of the arms.

2 Likes

Hey I stumbled upon this while lookin for barrage modules and the link doesnt work anymore.

Use this for now:
BarrageModule.rbxm (24.2 KB)
Not sure why but Roblox took down a few of my free models on the marketplace

thanks a bunch

postlimitpostlimit

It has been almost a year, but I’ll take my chances that some will reply.
So I have been currently working on a Jojo Game and I have encountered this bug regarding this module.

The barrage effect works completely as intended in server sided, (which is idiotic of me to do that initially) however when I decided to swap to client sided to handle the barrage effects, the visuals are bugged.

Bugged as in the arms are invisible.
I tried tweaking the speed, rates and etc but doesn’t seem like it did anything, the bug still persists.

Barrage handled by server:

Barrage handled by client:

You can see the arms are gone…

Client sided activation of module:

			local distance = 7
			local speed = 15
			local rate = 0.01 -- delay between punches
			
			
			--local damage = 0.3
			local Stand = player.Character:FindFirstChild("Stand_Model")
			barragemodule.barragestart(Stand, distance, speed, rate, true)

Cloned barrage model in workspace:

The “parts” are the decorative parts on the barraging arm. (The Star Platinum’s arm)

I was hoping and guessing streaming enabled would be the fix or somehow related but it wasn’t either.

I have no clue to what is causing this issue.
The module I used is the exactly same.

I did tweak a little but nothing to affect the barrage visual.

Just incase I’ll include it here too.

local module = {}

local function lerp(a, b, t)
	--a value is start position
	--b value is end position
	--t value is time

	return a + (b-a) * t

end





local ts = game:GetService("TweenService")


local function barrage(character,  distance, speed, rate, armCopy)
	task.spawn(function()

		local random = math.random(1,100)/100
		local xr = math.random(-6,0) + random
		local yr = math.random(-5,5) + random
		local zr = (distance * -1)/2
		local startpoint = character["Left Arm"].Position
		local dis = distance * -1
		local endpoint = character.HumanoidRootPart.CFrame * CFrame.new(xr/3,yr/3,dis)
		local endp = endpoint.Position
		local curvepoint  = character.HumanoidRootPart.CFrame * CFrame.new(xr,yr,zr)
		local curvep = curvepoint.Position


		local model = Instance.new("Model")
		model.Parent = workspace
		local hum = Instance.new("Humanoid")
		hum.Parent = model
		if character:FindFirstChild("Shirt") then
			local clothing = Instance.new("Shirt")
			clothing.ShirtTemplate = character.Shirt.ShirtTemplate
			clothing.Parent = model
		end



		local LeftArm = character["Left Arm"]:Clone()
		LeftArm.Name = "Left Arm"
		LeftArm.Parent = model
		LeftArm.Transparency = 1
		LeftArm.CanCollide = false
		LeftArm.Anchored = true
		LeftArm.Material = "SmoothPlastic"

		if armCopy then
			for i, v in pairs(character:GetChildren()) do
				if v:IsA("CharacterMesh") then
					if v.BodyPart == Enum.BodyPart.LeftArm then
						local mesh = v:Clone()
						mesh.Parent = model
					end
				end
			end			
		end


		local att1 = Instance.new("Attachment")
		att1.CFrame = CFrame.new(0,-0.45,0)
		local att2 = Instance.new("Attachment")
		att2.CFrame = CFrame.new(0,0.45,0)
		local trail = script.Trail:Clone()



		att1.Parent = LeftArm
		att2.Parent = LeftArm
		trail.Parent = LeftArm
		trail.Attachment1 = att1
		trail.Attachment0 = att2



		local trail2 = script.Trail2:Clone()


		trail2.Parent = LeftArm


		local att3 = Instance.new("Attachment")
		att3.CFrame = CFrame.new(0,-0.8,0)
		local att4 = Instance.new("Attachment")
		att4.CFrame = CFrame.new(0,0.8,0)
		att3.Parent = LeftArm
		att4.Parent = LeftArm
		trail2.Attachment1 = att3
		trail2.Attachment0 = att4

		ts:Create(LeftArm, TweenInfo.new(0.4), {Transparency = 0}):Play()


		game.Debris:AddItem(model, speed * 0.02)
		local i = 0
		local t = i/speed
		local l1 = lerp(startpoint, curvep, t)
		local l2 = lerp(curvep, endp, t)
		local last = lerp(l1,l2,t)



		for i = 0, speed, 1 do
			local t = i/speed

			local l1 = lerp(startpoint, curvep, t)
			local l2 = lerp(curvep, endp, t)

			--lerp1.Position = l1
			--lerp2.Position = l2


			local quad = lerp(l1,l2,t)



			LeftArm.CFrame = CFrame.lookAt(quad, last) * CFrame.Angles(math.rad(-90),90,0)
			task.wait(0.0001)

			last = quad


			if LeftArm.Position == endp then

				local biggersize = Vector3.new(1.196, 0.053, 1.196)
				local ring = script.PUNCHRING:Clone()
				ring.Transparency = 1
				ring.Parent = character
				ring.CanCollide = false
				ring.Anchored = true
				--ts:Create(ring, TweenInfo.new(0.1), {Transparency = 0.4}):Play()
				ts:Create(ring, TweenInfo.new(0.1), {Size = biggersize}):Play()
				ring.CFrame = LeftArm.CFrame
				ring.CFrame = endpoint * CFrame.new(0,0,-1.5) * CFrame.Angles(math.rad(90),90,0)
				game.Debris:AddItem(ring, 0.3) 


				for i, particle in pairs(script.hit:GetChildren()) do
					local clone = particle:Clone()
					clone.Parent = ring
					clone:Emit(clone:GetAttribute("EmitCount"))
					game.Debris:AddItem(clone, 1)
				end
			end

		end
	end)
	task.wait(rate)
	task.spawn(function()

		local random = math.random(1,100)/100
		local xr = math.random(0,6) + random
		local yr = math.random(-5,5) + random
		local zr = (distance * -1)/2
		local startpoint = character["Right Arm"].Position
		local dis = distance * -1
		local endpoint = character.HumanoidRootPart.CFrame * CFrame.new(xr/3,yr/3,dis)
		local endp = endpoint.Position
		local curvepoint  = character.HumanoidRootPart.CFrame * CFrame.new(xr,yr,zr)
		local curvep = curvepoint.Position


		local model = Instance.new("Model")
		model.Parent = workspace
		local hum = Instance.new("Humanoid")
		hum.Parent = model
		if character:FindFirstChild("Shirt") then
			local clothing = Instance.new("Shirt")
			clothing.ShirtTemplate = character.Shirt.ShirtTemplate
			clothing.Parent = model
		end



		local RightArm = character["Right Arm"]:Clone()
		RightArm.Name = "Right Arm"
		RightArm.Parent = model
		RightArm.Transparency = 1
		RightArm.CanCollide = false
		RightArm.Anchored = true
		RightArm.Material = "SmoothPlastic"

		if armCopy then
			for i, v in pairs(character:GetChildren()) do
				if v:IsA("CharacterMesh") then
					if v.BodyPart == Enum.BodyPart.RightArm then
						local mesh = v:Clone()
						mesh.Parent = model
					end
				end
			end			
		end

		local att1 = Instance.new("Attachment")
		att1.CFrame = CFrame.new(0,-0.45,0)
		local att2 = Instance.new("Attachment")
		att2.CFrame = CFrame.new(0,0.45,0)
		local trail = script.Trail:Clone()



		att1.Parent = RightArm
		att2.Parent = RightArm
		trail.Parent = RightArm
		trail.Attachment1 = att1
		trail.Attachment0 = att2



		local trail2 = script.Trail2:Clone()



		trail2.Parent = RightArm


		local att3 = Instance.new("Attachment")
		att3.CFrame = CFrame.new(0,-0.8,0)
		local att4 = Instance.new("Attachment")
		att4.CFrame = CFrame.new(0,0.8,0)
		att3.Parent = RightArm
		att4.Parent = RightArm
		trail2.Attachment1 = att3
		trail2.Attachment0 = att4

		ts:Create(RightArm, TweenInfo.new(0.4), {Transparency = 0}):Play()


		game.Debris:AddItem(model, speed * 0.02)--speed * 0.02
		local i = 0
		local t = i/speed
		local l1 = lerp(startpoint, curvep, t)
		local l2 = lerp(curvep, endp, t)
		local last = lerp(l1,l2,t)



		for i = 0, speed, 1 do
			local t = i/speed

			local l1 = lerp(startpoint, curvep, t)
			local l2 = lerp(curvep, endp, t)

			--lerp1.Position = l1
			--lerp2.Position = l2


			local quad = lerp(l1,l2,t)



			RightArm.CFrame = CFrame.lookAt(quad, last) * CFrame.Angles(math.rad(-90),-90,0)
			task.wait(0.0001)

			last = quad


			if RightArm.Position == endp then

				local biggersize = Vector3.new(1.196, 0.053, 1.196)
				local ring = script.PUNCHRING:Clone()
				ring.Transparency = 1
				ring.Parent = character
				ring.CanCollide = false
				ring.Anchored = true
				--ts:Create(ring, TweenInfo.new(0.1), {Transparency = 0.4}):Play()
				ts:Create(ring, TweenInfo.new(0.1), {Size = biggersize}):Play()
				ring.CFrame = RightArm.CFrame
				ring.CFrame = endpoint * CFrame.new(0,0,-1.5) * CFrame.Angles(math.rad(90),90,0)
				game.Debris:AddItem(ring, 0.3) 


				for i, particle in pairs(script.hit:GetChildren()) do
					local clone = particle:Clone()
					clone.Parent = ring
					clone:Emit(clone:GetAttribute("EmitCount"))
					game.Debris:AddItem(clone, 1)
				end
			end

		end
	end)
end







 function module.barragestart(char, distance, speed, rate, armCopy)
		
	if char:FindFirstChild("Pilot_Stand_Indicator_Bool") and char:FindFirstChild("Pilot_Stand_Indicator_Bool"):IsA("StringValue") then
		
		
		if char:FindFirstChild("Status_Folder"):FindFirstChild("Stunned_BoolValue").Value == true then return end
		if char then
			if char:FindFirstChild("InBarrage") == nil then
				local check = Instance.new("IntValue")
				check.Parent = char
				check.Name = "InBarrage"

				local light = Instance.new("PointLight")
				light.Parent = char.HumanoidRootPart
				light.Name = "BarrageLight"
				light.Color = Color3.fromRGB(255,255,255)
				light.Range = 8
				light.Brightness = 4

				char["Left Arm"].Transparency = 0
				char["Right Arm"].Transparency = 0




				local ATT = Instance.new("Attachment")
				ATT.Name = "BarrageAttachment"
				ATT.Parent = char.HumanoidRootPart
				local dis = distance * -1

				ATT.Position = Vector3.new(0,0,dis)
				local smoke = script.HeavySmoke3:Clone()
				smoke.Parent = ATT
				smoke.Enabled = true

				repeat
					barrage(char,  distance, speed, rate, armCopy)

					task.wait(rate)
				until char:FindFirstChild("InBarrage") == nil

				--track:Stop()

			end
		end

		
	else

		if char.Parent:FindFirstChild("Status_Folder") and char.Parent:FindFirstChild("Status_Folder"):FindFirstChild("Stunned_BoolValue") then
			if char.Parent:FindFirstChild("Status_Folder"):FindFirstChild("Stunned_BoolValue").Value == true then return end
			if char then
				if char:FindFirstChild("InBarrage") == nil then
					local check = Instance.new("IntValue")
					check.Parent = char
					check.Name = "InBarrage"

					local light = Instance.new("PointLight")
					light.Parent = char.HumanoidRootPart
					light.Name = "BarrageLight"
					light.Color = Color3.fromRGB(255,255,255)
					light.Range = 8
					light.Brightness = 4

					char["Left Arm"].Transparency = 0
					char["Right Arm"].Transparency = 0




					local ATT = Instance.new("Attachment")
					ATT.Name = "BarrageAttachment"
					ATT.Parent = char.HumanoidRootPart
					local dis = distance * -1

					ATT.Position = Vector3.new(0,0,dis)
					local smoke = script.HeavySmoke3:Clone()
					smoke.Parent = ATT
					smoke.Enabled = true

					repeat


						barrage(char,  distance, speed, rate, armCopy)



						
						task.wait(rate)
					until char:FindFirstChild("InBarrage") == nil or char == nil



				end
			end
		end
		
	end
		--player.Character:FindFirstChild("Pilot_Stand_Indicator_Bool") and player.Character:FindFirstChild("Pilot_Stand_Indicator_Bool"):IsA("StringValue") then

end


function module.barragend(char)
	if char:FindFirstChild("InBarrage") then
	  char.InBarrage:Destroy()
	end
	
	

								
								
	if char.HumanoidRootPart:FindFirstChild("BarrageLight") then
		char.HumanoidRootPart.BarrageLight:Destroy()
	end
	if char.HumanoidRootPart:FindFirstChild("BarrageAttachment") then
		char.HumanoidRootPart.BarrageAttachment:Destroy()
	end
	
	
	char["Left Arm"].Transparency = 0
	char["Right Arm"].Transparency = 0
end

return module

Any help would be great, thank you! :happy1:

EDIT:
I FOUND OUT THE ISSUE THAT IS CAUSING THIS.
I tried removing the humanoid that is created in the model of the barraging arms. This fixed the visuals instantly.

2 Likes