Quest Arrow Upon Completing Quest

I’m trying to make it so that as soon as the player meets the requirement for the quest like as soon as they hit the stats required or class required ect. They should have my beam appear for them. Also it should appear if you first joined the game

The issue is I don’t know how to do this like make something appear if as soon as you meet those requirements and appear if your first playing the game.

This is my arrow local script in scs

local RunService = game:GetService("RunService")
local player = game.Players.LocalPlayer

-- Wait for the character to load
local character = player.Character or player.CharacterAdded:Wait()
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
local targetPart = workspace:WaitForChild("QuestAreaArrow") -- Reference to the QuestAreaArrow part

print("QuestAreaArrow found:", targetPart)

-- Create the first Beam (Guiding Beam)
local beam1 = Instance.new("Beam")
beam1.TextureLength = 0 -- No texture on this beam
beam1.TextureSpeed = 0 -- No movement for guiding beam
beam1.Width0 = 1.5
beam1.Width1 = 1.5
beam1.Transparency = NumberSequence.new(1) -- Fully transparent background

-- Create Attachments for the first Beam
local attachment0 = Instance.new("Attachment", humanoidRootPart)
attachment0.Name = "GuideAttachment"
attachment0.Position = Vector3.new(0, 0, 0) -- Position slightly above the player
print("Attachment0 created:", attachment0)

local attachment1 = Instance.new("Attachment", targetPart) -- Attach to QuestAreaArrow part
attachment1.Name = "TargetAttachment"
attachment1.Position = Vector3.new(0, 0, 0) -- This will set the attachment's position relative to the part
print("Attachment1 created:", attachment1)

-- Set the first beam's attachments
beam1.Attachment0 = attachment0
beam1.Attachment1 = attachment1

-- Parent the first beam to the workspace
beam1.Parent = workspace
print("Beam1 created and parented to workspace.")

-- Create the second Beam (Arrow Beam)
local beam2 = Instance.new("Beam")
beam2.Texture = "rbxassetid://76564571897615" -- Example texture (arrow image)
beam2.TextureSpeed = 5 -- Adjust the speed of the texture moving along the beam
beam2.Width0 = 2.5
beam2.Width1 = 2.5

-- Set the second beam's attachments
beam2.Attachment0 = attachment0
beam2.Attachment1 = attachment1

-- Parent the second beam to the workspace
beam2.Parent = workspace
print("Beam2 created and parented to workspace.")

-- Update the TextureLength based on distance using RunService
RunService.RenderStepped:Connect(function()
	local distance = (humanoidRootPart.Position - targetPart.Position).Magnitude
	local textureLength

	if distance < 50 then  -- 10 * 10
		textureLength = 12
	elseif distance < 1000 then  -- 100 * 10
		textureLength = math.clamp(10 + (distance - 50) * (490 / 900), 10, 300) -- Adjusted to reflect new thresholds
	else
		textureLength = 300
	end

	-- Smooth transition: Adjust TextureLength gradually
	beam2.TextureLength = beam2.TextureLength * 0.8 + textureLength * 0.2
end)

-- Clean up when the player character dies
character:WaitForChild("Humanoid").Died:Connect(function()
	beam1:Destroy()
	beam2:Destroy()
	attachment0:Destroy()
	attachment1:Destroy()
	print("Cleaned up beams and attachments for player:", player.Name)
end)

And this is my quest module

local RS = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")

--// Variables
local RSmodules = RS.Modules
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local BigNum = require(RSmodules.BigNum)
local CREvents = RS.Remotes.Client.Events
local TypeQuestDialog = CREvents.TypeQuestDialog

--// Module
local Quests = {}
Quests.__index = Quests

Quests.Givers = {
	"Giver1"
}

Quests.QuestTable = {
	{ -- Giver1's Quests
		{
			["Name"] = "The Rise of a Warrior...",
			["Dialog"] = {
				"Welcome! Glad you were able to make it, we've been expecting you young warrior.",
				"You will be trained to become one of the strongest warriors known to mankind!",
				"Now, for your first task: gain 30 strength and 30 endurance. Seems easy enough, right?"
			},
			["NotfinishedText"] = "Come back to me once you've reached 30 Strength and 30 Endurance.",
			["Stats"] = {
				["Strength"] = 30,
				["Endurance"] = 30
			},
			["Status"] = "Innocent",
			["Class"] = "F-Class", -- Required class for this quest
			["Fusion"] = "None",
			["Rewards"] = {
				["Tokens"] = 250,
				["FireballAbility"] = true,
				["LightningAbility"] = true,
				["SoulharvestAbility"] = true,
				["ElasticalAbility"] = true,
				["EnergyPunchAbility"] = true,
				["WalkOnWaterAbility"] = true,
				["DamageReflectionAbility"] = true,
				["TeleportationAbility"] = true,
				["FlyAbility"] = true,
				["InvisibilityAbility"] = true
			}
		},
		{
			["Name"] = "Intelligence is the key...",
			["Dialog"] = {
				"HAHA! I knew you wouldn't be able to... wait... you did it?.",
				"I'm honestly impressed, didn't know you were worthy enough for what's about to come!",
				"Now, for your second task: gain 30 psychic. Let's see if you're smart enough for this."
			},
			["NotfinishedText"] = "Come back to me once you've reached 30 Psychic.",
			["Stats"] = {
				["Psychic"] = 30
			},
			["Rewards"] = {
				["Tokens"] = 400
			}
		},
		{
			["Name"] = "The warrior of speed",
			["Dialog"] = {
				"Impressive work! You are indeed smart enough to continue to the rest of the challenges.",
				"But are you fast enough to escape deadly enemies that will come your way? Or maybe you are the enemy.",
				"Now, for your third task: gain 50 speed. Maybe we shall race after."
			},
			["NotfinishedText"] = "Come back to me once you've reached 50 Speed.",
			["Stats"] = {
				["Speed"] = 50
			},
			["Rewards"] = {
				["Tokens"] = 750
			}
		},
		{
			["Name"] = "Mind over matter",
			["Dialog"] = {
				"From the looks of it you'll be running faster than flash soon!",
				"But let's take a chill pill and think about how we will become the most secret warriors known to mankind",
				"Now, for your fourth task: gain 200 Psychic. Think about your up and coming greatness"
			},
			["NotfinishedText"] = "Come back to me once you've reached 200 Psychic. There's a special skill waiting for you :)",
			["Stats"] = {
				["Psychic"] = 200
			},
			["Rewards"] = {
				["Tokens"] = 1000
			}	
		}	
	}
}

-- Function to abbreviate numbers
local function abbreviateNumber(value)
	local num = tonumber(value)
	if not num then return value end -- Return original if not a number

	local suffixes = { "", "K", "M", "B", "T", "Qa", "Qi", "Sx", "Sp", "Oc", "N", "Dc", "Ud", "Td", "Dd", "Qua", "Qui", "Sxd", "Spd", "Ocd", "Nod", "Vg" }
	local index = 1

	while num >= 1000 and index < #suffixes do
		num = num / 1000
		index = index + 1
	end

	local formattedNumber = string.format("%.2f", num)
	-- Remove trailing zeros
	formattedNumber = formattedNumber:gsub("%.?0*$", "")
	return formattedNumber .. suffixes[index]
end

local function FindNextQuest(player, giverNum)
	local curQuestInfo = string.split(player.QuestId.Value, "|") -- [questGiver, questNum]

	local curQuestGiver = tonumber(curQuestInfo[1])
	local curQuestId = tonumber(curQuestInfo[2])

	-- Check for valid quest giver
	if not Quests.QuestTable[curQuestGiver] then
		return {nil, "InvalidGiver"}
	end

	if curQuestId == 0 and curQuestGiver == 1 then
		player.QuestId.Value = "1|1"
		return {Quests.QuestTable[1][1], "New Quest"}
	elseif curQuestId == 0 and curQuestGiver > 1 then
		local state = (#Quests.Givers >= curQuestGiver) and "DoneWithThisGiver" or "NoMoreQuests"
		if state == "NoMoreQuests" then return {nil, state} end

		if curQuestGiver == giverNum then
			player.QuestId.Value = curQuestGiver.."|1"
			return {Quests.QuestTable[curQuestGiver][1], "New Quest"}
		end
	end

	local currentQuest = Quests.QuestTable[curQuestGiver][curQuestId]

	-- Check if the quest is valid
	if not currentQuest then
		return {nil, "InvalidQuest"}
	end

	if Quests.CurrentQuestCompleted(player) == false then
		return {currentQuest, "Hasn't Finished"}
	end

	-- Check class requirement
	local playerClass = player.leaderstats.Class.Value
	if currentQuest.Class and playerClass ~= currentQuest.Class then
		return {currentQuest, "ClassRequirementNotMet"}
	end
	
	local playerFusion = player.leaderstats.Fusion.Value 
	if currentQuest.Fusion and playerFusion ~= currentQuest.Fusion then
		return {currentQuest, "ClassRequirementNotMet"}
	end

	local playerStatus = player.leaderstats.Status.Value
	if currentQuest.Status and playerStatus ~= currentQuest.Status then
		return {currentQuest, "ClassRequirementNotMet"}
	end

	local Currency = player.Currency
	Currency.Tokens.Value += currentQuest["Rewards"].Tokens

	-- Set Abilities if specified in the rewards
	local abilities = player:FindFirstChild("Abilities")
	if abilities then
		local abilityMapping = {
			FireballAbility = "Fireball",
			LightningAbility = "LightningStrike",
			SoulharvestAbility = "SoulHarvest",
			ElasticalAbility = "Elastical",
			EnergyPunchAbility = "EnergyPunch",
			WalkOnWaterAbility = "WalkOnWater",
			DamageReflectionAbility = "DamageReflection",
			TeleportationAbility = "Teleport",
			FlyAbility = "Fly",
			InvisibilityAbility = "Invisibility"
		}

		for reward, abilityName in pairs(abilityMapping) do
			if currentQuest["Rewards"][reward] then
				local ability = abilities:FindFirstChild(abilityName)
				if ability then
					ability.Value = true
					-- Initialize the equipped state
					local equipped = abilities:FindFirstChild(abilityName.."Equipped")
					if equipped then
						equipped.Value = true -- Start as not equipped
					end
				end
			end
		end
	end

	-- TODO: Enable powers if needed
	if currentQuest["Rewards"]["Power"] then
		-- Implement power enabling logic
	end

	-- Find New Quest
	local state = "New Quest"

	if (curQuestId + 1 <= #Quests.QuestTable[curQuestGiver]) then
		curQuestId += 1
		player.QuestId.Value = curQuestGiver.."|"..curQuestId
		return {Quests.QuestTable[curQuestGiver][curQuestId], state}
	else
		player.QuestId.Value = (curQuestGiver + 1).."|0" 
		curQuestGiver += 1
		curQuestId = 0

		state = (#Quests.Givers >= curQuestGiver and "DoneWithThisGiver" or "NoMoreQuests")
		return {nil, state}
	end
end



function Quests.CurrentQuestCompleted(player)
	local curQuestInfo = string.split(player.QuestId.Value, "|") -- [questGiver, questNum]

	local curQuestGiverNum = tonumber(curQuestInfo[1])
	local curQuestId = tonumber(curQuestInfo[2])

	local curQuestGiver = Quests.QuestTable[curQuestGiverNum]
	if not curQuestGiver then return true end

	local curQuest = curQuestGiver[curQuestId]
	if curQuest == nil then return true end

	local pStats = player.PhysicalStats

	for Stat, Req in pairs(curQuest.Stats) do
		if not BigNum.mt.ge(pStats[Stat].Value, Req) then
			return false
		end
	end

	-- Check class requirement
	local playerClass = player.leaderstats.Class.Value
	if curQuest.Class and playerClass ~= curQuest.Class then
		return false
	end
	
	local playerFusion = player.leaderstats.Fusion.Value
	if curQuest.Fusion and playerFusion ~= curQuest.Fusion then
		return false
	end
	
	local playerStatus = player.leaderstats.Status.Value
	if curQuest.Status and playerStatus ~= curQuest.Status then
		return false
	end

	return true
end


function Quests.GiveQuest(Player, giverNum)
	local newQuest = {}

	-- Find the next quest and its state specific to the player
	local NextQuestData = FindNextQuest(Player, giverNum)
	local NextQuest = NextQuestData[1]
	local State = NextQuestData[2]

	-- Initialize the new quest based on state
	if State == "New Quest" then
		newQuest = NextQuest or {}
		newQuest.CurrentDialog = 0
		newQuest.State = State
	else
		newQuest = NextQuest or {}
		newQuest.State = State
		-- Make sure NotFinishedText is player-specific or dynamic if needed
		newQuest.NotFinishedText = NextQuest and NextQuest.NotfinishedText or "You have not completed the required tasks yet."
	end

	-- Ensure PlayerData is initialized correctly
	newQuest.PlayerData = newQuest.PlayerData or {}

	function newQuest:PerformDialog(Player)
		-- Initialize playerData for the specific player if it doesn't exist
		local playerData = self.PlayerData[Player.UserId]
		if not playerData then
			playerData = { CurrentDialog = 0 }
			self.PlayerData[Player.UserId] = playerData
		end

		-- Check the current state and perform the appropriate action
		if self.State == "Hasn't Finished" then
			-- Make sure NotFinishedText is specific to the current quest
			local notFinishedText = self.NotFinishedText or "You have not completed the required tasks yet."
			TypeQuestDialog:FireClient(Player, notFinishedText, true)
			return
		elseif self.State == "DoneWithThisGiver" then
			TypeQuestDialog:FireClient(Player, "Find the next quest giver!", true)
			return
		elseif self.State == "NoMoreQuests" then
			TypeQuestDialog:FireClient(Player, "Congratulations! You have completed all the quests. More quests coming soon, keep on grinding.", true)
			return
		end

		-- Increment dialog index only for the specific player
		playerData.CurrentDialog = playerData.CurrentDialog + 1

		local dialog = self.Dialog[playerData.CurrentDialog]

		-- Determine if it's the last dialog for this player
		local isLastDialog = self.Dialog[playerData.CurrentDialog + 1] == nil

		if isLastDialog then 
			-- Only add to the quest list if it is not the first dialog
			if playerData.CurrentDialog > 1 then
				self:AddToQuestList(Player)
			end
		else
			-- Add to quest list if it's the first dialog
			if playerData.CurrentDialog == 1 then
				self:AddToQuestList(Player)
			end
		end

		-- Send the dialog to the specific player
		TypeQuestDialog:FireClient(Player, dialog, isLastDialog)
	end

	function newQuest:AddToQuestList(Player)
		if self.Stats == nil or next(self.Stats) == nil then return end
		local PlrGui = Player.PlayerGui
		local QuestsGui = PlrGui:FindFirstChild("Quests")
		local QFrame = QuestsGui and QuestsGui:FindFirstChild("QuestsFrame")
		local Bg = QFrame and QFrame:FindFirstChild("Bg")

		if not Bg then
			warn("Quest UI elements not found for player: " .. Player.Name)
			return
		end

		local MainQuests = Bg:FindFirstChild("MainQuests")
		local QuestNameLabel = MainQuests and MainQuests:FindFirstChild("QuestName")

		local Frame = MainQuests and MainQuests:FindFirstChild("Frame")
		local BaseStatFrame = Frame and Frame:FindFirstChild("BaseProgressFrame")
		local RewardsFrame = Frame and Frame:FindFirstChild("RewardsFrame")

		if not (QuestNameLabel and Frame and BaseStatFrame) then
			warn("Quest UI components missing for player: " .. Player.Name)
			return
		end

		QuestNameLabel.Text = self.Name

		-- Clear previous content
		for _, Child in ipairs(Frame:GetChildren()) do
			if Child ~= BaseStatFrame and Child ~= RewardsFrame and Child:IsA("Frame") then
				Child:Destroy()
			end
		end

		-- Update Progress Bars
		for Stat, Req in pairs(self.Stats) do
			local Clone = BaseStatFrame:Clone()
			local ProgLabel = Clone:FindFirstChild("ProgressLabel")
			local Fill = Clone:FindFirstChild("Fill")

			local QStat = Player.PhysicalStats:FindFirstChild(Stat)
			if not (ProgLabel and Fill and QStat) then
				warn("Quest stat or progress elements missing for player: " .. Player.Name)
				return
			end

			ProgLabel.Text = abbreviateNumber(QStat.Value) .. "/" .. abbreviateNumber(Req) .. " " .. Stat

			local Ratio = math.min(QStat.Value / Req, 1)

			local tweenInfo = TweenInfo.new(1.5, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut)
			local tween = TweenService:Create(Fill, tweenInfo, {Size = UDim2.new(Ratio, 0, 1, 0)})
			tween:Play()

			QStat.Changed:Connect(function()
				ProgLabel.Text = abbreviateNumber(QStat.Value) .. "/" .. abbreviateNumber(Req) .. " " .. Stat
				Ratio = math.min(QStat.Value / Req, 1)
				local tweenUpdate = TweenService:Create(Fill, tweenInfo, {Size = UDim2.new(Ratio, 0, 1, 0)})
				tweenUpdate:Play()
			end)

			Clone.Name = Stat .. "ProgBar"
			Clone.Visible = true
			Clone.Parent = Frame
		end

		-- Display Class Requirement
		local ClassReq = Player.leaderstats.Class.Value -- Get current class from leaderstats
		local ClassRequirement = self.Class -- Assuming self.Class is the required class for the quest

		-- Only display class requirement if the class is different
		if ClassRequirement then
			local Clone = BaseStatFrame:Clone()
			local ProgLabel = Clone:FindFirstChild("ProgressLabel")
			local Fill = Clone:FindFirstChild("Fill")

			-- Update the progress label and fill based on the class requirement
			ProgLabel.Text = "Elevate to " ..ClassRequirement

			-- Set the fill ratio based on class requirement
			local Ratio = (ClassReq == ClassRequirement) and 1 or 0

			local tweenInfo = TweenInfo.new(1.5, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut)
			local tween = TweenService:Create(Fill, tweenInfo, {Size = UDim2.new(Ratio, 0, 1, 0)})
			tween:Play()

			-- Update the progress bar when class changes
			Player.leaderstats.Class.Changed:Connect(function()
				local newClass = Player.leaderstats.Class.Value
				ProgLabel.Text = "Elevate to " ..ClassRequirement
				local newRatio = (newClass == ClassRequirement) and 1 or 0
				local tweenUpdate = TweenService:Create(Fill, tweenInfo, {Size = UDim2.new(newRatio, 0, 1, 0)})
				tweenUpdate:Play()
			end)

			Clone.Name = "ClassReqProgBar"
			Clone.Visible = true
			Clone.Parent = Frame
		end
		
		local StatusReq = Player.leaderstats.Status.Value
		local StatusRequirement = self.Status
		
		if StatusRequirement then
			local Clone = BaseStatFrame:Clone()
			local ProgLabel = Clone:FindFirstChild("ProgressLabel")
			local Fill = Clone:FindFirstChild("Fill")

			-- Update the progress label and fill based on the class requirement
			ProgLabel.Text = "Become a "..StatusRequirement

			-- Set the fill ratio based on class requirement
			local Ratio = (StatusReq == StatusRequirement) and 1 or 0
			
			local tweenInfo = TweenInfo.new(1.5, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut)
			local tween = TweenService:Create(Fill, tweenInfo, {Size = UDim2.new(Ratio, 0, 1, 0)})
			tween:Play()
			
			Player.leaderstats.Status.Changed:Connect(function()
				local newStatus = Player.leaderstats.Status.Value
				ProgLabel.Text = "Become a "..StatusRequirement
				local newRatio = (newStatus == StatusRequirement) and 1 or 0
				local tweenUpdate = TweenService:Create(Fill, tweenInfo, {Size = UDim2.new(newRatio, 0, 1, 0)})
				tweenUpdate:Play()
			end)
			
			Clone.Name = "StatusReqProgBar"
			Clone.Visible = true
			Clone.Parent = Frame
		end
		
		local TweenService = game:GetService("TweenService")

		-- Display Fusion Requirement
		local FusionReq = Player.leaderstats.Fusion and Player.leaderstats.Fusion.Value -- Get current fusion level from leaderstats
		local FusionRequirement = self.Fusion -- Assuming self.Fusion is the required fusion level for the quest

		-- Debugging output to ensure correct values
		print("Current Fusion Level: " .. (FusionReq or "nil"))
		print("Required Fusion Level: " .. (FusionRequirement or "nil"))

		-- Only display fusion requirement if the fusion requirement is set and not nil
		if FusionRequirement and FusionReq then
			local Clone = BaseStatFrame:Clone()
			local ProgLabel = Clone:FindFirstChild("ProgressLabel")
			local Fill = Clone:FindFirstChild("Fill")

			-- Update the progress label and fill based on the fusion requirement
			ProgLabel.Text = "Reach Fusion Level " .. FusionRequirement

			-- Calculate the fill ratio based on the fusion requirement
			local Ratio = (FusionReq == FusionRequirement) and 1 or 0

			-- Create and play the tween for initial progress
			local tweenInfo = TweenInfo.new(1.5, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut)
			local tween = TweenService:Create(Fill, tweenInfo, {Size = UDim2.new(Ratio, 0, 1, 0)})
			tween:Play()

			-- Update the progress bar when fusion level changes
			Player.leaderstats.Fusion.Changed:Connect(function()
				local newFusion = Player.leaderstats.Fusion and Player.leaderstats.Fusion.Value
				print("Updated Fusion Level: " .. (newFusion or "nil")) -- Debugging output
				ProgLabel.Text = "Reach Fusion Level " .. (FusionRequirement or "unknown")
				local newRatio = (newFusion == FusionRequirement) and 1 or 0
				local tweenUpdate = TweenService:Create(Fill, tweenInfo, {Size = UDim2.new(newRatio, 0, 1, 0)})
				tweenUpdate:Play()
			end)

			Clone.Name = "FusionReqProgBar"
			Clone.Visible = true
			Clone.Parent = Frame
		else
			print("FusionRequirement or FusionReq is nil. Progress bar will not be displayed.")
		end


		-- Update Rewards Frame
		local TokensLabel = RewardsFrame:FindFirstChild("TokensLabel")
		if not TokensLabel then
			TokensLabel = Instance.new("TextLabel")
			TokensLabel.Name = "TokensLabel"
			TokensLabel.Size = UDim2.new(1, 0, 1, 0)
			TokensLabel.BackgroundTransparency = 1
			TokensLabel.TextColor3 = Color3.new(1, 1, 1)
			TokensLabel.TextScaled = true
			TokensLabel.Parent = RewardsFrame
		end
		TokensLabel.Text = "Reward: " .. abbreviateNumber(self.Rewards.Tokens) .. " Tokens"

		RewardsFrame.Visible = true
	end

	-- Remove or hide quest UI if all quests are completed
	if State == "NoMoreQuests" then
		local PlrGui = Player.PlayerGui
		local QuestsGui = PlrGui.Quests
		local QFrame = QuestsGui.QuestsFrame
		local MainQuests = QFrame.Bg.MainQuests
		local Frame = MainQuests.Frame
		for _, Child in ipairs(Frame:GetChildren()) do
			if Child:IsA("Frame") then
				Child:Destroy()
			end
		end
		local TokensLabel = Frame:FindFirstChild("TokensLabel")
		if TokensLabel then
			TokensLabel:Destroy()
		end
		MainQuests.QuestName.Text = "More quests coming soon!"
	end

	return newQuest
end


return Quests