Magic spell will not collide with the ground sometimes

I’m currently creating a magic spell. I’ve been encountering a very strange bug over the past couple of days, and despite my best efforts, I could not find the cause.

Here’s what the code is supposed to do:

The spell travels through the air. When it touches something, it explodes. It acts like this some of the time. However, sometimes, it does this instead.

Basically, it doesn’t seem to process the touch. When it comes in contact with a part, the fireball travels through it as if it isn’t there instead of exploding. Here is all the code:

local tweenService = game:GetService("TweenService")
local runService = game:GetService("RunService")

local TouchedPlus = require(game:GetService("ReplicatedStorage").TouchedPlus)

local inputBeganEvent = game.ReplicatedStorage.InputBeganEvent
local inputEndedEvent = game.ReplicatedStorage.InputEndedEvent
local updateMouseEvent = game.ReplicatedStorage.UpdateMouseEvent

local originalFireball = game.ReplicatedStorage.Fireball

local character = script.Parent
local player = game.Players:GetPlayerFromCharacter(character)
local rootPart = character:FindFirstChild("HumanoidRootPart")
local humanoid = character:FindFirstChild("Humanoid")
local equippedTool = character:WaitForChild("EquippedTool")

local immobilized = false

local bodyVelocity = Instance.new("BodyVelocity")

bodyVelocity.Velocity = Vector3.new(0,0,0)
bodyVelocity.MaxForce = Vector3.new(0,0,0)
bodyVelocity.P = 1000000
bodyVelocity.Parent = rootPart

local bodyGyro = Instance.new("BodyGyro")

bodyGyro.MaxTorque = Vector3.new(0,0,0)
bodyGyro.P = 1000000
bodyGyro.Parent = rootPart

--This will need to be changed later to accommodate customizable attacks.
local fireballTweenInfo = TweenInfo.new(1,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,false,0)
local explosionTweenInfo = TweenInfo.new(0.5,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,false,0)

local mouseHit = nil

local cooldown = 0

function fireOnCollision(part,functionToCall)
	local destroyedConnection
	local hitDetection = TouchedPlus.new(part,10)
	hitDetection.Touched:Connect(function(touchedPart)
		functionToCall(touchedPart)
	end)
	destroyedConnection = part.AncestryChanged:Connect(function()
		if part.Parent == nil then
			hitDetection:Destroy()
			destroyedConnection:Disconnect()
		end
	end)
end

function fireOnTweenCompletion(tween,functionToCall)
	local connection
	connection = tween.Completed:Connect(function()
		connection:Disconnect()
		functionToCall()
	end)
end

function changeImmobilization(bool)
	immobilized = bool
	if immobilized == true then
		bodyVelocity.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
		bodyGyro.MaxTorque = Vector3.new(math.huge,math.huge,math.huge)
	elseif immobilized == false then
		bodyVelocity.MaxForce = Vector3.new(0,0,0)
		bodyGyro.MaxTorque = Vector3.new(0,0,0)
	end
end

function createBlast()
	cooldown = 30
	local fireball = originalFireball:Clone()
	fireball.CFrame = rootPart.CFrame + mouseHit.LookVector * 6
	local fireballGoal = {}
	fireballGoal.CFrame = fireball.CFrame + mouseHit.LookVector * 100
	fireball.Parent = game.Workspace	
	local fireballMovementTween = tweenService:Create(fireball,fireballTweenInfo,fireballGoal)
	fireballMovementTween:Play()
	local function handleFireballCollision()
		fireballMovementTween:Cancel()
	end
	local function handleFireballTweenCompletion()
		local explosion = game.ReplicatedStorage.Explosion
		local explosionGoal = {}
		explosionGoal.Size = Vector3.new(10,10,10)
		explosionGoal.Transparency = 1
		local explosionClone = explosion:Clone()
		explosionClone.Position = fireball.Position
		fireball:Destroy()
		explosionClone.Parent = game.Workspace
		local explosionTween = tweenService:Create(explosionClone,explosionTweenInfo,explosionGoal)
		explosionTween:Play()
		local hitHumanoids = {}
		local function explosionDamage(part)
			local parent = part.Parent
			if parent then
				if part.Parent ~= character then
					local humanoid = part.Parent:FindFirstChildOfClass("Humanoid")
					if humanoid then
						local hitbefore = false
						for index,value in pairs(hitHumanoids) do
							if value == humanoid  then
								hitbefore = true
							end
						end
						if hitbefore == false then
							table.insert(hitHumanoids,humanoid)
							humanoid.Health = humanoid.Health - 50
						end
					end
				end
			end	
		end
		local function destroyExplosion()
			explosionClone:Destroy()
		end
		fireOnCollision(explosionClone,explosionDamage)
		fireOnTweenCompletion(explosionTween,destroyExplosion)
	end
	fireOnCollision(fireball,handleFireballCollision)
	fireOnTweenCompletion(fireballMovementTween,handleFireballTweenCompletion)			
end

inputBeganEvent.OnServerEvent:Connect(function(eventPlayer,keyCode)
	if eventPlayer == player then
		if keyCode == Enum.KeyCode.Q then
			if equippedTool.Value then
				if equippedTool.Value.Name == "FireMagic" then
					if cooldown == 0 then
						changeImmobilization(true)
					end
				end
			end
		end
	end
end)

inputEndedEvent.OnServerEvent:Connect(function(eventPlayer,keyCode)
	if eventPlayer == player then
		if equippedTool.Value then
			if equippedTool.Value.Name == "FireMagic" then
				if keyCode == Enum.KeyCode.Q then
					if immobilized == true then
						changeImmobilization(false)
						if cooldown == 0 then
							createBlast()
						end
					end
				end
			end
		end
	end	
end)

runService.Stepped:Connect(function()
	if cooldown > 0 then
		cooldown = cooldown - 1
	end
end)

updateMouseEvent.OnServerEvent:Connect(function(eventPlayer,eventMouseHit)
	if eventPlayer == player then
		mouseHit = eventMouseHit 
		bodyGyro.CFrame = CFrame.new(rootPart.Position,rootPart.Position + mouseHit.LookVector)
	end
end)

Notes:
I tried swapping out tweens for a different strategy of moving the fireball. It did not fix the bug.
I also tried switching out TouchedPlus for FindPartsInRegion3. That did not fix the bug either.
Whether or not the collision works does not seem fully random. It seems to depend on where and how the fireball hits the object.

2 Likes

Could it be this line? This line would ignore regular Parts that aren’t parented to an object, but would trigger the explosion if the parts hit were parented

I thought that might’ve been the solution, but it doesn’t seem like it was. I understand why you would think that, the variable names in that part of the script are pretty confusing.

Maybe try this?

function fireOnCollision(part,functionToCall)
	local destroyedConnection
	local hitDetection = TouchedPlus.new(part,10)
	hitDetection.Touched:Connect(function(touchedPart)
		functionToCall(touchedPart)
	end)
	destroyedConnection = part.AncestryChanged:Connect(function()
		if part.Parent ~= game.Players:GetPlayerFromCharacter(part.Parent) then
			hitDetection:Destroy()
			destroyedConnection:Disconnect()
		end
	end)
end

It still behaves the same. Do you have any other ideas? (Thanks for the help, by the way.)

Well the issue is somewhere lying in-between those lines here

function fireOnCollision(part,functionToCall)
	local destroyedConnection
	local hitDetection = TouchedPlus.new(part,10)
	hitDetection.Touched:Connect(function(touchedPart)
		functionToCall(touchedPart)
	end)
	destroyedConnection = part.AncestryChanged:Connect(function()
		if part.Parent == nil then
			hitDetection:Destroy()
			destroyedConnection:Disconnect()
		end
	end)
end

Preferably the part.Parent conditional check, could you maybe try checking if the part is equal to nil alone?

I commented out this whole part of the script and it didn’t fix the issue.

B r u h

function fireOnCollision(part,functionToCall)
	local destroyedConnection
	local hitDetection = TouchedPlus.new(part,10)
	hitDetection.Touched:Connect(function(touchedPart)
		functionToCall(touchedPart)
	end)
	destroyedConnection = part.AncestryChanged:Connect(function()
		if part == nil then
			hitDetection:Destroy()
			destroyedConnection:Disconnect()
            print("Test")
        else
            print("Oop")
		end
	end)
end

Now I’m at the point where I don’t even know where the issue could lie, it’s obviously relevant with the Touched event but I don’t know

I still don’t know what the issue was. I completely discarded everything and did the same thing a different way, and now it’s fixed.