-- StarterPlayerScripts: FireAbilityClient.lua

local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local SoundService = game:GetService("SoundService")

local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")

-- GUI elements
local playerGui = player:WaitForChild("PlayerGui")
local fireAttackGui = playerGui:WaitForChild("FireAttackGui")
local heatFrame = fireAttackGui:WaitForChild("HeatFrame")
local currentHeat = heatFrame:WaitForChild("CurrentHeat")

-- Buttons and other GUI elements
local holdButton = fireAttackGui:WaitForChild("Hold")
local overheatGui = playerGui:FindFirstChild("OverheatGui")
local petGui = playerGui:FindFirstChild("PetGui")
local codeGui = playerGui:FindFirstChild("CodeGui")
local shuDisplayer = playerGui:FindFirstChild("SHUDisplayer")

-- Constants
local DAMAGE_INTERVAL = 0.4
local FIRE_PARTICLE_LIFETIME = 1
local FIRE_PARTICLE_SPEED = 50
local FIRE_PARTICLE_RATE = 60
local FIRE_PARTICLE_SIZE = Vector3.new(2, 2, 2)
local FIRE_PARTICLE_SPREAD = 15
local FIRE_PARTICLE_ROTATION_SPEED = 720
local MIN_HEAT_REQUIRED = 0.01
local MIN_STAMINA_REQUIRED = 0.01
local INDICATOR_COOLDOWN = 0.5

-- Remote events
local fireAbilityEvent = ReplicatedStorage:WaitForChild("FireAbilityEvent")
local dealDamageEvent = ReplicatedStorage:WaitForChild("DealDamageEvent")
local createFireParticleEvent = ReplicatedStorage:WaitForChild("CreateFireParticleEvent")

-- Variables
local isUsingAbility = false
local fireParticles = {}
local isKeyHeld = false
local isMobileButtonHeld = false
local lastIndicatorTime = 0
local isPlayerAlive = true

-- Sound effect
local fireSound = Instance.new("Sound")
fireSound.SoundId = "rbxassetid://9068935533"
fireSound.Parent = SoundService

-- Damage indicator template
local damageIndicatorTemplate = ReplicatedStorage:WaitForChild("DMGIndicator")

-- Function to check if player is in arena
local function isPlayerInArena()
    local isInArena = player:FindFirstChild("IsInArena")
    return isInArena and isInArena.Value
end

-- Function to format damage numbers with suffixes
local function formatNumber(number)
    local suffixes = {
        "", "K", "M", "B", "T", "Qa", "Qi", "Sx", "Sp", "Oc", "No", "Dc", "Ud", "Dd", "Td",
        "Qad", "Qid", "Sxd", "Spd", "Ocd", "Nod", "Vg", "Uvg", "Tvg", "Qavg", "Qivg",
        "Sxvg", "Spvg", "Ocvg", "Novg", "Tg", "Utg", "Dtg", "Tdtg", "Qatg", "Qitg",
        "Sxtg", "Sptg", "Octg", "Notg"
    }
    local suffixIndex = 1
    while number >= 1000 and suffixIndex < #suffixes do
        number = number / 1000
        suffixIndex = suffixIndex + 1
    end
    if suffixIndex >= #suffixes then
        return string.format("%.3f%s+", number, suffixes[#suffixes])
    elseif math.floor(number) == number then
        return string.format("%d%s", number, suffixes[suffixIndex])
    else
        return string.format("%.3f%s", number, suffixes[suffixIndex]):gsub("%.?0+$", "")
    end
end

-- Function to create damage indicator
local function createDamageIndicator(target)
    local currentTime = tick()

    -- Ensure that the indicator only shows once every 0.5 seconds
    if currentTime - lastIndicatorTime < INDICATOR_COOLDOWN then
        return
    end

    lastIndicatorTime = currentTime

    -- Check if the target is still alive
    local humanoid = target:FindFirstChildOfClass("Humanoid")
    if not humanoid or humanoid.Health <= 0 then
        return
    end

    -- Remove existing damage indicator if present
    local existingIndicator = target:FindFirstChild("DMGIndicator")
    if existingIndicator then
        existingIndicator:Destroy()
    end

    local dmgIndicator = damageIndicatorTemplate:Clone()
    dmgIndicator.Name = "DMGIndicator"
    dmgIndicator.Parent = target
    local textLabel = dmgIndicator:FindFirstChild("TextLabel")

    if textLabel then
        local currentSHU = player:GetAttribute("CurrentSHU") or 1 -- Default to 1 if SHU is not set
        local formattedDamage = formatNumber(currentSHU) -- Format the SHU value for display

        print("Formatted Damage:", formattedDamage) -- Debugging line

        textLabel.Text = string.format("-%s", formattedDamage)

        -- Reset and play animation
        textLabel.Size = UDim2.new(0, 0, 0, 0)
        textLabel.TextTransparency = 0

        -- Grow animation
        local growTween = TweenService:Create(textLabel, TweenInfo.new(0.3), {Size = UDim2.new(0, 100, 0, 30)})
        growTween:Play()

        -- Fade out and remove
        delay(0.55, function()
            local fadeTween = TweenService:Create(textLabel, TweenInfo.new(0.2), {TextTransparency = 1})
            fadeTween:Play()
            fadeTween.Completed:Connect(function()
                dmgIndicator:Destroy()
            end)
        end)
    end
end

-- Function to create a fire particle (client-side)
local function createFireParticleClient(position, direction)
    local firePart = Instance.new("Part")
    firePart.Size = FIRE_PARTICLE_SIZE
    firePart.Anchored = false
    firePart.CanCollide = false
    firePart.Position = position
    firePart.BrickColor = BrickColor.new("Bright orange")
    firePart.Material = Enum.Material.Neon
    firePart.Transparency = 0

    -- Apply spread
    local spreadX = math.rad(math.random(-FIRE_PARTICLE_SPREAD, FIRE_PARTICLE_SPREAD))
    local spreadY = math.rad(math.random(-FIRE_PARTICLE_SPREAD, FIRE_PARTICLE_SPREAD))
    direction = CFrame.fromOrientation(spreadX, spreadY, 0) * direction

    local bodyVelocity = Instance.new("BodyVelocity")
    bodyVelocity.Velocity = direction * FIRE_PARTICLE_SPEED
    bodyVelocity.MaxForce = Vector3.new(1e5, 1e5, 1e5)
    bodyVelocity.Parent = firePart

    -- Add rotation
    local bodyAngularVelocity = Instance.new("BodyAngularVelocity")
    bodyAngularVelocity.AngularVelocity = Vector3.new(
        math.random(-FIRE_PARTICLE_ROTATION_SPEED, FIRE_PARTICLE_ROTATION_SPEED),
        math.random(-FIRE_PARTICLE_ROTATION_SPEED, FIRE_PARTICLE_ROTATION_SPEED),
        math.random(-FIRE_PARTICLE_ROTATION_SPEED, FIRE_PARTICLE_ROTATION_SPEED)
    )
    bodyAngularVelocity.MaxTorque = Vector3.new(1e5, 1e5, 1e5)
    bodyAngularVelocity.Parent = firePart

    firePart.Parent = workspace
    table.insert(fireParticles, firePart)

    -- Tween transparency and size
    TweenService:Create(firePart, TweenInfo.new(FIRE_PARTICLE_LIFETIME), {
        Transparency = 1,
        Size = FIRE_PARTICLE_SIZE * 0.1
    }):Play()

    -- Remove particle after lifetime
    delay(FIRE_PARTICLE_LIFETIME, function()
        local index = table.find(fireParticles, firePart)
        if index then
            table.remove(fireParticles, index)
        end
        firePart:Destroy()
    end)
end

-- Function to check for nearby characters and deal damage
local function checkForDamage()
    for _, firePart in ipairs(fireParticles) do
        local nearbyParts = workspace:GetPartBoundsInRadius(firePart.Position, FIRE_PARTICLE_SIZE.X * 2)
        for _, part in ipairs(nearbyParts) do
            local character = part:FindFirstAncestorOfClass("Model")
            if character and character:FindFirstChildOfClass("Humanoid") and character ~= player.Character then
                dealDamageEvent:FireServer(character) -- Fire server event to deal damage
                createDamageIndicator(character) -- Show the damage indicator
            end
        end
    end
end

-- Function to stop the fire ability
local function stopFireAbility()
    isUsingAbility = false
    fireAbilityEvent:FireServer(false)
    RunService:UnbindFromRenderStep("FireAbility")
    fireSound:Stop()
end

-- Function to check if the player can use the ability
local function canUseAbility()
    if not isPlayerAlive or not isPlayerInArena() then
        return false
    end
    local currentHeat = player:GetAttribute("CurrentHeat") or 0
    local currentStamina = player:GetAttribute("CurrentStamina") or 1
    return currentHeat > MIN_HEAT_REQUIRED and currentStamina > MIN_STAMINA_REQUIRED
end

-- Function to start the fire ability
local function startFireAbility()
    if not canUseAbility() then return end

    isUsingAbility = true
    fireAbilityEvent:FireServer(true)
    fireSound:Play()

    local lastParticleTime = 0
    local particleInterval = 1 / FIRE_PARTICLE_RATE

    RunService:BindToRenderStep("FireAbility", Enum.RenderPriority.Character.Value, function(deltaTime)
        if not (isKeyHeld or isMobileButtonHeld) or not canUseAbility() then
            stopFireAbility()
            return
        end

        lastParticleTime = lastParticleTime + deltaTime
        if lastParticleTime >= particleInterval then
            lastParticleTime = lastParticleTime - particleInterval
            local direction = character.PrimaryPart.CFrame.LookVector
            local firePosition = character.Head.Position + direction * 2
            createFireParticleEvent:FireServer(firePosition, direction) -- Fire server event to create particle
        end

        checkForDamage()
    end)
end

-- Function to update the heat display
local function updateHeatDisplay()
    local heat = player:GetAttribute("CurrentHeat") or 0
    TweenService:Create(currentHeat, TweenInfo.new(0.1), {Size = UDim2.new(heat, 0, 1, 0)}):Play()
end

-- Function to handle GUI visibility based on arena status and device type
local function updateGuiVisibility()
    local inArena = isPlayerInArena()
    
    -- Set holdButton visibility based on device type
    holdButton.Visible = UserInputService.TouchEnabled

    if inArena then
        -- Hide blacklisted GUIs
        if overheatGui then overheatGui.Enabled = false end
        if petGui then petGui.Enabled = false end
        if codeGui then codeGui.Enabled = false end
        if shuDisplayer then shuDisplayer.Enabled = false end
        
        -- Show FireAttackGui
        fireAttackGui.Enabled = true
    else
        -- Show blacklisted GUIs
        if overheatGui then overheatGui.Enabled = true end
        if petGui then petGui.Enabled = true end
        if codeGui then codeGui.Enabled = true end
        if shuDisplayer then shuDisplayer.Enabled = true end
        
        -- Hide FireAttackGui
        fireAttackGui.Enabled = false
    end
end

-- Input handling for PC
UserInputService.InputBegan:Connect(function(input, gameProcessed)
    if input.KeyCode == Enum.KeyCode.F and not gameProcessed then
        isKeyHeld = true
        if not isUsingAbility and canUseAbility() then
            startFireAbility()
        end
    end
end)

UserInputService.InputEnded:Connect(function(input, gameProcessed)
    if input.KeyCode == Enum.KeyCode.F and not gameProcessed then
        isKeyHeld = false
        stopFireAbility()
    end
end)

-- Input handling for mobile (using the existing Hold button)
holdButton.MouseButton1Down:Connect(function()
    isMobileButtonHeld = true
    if not isUsingAbility and canUseAbility() then
        startFireAbility()
    end
end)

holdButton.MouseButton1Up:Connect(function()
    isMobileButtonHeld = false
    stopFireAbility()
end)

-- Update loop for GUI visibility
player:GetAttributeChangedSignal("IsInArena"):Connect(updateGuiVisibility)
player:GetAttributeChangedSignal("IsInArena"):Connect(function()
    if isUsingAbility and not canUseAbility() then
        stopFireAbility()
    end
    updateGuiVisibility()
end)

-- Listen for changes in the IsInArena value initially
updateGuiVisibility()

-- Listen for the server's signal to create particles
createFireParticleEvent.OnClientEvent:Connect(function(position, direction)
    createFireParticleClient(position, direction)
end)

-- Initial setup
updateHeatDisplay()

-- Listen for changes in heat and stamina to update GUI and ability status
player:GetAttributeChangedSignal("CurrentHeat"):Connect(updateHeatDisplay)
player:GetAttributeChangedSignal("CurrentHeat"):Connect(function()
    if isUsingAbility and not canUseAbility() then
        stopFireAbility()
    end
end)

player:GetAttributeChangedSignal("CurrentStamina"):Connect(function()
    if isUsingAbility and not canUseAbility() then
        stopFireAbility()
    end
end)

-- Cleanup when player dies
humanoid.Died:Connect(function()
    isPlayerAlive = false
    stopFireAbility()
end)

-- Cleanup when character is removed
character.AncestryChanged:Connect(function(_, parent)
    if not parent then
        stopFireAbility()
    end
end) local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")

-- Remote events
local fireAbilityEvent = ReplicatedStorage:WaitForChild("FireAbilityEvent")
local dealDamageEvent = ReplicatedStorage:WaitForChild("DealDamageEvent")
local createFireParticleEvent = ReplicatedStorage:WaitForChild("CreateFireParticleEvent")

-- Constants
local COOLDOWN_DURATION = 5
local HEAT_REGENERATION_RATE = 0.2
local TOUCH_COOLDOWN = 0.205

-- Player data
local playerData = {}

-- Table to track last damage time for each target
local lastDamageTime = {}

-- Function to get SHU value from player
local function getPlayerSHU(player)
	local leaderstats = player:FindFirstChild("leaderstats")
	if leaderstats then
		local shuValue = leaderstats:FindFirstChild("SHU")
		if shuValue then
			return shuValue.Value
		end
	end
	return 1 -- Default SHU value
end

-- Function to check if player is in arena
local function isPlayerInArena(player)
	local isInArena = player:FindFirstChild("IsInArena")
	return isInArena and isInArena.Value
end

-- Function to reset player data when they respawn
local function resetPlayerData(player)
	local data = playerData[player]
	if data then
		data.heat = 1
		data.lastUseTime = 0
		data.isUsingAbility = false
		data.isPlayerAlive = true
		player:SetAttribute("CurrentHeat", 1)
		player:SetAttribute("CurrentSHU", getPlayerSHU(player))
	end
end

-- Initialize player data when they join
local function initializePlayerData(player)
	playerData[player] = {
		heat = 1,
		lastUseTime = 0,
		isUsingAbility = false,
		isPlayerAlive = true
	}
	player:SetAttribute("CurrentHeat", 1)
	player:SetAttribute("CurrentSHU", getPlayerSHU(player))

	-- Update SHU attribute when the leaderboard SHU value changes
	local leaderstats = player:WaitForChild("leaderstats")
	local shuValue = leaderstats:WaitForChild("SHU")
	shuValue.Changed:Connect(function(newValue)
		player:SetAttribute("CurrentSHU", newValue)
	end)

	-- Handle player respawn
	player.CharacterAdded:Connect(function(character)
		local humanoid = character:WaitForChild("Humanoid")

		-- Reset player data on respawn
		resetPlayerData(player)

		humanoid.Died:Connect(function()
			local data = playerData[player]
			if data then
				data.isUsingAbility = false
				data.isPlayerAlive = false
				fireAbilityEvent:FireClient(player, false)
			end
		end)
	end)
end

-- Handle when a player joins or leaves
Players.PlayerAdded:Connect(initializePlayerData)
Players.PlayerRemoving:Connect(function(player)
	playerData[player] = nil
	lastDamageTime[player] = nil
end)

-- Handle fire ability activation/deactivation
fireAbilityEvent.OnServerEvent:Connect(function(player, isUsing)
	local data = playerData[player]
	if not data or not data.isPlayerAlive or not isPlayerInArena(player) then return end
	data.isUsingAbility = isUsing
	if isUsing then
		data.lastUseTime = tick()
	end
end)

-- Handle damage dealing with throttling
dealDamageEvent.OnServerEvent:Connect(function(player, target)
	if not isPlayerInArena(player) then return end

	local currentTime = tick()
	if lastDamageTime[target] and currentTime - lastDamageTime[target] < TOUCH_COOLDOWN then
		return -- Prevent spamming damage
	end

	lastDamageTime[target] = currentTime
	local damage = getPlayerSHU(player)

	local targetHumanoid = target:FindFirstChild("Humanoid")
	if targetHumanoid then
		targetHumanoid:TakeDamage(damage)
	end
end)

-- Handle fire particle creation and replication to all clients
createFireParticleEvent.OnServerEvent:Connect(function(player, position, direction)
	if not isPlayerInArena(player) then return end
	-- Broadcast the particle creation to all clients
	createFireParticleEvent:FireAllClients(position, direction)
end)

-- Main loop for handling heat and cooldown mechanics
RunService.Heartbeat:Connect(function()
	for player, data in pairs(playerData) do
		local currentTime = tick()
		local elapsedTime = currentTime - data.lastUseTime

		-- Heat mechanics
		if data.isUsingAbility and isPlayerInArena(player) then
			data.heat = math.max(0, data.heat - elapsedTime / COOLDOWN_DURATION)
			if data.heat <= 0 then
				data.isUsingAbility = false -- Automatically stop the ability when heat is depleted
			end
		else
			data.heat = math.min(1, data.heat + HEAT_REGENERATION_RATE * elapsedTime)
		end

		-- Update player's heat attribute
		data.lastUseTime = currentTime
		player:SetAttribute("CurrentHeat", data.heat)
	end
end) (blacklist guis: "OverheatGui" "PetGui" "CodeGui" "SHUDisplayer" only when is arena value to true. the fireattackgui gets enabled. if the player has died and respawned. they get the following blacklisted guis back, show what code)