Loop Issue With NPC

This is a really weird issue I’m having where the AI in my game will repeat this specific ability indefinitely once its been used for the first time. (see video for better understanding). I see no errors within my script though that could be causing this and I’m really confused. The “Ability2” function is only being fired once, aka the first time the npc uses the attack, from there on it isn’t fired but the attack will keep repeating and things are still being printed as if the Remote Event is being fired multiple times, in the video pay attention to the prints in order to grasp what I’m saying.

This is my server script which handles basically everything the AI does (modified a little bit to reduce clutter)

-- // SERVICES // --
local TS = game:GetService("TweenService")
local PathfindingService = game:GetService("PathfindingService")

local Plr
game.Players.PlayerAdded:Connect(function(plr)
	Plr = plr
end)

-- // VARIABLES // --
local NPC = script.Parent
local WalkAnimation = NPC.Humanoid:LoadAnimation(NPC.Animations.Walk)
local IdleAnimation = NPC.Humanoid:LoadAnimation(NPC.Animations.Idle)
local Ability1Animation = NPC.Humanoid:LoadAnimation(NPC.Animations.Melee)
local Ability2Animation = NPC.Humanoid:LoadAnimation(NPC.Animations.IcicleRaise)
local Humanoid = NPC:FindFirstChild("Humanoid")
local Animator = Humanoid:FindFirstChild("Animator")

-- // SPAWNABLES // --

-- // ENEMY STATS // --
local WalkSpeed = 12
local MIN_DISTANCE = 6

-- // COOLDOWNS // --
local Ability1CDValue = false
local Ability2CDValue = false

-- // CHECKS // --
local IcicleRaiseTriggered = false

function ableToMove()
	local path = PathfindingService:CreatePath()
	local player, distance = getClosestPlayer()
	if player and distance > 1 then
		path:ComputeAsync(NPC.HumanoidRootPart.Position, player.PrimaryPart.Position)
		local waypoints = path:GetWaypoints()
		for _, waypoint in pairs(waypoints) do  
			if distance > MIN_DISTANCE then
				if Ability1Animation.IsPlaying then
					return
				end

				if Ability2Animation.IsPlaying then
					return
				end
				NPC.Humanoid.WalkSpeed = WalkSpeed
				NPC.Humanoid:MoveTo(waypoint.Position)
			else
				NPC.Humanoid.WalkSpeed = 0
			end
		end
	end
end

function Ability2CD()
	task.delay(10, function()
		Ability2CDValue = false
	end)
end

function Ability1()
	local player, distance = getClosestPlayer()
	if not Ability1CDValue then
		Ability1CDValue = true

		WalkAnimation:Stop()
		IdleAnimation:Stop()
		NPC.Humanoid.WalkSpeed = 0


		if Ability1Animation.IsPlaying == false then
			Ability1Animation:Play()
		end

		Ability1Animation.Stopped:Connect(function()
			if distance <= 6 then
				NPC.Humanoid.WalkSpeed = 0
			else
				NPC.Humanoid.WalkSpeed = WalkSpeed
			end
		end)

		Ability1CD()
	end
end

function Ability2()
	local player, distance = getClosestPlayer()
	if not Ability2CDValue then
		Ability2CDValue = true
		WalkAnimation:Stop()
		IdleAnimation:Stop()

		print("Ability 2 fired for the first time")
		game.ReplicatedStorage.Events.AnimationChecks.AnimationEvent:FireAllClients("IcicleRaise")

		Ability2Animation:Play()

		Ability2CD()
	end
end



game.ReplicatedStorage.Events.AnimationChecks.AnimationEventReturn.OnServerEvent:Connect(function(Player, animName, EventName)
	NPC.Humanoid.WalkSpeed = 0
	
	print(EventName)
	
	if animName == "IcicleRaise" then
		if EventName == "Start" then
			for _, plr in pairs(game.Players:GetPlayers()) do
				if plr.Character and plr.Character:FindFirstChild("HumanoidRootPart") then
					local IceCloudClone = game.ReplicatedStorage.Particles.IceCloud:Clone()
					IceCloudClone.Parent = game.Workspace
					IceCloudClone.Position = plr.Character.HumanoidRootPart.Position - Vector3.new(0, 2, 0)

					local heartbeatConnection
					heartbeatConnection = game:GetService("RunService").Heartbeat:Connect(function()
						if IcicleRaiseTriggered then
							IceCloudClone:Destroy()
							heartbeatConnection:Disconnect()
						else
							IceCloudClone.Position = plr.Character.HumanoidRootPart.Position - Vector3.new(0, 2, 0)
						end
					end)
				end
			end

		elseif EventName == "Trigger" then
			IcicleRaiseTriggered = true

			if Player.Character and Player.Character:FindFirstChild("HumanoidRootPart") then
				local IcicleClone = game.ReplicatedStorage.Spawnables.LargeIceShard:Clone()
				IcicleClone.Parent = game.Workspace
				IcicleClone.Position = Player.Character.HumanoidRootPart.Position - Vector3.new(0, 5, 0)
				
				task.delay(3, function()
					IcicleClone:Destroy()
				end)
			end
		end
	end
end)

while true do
	local player, distance = getClosestPlayer()
	local humanoid = NPC:FindFirstChild("Humanoid")
	local player_distance = (NPC.PrimaryPart.Position - player.PrimaryPart.Position).Magnitude
	
	ableToMove()

	if humanoid.MoveDirection.Magnitude <= 0 and humanoid.WalkSpeed > 0 then
		if not WalkAnimation.IsPlaying and not Ability2Animation.IsPlaying then
			IdleAnimation:Stop()
			WalkAnimation:Play()

			print(NPC.Humanoid.WalkSpeed)
		end
	end

	if humanoid.WalkSpeed == 0 then
		WalkAnimation:Stop()
		if not IdleAnimation.IsPlaying and not Ability1Animation.IsPlaying and not Ability2Animation.IsPlaying then
			IdleAnimation:Play()
		end
	end

	if player_distance < 7 then
		Ability1()
	end

	if player_distance > 40 and Ability2CDValue == false then
		Ability2()
	end
	
	--[[if player_distance < 1 then
		NPC.Humanoid:MoveTo((NPC.HumanoidRootPart.CFrame * CFrame.new(0, 0, -3)).p)
		break
	end--]]
	task.wait()
end

This is the client script that handles the animation events

-- // SERVICES // --
local RunService = game:GetService("RunService")

-- // SPAWNABLES // --
local IcicleShard = game.ReplicatedStorage.Spawnables.LargeIceShard

-- // VARIABLES // --
local Player = game.Players.LocalPlayer
local NPC repeat NPC = game.Workspace:FindFirstChild("Subzero") task.wait() until NPC
local Humanoid = NPC:FindFirstChild("Humanoid")
local Animator = Humanoid:FindFirstChild("Animator")
local WalkAnimation = Animator:LoadAnimation(NPC.Animations.Walk)
local IdleAnimation = Animator:LoadAnimation(NPC.Animations.Idle)
local Ability1Animation = Animator:LoadAnimation(NPC.Animations.Melee)
local Ability2Animation = Animator:LoadAnimation(NPC.Animations.IcicleRaise)

game.ReplicatedStorage.Events.AnimationChecks.AnimationEvent.OnClientEvent:Connect(function(animName)	
	if animName == "IcicleRaise" then
		Ability2Animation:Play()
		
		Ability2Animation:GetMarkerReachedSignal("Start"):Connect(function()
			game.ReplicatedStorage.Events.AnimationChecks.AnimationEventReturn:FireServer(animName, "Start") -- Ensure correct parameters
			print("Start Event fired")
		end)
		
		Ability2Animation:GetMarkerReachedSignal("Trigger"):Connect(function()
			game.ReplicatedStorage.Events.AnimationChecks.AnimationEventReturn:FireServer(animName, "Trigger")
			print("Trigger Event fired")
		end)
	end
end)

well first off all i noticed that this variable IcicleRaiseTriggered is set to true but never set to false. not sure if this is intentional or not but it kind of looks like it should be set to false when the icicle clone is destroyed in the task.delay function. like this

task.delay(3, function()
	IcicleClone:Destroy()
	IcicleRaiseTriggered = false -- i guess add this here maybe?
end)

this might fix your problem with the icicle cloud not appearing after the first time but I don’t think it will solve the main problem your having. other than that the script looks fine to me.
are you sure there arent any other scripts that are calling one of these two events? or maybe any other lines in your original server script that call an AnimationEvent for the client?

oh yeah thank you very much that did fix the ice cloud problem, for the main issue though i agree everything does look fine, there are no external scripts calling the events or anything so i’m really lost what the issue here could be, thank you though!

the main issue was because i had the animation itself looped by accident… :sob:

1 Like

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