The making of a basic skill (Bleach Flashstep)

This will be a tutorial on how to making a decent flashstep skill from the anime Bleach. Detecting activation button, making the player invisible, changing the walkspeed, server debounce, and applying a VFX to the player’s position.

Step 1 (Making the local script, Detecting the activation button, Firing Event)

I’ll be using ContextActionService opposed to UserInputService because it makes it so the button can’t be used for anything else unless it’s unbinded.

Place a localscript in StarterPlayer under StarterCharacterScripts. Name the script whatever suits you it doesn’t really matter.

Let’s get the local player (the user/you)

local plr = game:GetService("Players").LocalPlayer

You can also do

local plr = game.Players.LocalPlayer

We also want to get the character, but you might run into a bug where you click the skill button as you’re loading in, and you’ll get an error after. So we can fix this issue by waiting for the character busing a wait.

local char = plr.Character or plr.CharacterAdded:Wait() -- if no player it waits

Now let’s get the ContextActionService which is our button activation method.

local CAS = game:GetService("ContextActionService")

Here is the setup for ContextActionService

CAS:BindAction("Put the name you want", the function to run, Mobile Button?, Activation Key)
local plr = game:GetService("Players").LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local hum = char.Humanoid

local CAS = game:GetService("ContextActionService")

local FlashFunction = function(Name, State)
	if Name == "Flashstep" and State == Enum.UserInputState.Begin then
		
	end	
end

CAS:BindAction("Flashstep", FlashFunction, false, Enum.KeyCode.Q)

Alright now make a remote event in ReplicatedStorage. In my case I placed it in a folder called Remotes (Don’t worry about Replicate for now, but you can add it for later).
image

Next we get the service and make a variable for the remote so we can fire it. We’re gonna fire the remote event with a argument/param called “Trigger” (You can name it whatever but stick with me).

local plr = game:GetService("Players").LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local hum = char.Humanoid

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Flashstep = ReplicatedStorage.Remotes.Flashstep

local CAS = game:GetService("ContextActionService")

local FlashFunction = function(Name, State)
	if Name == "Flashstep" and State == Enum.UserInputState.Begin then
		Flashstep:FireServer("Trigger")
	end	
end

CAS:BindAction("Flashstep", FlashFunction, false, Enum.KeyCode.Q)
Step 2 (Making a Server Script, Adding exploit checks, Server Debounce, etc)

Let’s get ReplicatedStorage and the Remote Event

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Flashstep = ReplicatedStorage.Remotes.Flashstep

Connect the Remote Event so we can run our code. The first param is required to be the player, you can name it whatever but just know the first param is player.

Flashstep.OnServerEvent:Connect(function(plr, arg)

end)

Next is exploit checks. If the first param is not a Instance (Player or Object) don’t run the script, if the second param is not a string (“Trigger” or whatever you named it) don’t run the script.

Flashstep.OnServerEvent:Connect(function(plr, arg)
	if typeof(plr) ~= "Instance"or typeof(arg) ~= "string" then return end
end)

We’ll add a debounce table so we can store the player for cooldowns. If they’re in the table don’t run the rest of the script, otherwise place them in the table and continue.

local FlashstepDebounce = {}

Flashstep.OnServerEvent:Connect(function(plr, arg)
	if typeof(plr) ~= "Instance"or typeof(arg) ~= "string" then return end
	
	if table.find(FlashstepDebounce, plr.Name) ~= nil then return end
	table.insert(FlashstepDebounce, plr.Name)
end)

Next, we’ll check if the second param is our “Trigger”, add a integer variable for our active ability time, grab the humanoid, change the walkspeed, and remove the players from the table.

Flashstep.OnServerEvent:Connect(function(plr, arg)
	if typeof(plr) ~= "Instance"or typeof(arg) ~= "string" then return end
	
	if table.find(FlashstepDebounce, plr.Name) ~= nil then return end
	table.insert(FlashstepDebounce, plr.Name)

        local activetime = 2

	if arg == "Trigger" then
		local char = plr.Character or plr.CharacterAdded:Wait()
		local hum = char.Humanoid

		hum.WalkSpeed = 50
		task.wait(activetime)
		hum.WalkSpeed = 16
		
	end
	
	task.wait(2)
	FlashstepDebounce[table.find(FlashstepDebounce, plr.Name)] = nil -- table[find player] = nil
end)

We made the player faster but in the anime the character goes invisible to show speed. Let’s make a function that makes them invisble.

The first param is just to tell the function if we want to run the Started portion or Ended portion. Character has to be in here so we can get the players character. We’re also going to loop through the players character for any BaseParts (Legs, Arms, etc), Decals, along with accessories (we make the handle transparent). When we run the ended portion make sure that we don’t make the HumanoidRootPart visible.

local function Invisible(arg,char)
	if arg == "Started" then
		for _, v in char:GetDescendants() do
			if v:IsA("BasePart") or v:IsA("Decal") then
				v.Transparency = 1
			elseif v:IsA("Accessory") then
				v:FindFirstChild("Handle").Transparency = 1
			end
		end
	elseif arg == "Ended" then
		for _, v in char:GetDescendants() do
			if (v:IsA("BasePart") or v:IsA("Decal")) and v.Name ~= "HumanoidRootPart" then
				v.Transparency = 0
			elseif v:IsA("Accessory") then
				v:FindFirstChild("Handle").Transparency = 0
			end
		end
	end
end

Insert the function into our OnServerEvent.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Flashstep = ReplicatedStorage.Remotes.Flashstep
local Replicate = ReplicatedStorage.Remotes.Replicate

local FlashstepDebounce = {}

local function Invisible(arg,char)
	if arg == "Started" then
		for _, v in char:GetDescendants() do
			if v:IsA("BasePart") or v:IsA("Decal") then
				v.Transparency = 1
			elseif v:IsA("Accessory") then
				v:FindFirstChild("Handle").Transparency = 1
			end
		end
	elseif arg == "Ended" then
		for _, v in char:GetDescendants() do
			if (v:IsA("BasePart") or v:IsA("Decal")) and v.Name ~= "HumanoidRootPart" then
				v.Transparency = 0
			elseif v:IsA("Accessory") then
				v:FindFirstChild("Handle").Transparency = 0
			end
		end
	end
end

Flashstep.OnServerEvent:Connect(function(plr, arg)
	if typeof(plr) ~= "Instance"or typeof(arg) ~= "string" then return end
	
	if table.find(FlashstepDebounce, plr.Name) ~= nil then return end
	table.insert(FlashstepDebounce, plr.Name)
	
	local activetime = 2
	
	if arg == "Trigger" then
		local char = plr.Character or plr.CharacterAdded:Wait()
		local hum = char.Humanoid
		
		Invisible("Started",char)
		hum.WalkSpeed = 50

		task.wait(activetime)

		Invisible("Ended",char)
		hum.WalkSpeed = 16
		
	end
	
	task.wait(2)
	FlashstepDebounce[table.find(FlashstepDebounce, plr.Name)] = nil
	print(FlashstepDebounce)
end)
Step 3 (Replicating the effects)

For this you’ll have to get effects. I took mine from the roblox toolbox and modified it a bit.

Now the scripting section; Add a Remote in ReplicatedStorage called whatever but I named it Replicated. Make a local script in StarterCharacterScripts name it whatever. Lastly, add your VFX in ReplicatedStorage I placed mine in a folder.

We’re going to connect the Remote to a OnClientEvent, a function that runs when the server tells it to.

local Replicate = ReplicatedStorage.Remotes.Replicate

Replicate.OnClientEvent:Connect(function(arg, pos)
	
end)

Check if the arg is “Flashstep” (we’re checking the args because maybe we want to add more VFXs’ later on).

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Replicate = ReplicatedStorage.Remotes.Replicate

Replicate.OnClientEvent:Connect(function(arg, pos)
	if arg == "Flashstep" then
	
	end
end)

Make a variable to get the VFX, clone it, set it’s position to the second argument, parent it to workspace, emit it, and destroy it using a delay. (Don’t using CFrame to set it, messes it up).

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Replicate = ReplicatedStorage.Remotes.Replicate
local FlashStepVFX = ReplicatedStorage.Assets.Effects.FlashstepVFX


Replicate.OnClientEvent:Connect(function(arg, pos)
	if arg == "Flashstep" then
		local FlashClone = FlashStepVFX:Clone()
		FlashClone.Position = pos
		FlashClone.Parent = game.Workspace.Effects
		
		for _,v in FlashClone:GetChildren() do
			v:Emit(v.Rate)
		end
		
		task.delay(2.5, function()
			FlashClone:Destroy()
		end)
	end
end)

Now we can go back to the server script and Fire to all clients. I’m going to fire it 7 times so it can appear at our location 7 times using a for loop. Our position is going to be the character’s HumanoidRootPart position.

if arg == "Trigger" then
		local char = plr.Character or plr.CharacterAdded:Wait()
		local hum = char.Humanoid
		
		Invisible("Started",char)
		
		task.spawn(function()
			for i = 1,7 do
				Replicate:FireAllClients("Flashstep", char.HumanoidRootPart.Position)
				task.wait(0.3)
			end
		end)

		hum.WalkSpeed = 50
		task.wait(activetime)
		Invisible("Ended",char)
		hum.WalkSpeed = 16
		
	end

That should be it…

Mb if I didn’t explain anything good enough.

4 Likes

You should use better naming conventions “CAS” isn’t very ideal and could be shortened to ActionService aswell as hum, char and plr.

2 Likes

I’ll keep that in mind, did it make the tutorial harder to follow through with? :sweat:

naming conventions like those will affect readability yes.