Skill not always functioning right if player is holding down the walk key

Hey guys, I’m new to roblox studio and new to lua, and I really need help with this. So what I’m trying to do is make a script that makes a fireball (or waterball etc etc), sends it to the server, and then fires the ball. The script nearly works fine, but for some reason, at random instances, when the character is walking while firing the attack, the ball just decides to stop and stay in front of the character. I thought it might be the simple fact that another key was being pressed at the same time at first, and tried to fix that, but that wasn’t the problem, as this issue only occurs if it’s one of the movement keys I’m holding down when it’s fired. I also thought the character could possibly be touching the ball before it launches and is causing some reaction, but then I realized that wasn’t the case because I have my script set up so that the character using the skill and the skill object can not touch each other. I now think that the way I’m handling the ball’s position and velocity is causing it to reset when the player is moving, but I can’t seem to find the issue.

Video link because the file was too large:

Here’s the server script:

local UIS = game:GetService("UserInputService")
local RS = game:GetService("ReplicatedStorage")
local debris = game:GetService("Debris")
local TS = game:GetService("TweenService")
local SS = game:GetService("ServerStorage")
local fxFolder = workspace.Fx
local spawnBlocks = workspace.SpawnBlocks

local fireballEvent = RS.SkillRemoteEvents.FireballEvent
local chargeAttack = RS.SkillRemoteEvents.ChargeAttack
local makeBall = RS.Fx.ballAttacks.makeBall

--ALL FUNCTIONS START HERE------------------------------------------------------------------------------------------------------------------------------
local function receiveAttack(hit, attacker, damageBase, charge, resistanceIncrease, firePower)
--CODE IN THIS FUNCTION IS IRRELEVANT
end

local function beFireball(hit, player, fireball, current, charge, firePower)
--CODE IN THIS FUNCTION IS IRRELEVANT
end

local function createBall(player, current, skill)
	if RS.ToolsForSkills:FindFirstChild(skill) ~= nil then
		player:WaitForChild("leaderstats"):WaitForChild("Skills"):FindFirstChild(skill):SetAttribute("LastUsed", 0)
		local attack = RS.ToolsForSkills:FindFirstChild(skill):Clone()
		attack.Name = player.Name..skill..current
		attack.Parent = RS.ToolsForSkills
		local newForce = Instance.new("BodyForce")
		newForce.Force = Vector3.new(0, workspace.Gravity * attack:GetMass(), 0)
		newForce.Parent = attack
	end
end

local function chargeSkill(player, charge, current, skill)
	local attack
	if RS.ToolsForSkills:FindFirstChild(player.Name..skill..current) ~= nil then
		attack = RS.ToolsForSkills:FindFirstChild(player.Name..skill..current)
		attack.Parent = workspace.Map:FindFirstChild(player.Name.."CurrentProjectiles")
	else
		attack = workspace.Map:FindFirstChild(player.Name.."CurrentProjectiles"):FindFirstChild(player.Name..skill..current)
	end
	attack.Position = player.Character.HumanoidRootPart.Position + player.Character.HumanoidRootPart.CFrame.LookVector * 5

	local chargeFx = SS.Fx:FindFirstChild("chargeDisperse"..skill):Clone()
	chargeFx.Color = ColorSequence.new(attack.Color)
	chargeFx.Parent = attack.Attachment

	if charge > 1.5 then
		attack.ParticleEmitter.Enabled = true
		attack.ParticleEmitter.Rate = 50 * charge
	end

	if charge > 2 then
		chargeFx.Enabled = true
	end

	if charge >= 2.5 then
		chargeFx.Rate = 100
	end
	print("I REPEAT! Charge is "..charge)
end

local function fireAttack(player, MousePosition, current, charge, skill, attackName, velocity)
	local attack = workspace.Map:FindFirstChild(player.Name.."CurrentProjectiles"):FindFirstChild(player.Name..skill..current)
	if charge == 1 then
		attack.Parent = workspace.Map:FindFirstChild(player.Name.."CurrentProjectiles")
	end
	
	if attack:GetAttribute(player.Name..attack.Name) == nil then
		attack:SetAttribute(player.Name..attack.Name, "Exists")

		local attackElement = player.leaderstats.Skills:FindFirstChild(skill):GetAttribute("Element")

		local firePower = player.leaderstats.Stats:FindFirstChild(attackElement.." Power")

		local level = player.leaderstats.Stats:FindFirstChild("Level")
		local levelEXP = level:GetAttribute("CurrentEXP")
		local requiredLevelEXP = level:GetAttribute("RequiredEXP")
		local remainingLevelEXP = level:GetAttribute("RemainingEXP")

		local fireballLevel = player.leaderstats.Skills:FindFirstChild(skill)
		local fireballLevelEXP = fireballLevel:GetAttribute("CurrentEXP")
		local fireballRequiredLevelEXP = fireballLevel:GetAttribute("RequiredEXP")
		local fireballRemainingLevelEXP = fireballLevel:GetAttribute("RemainingEXP")

		firePower.Value += math.round(1 * charge)

		if math.round(1 * charge) > requiredLevelEXP - levelEXP then
			local obtainedEXP = requiredLevelEXP - levelEXP
			local leftoverEXP = math.round(1 * charge) - (requiredLevelEXP - levelEXP)
			local nextCurrentEXP = levelEXP + obtainedEXP

			level:SetAttribute("CurrentEXP", nextCurrentEXP)
			level:SetAttribute("RemainingEXP", leftoverEXP)
		else
			local nextCurrentEXP = levelEXP + math.round(1 * charge)
			level:SetAttribute("CurrentEXP", nextCurrentEXP)
		end

		if math.round(1 * charge) > fireballRequiredLevelEXP - fireballLevelEXP then
			local obtainedEXP = fireballRequiredLevelEXP - fireballLevelEXP
			local leftoverEXP = math.round(1 * charge) - (fireballRequiredLevelEXP - fireballLevelEXP)
			local nextCurrentEXP = fireballLevelEXP + obtainedEXP

			fireballLevel:SetAttribute("CurrentEXP", nextCurrentEXP)
			fireballLevel:SetAttribute("RemainingEXP", leftoverEXP)
		else
			local nextCurrentEXP = fireballLevelEXP + math.round(1 * charge)
			fireballLevel:SetAttribute("CurrentEXP", nextCurrentEXP)
		end

		attack.Anchored = false
		attack.Velocity *= 100
		print("Ball should be moving")
		attack.Touched:Connect(function(hit)

			if not hit:IsDescendantOf(workspace:FindFirstChild(player.Name)) and not hit:IsDescendantOf(workspace.SimpleRings) and not hit:IsDescendantOf(fxFolder) and not hit:IsDescendantOf(spawnBlocks)then
				if hit:IsDescendantOf(workspace.Map) or hit.Parent:FindFirstChild("Humanoid") then
					beFireball(hit, player, attack, current, charge, firePower)
					attack:Destroy()
					current -= 1
					print("THE PARENT OF WHAT WAS HIT IS "..hit.Name)
					if hit.Parent:FindFirstChild("Humanoid") then
						local resistanceIncrease = math.round(1 * charge)
						receiveAttack(hit, player, 25, charge, resistanceIncrease, firePower.Value)
					end
				end
			end
		end)
	end
end
--ALL FUNCTIONS END HERE--------------------------------------------------------------------------------------------------------------------------------
makeBall.OnServerEvent:Connect(function(player, current, skill)
	createBall(player, current, skill)
end)

chargeAttack.OnServerEvent:Connect(function(player, charge, current, skill)
	chargeSkill(player, charge, current, skill)
end)

fireballEvent.OnServerEvent:Connect(function(player, MousePosition, current, charge, skill)
	fireAttack(player, MousePosition, current, charge, skill)
end)

And here’s the local script:

local current = 0

while true do
	local UIS = game:GetService("UserInputService")
	local RS = game:GetService("ReplicatedStorage")
	local debris = game:GetService("Debris")
	local TS = game:GetService("TweenService")

	local player = game.Players.LocalPlayer
	local character = player.CharacterAdded:Wait()
	local humanoid = character:WaitForChild("Humanoid")
	local HRP = character:WaitForChild("HumanoidRootPart")
	local currentProjectiles = workspace.Map:WaitForChild(player.Name.."CurrentProjectiles"):GetChildren()

	local makeBall = RS.Fx.ballAttacks.makeBall
	local fireballEvent = RS.SkillRemoteEvents.FireballEvent
	local chargeAttack = RS.SkillRemoteEvents.ChargeAttack

	local mouse = player:GetMouse()
	local key
	local keyUnpressed

	local debounce = false
	local charging = false

	local cooldown = 3
	local charge = 1
	local movementKeys = {"W", "A", "S", "D"}
	
	local params = RaycastParams.new()
	params.FilterType = Enum.RaycastFilterType.Include -- Same as saying Enum.RaycastFilterType.Whitelist
	params.FilterDescendantsInstances = {workspace.Map}
	
	local function rip()
		humanoid = character:WaitForChild("Humanoid")
		local lastAttacker = humanoid:GetAttribute("LastAttacker")
		local lastAttackerHumanoid

		if lastAttacker ~= "None" then
			lastAttackerHumanoid = workspace:WaitForChild(lastAttacker):WaitForChild("Humanoid")
		end

		makeBall = RS.Fx.ballAttacks.makeBall
		fireballEvent = RS.SkillRemoteEvents.FireballEvent
		chargeAttack = RS.SkillRemoteEvents.ChargeAttack
		--current = 0
		charge = 1
		mouse = player:GetMouse()
		debounce = false

		if lastAttackerHumanoid ~= nil then
			print(humanoid.Parent.Name.." has died. The one who dealt the final blow was "..lastAttackerHumanoid.Parent.Name)
		end

		if charging == true then
			charging = false
		end

		humanoid = nil
		return
	end
	
	local function createAttack(input, gpe)
		local humanoid = workspace:FindFirstChild(player.Name):FindFirstChild("Humanoid")
		local keyPressed = input.KeyCode

		if keyPressed ~= nil and player.KeyBinds:FindFirstChild(input.KeyCode) ~= nil then
			if humanoid:GetAttribute("UsingSkill") == nil or humanoid:GetAttribute("UsingSkill") == false then
				local skill = player.KeyBinds:FindFirstChild(input.KeyCode).Value
				if skill ~= nil and skill ~= "None" and skill ~= "" then
					local lastUsed = player:WaitForChild("leaderstats"):WaitForChild("Skills"):FindFirstChild(skill):GetAttribute("LastUsed")
					local reloadTime = player:WaitForChild("leaderstats"):WaitForChild("Skills"):FindFirstChild(skill):GetAttribute("ReloadTime")
					if lastUsed > reloadTime then
						print("IT HAS A SKILL ASSIGNED!!! LAUNCHING")
						humanoid:SetAttribute("UsingSkill", true)
						if humanoid ~= nil then
							debounce = true
							local secondDebounce = false
							local thirdDebounce = false

							charging = true
							humanoid.WalkSpeed = 0

							if not secondDebounce then
								secondDebounce = true
								print("WE ARE MAKING THE BALL!!!")
								current += 1
								makeBall:FireServer(current, skill)
							end

							local attack = RS.ToolsForSkills:WaitForChild(player.Name..skill..current)
							attack.Position = player.Character.HumanoidRootPart.Position + player.Character.HumanoidRootPart.CFrame.LookVector * 5
							attack.Velocity = CFrame.new(attack.Position, mouse.Hit.p).LookVector
							attack.Anchored = true

							if player.Character:FindFirstChild("Humanoid"):GetState() == Enum.HumanoidStateType.Freefall then
								charging = false
							end

							repeat	
								wait(0.1)
								if charge + 0.03 > 2.5 then
									charge = 2.5
								else
									charge += 0.03
								end
								print("Charging is at "..charge.."For the attack "..attack.Name)
								attack.Position = player.Character.HumanoidRootPart.Position + player.Character.HumanoidRootPart.CFrame.LookVector * 5
								attack.Velocity = CFrame.new(attack.Position, mouse.Hit.p).LookVector
								chargeAttack:FireServer(charge, current, skill)
							until charging == false or humanoid.Health <= 0

							if not thirdDebounce then
								print("ADDING ALL THE EXP AND THAT OTHER GOOD STUFF")
								thirdDebounce = true
								attack.Anchored = false
								attack.Velocity *= 100
								fireballEvent:FireServer(mouse.Hit.p, current, charge, skill, player.Name..skill..current)
								charge = 1
							end
							wait(0.3)
							humanoid.WalkSpeed = 16
						end
						task.wait(cooldown)
						charge = 1.0
						debounce = false
						print("Debounce is false")			
					end
				end
			end
		end
	end
	
	local function releaseAttack(input, gpe, key)
		local humanoid = workspace:FindFirstChild(player.Name):FindFirstChild("Humanoid")
		local keyReleased = input.KeyCode
		if keyReleased == key and not gpe and charge > 1.03 then
			charging = false
			print("Attack Launched!!!")
			humanoid:SetAttribute("UsingSkill", false)
		end
	end

	player.Character.Humanoid.Died:Connect(function()
		rip()
	end)

	UIS.InputBegan:Connect(function(input, gpe)
		local keyPressed = input.KeyCode
		if keyPressed ~= nil and player.KeyBinds:FindFirstChild(input.KeyCode) ~= nil then
			key = input.KeyCode
			createAttack(input, gpe)
		end
	end)

	UIS.InputEnded:Connect(function(input, gpe)
		while charge <= 1.03 do
			wait()
		end
		releaseAttack(input, gpe, key)
	end)
end

Now as stated previously, I’m very new to programming on lua, as well as roblox studios. So if you also see any bad practices or inconsistencies in the process of helping me then please by all means point them out and help me improve. I’m going to try again to get the video to load, it was not loading at first. If it doesn’t load I will probably link it.

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.