Bone Style Attacks

Hello fellow developers!
I created a few attacks that are directly taken from an Undertale character called sans.
These scripts work perfectly fine and don’t have any issues when I use them, but I feel that something could make it better. So I would like your feedback on my creations.

(these are activated by tools if you didn’t know + don’t do damage yet)

Bonezone Event (Server Sided):

local RS = game:GetService("ReplicatedStorage")
local SS = game:GetService("ServerStorage")
local TS = game:GetService("TweenService")
local Debris = game:GetService("Debris")

local bonezoneEvent = RS:WaitForChild("Bonezone1")

local bonezone = SS:WaitForChild("Bonezone1")

local function tween(primary, position)
	local t = TS:Create(primary, TweenInfo.new(.05, Enum.EasingStyle.Linear, Enum.EasingDirection.In), {CFrame = position})
	t:Play()
end

bonezoneEvent.OnServerEvent:Connect(function(player, position)
	local newBonezone = bonezone:Clone()
	
	local warning = newBonezone.Warning
	local summon = newBonezone.Summon
	
	local bonePrimary = newBonezone.Bones.Primary
	local redPrimary = newBonezone.Red.Primary
	redPrimary.CFrame = CFrame.new(position.Position)
	bonePrimary.CFrame = CFrame.new(redPrimary.CFrame.X, redPrimary.CFrame.Y - 1.97, redPrimary.CFrame.Z)

	newBonezone.Parent = workspace
	
	warning:Play()
	
	Debris:AddItem(newBonezone, 2.35)
	
	task.wait(.55)
	
	tween(bonePrimary, CFrame.new(redPrimary.CFrame.X, redPrimary.CFrame.Y + .924, redPrimary.CFrame.Z))
	summon:Play()
	
	task.wait(1.75)
	
	tween(bonePrimary, CFrame.new(redPrimary.CFrame.X, redPrimary.CFrame.Y - 1.97, redPrimary.CFrame.Z))
	
	summon:Play()
end)

Bonewall Event (Server Sided):

local RS = game:GetService("ReplicatedStorage")
local SS = game:GetService("ServerStorage")
local TS = game:GetService("TweenService")
local Debris = game:GetService("Debris")

local bonewallEvent = RS:WaitForChild("Bonewall1")

local bonewall = SS:WaitForChild("Bonewall1")

local function tween(primary, position, length)
	local t = TS:Create(primary, TweenInfo.new(length or .05, Enum.EasingStyle.Linear, Enum.EasingDirection.In), {CFrame = position})
	t:Play();
end

local function raycast(root)
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Whitelist
	raycastParams.FilterDescendantsInstances = {root.Parent}
	
	local raycastResult = workspace:Raycast(root.Position, (root.Position - Vector3.new(0, 100, 0)), raycastParams)
	
	return raycastResult
end

bonewallEvent.OnServerEvent:Connect(function(player)
	local character = player.Character
	
	local newBonewall = bonewall:Clone()
	newBonewall.Parent = workspace
	
	local summon = newBonewall.Summon
	
	local bonePrimary = newBonewall.Bones.Primary
	local primary = newBonewall.Primary
	
	local result = raycast(character.HumanoidRootPart)
	primary.Position = Vector3.new(character.HumanoidRootPart.CFrame.X, character.HumanoidRootPart.CFrame.Y - 3, character.HumanoidRootPart.CFrame.Z) + character.HumanoidRootPart.CFrame.LookVector * 5
	local x,y,z = character.HumanoidRootPart.CFrame:ToEulerAnglesXYZ()
	bonePrimary.CFrame = CFrame.new(primary.CFrame.X, primary.CFrame.Y - 1.9, primary.CFrame.Z) * CFrame.Angles(x, y, z)
	
	summon:Play()
	
	Debris:AddItem(newBonewall, 2.4)
	
	tween(bonePrimary, CFrame.new(primary.CFrame.X, primary.CFrame.Y + 1, primary.CFrame.Z) * CFrame.Angles(x, y, z), .1)
	
	task.wait(.2)
	
	tween(bonePrimary, CFrame.new(bonePrimary.CFrame.Position + character.HumanoidRootPart.CFrame.LookVector * 75) * CFrame.Angles(x, y, z), 2)
	
	task.wait(2)
	
	tween(bonePrimary, CFrame.new(bonePrimary.CFrame.X, primary.CFrame.Y - 1.9, bonePrimary.CFrame.Z) * CFrame.Angles(x, y, z), .1)
	
	workspace.Summon:Play()
end)

Force Event (Server Sided):

local RS = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local Debris = game:GetService("Debris")

local forceEvent = RS:WaitForChild("Force1")

forceEvent.OnServerEvent:Connect(function(player)
	workspace.Force:Play()
	
	for i,v in pairs(Players:GetChildren()) do
		if v.UserId ~= player.UserId then
			local root = v.Character.HumanoidRootPart
			
			local bodyVelocity = Instance.new("BodyVelocity")
			bodyVelocity.Velocity = root.CFrame.LookVector * -50
			bodyVelocity.MaxForce = Vector3.new(math.huge, 0, math.huge)
			bodyVelocity.Parent = root
			
			Debris:AddItem(bodyVelocity, .75)
		end
	end
end)

Footage of attacks:

5 Likes

The attacks look great! I think something that could make it better would be animations, other than that it looks awesome

I’ve always wanted to make something like this.

But I just want the best way to go about it.

One thing I recommend is to make it a little less server sided.

One thing I would recommend adding a debounce on the serverside, so exploiters cannot fire the remote events several times and do several attacks.

1 Like

No idea on how to code but that looks AMAZING and great job with the SFX!

Why would this be necessary in this regard?

Hey! I don’t suggest tweening on the server as it’s pretty performance heavy - Tween on the server or client?

Also, by keeping a reference to tweens means theyll never be GC’d

In your case, you don’t need to use .Finished on the tween so just do this

TS:Create(primary, TweenInfo.new(.05, Enum.EasingStyle.Linear, Enum.EasingDirection.In), {CFrame = position}):Play()

The tween will automatically be GC’d after playing this way.

If in the future you do need to keep a reference to the tween, call :Destroy() on the tween after to remove it.

t:Destroy()

baseparts explains that doing anything, like tweens on the server, is performance heavy.