JIT
overhauling the timer gui for a roblox game
this code. local currentTimer = nil local timerActive = false function createTimerGui(player, triggeringPart) if timerActive then return end timerActive = true timerStatusEvent:FireClient(player, true, false) local playerGui = player:WaitForChild("PlayerGui") if playerGui:FindFirstChild("TimerGui") then return end local cfg = Config.TimerGui local duration = (triggeringPart and triggeringPart:GetAttribute("TimerDuration")) or Config.MainTimerDuration local screenGui = Instance.new("ScreenGui") screenGui.Name = "TimerGui" screenGui.ResetOnSpawn = false screenGui.IgnoreGuiInset = true screenGui.Parent = playerGui local backdrop = Instance.new("Frame") backdrop.Size = UDim2.new(1, 0, 1, 0) backdrop.BackgroundColor3 = cfg.backdropColor backdrop.BackgroundTransparency = cfg.backdropTransparency backdrop.ZIndex = 1 backdrop.Parent = screenGui local container = Instance.new("Frame") container.Size = UDim2.new(0.4, 0, 0.4, 0) container.AnchorPoint = Vector2.new(0.5, 0.5) container.Position = UDim2.new(0.5, 0, -0.5, 0) -- Start offscreen container.BackgroundTransparency = 1 container.ZIndex = 2 container.Parent = screenGui local ring = Instance.new("ImageLabel") ring.Name = "CountdownRing" ring.Size = UDim2.new(1, 0, 1, 0) ring.AnchorPoint = Vector2.new(0.5, 0.5) ring.Position = UDim2.new(0.5, 0, 0.5, 0) ring.BackgroundTransparency = 1 ring.Image = cfg.ringImageId ring.ImageColor3 = cfg.ringColor ring.ScaleType = Enum.ScaleType.Slice ring.SliceCenter = Rect.new(64, 64, 192, 192) ring.SliceScale = 0.5 ring.Parent = container local timerLabel = Instance.new("TextLabel") timerLabel.Name = "TimerLabel" timerLabel.AnchorPoint = Vector2.new(0.5, 0.5) timerLabel.Position = UDim2.new(0.5, 0, 0.5, 0) timerLabel.Size = UDim2.new(0.8, 0, 0.5, 0) timerLabel.BackgroundTransparency = 1 timerLabel.Font = cfg.labelFont timerLabel.TextSize = cfg.labelTextSize timerLabel.TextColor3 = cfg.labelTextColor timerLabel.TextStrokeColor3 = cfg.labelStrokeColor timerLabel.TextStrokeTransparency = 0 timerLabel.Text = string.format("%d:%02d", math.floor(duration/60), duration%60) timerLabel.Parent = container local barBg = Instance.new("Frame") barBg.AnchorPoint = Vector2.new(0.5, 1) barBg.Position = UDim2.new(0.5, 0, 1, -cfg.barPadding) barBg.Size = UDim2.new(0.6, 0, 0, cfg.barHeight) barBg.BackgroundColor3 = cfg.barBgColor barBg.BackgroundTransparency = 0.3 barBg.Parent = container local bar = Instance.new("Frame") bar.Name = "ProgressBar" bar.Size = UDim2.new(1, 0, 1, 0) bar.BackgroundColor3 = cfg.barColor bar.Parent = barBg -- Animate slide in TweenService:Create(container, TweenInfo.new(1, Enum.EasingStyle.Quad), { Position = UDim2.new(0.5, 0, 0.4, 0) }):Play() local tickSound = Instance.new("Sound", screenGui) tickSound.SoundId = cfg.tickSoundId tickSound.Volume = cfg.tickVolume tickSound.Looped = false local remaining = duration local function updateUI() timerLabel.Text = string.format("%d:%02d", math.floor(remaining / 60), remaining % 60) local pct = remaining / duration ring.ImageTransparency = 1 - pct bar.Size = UDim2.new(pct, 0, 1, 0) if pct > 0.5 then bar.BackgroundColor3 = Color3.new(0, 1, 0) elseif pct > 0.25 then bar.BackgroundColor3 = Color3.new(1, 1, 0) else bar.BackgroundColor3 = Color3.new(1, 0, 0) end tickSound:Play() if remaining <= 10 then TweenService:Create(container, TweenInfo.new(0.15), {Size = UDim2.new(0.42, 0, 0.42, 0)}):Play() TweenService:Create(container, TweenInfo.new(0.15), {Size = UDim2.new(0.4, 0, 0.4, 0)}):Play() end if remaining == 30 and cfg.dingSoundId then local ding = Instance.new("Sound", screenGui) ding.SoundId = cfg.dingSoundId ding.Volume = cfg.dingVolume ding:Play() Debris:AddItem(ding, 3) end end local function onComplete() TweenService:Create(container, TweenInfo.new(1), { Position = UDim2.new(0.5, 0, -0.5, 0) }):Play() TweenService:Create(backdrop, TweenInfo.new(1), {BackgroundTransparency = 1}):Play() task.delay(1, function() screenGui:Destroy() timerActive = false timerStatusEvent:FireClient(player, false, false) end) end currentTimer = Timer.new(duration, timerLabel, player, onComplete, (triggeringPart and not triggeringPart:GetAttribute("DisableOvertime"))) currentTimer._onTick = updateUI function currentTimer:start() task.spawn(function() while not self.cancelled do if self.remaining > 0 then self.remaining -= 1 if self._onTick then self._onTick() end else break end task.wait(1) end if not self.cancelled and self.onComplete then self.onComplete() end end) end currentTimer:start() end give the gui an entire overhaul of details and improved gui --[[ TimerDemonSystem.server.lua Modular Roblox Timer Demon System (Overtime Spawns Demon and Effects) Place this script in ServerScriptService All configuration and logic is in this single file for easy modification. ]] --------------------------------------------------------------------- -- CONFIGURATION SECTION --------------------------------------------------------------------- local Config = {} -- Main timer duration (in seconds) Config.MainTimerDuration = 103 -- Audio presets for timer activation Config.AudioPresets = { preset1 = { soundId = "rbxassetid://133014492553616", volume = 10, pitch = 1.05, looped = false, }, preset2 = { soundId = "rbxassetid://71472790339951", volume = 15, pitch = 1.15, looped = false, }, } -- Demon spawn settings Config.Demon = { offset = Vector3.new(0, 10, -15), -- relative to player look direction size = Vector3.new(10, 10, 10), color = Color3.fromRGB(17, 17, 17), material = Enum.Material.Neon, shape = Enum.PartType.Ball, particleTexture = "http://www.roblox.com/asset/?id=2996538390", smileTexture = "rbxassetid://120549545145829", } -- Overtime sound settings Config.OvertimeSounds = { run = { soundId = "rbxassetid://1034263055", volume = 0.5, pitch = 1, effects = { DistortionSoundEffect = { Level = 0.4 }, PitchShiftSoundEffect = { Octave = 0.35 }, EqualizerSoundEffect = { LowGain = 10, MidGain = 10 }, ReverbSoundEffect = { WetLevel = 2.5 }, } }, bell = { soundId = "rbxassetid://78781475442496", volume = 0.5, pitch = 0.9, effects = { DistortionSoundEffect = { Level = 0.35 }, EqualizerSoundEffect = { LowGain = 10, MidGain = 10 }, PitchShiftSoundEffect = { Octave = 0.5 }, ReverbSoundEffect = { WetLevel = 2.5 }, } }, laugh = { soundId = "rbxassetid://18186817573", volume = 1, pitch = 0.75, minDistance = 500, maxDistance = 1500, effects = { DistortionSoundEffect = { Level = 0.65 }, } } } -- Death sounds Config.DeathSounds = { { soundId = "rbxassetid://169310273", volume = 0.5, pitch = 0.8, maxDistance = 750, minDistance = 0 }, { soundId = "rbxassetid://82176913611683", volume = 1, pitch = 1, maxDistance = 750, minDistance = 0 }, } -- Decal settings Config.Decal = { defaultId = "rbxassetid://834811660", winSoundId = "rbxassetid://4879566787", winSoundVolume = 1, winSoundPitch = 1, displayTime = 5, } -- GUI settings Config.TimerGui = { labelSize = UDim2.new(1, 0, 0.05, 0), labelPosition = UDim2.new(0, 0, -0.1, 0), labelFont = Enum.Font.SourceSansBold, labelTextSize = 48, labelTextColor = Color3.new(1, 1, 1), labelBackgroundColor = Color3.new(0, 0, 0), labelBackgroundTransparency = 0.5, tweenTime = 3, tweenPosition = UDim2.new(0, 0, 0.6, 80), } -- Overtime flash colors Config.OvertimeFlashColors = { Color3.new(1, 0, 0), Color3.new(0.5, 0, 1) } Config.OvertimeFlashInterval = 0.25 --------------------------------------------------------------------- -- SERVICES --------------------------------------------------------------------- local TweenService = game:GetService("TweenService") local Players = game:GetService("Players") local Workspace = game:GetService("Workspace") local RunService = game:GetService("RunService") local ReplicatedStorage = game:GetService("ReplicatedStorage") local Debris = game:GetService("Debris") --------------------------------------------------------------------- -- REMOTE EVENT --------------------------------------------------------------------- local timerStatusEvent = ReplicatedStorage:FindFirstChild("TimerStatusEvent") if not timerStatusEvent then timerStatusEvent = Instance.new("RemoteEvent") timerStatusEvent.Name = "TimerStatusEvent" timerStatusEvent.Parent = ReplicatedStorage end --------------------------------------------------------------------- -- STATE --------------------------------------------------------------------- local timerActive = false local soundPlayed = false local currentTimer = nil local activeDecalPlayers = {} --------------------------------------------------------------------- -- UTILITY: SOUND EFFECTS --------------------------------------------------------------------- local function applySoundEffects(sound, effects) for effectType, props in pairs(effects or {}) do local effect = Instance.new(effectType) for k, v in pairs(props) do effect[k] = v end effect.Parent = sound end end --------------------------------------------------------------------- -- DEMON SPAWN & OVERTIME EFFECTS --------------------------------------------------------------------- local function spawnOrbitalDemonWithEffects(player) -- Overtime sounds for _, soundConfig in pairs({Config.OvertimeSounds.run, Config.OvertimeSounds.bell}) do local sound = Instance.new("Sound") sound.Name = "OvertimeSound" sound.SoundId = soundConfig.soundId sound.Volume = soundConfig.volume sound.Pitch = soundConfig.pitch sound.Looped = false sound.Parent = player:FindFirstChild("PlayerGui") or game:GetService("SoundService") applySoundEffects(sound, soundConfig.effects) sound:Play() Debris:AddItem(sound, 20) end -- Red flash GUI local flashGui = Instance.new("ScreenGui") flashGui.Name = "FlashGui" flashGui.ResetOnSpawn = false flashGui.IgnoreGuiInset = true flashGui.Parent = player:WaitForChild("PlayerGui") local redFlash = Instance.new("Frame") redFlash.Size = UDim2.new(1, 0, 1, 0) redFlash.Position = UDim2.new(0, 0, 0, 0) redFlash.BackgroundColor3 = Color3.new(1, 0, 0) redFlash.BackgroundTransparency = 0 redFlash.ZIndex = 10 redFlash.Parent = flashGui local redFlashTween = TweenService:Create(redFlash, TweenInfo.new(5, Enum.EasingStyle.Linear), { BackgroundTransparency = 1 }) redFlashTween:Play() redFlashTween.Completed:Connect(function() flashGui:Destroy() end) -- Demon spawn local character = player.Character if not character or not character:FindFirstChild("HumanoidRootPart") then return end local hrp = character.HumanoidRootPart local lookVec = hrp.CFrame.LookVector local spawnPos = hrp.Position + Vector3.new(0, Config.Demon.offset.Y, 0) - lookVec * math.abs(Config.Demon.offset.Z) local demon = Instance.new("Part") demon.Name = "Orbital Demon" demon.CFrame = CFrame.new(spawnPos) demon.BottomSurface = Enum.SurfaceType.Smooth demon.CanCollide = false demon.TopSurface = Enum.SurfaceType.Smooth demon.Color = Config.Demon.color demon.Material = Config.Demon.material demon.Size = Config.Demon.size demon.Anchored = true demon.Shape = Config.Demon.shape local hitbox = Instance.new("Part") hitbox.Name = "Orbital hitbox" hitbox.CFrame = CFrame.new(spawnPos) hitbox.BottomSurface = Enum.SurfaceType.Smooth hitbox.CanCollide = false hitbox.TopSurface = Enum.SurfaceType.Smooth hitbox.Size = Config.Demon.size / 3.5 hitbox.Anchored = true hitbox.Shape = Config.Demon.shape hitbox.Parent = demon local hitboxweld = Instance.new("WeldConstraint") hitboxweld.Part0 = hitbox hitboxweld.Part1 = demon hitboxweld.Parent = hitbox local heliight = Instance.new("Highlight") heliight.Parent = hitbox -- Attachments and particles local RedVoidcircle = Instance.new("Attachment") RedVoidcircle.Name = "RedVoidcircle" RedVoidcircle.CFrame = CFrame.new(0, -0.25, 0) RedVoidcircle.Position = Vector3.new(0, -0.25, 0) RedVoidcircle.Parent = demon local Redcirclevoid = Instance.new("ParticleEmitter") Redcirclevoid.Name = "Redcirclevoid" Redcirclevoid.Lifetime = NumberRange.new(5, 5) Redcirclevoid.LockedToPart = true Redcirclevoid.Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0, 0), NumberSequenceKeypoint.new(0.5, 1), NumberSequenceKeypoint.new(1, 0)}) Redcirclevoid.Color = ColorSequence.new(Color3.fromRGB(255, 0, 0)) Redcirclevoid.Speed = NumberRange.new(0.175, 0.175) Redcirclevoid.Brightness = 10 Redcirclevoid.Size = NumberSequence.new({NumberSequenceKeypoint.new(0, 4), NumberSequenceKeypoint.new(0.5, 10), NumberSequenceKeypoint.new(1, 4)}) Redcirclevoid.VelocityInheritance = 1 Redcirclevoid.Rate = 100 Redcirclevoid.Texture = Config.Demon.particleTexture Redcirclevoid.RotSpeed = NumberRange.new(380, 380) Redcirclevoid.Orientation = Enum.ParticleOrientation.VelocityPerpendicular Redcirclevoid.Parent = RedVoidcircle local Center = Instance.new("Attachment") Center.Name = "Center" Center.Parent = demon local Redholeblackglow = Instance.new("ParticleEmitter") Redholeblackglow.Name = "Redholeblackglow" Redholeblackglow.Lifetime = NumberRange.new(5, 5) Redholeblackglow.LockedToPart = true Redholeblackglow.LightEmission = 0.8 Redholeblackglow.Color = ColorSequence.new(Color3.fromRGB(0, 0, 0)) Redholeblackglow.Squash = NumberSequence.new(0.5) Redholeblackglow.Speed = NumberRange.new(0, 0) Redholeblackglow.Size = NumberSequence.new(4) Redholeblackglow.ZOffset = -0.5 Redholeblackglow.VelocityInheritance = 1 Redholeblackglow.Rate = 100 Redholeblackglow.Texture = Config.Demon.particleTexture Redholeblackglow.RotSpeed = NumberRange.new(380, 380) Redholeblackglow.Parent = Center local Redholeredglow = Instance.new("ParticleEmitter") Redholeredglow.Name = "Redholeredglow" Redholeredglow.Lifetime = NumberRange.new(5, 5) Redholeredglow.LockedToPart = true Redholeredglow.LightEmission = 0.8 Redholeredglow.Color = ColorSequence.new(Color3.fromRGB(255, 0, 0)) Redholeredglow.Squash = NumberSequence.new(0.5) Redholeredglow.Speed = NumberRange.new(0, 0) Redholeredglow.Size = NumberSequence.new(4.25) Redholeredglow.ZOffset = -0.75 Redholeredglow.VelocityInheritance = 1 Redholeredglow.Rate = 100 Redholeredglow.Texture = Config.Demon.particleTexture Redholeredglow.RotSpeed = NumberRange.new(380, 380) Redholeredglow.Parent = Center local RedholeSmile = Instance.new("ParticleEmitter") RedholeSmile.Name = "RedholeSmile" RedholeSmile.Lifetime = NumberRange.new(0.25, 0.25) RedholeSmile.LockedToPart = true RedholeSmile.Color = ColorSequence.new(Color3.fromRGB(255, 0, 0)) RedholeSmile.Drag = 100 RedholeSmile.Speed = NumberRange.new(0, 0) RedholeSmile.Size = NumberSequence.new(5) RedholeSmile.ZOffset = 7 RedholeSmile.VelocityInheritance = 1 RedholeSmile.Texture = Config.Demon.smileTexture RedholeSmile.RotSpeed = NumberRange.new(-1, 1) RedholeSmile.Parent = Center local Redholeshine = Instance.new("ParticleEmitter") Redholeshine.Name = "Redholeshine" Redholeshine.LightInfluence = 1 Redholeshine.LockedToPart = true Redholeshine.Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0, 1), NumberSequenceKeypoint.new(0.5037407, 0.96875), NumberSequenceKeypoint.new(1, 1)}) Redholeshine.LightEmission = 1 Redholeshine.Color = ColorSequence.new(Color3.fromRGB(255, 0, 4)) Redholeshine.Drag = 100 Redholeshine.Speed = NumberRange.new(0, 0) Redholeshine.Size = NumberSequence.new(1, 10) Redholeshine.ZOffset = 6 Redholeshine.VelocityInheritance = 1 Redholeshine.RotSpeed = NumberRange.new(-15, 15) Redholeshine.Parent = Center -- Laugh sound local laughConfig = Config.OvertimeSounds.laugh local SpawnLaugh = Instance.new("Sound") SpawnLaugh.Name = "SpawnLaugh" SpawnLaugh.Volume = laughConfig.volume SpawnLaugh.Pitch = laughConfig.pitch SpawnLaugh.MinDistance = laughConfig.minDistance SpawnLaugh.MaxDistance = laughConfig.maxDistance SpawnLaugh.SoundId = laughConfig.soundId applySoundEffects(SpawnLaugh, laughConfig.effects) SpawnLaugh.Parent = demon SpawnLaugh:Play() demon.Parent = Workspace hitbox.Touched:Connect(function(hit) local touchedPlayer = Players:GetPlayerFromCharacter(hit.Parent) if touchedPlayer and touchedPlayer == player then local humanoid = player.Character and player.Character:FindFirstChild("Humanoid") if humanoid then humanoid.BreakJointsOnDeath = true for _, soundConfig in ipairs(Config.DeathSounds) do local deathSound = Instance.new("Sound") deathSound.SoundId = soundConfig.soundId deathSound.Volume = soundConfig.volume deathSound.Pitch = soundConfig.pitch deathSound.MaxDistance = soundConfig.maxDistance deathSound.MinDistance = soundConfig.minDistance deathSound.Parent = humanoid deathSound:Play() end local function createBloodEffect(part) local bloody = Instance.new("ParticleEmitter") bloody.Name = "bloody" bloody.LightInfluence = 1 bloody.Lifetime = NumberRange.new(0.35, 0.35) bloody.SpreadAngle = Vector2.new(360, 360) bloody.LockedToPart = false bloody.Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0, 0.59375), NumberSequenceKeypoint.new(0.5236908, 0.4125), NumberSequenceKeypoint.new(1, 0.74375)}) bloody.WindAffectsDrag = true bloody.Drag = 25 bloody.VelocitySpread = 360 bloody.Squash = NumberSequence.new(-0.3000002, 0.2250001) bloody.Speed = NumberRange.new(15, 15) bloody.Size = NumberSequence.new(0, 3.4999995) bloody.Acceleration = Vector3.new(0, -2, 0) bloody.ZOffset = 1 bloody.VelocityInheritance = 0.25 bloody.Rate = 50 bloody.Texture = "rbxassetid://2787218577" bloody.RotSpeed = NumberRange.new(-100, 100) bloody.Parent = part end for _, part in pairs(player.Character:GetChildren()) do if part:IsA("BasePart") then createBloodEffect(part) end end local randomDirection = Vector3.new(math.random(-100, 100), math.random(100, 200), math.random(-100, 100)) local velocity = Instance.new("BodyVelocity") velocity.MaxForce = Vector3.new(10000, 10000, 10000) velocity.Velocity = randomDirection velocity.Parent = player.Character:FindFirstChild("HumanoidRootPart") Debris:AddItem(velocity, 0.25) humanoid.Health = 0 demon:Destroy() wait(0.1) for _, part in ipairs(player.Character:GetDescendants()) do if part:IsA("BallSocketConstraint") or part:IsA("Motor6D") then part:Destroy() end end end end end) local humanoidRootPart = player.Character and player.Character:FindFirstChild("HumanoidRootPart") if humanoidRootPart then local currentVelocity = Vector3.zero local function updateDemonMovement() RunService.Heartbeat:Connect(function(dt) if humanoidRootPart and humanoidRootPart.Parent and demon and demon.Parent then local toTarget = humanoidRootPart.Position - demon.Position local distance = toTarget.Magnitude local desiredVelocity = toTarget.Unit * math.clamp(distance * 2.25, 0, math.huge) local velocityDelta = desiredVelocity - currentVelocity local isAccelerating = velocityDelta.Magnitude > 0.25 and currentVelocity:Dot(velocityDelta) > 0 -- Adjust acceleration/deceleration rates local accelRate = math.clamp(dt * 16 * distance, 0, 0.45) local maxDecel = 0.125 -- 🔽 significantly lowered for softer decel local minDecel = 0 -- 🔽 very low base decel local decelRate = math.clamp(dt * distance * 0.0625, minDecel, maxDecel) local lerpAlpha = isAccelerating and accelRate or decelRate currentVelocity = currentVelocity:Lerp(desiredVelocity, lerpAlpha) demon.CFrame = demon.CFrame + currentVelocity * dt hitbox.CFrame = demon.CFrame end end) end task.delay(5, function() updateDemonMovement() end) end end --------------------------------------------------------------------- -- TIMER CLASS --------------------------------------------------------------------- local Timer = {} Timer.__index = Timer function Timer.new(duration, guiLabel, player, onComplete, allowOvertime) local self = setmetatable({}, Timer) self.duration = duration self.remaining = duration self.guiLabel = guiLabel self.player = player self.onComplete = onComplete self.cancelled = false self.isOvertime = false self.allowOvertime = allowOvertime ~= false return self end function Timer:start(spawnDemonFunc) task.spawn(function() while not self.cancelled do if self.remaining > 0 then self.guiLabel.Text = string.format("%d:%02d", math.floor(self.remaining / 60), self.remaining % 60) self.remaining = self.remaining - 1 else if not self.allowOvertime then self.guiLabel.Text = "0:00" local character = self.player.Character if character then local humanoid = character:FindFirstChildOfClass("Humanoid") if humanoid then humanoid.Health = 0 else self.player:LoadCharacter() end end if self.onComplete then self.onComplete() end break end if not self.isOvertime then self.isOvertime = true self.guiLabel.Text = "Overtime!" timerStatusEvent:FireClient(self.player, true, true) if spawnDemonFunc then spawnDemonFunc(self.player) end self:flashTextColor() end end task.wait(1) end if not self.cancelled and self.onComplete then self.onComplete() end end) end function Timer:cancel() self.cancelled = true end function Timer:flashTextColor() local colors = Config.OvertimeFlashColors local colorIndex = 1 while self.isOvertime and not self.cancelled do self.guiLabel.TextColor3 = colors[colorIndex] colorIndex = colorIndex == 1 and 2 or 1 task.wait(Config.OvertimeFlashInterval) end end --------------------------------------------------------------------- -- DECAL & TELEPORT --------------------------------------------------------------------- local function showDecalAndTeleport(player, part) if activeDecalPlayers[player] then return end activeDecalPlayers[player] = true local playerGui = player:WaitForChild("PlayerGui") local decalGui = Instance.new("ScreenGui") decalGui.Name = "DecalGui" decalGui.IgnoreGuiInset = true decalGui.Parent = playerGui local imageLabel = Instance.new("ImageLabel") imageLabel.Size = UDim2.new(1, 0, 1, 0) imageLabel.Position = UDim2.new(0, 0, 0, 0) imageLabel.BackgroundTransparency = 1 imageLabel.Image = part:GetAttribute("DecalId") or Config.Decal.defaultId imageLabel.Parent = decalGui local Win = Instance.new("Sound") Win.SoundId = Config.Decal.winSoundId Win.Volume = Config.Decal.winSoundVolume Win.Pitch = Config.Decal.winSoundPitch Win.Parent = player Win:Play() wait(Config.Decal.displayTime) decalGui:Destroy() Win:Destroy() activeDecalPlayers[player] = nil if part:GetAttribute("TeleportToSpawn") then player:LoadCharacter() end end --------------------------------------------------------------------- -- PART APPEARANCE RESET --------------------------------------------------------------------- local function resetPartAppearance(part) if part:GetAttribute("DisappearOnTimerActivate") then part.Transparency = 0 part.CanCollide = true for _, descendant in ipairs(part:GetDescendants()) do if descendant:IsA("BasePart") then descendant.Transparency = 0 descendant.CanCollide = true elseif descendant:IsA("TextLabel") or descendant:IsA("TextButton") then descendant.TextTransparency = 0 elseif descendant:IsA("ParticleEmitter") then descendant.Enabled = true end end end end --------------------------------------------------------------------- -- GUI TIMER CREATION --------------------------------------------------------------------- local function createTimerGui(player, triggeringPart) if timerActive then return end timerActive = true timerStatusEvent:FireClient(player, true, false) if player:FindFirstChild("PlayerGui"):FindFirstChild("TimerGui") then return end local screenGui = Instance.new("ScreenGui") screenGui.Name = "TimerGui" screenGui.Parent = player:FindFirstChild("PlayerGui") local timerLabel = Instance.new("TextLabel") timerLabel.Size = Config.TimerGui.labelSize timerLabel.Position = Config.TimerGui.labelPosition timerLabel.BackgroundTransparency = Config.TimerGui.labelBackgroundTransparency timerLabel.BackgroundColor3 = Config.TimerGui.labelBackgroundColor local duration = triggeringPart and triggeringPart:GetAttribute("TimerDuration") or Config.MainTimerDuration timerLabel.Text = string.format("%d:%02d", math.floor(duration / 60), duration % 60) timerLabel.Font = Config.TimerGui.labelFont timerLabel.TextSize = Config.TimerGui.labelTextSize timerLabel.TextColor3 = Config.TimerGui.labelTextColor timerLabel.Parent = screenGui local tween = TweenService:Create(timerLabel, TweenInfo.new(Config.TimerGui.tweenTime, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Position = Config.TimerGui.tweenPosition}) tween:Play() local function onTimerComplete() if triggeringPart and triggeringPart:GetAttribute("DisappearOnTimerActivate") then triggeringPart.Transparency = 0 triggeringPart.CanCollide = true for _, descendant in ipairs(triggeringPart:GetDescendants()) do if descendant:IsA("BasePart") then descendant.Transparency = 0 descendant.CanCollide = true elseif descendant:IsA("TextLabel") or descendant:IsA("TextButton") then descendant.TextTransparency = 0 elseif descendant:IsA("ParticleEmitter") then descendant.Enabled = true end end end screenGui:Destroy() timerActive = false timerStatusEvent:FireClient(player, false, false) currentTimer = nil end local allowOvertime = true if triggeringPart and triggeringPart:GetAttribute("DisableOvertime") then allowOvertime = false end currentTimer = Timer.new(duration, timerLabel, player, onTimerComplete, allowOvertime) currentTimer:start(spawnOrbitalDemonWithEffects) task.spawn(function() while currentTimer and not currentTimer.cancelled and currentTimer.remaining > 0 do if Workspace:FindFirstChild("CancelTimer") and Workspace.CancelTimer.Value then currentTimer:cancel() screenGui:Destroy() timerActive = false timerStatusEvent:FireClient(player, false, false) currentTimer = nil break end task.wait(0.1) end end) end --------------------------------------------------------------------- -- PART TOUCHED HANDLING --------------------------------------------------------------------- local function onPartTouched(part, player) if part:GetAttribute("ExitTimer") then if currentTimer then currentTimer:cancel() if demon then demon:Destroy() end timerStatusEvent:FireClient(player, false) if part:GetAttribute("ShowDecalBeforeTeleport") then task.spawn(function() showDecalAndTeleport(player, part) end) else if part:GetAttribute("TeleportToSpawn") then wait(0.1) player:LoadCharacter() end end end return end if part:GetAttribute("LocalTimeActivate") then createTimerGui(player, part) elseif part:GetAttribute("PublicTimeActivate") then for _, plr in ipairs(Players:GetPlayers()) do createTimerGui(plr, part) end end if part:GetAttribute("PlaySoundOnTimerActivate") and not soundPlayed then local presetNumber = part:GetAttribute("SoundPreset") local preset = presetNumber and Config.AudioPresets["preset" .. presetNumber] if preset then local sound = part:FindFirstChildOfClass("Sound") or Instance.new("Sound", part) sound.SoundId = preset.soundId sound.Volume = preset.volume sound.Pitch = preset.pitch sound.Looped = preset.looped or false sound:Play() end soundPlayed = true end if part:GetAttribute("DisappearOnTimerActivate") then part.Transparency = 1 part.CanCollide = false for _, descendant in ipairs(part:GetDescendants()) do if descendant:IsA("BasePart") then descendant.Transparency = 1 descendant.CanCollide = false elseif descendant:IsA("TextLabel") or descendant:IsA("TextButton") then descendant.TextTransparency = 1 elseif descendant:IsA("ParticleEmitter") then descendant.Enabled = false end end end end --------------------------------------------------------------------- -- CONNECTION HELPER --------------------------------------------------------------------- local function connectPart(part) if part:IsA("BasePart") then part.Touched:Connect(function(hit) local player = Players:GetPlayerFromCharacter(hit.Parent) if player then onPartTouched(part, player) end end) end end for _, part in ipairs(workspace:GetChildren()) do connectPart(part) end workspace.ChildAdded:Connect(connectPart) --------------------------------------------------------------------- -- RESET TIMER AND PARTS ON PLAYER RESPAWN / JOIN --------------------------------------------------------------------- Players.PlayerAdded:Connect(function(player) player.CharacterAdded:Connect(function() timerActive = false soundPlayed = false if currentTimer then currentTimer:cancel() currentTimer = nil end activeDecalPlayers[player] = nil for _, part in ipairs(workspace:GetChildren()) do resetPartAppearance(part) end timerStatusEvent:FireClient(player, false, false) end) end)
Updated files
v1
just make it a visual
Updated files
v2
Updated files
v3