Game erroring when changing auras

Hello, I’ve been working on my game “Killstreak Experience”, and I keep getting the same bug continuously over the past few months

While working on some effects, the game suddenly keeps deleting things that the script is supposed to use, doesn’t correctly Clone aura elements or delete them, keeps printing out “Phase1Highlight is not apart of workspace.Zorgoths”, etc.

I have tried to debug this issue, turn off StreamingEnabled, and double check the code to no avail. I’ve been feeling pretty hopeless about and I’m not sure if it’s because a Roblox feature or not, it’s been happening for months now and I’ve only ever fixed it once and it just went back to the same problem after I added more stuff to the script.

I shortened the script to make it easier to read and used a separate de-bugging server script.

Server:

-- @Zorgoths/Zoneriuz on RBLX (TKE: PhaseScript)
local PlayersService = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local LightingService = game:GetService("Lighting")
local TweenService = game:GetService("TweenService")
local DebrisService = game:GetService("Debris")

local Assets = ReplicatedStorage:WaitForChild("Assets")
local Events = ReplicatedStorage:WaitForChild("Events")
local Modules = ReplicatedStorage:WaitForChild("Modules")

local GloveRemotes = Events:WaitForChild("GloveRemotes")
local Remotes = Events:WaitForChild("Remotes")

local AuraMod = require(Modules:WaitForChild("ChangeAuraMod"))

local Container = script:WaitForChild("CONTAINER")
local ConnectonsModule = require(Container.DeathConnectionsMod)
local FunctionsModule = require(Container.FunctionsMod)

local playerPhases = {}
local playerPhaseTimes = {}

local phasesTable = {
	{name = "LilFire", kills = 1, nextKills = 2},
	{name = "BigFire", kills = 2, nextKills = 3},
	{name = "StrongFire", kills = 3, nextKills = 4},

	{name = "P1", kills = 4, nextKills = 5},
	{name = "P1_2", kills = 5, nextKills = 6},
	{name = "P1_3", kills = 6, nextKills = 8},
	{name = "P1_4", kills = 8, nextKills = 10},

	{name = "P2", kills = 10, nextKills = 25},
	{name = "P3", kills = 25, nextKills = 50},
	{name = "P4", kills = 50, nextKills = 75},
	{name = "P5", kills = 75, nextKills = 80},
	{name = "P5_2", kills = 80, nextKills = 100},
	{name = "P6", kills = 100, nextKills = 150},
	{name = "P7", kills = 150, nextKills = 250},
	{name = "P8", kills = 250, nextKills = 350},
	{name = "P9", kills = 350, nextKills = 425},
	{name = "P10", kills = 425, nextKills = 500},
	{name = "P11", kills = 666, nextKills = 777},
	{name = "P12", kills = 777, nextKills = 850},
	{name = "P13", kills = 850, nextKills = 935},
	{name = "P14", kills = 935, nextKills = 1000},
	{name = "P15", kills = 1000, nextKills = 1001},
}

function getPhase(kills)
	if not kills or type(kills) ~= "number" then
		warn("nonvalid kills input for getPhase:", kills)
		return {name = "P1", kills = 0, nextKills = 1}
	end

	for _, phase in ipairs(phasesTable) do
		if kills >= phase.kills and kills < phase.nextKills then
			return phase
		end
	end

	warn("no phase found for kills:", kills)
	return {name = "P1", kills = 0, nextKills = 1}
end

function handlePhase(char, phase)
	if not char or not phase then
		warn("Invalid inputs for handlePhase. Char:", char, "Phase:", phase)
		return
	end

	local player = FunctionsModule.getPlayer(char)
	if not player then
		warn("Could not retrieve player for character:", char)
		return
	end

	local character = FunctionsModule.getCharacter(player)
	if not character then
		warn("Could not retrieve character for player:", player)
		return
	end

	local Overhead = character:FindFirstChild("Head") and character.Head:FindFirstChild("Overhead") and character.Head.Overhead:FindFirstChild("Label")
	if not Overhead then
		warn("Overhead Label not found for character:", character)
		return
	end

	local humanoid = character:FindFirstChildOfClass("Humanoid")
	local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
	local Killstreak = character:FindFirstChild("Killstreak") or (player.Backpack and player.Backpack:FindFirstChild("Killstreak"))
	if not humanoid or not humanoidRootPart or not Killstreak then
		warn("Missing essential character components for player:", player)
		return
	end

	local Glove = Killstreak:FindFirstChild("Glove")
	local Hitbox = Killstreak:FindFirstChild("GloveHitbox")
	local GloveVFXPart = Glove and Glove:FindFirstChild("GloveFireVFX")
	local PowerVal = Killstreak:FindFirstChild("Scripts") and Killstreak.Scripts:FindFirstChild("SlapHandler") and Killstreak.Scripts.SlapHandler:FindFirstChild("Configuration") and Killstreak.Scripts.SlapHandler.Configuration:FindFirstChild("Power")
	local SlapSFX = Glove and Glove:FindFirstChild("SlapSFX")

	if not GloveVFXPart or not PowerVal or not SlapSFX then
		warn("Missing Glove components for player:", player)
		return
	end

	ConnectonsModule.CleanupEffects(player, playerPhaseTimes)

	if phase.name == "LilFire" then
		humanoid.MaxHealth = 110
		humanoid.Health = humanoid.MaxHealth

		FunctionsModule.setVFXState(GloveVFXPart, "Bottom", { Enabled = true, Rate = 3 }, "Bottom effect not found in GloveFireVFX for", player)
	elseif phase.name == "BigFire" then
		humanoid.MaxHealth = 112.25
		humanoid.Health = humanoid.MaxHealth

		FunctionsModule.setVFXState(GloveVFXPart, "Top", { Enabled = false, Rate = 0 }, "top effect not found in GloveFireVFX for", player)
		FunctionsModule.setVFXState(GloveVFXPart, "Bottom", { Enabled = true, Rate = 15 }, "Bottom effect not found in GloveFireVFX for", player)

		PowerVal.Value = 38
	elseif phase.name == "StrongFire" then
		FunctionsModule.copySound(SlapSFX, Glove.SFX["3SlapSFX"])

		humanoid.MaxHealth = 117.5
		humanoid.Health = humanoid.MaxHealth

		FunctionsModule.setVFXState(GloveVFXPart, "Top", { Enabled = false, Rate = 0 }, "top effect not found in GloveFireVFX for", player)
		FunctionsModule.setVFXState(GloveVFXPart, "Bottom", { Enabled = true, Rate = 25 }, "Bottom effect not found in GloveFireVFX for", player)
		PowerVal.Value = 42
	elseif phase.name == "P1" then
		FunctionsModule.creditSong(character)
		local Dummy = FunctionsModule.findDummy("PrekillstreakPhase")
		AuraMod.CloneAuraElements(Dummy, character)

		humanoid.WalkSpeed = 21
		humanoid.MaxHealth = 125
		humanoid.Health = humanoid.MaxHealth

		FunctionsModule.setVFXState(GloveVFXPart, "Bottom", { Enabled = true, Rate = 37 }, "Bottom effect not found in GloveFireVFX for", player)
	elseif phase.name == "P1_P2" then
		local Dummy = FunctionsModule.findDummy("KillstreakPhase1")
		AuraMod.CloneAuraElements(Dummy, character)

		local Highlight = Instance.new("Highlight", character)
		Highlight.Name = "Phase1Highlight"
		Highlight.Adornee = character
		Highlight.DepthMode = Enum.HighlightDepthMode.AlwaysOnTop
		Highlight.FillColor = Color3.fromRGB(185, 0, 0)
		Highlight.OutlineColor = Color3.fromRGB(0, 0, 0)
		Highlight.FillTransparency = 1
		Highlight.OutlineTransparency = 0
		Highlight:SetAttribute("KSAURA")

		if not Highlight then
			warn("Highlight not found for player:", player, Highlight)
		end

		humanoid.WalkSpeed = 25
		humanoid.MaxHealth = 135
		humanoid.Health = humanoid.MaxHealth

		humanoidRootPart["Phase1OST"].Volume = 2.5
		FunctionsModule.setVFXState(GloveVFXPart, "Bottom", { Enabled = true, Rate = 60 }, "Bottom effect not found in GloveFireVFX for", player)
	elseif phase.name == "P1_P3" then
		character["Phase1Highlight"].FillTransparency = 0.8
		humanoidRootPart["Phase1OST"].Volume = 3.78

		humanoid.WalkSpeed = 29
		humanoid.MaxHealth = 150
		humanoid.Health = humanoid.MaxHealth

		PowerVal.Value = 50
	elseif phase.name == "P2" then
		FunctionsModule.changeOverhead(character, "10Grad")
		AuraMod.DeleteClonedElements(character)
		AuraMod.DeleteSound(character)
		AuraMod.DeleteHighlights(character)
		task.wait()

		local Dummy = FunctionsModule.findDummy("KillstreakPhase2")
		AuraMod.CloneAuraElements(Dummy, character)

		local Tendrils = Dummy:FindFirstChild("Tendrils"):Clone()
		Tendrils.Parent = character
		Tendrils.CFrame = humanoidRootPart.CFrame
		Tendrils.PartConstraint.Part1 = humanoidRootPart
		Tendrils:SetAttribute("KSAURA")

		FunctionsModule.creditSong(character)
		FunctionsModule.copySound(SlapSFX, Glove.SFX["3SlapSFX"])

		FunctionsModule.setVFXState(GloveVFXPart, "Top", { Enabled = true, Rate = 60 }, "top effect not found in GloveFireVFX for", player)
		FunctionsModule.setVFXState(GloveVFXPart, "Bottom", { Enabled = false, Rate = 0 }, "Bottom effect not found in GloveFireVFX for", player)

		local ShockBall = FunctionsModule.findAsset("10ShockBall")
		FunctionsModule.shockBall(player, ShockBall, "45, 45, 45")

		local Highlight = Instance.new("Highlight", character)
		Highlight.Name = "Phase2Highlight"
		Highlight.Adornee = character
		Highlight.DepthMode = Enum.HighlightDepthMode.AlwaysOnTop
		Highlight.FillColor = Color3.fromRGB(255, 61, 61)
		Highlight.OutlineColor = Color3.fromRGB(0, 0, 0)
		Highlight.FillTransparency = 0.5
		Highlight.OutlineTransparency = 0
		Highlight:SetAttribute("KSAURA")

		PowerVal.Value = 70
		humanoid.WalkSpeed = 35

		humanoid.MaxHealth = 200
		humanoid.Health = humanoid.MaxHealth

		local CC =	Instance.new("ColorCorrectionEffect", LightingService)
		CC.Name = player.Name.."'s 10 ColorCorrection"
		CC.TintColor = Color3.fromRGB(255, 0, 0)
		CC:AddTag(player.Name)
		DebrisService:AddItem(CC, 3)

		local Tweeninfo = TweenInfo.new(
			0.52,
			Enum.EasingStyle.Linear,
			Enum.EasingDirection.Out,
			4,
			true,
			0
		)
		local TweenProp = {
			TintColor = Color3.fromRGB(170, 0, 0)
		}
		local Tween = TweenService:Create(CC, Tweeninfo, TweenProp)
		Tween:Play()

		task.wait((4 - 0.52) / 0.03)
		CC.TintColor = Color3.fromRGB(255, 255, 255)
	end
end

function verifyPhase(character, phase)
	if not character or not phase then
		warn("Nonvalid inputs for verifyPhase. Character:", character, "Phase:", phase)
		return
	end

	local player = FunctionsModule.getPlayer(character)
	if not player then
		return
	end

	if playerPhases[player] == phase.name then
		return
	end

	if phase.name == "LilFire" and not playerPhaseTimes[player] then
		playerPhaseTimes[player] = tick()
	end

	if playerPhaseTimes[player] and phase.name ~= "LilFire" then
		local elapsedTime = tick() - playerPhaseTimes[player]
		if elapsedTime <= 60 then
			local badgeID = 1689200691609278
			FunctionsModule.awardBadge(player, badgeID)
		end
		playerPhaseTimes[player] = nil
	end

	playerPhases[player] = phase.name
	handlePhase(character, phase)
end

function onBindEventFired(character, kills)
	if not character or not kills then
		warn("Invalid inputs for onBindEventFired. Char:", character, "Kills:", kills)
		return
	end

	local currentPhase = getPhase(kills)

	if currentPhase then
		verifyPhase(character, currentPhase)
	else
		warn("Error retrieving phase for kills:", kills, "Character:", character)
	end
end

local phaseEvent = GloveRemotes.KSPhaseEvent
phaseEvent.Event:Connect(onBindEventFired)

AuraModule:

local Module = {}

function Module.CloneAuraElements(DummyRig, PlayerCharacter)
	if not DummyRig or not PlayerCharacter then
		warn("Non-valid arguments for function -", DummyRig, PlayerCharacter)
		return
	end

	for _, child in ipairs(DummyRig:GetDescendants()) do
		if child.Parent then  -- added to check before movng on.
			local parentPart = PlayerCharacter:FindFirstChild(child.Parent.Name)
			if parentPart then
				if (child:IsA("BillboardGui") or child:IsA("Attachment") or child:IsA("Sound") or child:IsA("PointLight")) and child:GetAttribute("KSAURA") then
					local clone = child:Clone()
					clone.Parent = parentPart

					if child:IsA("Sound") then
						clone.Loaded:Connect(function()
							clone:Play()
						end)
					end
				elseif child:IsA("ParticleEmitter") and not child.Parent:IsA("Attachment") then
					local clone = child:Clone()
					clone.Parent = parentPart
				end
			end
		else
			warn("Child has no parent:", child.Name)
		end
	end
end

function Module.AddSound(part, name, id, volume, looped, pbs, author, title)
	if not part then
		warn("Invalid part for AddSound")
		return
	end

	local sound = Instance.new("Sound")
	sound.Name = name or "UnnamedSound"
	sound.SoundId = "rbxassetid://" .. id
	sound.Volume = tonumber(volume) or 1
	sound.Looped = looped or false
	sound.PlaybackSpeed = tonumber(pbs) or 1
	sound:SetAttribute("KSAURA", true)
	sound.Parent = part

	if author then
		local v1 = Instance.new("StringValue")
		v1.Name = "Author"
		v1.Value = author
		v1.Parent = sound
		if title then
			local v2 = Instance.new("StringValue")
			v2.Name = "Song"
			v2.Value = title
			v2.Parent = sound
		end
	end

	sound.Loaded:Connect(function()
		sound:Play()
	end)

	sound.Ended:Connect(function()
		if not sound.Looped then
			sound:Destroy()
		end
	end)
end

function Module.DeleteSound(PlayerCharacter)
	if not PlayerCharacter then return end
	for _, child in ipairs(PlayerCharacter:GetDescendants()) do
		if child:IsA("Sound") and child:GetAttribute("KSAURA") then
			child:Destroy()
		end
	end
end

function Module.DeleteHighlights(PlayerCharacter)
	if not PlayerCharacter then return end
	for _, child in ipairs(PlayerCharacter:GetDescendants()) do
		if child:IsA("Highlight") and child:GetAttribute("KSAURA") then
			child:Destroy()
		end
	end
end

function Module.DeleteClonedElements(PlayerCharacter)
	if not PlayerCharacter then return end
	for _, child in ipairs(PlayerCharacter:GetDescendants()) do
		if (child:IsA("BillboardGui") or child:IsA("Attachment") or child:IsA("Sound") or child:IsA("PointLight") or child:IsA("BasePart")) and child:GetAttribute("KSAURA") then
			child:Destroy()
		elseif child:IsA("ParticleEmitter") and not child:GetAttribute("NOAURA") then -- for shop particles
			child:Destroy()
		end
	end
end

return Module
1 Like

Make sure that there are no race conditions where one part of your script is trying to access an object that another part has already deleted.

1 Like

The auras in the game don’t really have any scripts in them, I was planning to add a script for the Tendrils part but scrapped it due to server lag. There are some models with scripts like effects but they don’t delete each other.

I think it may have to do with the settings of the effect parts since I turned Massless on and EnableFluidForces off to prevent the player from unusual movement.

1 Like

continuing on, I’ve found that the console prints out “Non-valid arguments for function - nil Zorgoths” when trying to switch phases for the KillstreakPhase1 phase.

1 Like