Spells Power, Movement & Damage

Hey,

I’m mading spells power for one of my game project, and i got a problem with tween position and damages.

  • When i’m using Tween Service, the MeshPart need to be anchored, when i move the spell forward the character, it work and the movement is smooth but it do no damage, i don’t understand why.

  • When i’m using BodyVelocity, the MeshPart isn’t anchored, Damages work but spell movement isn’t smooth, it’s a bit laggy.

So here i want to keep a smooth movement for my spell, but fix this damage problem


TweenService

BodyVelocity


Here is the main script [Tween Service]:

local Module = {}

Module.QSpell = function(Player)
	local Character = Player.Character
	local Slash = game.ReplicatedStorage.Spells.Knight.Slash
	if Character ~= nil and Slash ~= nil then
		local TweenService = game:GetService("TweenService")
		local TweenInfos = TweenInfo.new(1)
		
		local Clone1 = Slash:Clone()
		local Clone2 = Slash:Clone()
		local Clone3 = Slash:Clone()
		
		Clone1.Touched:Connect(function(Part)
			if Part.Parent:FindFirstChild("Humanoid")and not game.Players:FindFirstChild(Part.Parent.Name)then
				Part.Parent.Humanoid:TakeDamage(15)
				Clone1:Destroy()
			end
		end)
		Clone2.Touched:Connect(function(Part)
			if Part.Parent:FindFirstChild("Humanoid")and not game.Players:FindFirstChild(Part.Parent.Name)then
				Part.Parent.Humanoid:TakeDamage(15)
				Clone2:Destroy()
			end
		end)
		Clone3.Touched:Connect(function(Part)
			if Part.Parent:FindFirstChild("Humanoid")and not game.Players:FindFirstChild(Part.Parent.Name)then
				Part.Parent.Humanoid:TakeDamage(15)
				Clone3:Destroy()
			end
		end)
		
		Clone1.Parent = game.Workspace
		Clone1.CFrame = Character.Torso.CFrame
		
		local Goal1 = {}
		Goal1.CFrame = Clone1.End.CFrame

		local Tween1 = TweenService:Create(Clone1, TweenInfos, Goal1)
		Tween1:Play()
		
		wait(0.2)
		
		Clone2.Parent = game.Workspace
		Clone2.CFrame = Character.Torso.CFrame
		
		local Goal2 = {}
		Goal2.CFrame = Clone2.End.CFrame

		local Tween2 = TweenService:Create(Clone2, TweenInfos, Goal2)
		Tween2:Play()
		
		wait(0.2)

		Clone3.Parent = game.Workspace
		Clone3.CFrame = Character.Torso.CFrame
		
		local Goal3 = {}
		Goal3.CFrame = Clone3.End.CFrame

		local Tween3 = TweenService:Create(Clone3, TweenInfos, Goal3)
		Tween3:Play()
		
		wait(1)
		if Clone1 ~= nil then
			Clone1:Destroy()
		end
		wait(0.2)
		if Clone2 ~= nil then
			Clone2:Destroy()
		end
		wait(0.2)
		if Clone3 ~= nil then
			Clone3:Destroy()
		end
	end
end

return Module

Here is the main script [Body Velocity]:

local Module = {}

Module.QSpell = function(Player)
	local Character = Player.Character
	local Slash = game.ReplicatedStorage.Spells.Knight.Slash
	if Character ~= nil and Slash ~= nil then
		
		local Clone1 = Slash:Clone()
		local Clone2 = Slash:Clone()
		local Clone3 = Slash:Clone()
		
		local BodyVel1 = Instance.new("BodyVelocity", Clone1)
		local BodyVel2 = Instance.new("BodyVelocity", Clone2)
		local BodyVel3 = Instance.new("BodyVelocity", Clone3)
		
		Clone1.Touched:Connect(function(Part)
			if Part.Parent:FindFirstChild("Humanoid")and not game.Players:FindFirstChild(Part.Parent.Name)then
				Part.Parent.Humanoid:TakeDamage(15)
				Clone1:Destroy()
			end
		end)
		Clone2.Touched:Connect(function(Part)
			if Part.Parent:FindFirstChild("Humanoid")and not game.Players:FindFirstChild(Part.Parent.Name)then
				Part.Parent.Humanoid:TakeDamage(15)
				Clone2:Destroy()
			end
		end)
		Clone3.Touched:Connect(function(Part)
			if Part.Parent:FindFirstChild("Humanoid")and not game.Players:FindFirstChild(Part.Parent.Name)then
				Part.Parent.Humanoid:TakeDamage(15)
				Clone3:Destroy()
			end
		end)
		
		Clone1.Parent = game.Workspace
		Clone1.CFrame = Character.Torso.CFrame
		BodyVel1.Velocity = Character.Torso.CFrame.lookVector * 50
		
		wait(0.2)
		
		Clone2.Parent = game.Workspace
		Clone2.CFrame = Character.Torso.CFrame
		BodyVel2.Velocity = Character.Torso.CFrame.lookVector * 50
		
		wait(0.2)

		Clone3.Parent = game.Workspace
		Clone3.CFrame = Character.Torso.CFrame
		BodyVel3.Velocity = Character.Torso.CFrame.lookVector * 50
		
		wait(1)
		if Clone1 ~= nil then
			Clone1:Destroy()
		end
		wait(0.2)
		if Clone2 ~= nil then
			Clone2:Destroy()
		end
		wait(0.2)
		if Clone3 ~= nil then
			Clone3:Destroy()
		end
	end
end

return Module
1 Like

do those Touched events even run in the tweenservice script?

Yes, i tried to make this touched function directly in a script into the Spell MeshPart but it not work too

no I mean have you tried printing inside the three touched events to see if they even run at all?

Nop touched function not work with CFraming, i got help on discord.

“Thats probably because CFraming doesnt take into account touch connections, because technically you are teleporting the part small distances, whereas BodyVelocity actually moves the part through the 3D space, which allows for touch connections to happen.”

I will try to use magnitude to cast the spell damage instead of touched function

Use raycasting for the trajectory instead of touched with tweenservice.

local params = RaycastParams.new()
params.FilterDescendantsInstances = {character, script.Parent}
params.FilterType = Enum.RaycastFilterType.Blacklist

local ray = workspace:Raycast(origin, direction * range, params)

if ray then
    local hit, pos = ray.Instance, ray.Position
end

Alright, it work with magnitude, i just need to find a better optimisation by replacing the loop

while wait(0.1)do
	for _,Child in pairs(game.Workspace.Enemies:GetChildren())do
		if Child:IsA("Model") then
			local EnemiesHumanoid = Child:FindFirstChild("Humanoid")
			local EnemiesTorso = Child:FindFirstChild("Torso")
			local Part = script.Parent

			if EnemiesHumanoid ~= nil and EnemiesTorso ~= nil and (EnemiesTorso.Position - Part.Position).magnitude < 5 then
				EnemiesHumanoid:TakeDamage(15)
				script.Parent:Destroy()
			end
		end
	end
end

Tween’s don’t trigger a .touched if the other player is not moving. Something needs to interact with it/ touch it. Try using raycasting like @8_8io said, using magnitude to check if it’s in distance and giving it damage. Here’s some more info on it: Raycasting | Roblox Creator Documentation. Unsure if you’re familiar with it, so just sending it just in case. You can then delete the spell or make it transparent once you’re done.

TLDR: Tweens dont work with .touched because it’s not movement. Use raycasting. check if player close, give damage. delete spell thingy majig

Alright, i will try to use raycasting, thanks !

1 Like

also I recommend using for loops to prevent repeated code, you seem to repeat code for each clone

As far as detecting “touch”, I would recommend using Region3 as it’s far better at detecting part intersections. However, you’ll probably want to use RotatedRegion3.

You can also try GetTouchingParts, but I doubt that’ll work as well, if at all.

Do not recommend magnitude detection for every enemy count, as the count increases the performance is severely affected from continuous loops. Raycast instead for one time detection.

Alright, thanks for your help everyone
Here is my new codes, and it perfectly work now

Main Script

local Module = {}

Module.QSpell = function(Player)
	local Character = Player.Character
	local Slash = game.ReplicatedStorage.Spells.Knight.Slash
	if Character ~= nil and Slash ~= nil then
		local TweenService = game:GetService("TweenService")
		local TweenInfos = TweenInfo.new(1)
		
		for Count = 1, 3 do
			local Clone = Slash:Clone()
			
			Clone.Parent = game.Workspace.Spell
			Clone.Name = "KnightSlash"
			Clone.CFrame = Character.Torso.CFrame
			
			local Goal = {}
			Goal.CFrame = Clone.End.CFrame

			local Tween = TweenService:Create(Clone, TweenInfos, Goal)
			Tween:Play()
			
			wait(0.2)
		end
	end
end

return Module

Raycast script

script.Parent.Changed:Connect(function()
	if script.Parent.Parent.Name == "Spell" then
		local rayOrigin = script.Parent.Position
		local rayDirection = Vector3.new(20, 20, 20)

		local raycastParams = RaycastParams.new()
		raycastParams.FilterDescendantsInstances = {game.Workspace.Enemies}
		raycastParams.FilterType = Enum.RaycastFilterType.Whitelist
		local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)

		if raycastResult then
			local Part = raycastResult.Instance
			if Part.Parent:FindFirstChild("Humanoid") and not game.Players:FindFirstChild(Part.Parent.Name) then
				local Humanoid = Part.Parent:FindFirstChild("Humanoid")
				if Humanoid ~= nil then
					Humanoid:TakeDamage(15)
					script.Parent:Destroy()
				end
			end
		end
		wait(0.9)
		script.Parent:Destroy()
	end
end)